diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ee2fb66..d2f0331 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -38,7 +38,7 @@ body: attributes: label: Versions description: Provide Python, cometapi, and openai versions. - placeholder: "Python 3.13; cometapi 0.1.0a1; openai 2.45.0" + placeholder: "Python 3.13; cometapi ; openai 2.45.0" validations: required: true - type: input diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 454432c..088dd17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,10 @@ jobs: run: uv run pyright - name: Run offline unit and contract tests run: uv run pytest -m "not live" + - name: Select latest OpenAI within the supported major + run: uv pip install --python .venv/bin/python --upgrade "openai>=2.45.0,<3.0.0" + - name: Run latest-within-major tests without resyncing the lock + run: uv run --no-sync pytest -m "not live" - name: Check version agreement and durable public content run: uv run python scripts/check_version.py --require-changelog --require-public-preview-docs - name: Scan for credentials and scope mistakes @@ -95,27 +99,6 @@ jobs: - name: Run offline tests without resyncing the lock run: uv run --no-sync pytest -m "not live" - latest-openai: - name: Latest OpenAI within major canary - if: github.event_name == 'schedule' || github.actor == 'dependabot[bot]' - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - name: Check out the candidate - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Set up Python - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - - name: Install the pinned uv frontend - run: python -m pip install --disable-pip-version-check "uv==$UV_VERSION" - - name: Create the development environment - run: uv sync --locked - - name: Select latest OpenAI within the supported major - run: uv pip install --python .venv/bin/python --upgrade "openai>=2.45.0,<3.0.0" - - name: Run canary tests without resyncing the lock - run: uv run --no-sync pytest -m "not live" - package: name: Build, inspect, and clean-install exact artifacts needs: [quality, locked-runtime, minimum-openai] diff --git a/.github/workflows/live-smoke.yml b/.github/workflows/live-smoke.yml index f51a1f7..74a19a8 100644 --- a/.github/workflows/live-smoke.yml +++ b/.github/workflows/live-smoke.yml @@ -4,6 +4,16 @@ on: schedule: - cron: "17 3 * * *" workflow_dispatch: + inputs: + max_output_tokens: + description: Maximum output tokens for each bounded live request + required: true + default: "64" + type: choice + options: + - "64" + - "128" + - "256" permissions: contents: read @@ -15,8 +25,8 @@ concurrency: env: UV_VERSION: 0.11.8 COMETAPI_LIVE_MAX_REQUESTS: "4" - COMETAPI_LIVE_MAX_OUTPUT_TOKENS: "16" - COMETAPI_LIVE_MODEL: gpt-5.4 + COMETAPI_LIVE_MAX_OUTPUT_TOKENS: ${{ inputs.max_output_tokens || '64' }} + COMETAPI_LIVE_MODEL: gpt-5.6-sol COMETAPI_LIVE_REQUEST_TIMEOUT_SECONDS: "30" COMETAPI_LIVE_CONCURRENCY: "1" COMETAPI_LIVE_RUN: "1" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f77c17c..466ae16 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -314,14 +314,14 @@ jobs: timeout-minutes: 10 permissions: contents: read - # Required repository configuration: protect this environment without required reviewers, - # and configure COMETAPI_KEY plus the approved COMETAPI_LIVE_MODEL variable. + # Required repository configuration: protect this environment without required reviewers + # and configure only the scoped COMETAPI_KEY credential. environment: live-smoke env: COMETAPI_LIVE_CONCURRENCY: "1" - COMETAPI_LIVE_MAX_OUTPUT_TOKENS: "16" + COMETAPI_LIVE_MAX_OUTPUT_TOKENS: "64" COMETAPI_LIVE_MAX_REQUESTS: "4" - COMETAPI_LIVE_MODEL: ${{ vars.COMETAPI_LIVE_MODEL || 'gpt-5.4' }} + COMETAPI_LIVE_MODEL: gpt-5.6-sol COMETAPI_LIVE_REQUEST_TIMEOUT_SECONDS: "30" COMETAPI_LIVE_RUN: "1" COMETAPI_LIVE_STOP_ON_FAILURE: "1" @@ -381,7 +381,7 @@ jobs: working-directory: release-bundle run: sha256sum --check artifact-sha256.txt - name: Publish through the configured PyPI Trusted Publisher - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 + uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1, node24 with: packages-dir: release-bundle/dist/ print-hash: true diff --git a/AGENTS.md b/AGENTS.md index a3bdee8..fe50c53 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -64,44 +64,8 @@ Registry Alpha, and the first stable release are completed historical steps and must not be repeated. The canonical repository is public with protected branch and version-tag rules, Private Vulnerability Reporting, immutable releases, protected environments, public default-branch CI, and protected release and -registry evidence. - -The accepted `0.1.1` maintenance release evidence is: - -| Field | Value | -| --- | --- | -| Release commit and tag target | `576e7503a0a8c1103faca5143e4b8d576f8e8b44` | -| Release tag | `v0.1.1` | -| GitHub release | `https://github.com/cometapi-dev/cometapi-python/releases/tag/v0.1.1` | -| Release workflow | `https://github.com/cometapi-dev/cometapi-python/actions/runs/30429821548` | -| PyPI release | `https://pypi.org/project/cometapi/0.1.1/` | -| Wheel SHA256 | `27e7904542f82fbbcd60e0de23a4a62c042420b6d004d00286d1f37d2ec4c5e5` | -| Source SHA256 | `64c7cb87745032703b3374cc562ea00b979416c54908862dbcebd116b2dc44c8` | - -The accepted `0.1.0` stable release evidence is: - -| Field | Value | -| --- | --- | -| Release commit and tag target | `6f42981edcc6c252f8db997606671c3da84d1dd8` | -| Release tag | `v0.1.0` | -| GitHub release | `https://github.com/cometapi-dev/cometapi-python/releases/tag/v0.1.0` | -| Release workflow | `https://github.com/cometapi-dev/cometapi-python/actions/runs/30359383715` | -| PyPI release | `https://pypi.org/project/cometapi/0.1.0/` | -| Wheel SHA256 | `8eae758688bb6c98274e48d8d81f882eeae760f69cfd2f5e125004881d60e90f` | -| Source SHA256 | `e9308b44f6091200b5121e24d1a0e1b9ea3e6bcccc109d6de87554b1ab2a8bca` | - -The accepted Registry Alpha evidence is: - -| Field | Value | -| --- | --- | -| Release commit | `31b68904141489ca04932edbf305ccf88af09372` | -| Recovery tag | `v0.1.0-alpha.1+recovery.1` | -| Tag object | `fdc4a6cce31f4534f83903f3f95e7757a4d4049f` | -| GitHub release | `https://github.com/cometapi-dev/cometapi-python/releases/tag/v0.1.0-alpha.1%2Brecovery.1` | -| Release workflow | `https://github.com/cometapi-dev/cometapi-python/actions/runs/30261746138` | -| PyPI release | `https://pypi.org/project/cometapi/0.1.0a1/` | -| Wheel SHA256 | `a6820347317943ca22f7632acbe354dd992f31a122a6172dfe45b57960e3a093` | -| Source SHA256 | `98d86829ef14771e8b7ec180d452c6638289f49c14a39b7207be5c47cb64cde7` | +registry evidence. Exact historical identities and digests belong only in the +validated evidence blocks in `ROADMAP.md` and `RELEASING.md`. The accepted identity is: @@ -155,7 +119,7 @@ Post-stable invariants: direct dependency's `result` to equal `success`. A skipped, cancelled, failed, or missing dependency must never make build, live smoke, publication, or registry verification eligible. -9. Keep Release Please pinned to the reviewed `v5.0.0` commit +9. Keep Release Please v5.0.0 pinned to the reviewed commit `45996ed1f6d02564a971a2fa1b5860e934307cf7`, whose immutable action metadata uses `node24`. The workflow semantic checker must reject any different pin. Invoke that action release-only first with `skip-github-pull-request: true`; @@ -170,6 +134,10 @@ Post-stable invariants: state read-only, and stop. Do not use another main push or recovery path until the exact external state is known and recovery is separately authorized. + Keep the PyPI publisher v1.14.1 pinned to the reviewed commit whose + composite action uses the Node 24 `setup-python` fallback. The workflow + checker must reject any other publisher SHA without changing the top-level + workflow, job, environment, or Trusted Publisher identity. 10. `README.md` is the distribution long description and must remain accurate before and after publication. Use `python -m pip install cometapi`, unversioned project links, and publication-neutral maintenance language. @@ -181,8 +149,11 @@ Post-stable invariants: persistent guidance or current-state documentation. Query public PyPI when current registry state is required. Keep candidate version truth in `pyproject.toml` and `.release-please-manifest.json`, and keep exact released - versions only in immutable historical evidence. The document/version - checker must fail before merge or release when this boundary is violated. + versions only in `CHANGELOG.md` or validated immutable evidence blocks in + `ROADMAP.md` and `RELEASING.md`. All other persistent/current-state public + documents must contain no exact CometAPI patch or recovery identity. The + document/version checker must fail before merge or release when this + boundary is violated. ## Repository independence @@ -265,9 +236,9 @@ that exact version. Runtime dependencies belong in the manifest only when CometAPI source directly imports and owns their use. Compatibility checks cover the minimum supported OpenAI version, the locked -development version, and a scheduled or dependency-PR latest-within-major -canary. Python 3.10 through 3.14 is the initial blocking runtime range while -Python 3.10 remains upstream-supported. +development version, and a blocking latest-within-major lane on every pull +request and default-branch push. Python 3.10 through 3.14 is the initial +blocking runtime range while Python 3.10 remains upstream-supported. ## Development and verification @@ -312,7 +283,7 @@ committed. ## Release and documentation rules -- The first public artifact must be functional `0.1.0a1`, never a placeholder. +- The first public artifact was functional Registry Alpha, never a placeholder. - Publication uses a reviewed immutable tag, a protected `pypi` environment, and PyPI OIDC Trusted Publishing. - The release commit must equal the tag target and belong to the protected @@ -339,11 +310,10 @@ committed. - Every distribution `Project-URL` must use HTTPS. The canonical Support URL is `https://github.com/cometapi-dev/cometapi-python/blob/main/SUPPORT.md`; `support@cometapi.com` remains the support and conduct contact. -- GitHub permanently reserved `v0.1.0-alpha.1` after its immutable release - reached OIDC publication but failed before any PyPI distribution was - accepted. The sole approved recovery tag is - `v0.1.0-alpha.1+recovery.1`, which maps to package version `0.1.0a1`. - Later releases must use their ordinary canonical tag spelling. +- The initial Registry Alpha recovery exception is immutable historical + evidence recorded in `ROADMAP.md` and `RELEASING.md`. Later releases must use + their ordinary canonical tag spelling; do not reuse or increment that + exception. - Keep Release Please disabled outside an explicitly authorized release sequence. The stable-readiness configuration used a reviewed and tested `last-release-sha` bridge because the recovery tag's build metadata could not @@ -362,7 +332,9 @@ committed. - Keep README, roadmap, compatibility matrix, examples, and changelog aligned with shipped behavior. README installation and availability guidance must be publication-neutral because it is embedded in immutable distribution - metadata. Use currently supported model IDs. + metadata. Keep the active example/live model in the checker's canonical + model constant; executable README examples and both live workflows must fail + validation when they drift from it. - All repository documentation is written in English. The Public Preview readiness record requires diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0d0f602..806b951 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -101,7 +101,7 @@ Compatibility evidence has three lanes: - minimum OpenAI on the oldest supported Python runtime; - locked OpenAI across the blocking Python runtime matrix; and -- latest OpenAI below 3.0 as a scheduled and dependency-update canary. +- latest OpenAI below 3.0 as a blocking pull-request and default-branch lane. ## Verification boundaries @@ -135,11 +135,19 @@ and after a release. Source-document and artifact checks reject approval, unpublished, exact-version installation, and versioned release-link text; each artifact long description must also exactly match the source README. -Release Please is pinned to the immutable `v5.0.0` commit whose action metadata +Release Please v5.0.0 is pinned to the immutable commit whose action metadata uses `node24`. The workflow semantic contract fixes that SHA and runtime disposition so GitHub does not need to force a deprecated Node 20 action onto a newer runtime. +The version gate accepts Release Please's native linked, dated changelog heading +as well as the existing legacy dated form. It validates repository, previous +tag, candidate tag, and calendar date rather than rewriting generated history. + +The PyPI publisher remains directly in `publish.yml` and is pinned to its +reviewed Node 24 maintenance release. Pinning its exact SHA prevents a syntactic +full-SHA substitution from silently changing the OIDC publication supply chain. + Release Please execution is split at the mutability boundary. The first pinned action invocation is release-only (`skip-github-pull-request: true`) and is neither continued on error nor retried. Only when that invocation succeeds @@ -150,39 +158,10 @@ failure ends the job. Updating a branch or pull request is mutable and idempotent, while retrying immutable tag or GitHub Release creation could leave ambiguous external state and is forbidden. -[Release Please run 30509764960](https://github.com/cometapi-dev/cometapi-python/actions/runs/30509764960) -isolated the motivating failure to the action's Undici/global `fetch`: the PR -workflow reached its write boundary and then failed with `other side closed` -before any branch, pull-request, tag, GitHub Release, live, or registry write. -The existing release branch and repository pull-request permission were not the -cause. This is negative transport evidence, not evidence of a stale branch or -authorization drift. - -This complete trust chain executed successfully in -[release workflow run 30261746138](https://github.com/cometapi-dev/cometapi-python/actions/runs/30261746138) -for release commit `31b68904141489ca04932edbf305ccf88af09372`, recovery tag -`v0.1.0-alpha.1+recovery.1`, and PyPI version `0.1.0a1`. The public wheel and -source distribution matched the retained pre-publication digests, Trusted -Publisher provenance was verified, and the clean registry install/import/mocked -smoke passed. - -The same trust chain executed successfully for stable `0.1.0` in -[release workflow run 30359383715](https://github.com/cometapi-dev/cometapi-python/actions/runs/30359383715). -The immutable `v0.1.0` tag resolves to release commit -`6f42981edcc6c252f8db997606671c3da84d1dd8`; the protected live suite, direct -top-level OIDC publication, public digest and provenance comparison, and clean -registry install all passed. The selector-descendant conditions were therefore -verified in GitHub's hosted scheduler, not only by local static checks. - -The same trust chain completed for maintenance release `0.1.1` in -[release workflow run 30429821548](https://github.com/cometapi-dev/cometapi-python/actions/runs/30429821548). -The immutable `v0.1.1` tag resolves to release commit -`576e7503a0a8c1103faca5143e4b8d576f8e8b44`; exact-release live smoke, direct -top-level OIDC publication, public digest and provenance comparison, and clean -registry installation all passed. The public wheel SHA256 is -`27e7904542f82fbbcd60e0de23a4a62c042420b6d004d00286d1f37d2ec4c5e5`, and the -source-distribution SHA256 is -`64c7cb87745032703b3374cc562ea00b979416c54908862dbcebd116b2dc44c8`. +Immutable run, tag, commit, registry, and digest records live only in the +validated release-evidence blocks in `ROADMAP.md` and `RELEASING.md`. +Architecture documents mechanisms and boundaries, not a second historical +ledger. The scheduled/manual default-branch smoke is an operational canary only; it does not prove the release commit. `COMETAPI_KEY` is exposed only to the @@ -218,11 +197,9 @@ reject every rerun, and require every direct dependency's result to equal `success`. This crosses only the unused branch's skipped ancestry; cancellation, failure, a skipped direct dependency, or a missing result remains fail-closed. -The initial alpha has one release-identity exception. GitHub's immutable -release tombstone permanently reserves `v0.1.0-alpha.1`, so the reviewed -recovery release uses SemVer build metadata in -`v0.1.0-alpha.1+recovery.1`. The build suffix does not change the package -artifact identity: the PyPI version remains `0.1.0a1`. +The initial Registry Alpha has one immutable release-identity exception. Its +exact recovery tag and package mapping are historical evidence in +`RELEASING.md`; later releases use the ordinary canonical tag spelling. Release Please remains disabled outside an explicitly authorized release sequence. The stable-readiness configuration used a tested `last-release-sha` diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 6a40798..7b2a129 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -48,7 +48,7 @@ openai>=2.45.0,<3.0.0 | --- | --- | --- | | Minimum `2.45.0` | Prove the declared lower bound | Oldest supported Python runtime | | Locked development version | Reproducible contributor and blocking CI environment | Every blocking Python runtime | -| Latest available below `3.0.0` | Detect upstream drift | Scheduled and dependency-update canary | +| Latest available below `3.0.0` | Detect upstream drift | Every pull request and default-branch push | The lock file is development evidence only. It does not narrow the dependency range installed for library users. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 55fb740..edefcb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,8 +38,8 @@ uv run python scripts/check_repository_independence.py uv run python scripts/run_actionlint.py ``` -`scripts/run_actionlint.py` downloads and checksum-verifies `actionlint` -1.7.12 when it is not cached. A passing static workflow check does not mean the +`scripts/run_actionlint.py` downloads and checksum-verifies actionlint 1.7.12 +when it is not cached. A passing static workflow check does not mean the workflow has run successfully on GitHub. If a check is unavailable, say so in the pull request rather than describing diff --git a/README.md b/README.md index e640d55..327b1fa 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ from cometapi import CometAPI with CometAPI() as client: response = client.chat.completions.create( - model="gpt-5.4", + model="gpt-5.6-sol", messages=[{"role": "user", "content": "Hello!"}], ) print(response.choices[0].message.content) @@ -88,7 +88,7 @@ from cometapi import CometAPI with CometAPI() as client: stream = client.chat.completions.create( - model="gpt-5.4", + model="gpt-5.6-sol", messages=[{"role": "user", "content": "Write one sentence."}], stream=True, ) @@ -104,7 +104,7 @@ from cometapi import CometAPI with CometAPI() as client: response = client.responses.create( - model="gpt-5.4", + model="gpt-5.6-sol", input="Explain API compatibility in one sentence.", ) models = client.models.list() @@ -125,7 +125,7 @@ from cometapi import AsyncCometAPI async def main() -> None: async with AsyncCometAPI() as client: response = await client.responses.create( - model="gpt-5.4", + model="gpt-5.6-sol", input="Say hello.", ) print(response.output_text) diff --git a/RELEASING.md b/RELEASING.md index 4a28782..d604ecc 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -9,7 +9,7 @@ Use these states precisely: | Local code-complete | Source, tests, documentation, metadata, scripts, and workflow definitions exist and applicable offline checks pass. | | Private Remote Validation ready | Local gates pass, the sanitized history and maintainer-confirmed identity are complete, and real credential-free private default-branch CI passes. | | Public Preview ready | After visibility changes, public-only repository rules, security reporting, environments, default-branch CI, the content gate, and authorized protected live smoke all pass. | -| Registry Alpha candidate | The exact `0.1.0a1` wheel and source distribution pass metadata, file-list, clean-install, import, and mocked-call checks. | +| Registry Alpha candidate | The exact candidate wheel and source distribution pass metadata, file-list, clean-install, import, and mocked-call checks. | | Registry Alpha released | The public PyPI artifact has provenance, installs cleanly, imports, and passes the post-publication mocked-call smoke. | | Stable released | Every stable runtime, release-PR, live, example, provenance, and registry gate has separate evidence. | @@ -54,8 +54,8 @@ corresponding gated job from executing. `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` are absent by default and may exist only during an explicitly authorized recovery of that exact existing immutable release identity. -The release live-model configuration resolves an unset or empty -`COMETAPI_LIVE_MODEL` to `gpt-5.4`. +The release live-model configuration is fixed to the canonical active model +enforced by the workflow checker; repository variables cannot override it. The completed private stage validated sanitized history, the complete local gate, and real credential-free default-branch CI only. It did not configure or @@ -167,12 +167,19 @@ secret separation, and checkout-before-bundle-download ordering. Its git-backed tests exercise accepted and rejected release histories locally; they still do not emulate GitHub Actions. -The Release Please step is pinned to -`googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7` -(`v5.0.0`), whose immutable action metadata selects `node24`. The semantic +The Release Please v5.0.0 step is pinned to +`googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7`, +whose immutable action metadata selects `node24`. The semantic checker rejects any other pin so the workflow cannot silently regress to the deprecated Node 20 runtime. +The direct PyPI publisher v1.14.1 is pinned to the reviewed commit. Its only +action-definition change from the previously reviewed publisher is the +conditional `setup-python` fallback moving from Node 20 to Node 24; the +top-level `publish.yml`, `publish` job, `pypi` environment, and Trusted +Publisher identity remain unchanged. The semantic checker requires this exact +publisher SHA. + The job invokes the pinned action release-only first with `skip-github-pull-request: true`. That step cannot continue on error and is never retried. If it succeeds without creating a release, PR-only maintenance @@ -193,10 +200,12 @@ authorization failure. Release mode (`check_version.py --require-releasable-docs`) also fails closed until project authorship, the canonical GitHub repository URL, the copyright -holder, security and support contacts, a publication-neutral README, and a dated -changelog release section are present. Public Preview validation reports all -discovered violations in one run and still returns non-zero when any violation -exists. +holder, security and support contacts, a publication-neutral README, and a +canonical dated changelog release section are present. It accepts Release +Please's native linked heading and the legacy historical heading, so release PRs +do not require a formatting-only finalization commit. Public Preview validation +reports all discovered violations in one run and still returns non-zero when any +violation exists. `pyproject.toml` embeds `README.md` as the immutable distribution long description. The README therefore uses the unpinned @@ -211,12 +220,17 @@ descriptions cannot drift. - `ci.yml` runs credential-free lint, type, unit, contract, package, artifact, and clean-install checks for pull requests and default-branch pushes. - `live-smoke.yml` checks out and runs only the canonical default branch on - trusted scheduled or manual events with a maintainer-approved key and model. It - is ongoing monitoring only and cannot satisfy a release gate. It is capped at - four requests, 16 output tokens - per generation, a 30-second request timeout, concurrency one, a ten-minute - workflow timeout, and stop on the first failure. Every trigger requires - `LIVE_SMOKE_ENABLED=true`. + trusted scheduled or manual events with a maintainer-approved key and the + checker-fixed canonical model. It is ongoing monitoring only and cannot + satisfy a release gate. It is capped at four requests, a reviewed 64/128/256 + output-token calibration choice with a 64-token default, a 30-second request + timeout, concurrency one, a ten-minute workflow timeout, and stop on the first + failure. Every trigger requires `LIVE_SMOKE_ENABLED=true`. +- Calibrate monitoring strictly in the order 64, 128, then 256, stopping on the + first pass. Run at most three workflows and twelve requests. Escalate only + when the validator reports `finish_reason=length` or an incomplete reason of + `max_output_tokens`; authentication, routing, model, transport, timeout, API + event, or any other failure stops calibration and blocks release. - Before enabling `RELEASE_PLEASE_ENABLED` or merging the change intended to open or update a release PR, verify the effective repository setting: @@ -262,8 +276,9 @@ descriptions cannot drift. before the protected `pypi` job becomes eligible. The workflow publishes the previously verified artifacts with OIDC, then checks the public package against the exact pre-publication digests and Trusted Publisher provenance - before a clean install explicitly from `https://pypi.org/simple/`. An unset - or empty live-model repository variable resolves to `gpt-5.4`. + before a clean install explicitly from `https://pypi.org/simple/`. The exact + release live model is the canonical active model enforced by the workflow + checker and cannot be overridden by repository variables. Because the unused Release Please or recovery path is intentionally skipped, every job after the selector must use `always() && !cancelled()`, reject reruns, and require each direct dependency's result to equal `success`. This @@ -305,16 +320,13 @@ Maintainers then completed these steps in order: concurrency-one, stop-on-failure budget. 3. Finalized the dated changelog and prerelease documentation and reran every candidate verification gate, including - `uv run python scripts/check_version.py --expected 0.1.0a1 --require-changelog --require-releasable-docs`. -4. Reviewed the exact candidate and created the immutable SemVer recovery tag - `v0.1.0-alpha.1+recovery.1` and corresponding GitHub prerelease. GitHub - permanently reserved `v0.1.0-alpha.1` after its immutable release reached - OIDC publication but failed before PyPI accepted any distribution. The - recovery build suffix preserves the equivalent PEP 440 package version - `0.1.0a1`; it is a one-time exception and must not be incremented or reused - for later releases. Release Please was kept disabled until a separate - reviewed and tested `last-release-sha` bridge established this recovery - commit as its previous-release boundary. + `uv run python scripts/check_version.py --require-changelog --require-releasable-docs`. +4. Reviewed the exact candidate and created the one-time immutable recovery tag + and corresponding GitHub prerelease. The exact tombstone, tag, and package + mapping are retained in the Registry Alpha evidence block and must not be + incremented or reused for later releases. Release Please was kept disabled + until a separate reviewed and tested `last-release-sha` bridge established + this recovery commit as its previous-release boundary. 5. The release workflow proved `immutable=true`, resolved the tag to the checked-out commit, verified that commit was reachable from the protected default branch, and ran the bounded protected live suite against that exact @@ -331,11 +343,14 @@ Python publication is OIDC-only. There is no token-bootstrap exception for PyPI. The version checker must normalize the SemVer tag and PEP 440 package spelling -to the same `0.1.0a1` value across the tag, release manifest, package metadata, +to the same candidate value across the tag, release manifest, package metadata, changelog, GitHub release, wheel, and source distribution. ### Completed Registry Alpha evidence + + + - Metadata [PR #16](https://github.com/cometapi-dev/cometapi-python/pull/16) merged as `6344c2d0e2e975360b42c887275c1950b82918ee`; recovery contract [PR #17](https://github.com/cometapi-dev/cometapi-python/pull/17) merged as @@ -358,6 +373,8 @@ changelog, GitHub release, wheel, and source distribution. bridge generated the stable release PR and was removed during human finalization. + + ## Stable release sequence ```text @@ -379,7 +396,7 @@ feature or fix pull request -> roadmap milestone marked released ``` -Stable `0.1.0` additionally required the complete blocking Python matrix, +The first stable release additionally required the complete blocking Python matrix, executed README examples against the built package, trusted live evidence, and reviewed release-PR and changelog agreement. Its one-time finalization removed the `last-release-sha` and prerelease-versioning controls. Later maintenance @@ -446,13 +463,16 @@ then passed immutable recovery verification and the shared release selector, but GitHub propagated the intentionally skipped Release Please ancestry to the plain downstream job conditions. Build, live smoke, publication, and registry verification were all skipped while the overall workflow incorrectly reported -success. No live request or PyPI upload occurred, and `cometapi==0.1.0` remained -absent. The permanent correction explicitly evaluates every selector descendant +success. No live request or PyPI upload occurred, and the stable distribution +remained absent. The permanent correction explicitly evaluates every selector descendant and requires all of its direct dependencies to succeed. A further recovery remained blocked until that fix reached `main` and a new recovery was explicitly authorized. -### Completed `0.1.0` stable release evidence +### Completed first stable release evidence + + + - The immutable non-draft [GitHub release](https://github.com/cometapi-dev/cometapi-python/releases/tag/v0.1.0) and lightweight tag `v0.1.0` resolve to release commit @@ -482,7 +502,12 @@ authorized. `LIVE_SMOKE_ENABLED=false` was the only remaining release-related repository variable. -### Completed `0.1.1` maintenance release evidence + + +### Completed configuration maintenance release evidence + + + - Configuration fix [PR #25](https://github.com/cometapi-dev/cometapi-python/pull/25) passed [pull-request CI run 30419881169](https://github.com/cometapi-dev/cometapi-python/actions/runs/30419881169) @@ -526,7 +551,12 @@ authorized. `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` are absent; no recovery tag or recovery workflow was used for `0.1.1`. -### Completed `0.1.2` maintenance release evidence + + +### Completed release-metadata maintenance evidence + + + - Metadata and runtime [PR #29](https://github.com/cometapi-dev/cometapi-python/pull/29) made packaged long descriptions release-neutral, added artifact assertions, @@ -576,7 +606,12 @@ authorized. `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` are absent; no recovery tag, workflow dispatch, or workflow rerun was used for `0.1.2`. -### Completed `0.1.3` maintenance release evidence + + +### Completed release-claim maintenance evidence + + + - Mutable-release-claim [PR #34](https://github.com/cometapi-dev/cometapi-python/pull/34) removed the published patch number from persistent guidance and extended the @@ -629,3 +664,5 @@ authorized. - `RELEASE_PLEASE_ENABLED=false` and `LIVE_SMOKE_ENABLED=false`. `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` are absent; no recovery tag, workflow dispatch, or release-workflow rerun was used for `0.1.3`. + + diff --git a/ROADMAP.md b/ROADMAP.md index 46c0ab7..165a002 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -29,13 +29,13 @@ roadmap and `COMPATIBILITY.md`. | Repository foundation | Complete | Public files, offline gates, packaging checks, and self-containment are complete. | | Private Remote Validation | Complete | The sanitized private repository passes real credential-free default-branch CI; public-only controls and live tests remain disabled. | | Public Preview | Complete | The public repository has blocking CI, repository rules, security reporting, protected environments, immutable releases, and authorized live-smoke evidence. | -| `0.1.0a1` Registry Alpha | Complete | Early adopters can install the functional prerelease from PyPI; every release and registry gate passed. | -| `0.1.0` stable | Complete | Complete runtime, release-PR, example, provenance, and registry gates passed. | -| `0.1.1` maintenance | Complete | Configuration validation and every stable release, live, provenance, and registry gate passed. | -| `0.1.2` maintenance | Complete | Publication-neutral metadata and release-transport boundaries passed every normal release, live, provenance, and registry gate. | -| `0.1.3` maintenance | Complete | Mutable-release-claim detection passed every normal release, live, provenance, and registry gate. | -| `0.2.0` provider-native text | Planned | Optional official Anthropic and Gemini adapters. | -| `0.3.0` CometAPI resources | Planned | First schema-backed typed CometAPI-specific resource. | +| Registry Alpha | Complete | Early adopters could install the functional prerelease from PyPI; every release and registry gate passed. | +| First stable release | Complete | Complete runtime, release-PR, example, provenance, and registry gates passed. | +| Configuration maintenance | Complete | Configuration validation and every stable release, live, provenance, and registry gate passed. | +| Release metadata maintenance | Complete | Publication-neutral metadata and release-transport boundaries passed every normal release, live, provenance, and registry gate. | +| Release-claim maintenance | Complete | Durable release-claim detection passed every normal release, live, provenance, and registry gate. | +| Provider-native text | Planned | Optional official Anthropic and Gemini adapters after separately authorized 0.2 activation. | +| CometAPI resources | Planned | First schema-backed typed CometAPI-specific resource after separately authorized 0.2 activation. | | Media and task APIs | Planned | Coherent task lifecycle precedes individual media helpers. | ## `0.1.x` maintenance @@ -55,7 +55,7 @@ CLI, translation, or Go surface without a separate maintainer request. Deliverables: -- Package `cometapi`, version `0.1.0a1`, with `CometAPI` and `AsyncCometAPI` and +- Package `cometapi`, with `CometAPI` and `AsyncCometAPI` and no legacy aliases. - Standalone documentation, MIT licensing, contribution and conduct guidance, security and support policies, architecture, release guide, changelog, @@ -145,9 +145,9 @@ Recorded pre-visibility dependency dispositions: | --- | --- | --- | | Dependabot [PR #1](https://github.com/cometapi-dev/cometapi-python/pull/1): `actions/download-artifact` 4.3.0 to 8.0.1 | Closed unmerged; superseded by merged private [PR #9](https://github.com/cometapi-dev/cometapi-python/pull/9) | PR #9 applies the reviewed SHA pin throughout the release workflow and adds a credential-free CI artifact download plus SHA256 round trip. Its final [CI run 29916685839](https://github.com/cometapi-dev/cometapi-python/actions/runs/29916685839) passed, PR #9 squash-merged as `72b212dd72e66bbde9c6714329f72071cc1ca129`, and PR #1 was closed without merging. | | Dependabot [PR #2](https://github.com/cometapi-dev/cometapi-python/pull/2): `actions/checkout` 4.2.2 to 7.0.1 | Closed unmerged; superseded by merged private [PR #9](https://github.com/cometapi-dev/cometapi-python/pull/9) | PR #2's [CI run 29796719306](https://github.com/cometapi-dev/cometapi-python/actions/runs/29796719306) failed because its regression test hard-coded the previous checkout SHA. PR #9 instead validates parsed action references independently of version, passed final CI run 29916685839, and squash-merged as `72b212dd72e66bbde9c6714329f72071cc1ca129`; PR #2 was closed without merging, and its failed run remains negative evidence only. | -| Dependabot [PR #3](https://github.com/cometapi-dev/cometapi-python/pull/3): `pypa/gh-action-pypi-publish` 1.14.0 to 1.14.1 | Deferred; keep out of `main` | Pull-request CI does not execute the release-triggered OIDC publish action or prove PyPI publication, provenance, or registry installation. Revisit with an authorized release-path review and the separately required protected release evidence; credential-free CI success alone is insufficient. | +| Dependabot [PR #3](https://github.com/cometapi-dev/cometapi-python/pull/3): `pypa/gh-action-pypi-publish` 1.14.0 to 1.14.1 | Superseded by current maintenance | The stale dependency PR remains unsuitable for merge, but its one-line Node 24 fallback update was independently reviewed and applied on the current maintenance branch with an exact-SHA semantic gate. Pull-request CI still does not prove OIDC publication, provenance, or registry installation; the authorized normal release supplies that evidence. | | Dependabot [PR #4](https://github.com/cometapi-dev/cometapi-python/pull/4): `actions/upload-artifact` 4.6.2 to 7.0.1 | Closed unmerged; superseded by merged private [PR #9](https://github.com/cometapi-dev/cometapi-python/pull/9) | PR #9 applies the reviewed SHA pin in CI and release builds, requires missing artifacts to fail, retains digest evidence, passed final CI run 29916685839, and squash-merged as `72b212dd72e66bbde9c6714329f72071cc1ca129`; PR #4 was closed without merging. | -| Dependabot [PR #5](https://github.com/cometapi-dev/cometapi-python/pull/5): `googleapis/release-please-action` 4.4.1 to 5.0.0 | Closed unmerged; superseded by merged [PR #29](https://github.com/cometapi-dev/cometapi-python/pull/29) | PR #29 pins the reviewed upstream `v5.0.0` commit, verifies its Node 24 runtime through the workflow semantic contract, and carries the release-metadata hardening required for `0.1.2`. Its final [CI run 30509063138](https://github.com/cometapi-dev/cometapi-python/actions/runs/30509063138) passed, and it squash-merged as `67bd1893983c724d1cc81b824106b7c3d9418e97`; PR #5 was then closed without merging. PR #5's failed CI remains negative evidence from the former semantic check that required the old action pin and is not runtime evidence. | +| Dependabot [PR #5](https://github.com/cometapi-dev/cometapi-python/pull/5): `googleapis/release-please-action` 4.4.1 to 5.0.0 | Closed unmerged; superseded by merged [PR #29](https://github.com/cometapi-dev/cometapi-python/pull/29) | PR #29 pins the reviewed upstream Release Please `v5.0.0` commit, verifies its Node 24 runtime through the workflow semantic contract, and carries the required release-metadata hardening. Its final [CI run 30509063138](https://github.com/cometapi-dev/cometapi-python/actions/runs/30509063138) passed, and it squash-merged as `67bd1893983c724d1cc81b824106b7c3d9418e97`; PR #5 was then closed without merging. PR #5's failed CI remains negative evidence from the former semantic check that required the old action pin and is not runtime evidence. | | Dependabot [PR #6](https://github.com/cometapi-dev/cometapi-python/pull/6): `actions/setup-python` 5.6.0 to 7.0.0 | Closed unmerged; superseded by merged private [PR #9](https://github.com/cometapi-dev/cometapi-python/pull/9) | PR #9 applies the reviewed SHA pin across CI, monitoring, and release workflows, passed final CI run 29916685839 on every blocking lane, and squash-merged as `72b212dd72e66bbde9c6714329f72071cc1ca129`; PR #6 was closed without merging. | Recorded pre-visibility replacement evidence on 2026-07-22: @@ -160,12 +160,12 @@ Local and package evidence at commit `uv run ruff format --check src tests scripts`, and `uv run pyright` passed. - `uv run pytest -m "not live"` passed with 173 tests passed and one separately marked live test deselected. -- `uv run python scripts/check_version.py --expected 0.1.0a1 --require-changelog` +- `uv run python scripts/check_version.py --require-changelog` and `uv run python scripts/check_version.py --require-public-preview-docs` passed. - `uv run python scripts/check_secrets.py` and `uv run python scripts/check_workflows.py` passed. -- `rm -rf dist` completed, and `uv build` produced the `0.1.0a1` wheel and source +- `rm -rf dist` completed, and `uv build` produced the candidate wheel and source distribution in the clean output directory. - `uv run twine check dist/*`, `uv run python scripts/check_artifacts.py dist/*`, and @@ -186,7 +186,7 @@ Follow-up verifier-hardening evidence at commit `uv run ruff format --check src tests scripts`, and `uv run pyright` passed. - `uv run pytest -m "not live"` passed with 197 tests passed and one separately marked live test deselected. -- `uv run python scripts/check_version.py --expected 0.1.0a1 --require-changelog`, +- `uv run python scripts/check_version.py --require-changelog`, `uv run python scripts/check_version.py --require-public-preview-docs`, `uv run python scripts/check_secrets.py`, and `uv run python scripts/check_workflows.py` passed. @@ -215,7 +215,7 @@ Final workflow-inventory hardening evidence at commit `uv run ruff format --check src tests scripts`, and `uv run pyright` passed. - `uv run pytest -m "not live"` passed with 200 tests passed and one separately marked live test deselected. -- `uv run python scripts/check_version.py --expected 0.1.0a1 --require-changelog`, +- `uv run python scripts/check_version.py --require-changelog`, `uv run python scripts/check_version.py --require-public-preview-docs`, `uv run python scripts/check_secrets.py`, and `uv run python scripts/check_workflows.py` passed. @@ -234,12 +234,12 @@ Final pre-visibility refresh evidence on 2026-07-23: `uv run ruff format --check src tests scripts`, and `uv run pyright` passed. - `uv run pytest -m "not live"` passed with 200 tests passed and one separately marked live test deselected. -- `uv run python scripts/check_version.py --expected 0.1.0a1 --require-changelog`, +- `uv run python scripts/check_version.py --require-changelog`, `uv run python scripts/check_version.py --require-public-preview-docs`, `uv run python scripts/check_secrets.py`, and `uv run python scripts/check_workflows.py` passed. -- `uv build --out-dir dist/previsibility-20260723` built exactly the - `0.1.0a1` wheel and source distribution in a newly created empty directory. +- `uv build --out-dir dist/previsibility-20260723` built exactly the candidate + wheel and source distribution in a newly created empty directory. `uv run twine check dist/previsibility-20260723/*`, `uv run python scripts/check_artifacts.py dist/previsibility-20260723/*`, and `uv run python scripts/check_clean_install.py dist/previsibility-20260723/*` @@ -357,7 +357,7 @@ Public Preview remains ready only while: 16-output-token, 30-second-per-request, concurrency-one, stop-on-first-failure budget. -## `0.1.0a1`: Registry Alpha +## Registry Alpha Registry Alpha completed on 2026-07-27. @@ -409,13 +409,14 @@ PyPI publication is OIDC-only; Python has no token-bootstrap exception. The first immutable release reached PyPI OIDC publication but Warehouse rejected its non-HTTPS Support project URL before accepting any distribution. -GitHub permanently reserved the deleted `v0.1.0-alpha.1` release identity. The -approved recovery release therefore uses -`v0.1.0-alpha.1+recovery.1`, whose SemVer build suffix leaves the PyPI package -version at the required first public artifact `0.1.0a1`. +The exact tombstoned and recovery identities are recorded in the immutable +Registry Alpha evidence block. Accepted release evidence: + + + - Metadata fix [PR #16](https://github.com/cometapi-dev/cometapi-python/pull/16) merged as `6344c2d0e2e975360b42c887275c1950b82918ee`; recovery contract [PR #17](https://github.com/cometapi-dev/cometapi-python/pull/17) merged as @@ -442,7 +443,15 @@ Accepted release evidence: `last-release-sha` bridge generated the stable release PR and was removed during human finalization. -## `0.1.0`: OpenAI protocol foundation + + +## First stable OpenAI protocol foundation + + + + +Canonical [GitHub release](https://github.com/cometapi-dev/cometapi-python/releases/tag/v0.1.0) +and [PyPI release](https://pypi.org/project/cometapi/0.1.0/) identity. Stable 0.1 retains the alpha surface. Its additional exit criteria are: @@ -514,7 +523,12 @@ Trusted Publisher provenance. Recovery variables were removed immediately after identity verification. At that closeout, `LIVE_SMOKE_ENABLED=false` was the only remaining release-related repository variable. -## `0.1.1`: Configuration validation maintenance + + +## Configuration validation maintenance + + + Maintenance release `0.1.1` rejects explicitly blank API keys and base URLs, treats a blank environment key as missing, and uses the default CometAPI URL @@ -571,7 +585,12 @@ imports, and passed every supported mocked call and README example. `RELEASE_PLEASE_ENABLED=false` and `LIVE_SMOKE_ENABLED=false`. Recovery variables are absent. No recovery tag or recovery workflow was used. -## `0.1.2`: Release metadata and transport maintenance + + +## Release metadata and transport maintenance + + + [Release Please run 30509764960](https://github.com/cometapi-dev/cometapi-python/actions/runs/30509764960) failed while maintaining the `0.1.2` release PR. The pinned v5 action had built @@ -640,7 +659,12 @@ guidance rather than a stale pre-publication version claim. variables are absent. No recovery tag, workflow dispatch, or workflow rerun was used for `0.1.2`. -## `0.1.3`: Durable release-claim maintenance + + +## Durable release-claim maintenance + + + [Implementation PR #34](https://github.com/cometapi-dev/cometapi-python/pull/34) removed the mutable published-patch claim from persistent guidance and extended @@ -701,7 +725,9 @@ bounded retry then completed the same registry smoke successfully. `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` are absent; no recovery tag, workflow dispatch, or release-workflow rerun was used for `0.1.3`. -## `0.2.0`: Provider-native text adapters + + +## Provider-native text adapters (future milestone) Planned scope: @@ -713,7 +739,7 @@ Planned scope: No 0.2 adapter is added without mocked and authorized live contract coverage. -## `0.3.0`: CometAPI-specific resources +## CometAPI-specific resources (future milestone) Candidate account or platform resources require an authoritative schema, authentication contract, error contract, fixtures, precise public types, and a @@ -727,8 +753,9 @@ The repository maintains three independently auditable workflows: - `ci.yml`: offline lint, type, unit, contract, build, artifact, and clean install checks for pull requests and default-branch pushes. - `live-smoke.yml`: scheduled and manual default-branch monitoring capped at - four requests, 16 output tokens per generation, a 30-second request timeout, - concurrency one, a ten-minute workflow timeout, and stop on first failure. + four requests, a reviewed 64/128/256 output-token calibration choice with a + 64-token default, a 30-second request timeout, concurrency one, a ten-minute + workflow timeout, and stop on first failure. - `publish.yml`: the single top-level release and PyPI Trusted Publisher identity. Its gated push path first attempts non-retryable release-only creation, then, only when no release exists, permits one bounded retry for @@ -750,8 +777,8 @@ Release Please requires `RELEASE_PLEASE_ENABLED=true` and remains disabled outside an explicitly authorized release sequence. Its reviewed one-time `last-release-sha` bridge established the recovery alpha boundary, generated the stable release PR, and was removed during human finalization. Release jobs -must resolve an unset or empty `COMETAPI_LIVE_MODEL` to `gpt-5.4` rather than -attempt a request with an empty model. Immutable-release recovery additionally +must use the canonical active model enforced by the workflow checker, without +accepting a repository-variable override. Immutable-release recovery additionally requires `RELEASE_RECOVERY_TAG` and `RELEASE_RECOVERY_SHA` to equal the exact dispatch inputs; keep both variables absent except for one explicitly authorized identity and delete them immediately after recovery identity verification or a diff --git a/scripts/_checks.py b/scripts/_checks.py index e5e1f30..8a79a66 100644 --- a/scripts/_checks.py +++ b/scripts/_checks.py @@ -9,12 +9,13 @@ import sys import unicodedata from collections.abc import Iterable +from dataclasses import dataclass from datetime import date from email.message import Message from email.parser import Parser -from itertools import pairwise from pathlib import Path -from typing import NamedTuple, cast +from typing import cast +from urllib.parse import quote, unquote if sys.version_info >= (3, 11): import tomllib @@ -23,6 +24,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] DIST_NAME = "cometapi" +CANONICAL_ACTIVE_MODEL = "gpt-5.6-sol" CANONICAL_AUTHOR = "CometAPI" CANONICAL_COPYRIGHT = "Copyright (c) 2026 CometAPI" CANONICAL_REPOSITORY = "https://github.com/cometapi-dev/cometapi-python" @@ -58,159 +60,96 @@ SDIST_PUBLIC_DOCUMENTS = tuple( name for name in PERSISTENT_DOCUMENTS if not name.startswith(".github/") and name != "CLAUDE.md" ) -MUTABLE_PUBLISHED_VERSION_FIX = ( - "replace the exact patch with version-neutral 0.1.x guidance, query PyPI for current " - "registry state, and keep exact released versions only in immutable historical evidence" +EXACT_RELEASE_VERSION_FIX = ( + "replace the exact patch with version-neutral 0.1.x guidance, or move complete " + "immutable history into a validated release-evidence block in ROADMAP.md or " + "RELEASING.md; query PyPI when current registry state is required" ) -MUTABLE_PUBLISHED_VERSION_CATEGORY = "mutable latest/current published patch version" -_BARE_PATCH_VERSION = r"v?\d+\.\d+\.\d+(?:[-_.]?(?:a|alpha)[-_.]?\d+)?(?:\+[0-9A-Za-z.-]+)?" -_EXACT_PATCH_VERSION = rf"(?)\]]+", flags=re.IGNORECASE) -_HTML = re.compile(r"|<[^>]*>", flags=re.DOTALL) -_MARKDOWN_LINK = re.compile(r"\[([^\]]+)\]\((?:[^()]|\([^()]*\))*\)") -_VERSIONED_RELEASE_URL = re.compile( - rf"https?://(?:" - rf"pypi\.org/project/cometapi/(?P{_BARE_PATCH_VERSION})" - rf"|github\.com/cometapi-dev/cometapi-python/releases/tag/(?P{_BARE_PATCH_VERSION})" - rf")(?=$|[/#?\s<>\"')\]])", - flags=re.IGNORECASE, +EXACT_RELEASE_VERSION_CATEGORY = ( + "exact CometAPI patch/recovery version outside immutable release evidence" ) -_CLAIM_TOKEN = re.compile( - rf"(?P{_EXACT_PATCH_VERSION})" - r"|(?P[A-Za-z0-9]+(?:[-'][A-Za-z0-9]+)*)" - r"|(?P[.!?;](?=\s|$))" - r"|(?P[,:|\u2013\u2014])", - flags=re.IGNORECASE, +RELEASE_EVIDENCE_DOCUMENTS = {"ROADMAP.md", "RELEASING.md"} +RELEASE_EVIDENCE_MARKER = re.compile( + r"(?m)^$" ) -_CURRENT_WORDS = {"current", "currently", "latest", "newest", "now"} -_RELEASE_IDENTITY_WORDS = {"build", "distribution", "patch", "release", "version"} -_PUBLICATION_STATE_WORDS = { - "available", - "hosts", - "lists", - "offers", - "published", - "publishes", - "released", - "serves", -} -_HISTORICAL_ACTION_WORDS = { - "accepted", - "completed", - "created", - "executed", - "failed", - "passed", - "published", - "reached", - "reserved", - "verified", -} -_PRESENT_WORDS = {"are", "is", "now", "currently", "remains"} -_PAST_WORDS = {"had", "was", "were"} -_ATTRIBUTION_SKIP_WORDS = { - "a", - "an", - "accepted", - "active", - "are", - "as", - "at", - "available", - "build", - "candidate", - "client", - "cometapi", - "completed", - "current", - "currently", - "distribution", - "exact", - "for", - "from", - "has", - "hosts", - "immutable", - "install", - "installed", - "is", - "its", - "latest", - "library", - "lists", - "maintenance", - "most", - "newest", - "now", - "of", - "offers", - "on", - "our", - "package", - "patch", - "project", - "public", - "publicly", - "published", - "publishes", - "recent", - "registry", - "release", - "released", - "repository", - "sdk", - "serves", - "stable", - "status", - "supported", - "that", - "the", - "these", - "this", - "those", - "verified", - "version", - "was", - "were", -} -_IMMUTABLE_CONTEXT_WORDS = { - "commit", - "completed", - "digest", - "evidence", - "executed", - "immutable", - "recovery", - "run", - "tag", - "workflow", -} -_CANONICAL_ATTRIBUTIONS = { - "client", - "cometapi", - "cometapi-python", - "library", - "package", - "project", - "repository", - "sdk", - "this", -} -_KNOWN_THIRD_PARTY_ATTRIBUTIONS = { - "httpx", - "openai", - "pyright", - "pytest", - "ruff", - "twine", - "uv", -} -_MUTABLE_LABEL_WORDS = { - "current", - "latest", - "newest", - "pypi", -} +RELEASE_EVIDENCE_IDENTITY = re.compile( + r"^$" +) +_ANY_RELEASE_EVIDENCE_IDENTITY = re.compile(r"(?m)^.*cometapi-release-identity.*$") +_ANY_RELEASE_EVIDENCE_MARKER = re.compile(r"(?m)^.*cometapi-release-evidence:.*$") +_EXACT_VERSION = ( + r"(?:v\s*)?\d+\s*\.\s*\d+\s*\.\s*\d+" + r"(?:\s*[-_.]?\s*(?:a|alpha|b|beta|rc)\s*[-_.]?\s*\d+)?" + r"(?:\s*(?:\+|%2b)\s*[0-9a-z][0-9a-z.-]*)?" +) +_EXACT_VERSION_PATTERN = re.compile( + rf"(?{_EXACT_VERSION})(?!\w|\s*\.\s*\d)", + re.IGNORECASE, +) +_THIRD_PARTY_OWNER = ( + r"(?:openai|httpx|ruff|pyright|pytest|python|node(?:\.js)?|twine|uv|actionlint|" + r"release[\s-]+please|pypi[\s-]+publisher|" + r"actions[ /-](?:checkout|download-artifact|setup-python|upload-artifact)|" + r"googleapis/release-please-action|pypa/gh-action-pypi-publish|pypi-attestations)" +) +_THIRD_PARTY_RELEASE_COMPONENT = ( + rf"(?:{_THIRD_PARTY_OWNER}|minimum(?:\s+supported)?(?:\s+openai)?|" + rf"latest\s+available\s+below|pypi\s+publisher|release\s+please)" +) +_DEPENDENCY_RANGE = re.compile( + rf"(?i)(?[a-z][a-z0-9_.-]*(?:\[[a-z0-9_.-]+\])?)\s*" + rf"(?P(?:==|~=|!=|<=|>=|<|>)\s*{_EXACT_VERSION}" + rf"(?:\s*,\s*(?:==|~=|!=|<=|>=|<|>)\s*{_EXACT_VERSION})*)" +) +_THIRD_PARTY_VERSION_URL = re.compile( + rf"(?i)(?:" + rf"https://pypi\.org/project/(?!cometapi/)[^/\s)]+/(?P{_EXACT_VERSION})/|" + rf"https://github\.com/(?!cometapi-dev/cometapi-python/releases/tag/)" + rf"[^/\s)]+/[^/\s)]+/releases/tag/(?P{_EXACT_VERSION})" + rf")" +) +_RAW_HTML_MARKUP = re.compile(r"|]*>", re.DOTALL) +_DECODED_HTML_TAG = re.compile(r"\n]*>") +_MARKDOWN_LINK = re.compile( + r"\[(?P