diff --git a/CHANGELOG.md b/CHANGELOG.md index df0d169e..c0807d10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ project used alpha/beta prerelease tags while the first-user setup path, provider posture, and optional cloud sharing loop were hardening; v1.0 and later entries are regular releases. +## v1.2.1 + +Code Mower v1.2.1 hardens maintained Claude release qualification without +changing validation, retry policy, event shapes, or the metadata-only privacy +boundary. + +### Fixed + +- Claude qualification prompts now require non-negative integer step durations + and an exact top-level arithmetic sum. Measured setup or serialization time + is represented as an explicit overhead step, preventing independently + estimated totals from being rejected after otherwise successful runs. The + adapter still validates provider-authored evidence, fails closed on a + mismatch, and never adds an automatic paid retry (issue #854, PR #855). + ## v1.2.0 Code Mower v1.2.0 makes multi-agent orchestration safer and more portable diff --git a/README.md b/README.md index b37e2a6a..97e2fec8 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ Default cloud bundles exclude source code, raw diffs, raw model transcripts, raw stdout/stderr, auth output, and secrets. Documentation on `main` follows the source on `main`. If you install the -published `code-mower==1.2.0` package, use the documentation from the matching -[`v1.2.0` tag](https://github.com/codemower-ai/code-mower/tree/v1.2.0) so the +published `code-mower==1.2.1` package, use the documentation from the matching +[`v1.2.1` tag](https://github.com/codemower-ai/code-mower/tree/v1.2.1) so the commands and package stay aligned as development continues. ## Design Principles @@ -222,7 +222,7 @@ agent report its actual host posture, exact installed version, doctor result, Board URL, and any owner-only click-list before it mutates the repo. The current package-index announcement entry point is the tagged -[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.2.0/docs/try-in-10-minutes.md) +[Try Code Mower In 10 Minutes](https://github.com/codemower-ai/code-mower/blob/v1.2.1/docs/try-in-10-minutes.md) guide. The v1.0 supervised-pilot release includes the native Board, the controller dry-run and policy contract, adoption and upgrade hardening from recent install rehearsals, package-index release checks, provider-diversity @@ -337,7 +337,7 @@ Provider-contract baseline for the next release train: For release verification, [First-User Install Rehearsal](docs/first-user-install-rehearsal.md) records -the package-index procedure for `v1.2.0` / `code-mower==1.2.0`. The +the package-index procedure for `v1.2.1` / `code-mower==1.2.1`. The GitHub release records the workflow and rehearsal evidence for the exact tag. After publication, [Release Qualification](docs/release-qualification.md) coordinates provider-specific install and operational checks without treating @@ -531,8 +531,8 @@ measurement work. ## Installation Status -The current package-index release baseline is `v1.2.0`, with pinned package -install spec `code-mower==1.2.0`. Release evidence is recorded on the GitHub +The current package-index release baseline is `v1.2.1`, with pinned package +install spec `code-mower==1.2.1`. Release evidence is recorded on the GitHub release and in the first-user install rehearsal. The public repository is [codemower-ai/code-mower](https://github.com/codemower-ai/code-mower), and GitHub releases remain the auditable source for tags, build artifacts, and @@ -645,6 +645,7 @@ first so local work exercises the same package entrypoint users install. - [v1.1.1 Release Notes](docs/v111-release-notes.md) - [v1.1.2 Release Notes](docs/v112-release-notes.md) - [v1.2 Release Notes](docs/v12-release-notes.md) +- [v1.2.1 Release Notes](docs/v121-release-notes.md) - [Post-v0.8 Effectiveness Assessment](docs/post-v08-effectiveness-assessment.md) - [v1.0.1 Effectiveness Assessment](docs/v101-effectiveness-assessment.md) diff --git a/docs/build-loop-in-30-minutes.md b/docs/build-loop-in-30-minutes.md index 67f0f89c..ebd74617 100644 --- a/docs/build-loop-in-30-minutes.md +++ b/docs/build-loop-in-30-minutes.md @@ -60,7 +60,7 @@ audit evidence, skip to section 2. ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 gh auth status >/dev/null 2>&1 && echo "gh auth ok" || { echo "gh auth NOT ready"; false; } code-mower init --easy code-mower init --easy --apply --output-dir .code-mower.generated diff --git a/docs/cloud-benchmarking.md b/docs/cloud-benchmarking.md index 31a084de..80d0871e 100644 --- a/docs/cloud-benchmarking.md +++ b/docs/cloud-benchmarking.md @@ -29,9 +29,9 @@ observability/evaluation backend. ## Release Stages -### Current v1.2.0: Metadata-Only Upload, Board, Productivity, And Qualification +### Current v1.2.1: Metadata-Only Upload, Board, Productivity, And Qualification -The current v1.2.0 line keeps cloud sharing opt-in for adopters who explicitly +The current v1.2.1 line keeps cloud sharing opt-in for adopters who explicitly want to share sanitized benchmark metadata, summarized Board mirrors, or aggregate productivity metrics with Code Mower Cloud. The OSS tool is still local-first: @@ -43,7 +43,7 @@ code-mower cloud upload .code-mower/cloud-benchmark-bundle --yes --json code-mower cloud dogfood --json code-mower cloud dogfood --event productivity_summary=productivity-summary.json --json code-mower cloud board-snapshot --repo-slug OWNER/REPO --json -code-mower release qualify --release-tag v1.2.0 --package-spec code-mower==1.2.0 --output adoption-result.json --execute +code-mower release qualify --release-tag v1.2.1 --package-spec code-mower==1.2.1 --output adoption-result.json --execute code-mower cloud export --event adoption_run=adoption-result.json --repo-slug OWNER/REPO --json ``` diff --git a/docs/current-state-and-roadmap.md b/docs/current-state-and-roadmap.md index 77834211..7bded321 100644 --- a/docs/current-state-and-roadmap.md +++ b/docs/current-state-and-roadmap.md @@ -1,7 +1,7 @@ # Code Mower Current State And Roadmap This is the short source-of-truth snapshot for the public OSS package, the -hosted CodeMower.com surface, and the near-term path from the current v1.2.0 +hosted CodeMower.com surface, and the near-term path from the current v1.2.1 line toward broader supervised adoption. ## Positioning @@ -28,13 +28,13 @@ The public OSS repository is: https://github.com/codemower-ai/code-mower ``` -The current package-index release baseline is `v1.2.0`, with pinned package -install spec `code-mower==1.2.0`. Release evidence is recorded on the GitHub +The current package-index release baseline is `v1.2.1`, with pinned package +install spec `code-mower==1.2.1`. Release evidence is recorded on the GitHub release and in the first-user install rehearsal. It is intended to be installed from the package index for supervised pilots, with GitHub tag/source installs kept as a fallback and development path. -The v1.2.0 supervised-pilot release keeps the Python 3.12+ runtime contract, +The v1.2.1 supervised-pilot release keeps the Python 3.12+ runtime contract, pipx/uv install matrix, non-expiring dispatch-token diagnostics, native redacted lane status, the local Board, Board history and admin commands, spend/verdict timelines, owner queue, optional metadata-only agent cards, explicit cloud Board @@ -144,8 +144,8 @@ The beta-to-v1.0 line has proved: - a friendly-user rollout plan that turns install, doctor, first report, optional cloud dry-run/upload, and dashboard usefulness into explicit acceptance criteria for the first 5-10 users; and -- the current public PyPI package-install rehearsal from `v1.2.0` / - `code-mower==1.2.0` with a +- the current public PyPI package-install rehearsal from `v1.2.1` / + `code-mower==1.2.1` with a 10/10 first-user readiness score, proving install, generated setup, doctor, draft calibration, value-report, cloud export, and dry-run dogfood without a local Code Mower checkout. The earlier beta.52 package rehearsal remains @@ -324,7 +324,7 @@ these questions in the first few minutes: - Where is the code intentionally structured, and where is it still being refactored from extraction-era shape? -The v1.2.0 line now gives adopters that trust test plus first productivity +The v1.2.1 line now gives adopters that trust test plus first productivity visibility. More provider adapters are useful only when install, doctor, first report, privacy, measurement, and code structure remain boring and credible. diff --git a/docs/early-adopter-invite-runbook.md b/docs/early-adopter-invite-runbook.md index 89abc9fa..467ac7b7 100644 --- a/docs/early-adopter-invite-runbook.md +++ b/docs/early-adopter-invite-runbook.md @@ -38,7 +38,7 @@ It is an OSS local-first tool for setting up AI peer-programmer/reviewer lanes on your real codebase, with optional privacy-first cloud reporting. Start here: -https://github.com/codemower-ai/code-mower/blob/v1.2.0/docs/try-in-10-minutes.md +https://github.com/codemower-ai/code-mower/blob/v1.2.1/docs/try-in-10-minutes.md Cloud sharing is optional. The default bundle excludes source code, raw diffs, model transcripts, raw stdout/stderr, auth output, and secrets. @@ -53,7 +53,7 @@ Before inviting a user: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" - pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 + pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` diff --git a/docs/early-adopter-v05.md b/docs/early-adopter-v05.md index 0a5d7beb..b5e1120e 100644 --- a/docs/early-adopter-v05.md +++ b/docs/early-adopter-v05.md @@ -1,7 +1,7 @@ # Code Mower Early Adopter Guide This document records the historical v0.5 early-adopter product plan. The -current public install path is the v1.2.0 supervised-pilot release; use +current public install path is the v1.2.1 supervised-pilot release; use [Install And Bootstrap](install.md), [Try Code Mower In 10 Minutes](try-in-10-minutes.md), and [Quickstart](quickstart.md) for live adoption steps. @@ -145,7 +145,7 @@ Cut a v0.5 alpha or beta only after: ## Current Release -`v1.2.0` is the current supervised-pilot release. It keeps the +`v1.2.1` is the current supervised-pilot release. It keeps the local-first package path from alpha.1, the cloud doctor service-readiness check from alpha.5, the hardened provider-auth doctor diagnostics needed for early-adopter troubleshooting, the dogfood dry-run path that feeds the diff --git a/docs/first-run-transcript.md b/docs/first-run-transcript.md index 494901d4..44a9d411 100644 --- a/docs/first-run-transcript.md +++ b/docs/first-run-transcript.md @@ -9,7 +9,7 @@ same provider warnings. ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` @@ -17,7 +17,7 @@ Expected shape: ```text Python 3.12.x -code-mower 1.2.0 +code-mower 1.2.1 ``` ## Generate Local Setup diff --git a/docs/first-user-demo-transcript.md b/docs/first-user-demo-transcript.md index 281e1c8c..410010e6 100644 --- a/docs/first-user-demo-transcript.md +++ b/docs/first-user-demo-transcript.md @@ -14,9 +14,9 @@ release. ```bash python3.12 -m venv "$WORK_DIR/venv" "$WORK_DIR/venv/bin/python" -m pip install --upgrade pip -"$WORK_DIR/venv/bin/python" -m pip install code-mower==1.2.0 +"$WORK_DIR/venv/bin/python" -m pip install code-mower==1.2.1 "$WORK_DIR/venv/bin/code-mower" migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --python "$(command -v python3.12)" \ --json @@ -29,7 +29,7 @@ python3.12 -m venv "$WORK_DIR/venv" "mode": "package-install-rehearsal", "status": "pass", "steps": 27, - "package_spec": "code-mower==1.2.0", + "package_spec": "code-mower==1.2.1", "toy_repo": "$WORK_DIR/toy-repo", "doctor_status": "warn", "generated_artifacts": { diff --git a/docs/first-user-install-rehearsal.md b/docs/first-user-install-rehearsal.md index dfa3f3dc..b732e6e0 100644 --- a/docs/first-user-install-rehearsal.md +++ b/docs/first-user-install-rehearsal.md @@ -48,7 +48,7 @@ Use the current public tag or release candidate: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --python "$(command -v python3.12)" \ --json @@ -72,7 +72,7 @@ For a fixed output directory: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --python "$(command -v python3.12)" \ --work-dir /tmp/code-mower-first-user-rehearsal \ @@ -101,7 +101,7 @@ For a GitHub tag fallback, pass the tag URL explicitly: ```bash code-mower migration package-install-rehearsal \ - --package-spec "git+https://github.com/codemower-ai/code-mower.git@v1.2.0" \ + --package-spec "git+https://github.com/codemower-ai/code-mower.git@v1.2.1" \ --python "$(command -v python3.12)" \ --json ``` @@ -113,14 +113,14 @@ deciding the package index or the release is broken. For pipx: ```bash export CODE_MOWER_PYTHON="$(command -v python3.12)" -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` For uv: ```bash -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 code-mower --version ``` @@ -148,7 +148,7 @@ repository after the package install succeeds: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path /path/to/external-repo \ --python "$(command -v python3.12)" \ @@ -240,7 +240,7 @@ When a product repository already has Code Mower wrapper files, the same ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path /path/to/product-repo \ --python "$(command -v python3.12)" \ @@ -303,7 +303,7 @@ If this fails, fix the first-user path before cutting or promoting a release. Publish and rehearse the package-index artifacts in this order. After the release tag exists at the release commit, dispatch both package-index publication runs with -`--ref v1.2.0`; never substitute mutable `main`, because the TestPyPI +`--ref v1.2.1`; never substitute mutable `main`, because the TestPyPI and production PyPI builds must check out identical source. First, run `release.yml` for TestPyPI only: @@ -311,7 +311,7 @@ First, run `release.yml` for TestPyPI only: ```bash gh workflow run release.yml \ --repo codemower-ai/code-mower \ - --ref v1.2.0 \ + --ref v1.2.1 \ -f publish_testpypi=true \ -f publish_pypi=false ``` @@ -321,7 +321,7 @@ candidate from TestPyPI: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --upgrade-pip \ --pip-index-url https://test.pypi.org/simple/ \ @@ -336,7 +336,7 @@ Then run `release.yml` for production PyPI only: ```bash gh workflow run release.yml \ --repo codemower-ai/code-mower \ - --ref v1.2.0 \ + --ref v1.2.1 \ -f publish_testpypi=false \ -f publish_pypi=true ``` @@ -346,7 +346,7 @@ production package from PyPI: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --upgrade-pip \ --python "$(command -v python3.12)" \ @@ -364,7 +364,7 @@ against a private external TypeScript product repository: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path "$REPO_PATH" \ --work-dir "$WORK_DIR" \ diff --git a/docs/friendly-user-rollout-v05.md b/docs/friendly-user-rollout-v05.md index 4c77dd7f..c4f9e320 100644 --- a/docs/friendly-user-rollout-v05.md +++ b/docs/friendly-user-rollout-v05.md @@ -4,7 +4,7 @@ This is the operating plan for the first 5-10 friendly users before Code Mower widens to 20-50 early adopters. The filename is historical from the v0.5 planning pass. The live baseline in -this document is the current v1.2.0 supervised-pilot release. +this document is the current v1.2.1 supervised-pilot release. Code Mower is beta, bring-your-own-agent-loop software for teams willing to calibrate reviewers. It is not a drop-in autonomous merge gate. @@ -28,10 +28,10 @@ out in the invite: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 ``` -The current package-index release baseline is `v1.2.0`, with pinned package install spec `code-mower==1.2.0`. Release evidence is recorded on the GitHub release and in the first-user install rehearsal. +The current package-index release baseline is `v1.2.1`, with pinned package install spec `code-mower==1.2.1`. Release evidence is recorded on the GitHub release and in the first-user install rehearsal. ## Invite Criteria diff --git a/docs/install.md b/docs/install.md index 1e01f0ae..21d27e41 100644 --- a/docs/install.md +++ b/docs/install.md @@ -63,7 +63,7 @@ Install with pipx and an explicit Python 3.12+ interpreter: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` @@ -84,7 +84,7 @@ To replace an existing pipx install with an exact release, use `--force` so the old venv cannot keep serving the previous package: ```bash -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` @@ -97,7 +97,7 @@ export PIPX_HOME="$CODE_MOWER_AGENT_TOOLS/pipx" export PIPX_BIN_DIR="$CODE_MOWER_AGENT_TOOLS/bin" export PIPX_LOG_DIR="$CODE_MOWER_AGENT_TOOLS/logs" mkdir -p "$PIPX_HOME" "$PIPX_BIN_DIR" "$PIPX_LOG_DIR" -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 "$PIPX_BIN_DIR/code-mower" --version ``` @@ -108,7 +108,7 @@ interactive shell profile: ```bash uv python install 3.12 -uv tool install --python 3.12 code-mower==1.2.0 +uv tool install --python 3.12 code-mower==1.2.1 code-mower --version ``` @@ -118,7 +118,7 @@ installed command directly from the uv tool bin directory for that session. To replace an existing uv tool install with an exact release: ```bash -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 code-mower --version ``` @@ -133,7 +133,7 @@ command -v code-mower code-mower --version pipx uninstall code-mower uv python install 3.12 -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 hash -r command -v code-mower code-mower --version @@ -153,7 +153,7 @@ For pipx: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` @@ -161,7 +161,7 @@ For uv: ```bash uv python install 3.12 -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 code-mower --version ``` diff --git a/docs/jira-cloud-setup.md b/docs/jira-cloud-setup.md index 2387f033..5ae6dcd2 100644 --- a/docs/jira-cloud-setup.md +++ b/docs/jira-cloud-setup.md @@ -211,7 +211,7 @@ GitHub state only. Controller dry-run never dispatches, merges, or writes Jira. This shared session-brief contract, the Jira REST commands, and the double write guard described elsewhere in this guide are available in -`code-mower==1.2.0`. +`code-mower==1.2.1`. `code-mower session start` adds a `tracker` section to the operating brief whenever `tracker.kind` is `jira_cloud`. Codex, Claude, and every other diff --git a/docs/mirror-removal-runbook.md b/docs/mirror-removal-runbook.md index 218663f8..08b2a93e 100644 --- a/docs/mirror-removal-runbook.md +++ b/docs/mirror-removal-runbook.md @@ -32,7 +32,7 @@ Run: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path /path/to/product-repo \ --json diff --git a/docs/oss-v1-checklist.md b/docs/oss-v1-checklist.md index 4cb06451..a1b18459 100644 --- a/docs/oss-v1-checklist.md +++ b/docs/oss-v1-checklist.md @@ -46,7 +46,7 @@ history opens the repository. They should be able to confirm: ## Current v1.0 Baseline -The current public-release baseline is `v1.2.0` of the standalone +The current public-release baseline is `v1.2.1` of the standalone package. Before widening the release, record: - non-editable package-install rehearsal in a clean venv; @@ -55,7 +55,7 @@ package. Before widening the release, record: runs: TestPyPI first with `publish_testpypi=true`, `publish_pypi=false`, then production PyPI with `publish_testpypi=false`, `publish_pypi=true`; - package-install rehearsals against the exact TestPyPI and PyPI artifacts as - `code-mower==1.2.0` after those workflow runs finish, with workflow run + `code-mower==1.2.1` after those workflow runs finish, with workflow run links recorded as release evidence; - public-tag/source install validation as a fallback path; - production dogfood uploads from Code Mower OSS, CodeMower.com, and two @@ -187,7 +187,7 @@ It has not yet proved: ```bash CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower init --easy code-mower init --easy --apply --output-dir .code-mower.generated code-mower doctor --preflight @@ -197,7 +197,7 @@ code-mower --help-all code-mower next-steps --profile recommended code-mower migration wrapper-rehearsal --repo-path /path/to/product-repo --json code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path /path/to/repo \ --json diff --git a/docs/package-customization.md b/docs/package-customization.md index a8c67350..cb699fab 100644 --- a/docs/package-customization.md +++ b/docs/package-customization.md @@ -285,7 +285,7 @@ run: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --repo-path /path/to/product-repo \ --json diff --git a/docs/provider-matrix.md b/docs/provider-matrix.md index bf57df71..01e768b5 100644 --- a/docs/provider-matrix.md +++ b/docs/provider-matrix.md @@ -29,7 +29,7 @@ agent hosting a session is the default orchestrator. | Devin, Grok Bot, Antigravity, Muse, custom hosts | Recognized host identities for briefs and telemetry; execution remains an explicit handoff or provider-specific transport until separately qualified | No implicit Jira authority; use the guarded Code Mower tracker commands for writes | The lease, shared Jira brief, and explicit Cursor qualification are available -in `code-mower==1.2.0`; see [Participants And Sessions](sessions.md) for the +in `code-mower==1.2.1`; see [Participants And Sessions](sessions.md) for the operating contract. ## Provider Classes diff --git a/docs/public-release-checklist.md b/docs/public-release-checklist.md index 9fec6b2b..6bed307f 100644 --- a/docs/public-release-checklist.md +++ b/docs/public-release-checklist.md @@ -11,11 +11,11 @@ not know the original reference repos. - Apache-2.0 `LICENSE` and `NOTICE` are present. - The package has public releases and reports its version with `code-mower --version`. -- The current package-index release entrypoint is `code-mower==1.2.0`, with +- The current package-index release entrypoint is `code-mower==1.2.1`, with `code-mower doctor --adoption --repo OWNER/REPO` as the human-facing first-run setup diagnostic and `code-mower lanes status --repo OWNER/REPO` as the operator snapshot. The corresponding GitHub tag is - `v1.2.0`; `doctor --preflight` and `doctor --v05` remain + `v1.2.1`; `doctor --preflight` and `doctor --v05` remain compatibility presets for scripts. - The v1.0 supervised-pilot release includes Python 3.12+ install hardening, hosted-builder doctor postures, non-expiring token diagnostics, native diff --git a/docs/pypi-release.md b/docs/pypi-release.md index dae11ced..23b87796 100644 --- a/docs/pypi-release.md +++ b/docs/pypi-release.md @@ -6,7 +6,7 @@ TestPyPI or production PyPI through trusted publishing. ```bash CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 ``` ## Current Status @@ -88,7 +88,7 @@ should be the `/releases/latest` result, and exact-version installs should resolve from PyPI. ```bash -gh release view v1.2.0 \ +gh release view v1.2.1 \ --repo codemower-ai/code-mower \ --json tagName,isPrerelease gh api repos/codemower-ai/code-mower/releases/latest \ @@ -139,7 +139,7 @@ For pipx: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` @@ -147,7 +147,7 @@ For uv: ```bash uv python install 3.12 -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 code-mower --version ``` @@ -176,7 +176,7 @@ For production PyPI verification: ```bash python3.12 -m venv /tmp/code-mower-pypi-smoke /tmp/code-mower-pypi-smoke/bin/python -m pip install --upgrade pip -/tmp/code-mower-pypi-smoke/bin/python -m pip install code-mower==1.2.0 +/tmp/code-mower-pypi-smoke/bin/python -m pip install code-mower==1.2.1 /tmp/code-mower-pypi-smoke/bin/code-mower --version ``` @@ -184,7 +184,7 @@ Then run the release-gate first-user rehearsal against the same package: ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --upgrade-pip \ --python "$(command -v python3.12)" \ @@ -206,8 +206,8 @@ on production PyPI -- see ```bash code-mower release qualify \ - --release-tag v1.2.0 \ - --package-spec code-mower==1.2.0 \ + --release-tag v1.2.1 \ + --package-spec code-mower==1.2.1 \ --output result.json \ --package-source testpypi \ --execute @@ -250,7 +250,7 @@ an agent, and the release rehearsal all install the same artifact: ```bash CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 ``` An unpinned `pipx install code-mower` may be mentioned as a convenience only diff --git a/docs/quickstart.md b/docs/quickstart.md index 3ecb44cf..e47313b9 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -23,7 +23,7 @@ is the first-class isolated path: ```bash uv python install 3.12 -uv tool install --python 3.12 code-mower==1.2.0 +uv tool install --python 3.12 code-mower==1.2.1 code-mower --version ``` @@ -32,11 +32,11 @@ For a laptop or workstation that already uses pipx: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 code-mower --version ``` -`1.2.0` is the supervised-pilot release. If you want a future prerelease instead +`1.2.1` is the supervised-pilot release. If you want a future prerelease instead of this exact verified release, use: ```bash @@ -437,7 +437,7 @@ export bundle, upload dry run, and CodeMower.com dogfood dry run. ```bash code-mower migration package-install-rehearsal \ - --package-spec code-mower==1.2.0 \ + --package-spec code-mower==1.2.1 \ --allow-package-index \ --python "$(command -v python3.12)" \ --json diff --git a/docs/sessions.md b/docs/sessions.md index b0f06c1b..4832f364 100644 --- a/docs/sessions.md +++ b/docs/sessions.md @@ -6,7 +6,7 @@ your conversation is the default orchestrator for that session. The participant picker, host-led session brief, single-orchestrator lease, shared Jira tracker brief, controller host telemetry, and explicit Cursor -qualification documented below are available in `code-mower==1.2.0`. +qualification documented below are available in `code-mower==1.2.1`. Install from the matching tag when following release documentation, or use a contributor checkout when testing later source changes. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 296de3f4..d726390b 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -129,7 +129,7 @@ If pipx should own the command, reinstall the exact beta with cache bypass: ```bash export CODE_MOWER_PYTHON="$(command -v python3.12)" -PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 hash -r code-mower --version ``` @@ -140,7 +140,7 @@ path: ```bash pipx uninstall code-mower -uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.0 +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 hash -r command -v code-mower code-mower --version diff --git a/docs/try-in-10-minutes.md b/docs/try-in-10-minutes.md index fc72e4a0..f2c1eac3 100644 --- a/docs/try-in-10-minutes.md +++ b/docs/try-in-10-minutes.md @@ -21,8 +21,8 @@ Use this install matrix: | Environment | Command shape | | --- | --- | -| Laptop/workstation | `pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0` | -| Hosted agent, CI box, or minimal Linux VM | `uv tool install --python 3.12 code-mower==1.2.0` | +| Laptop/workstation | `pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1` | +| Hosted agent, CI box, or minimal Linux VM | `uv tool install --python 3.12 code-mower==1.2.1` | | Code Mower contributor checkout | `scripts/dev-python -m venv .venv` then `.venv/bin/python -m pip install -e ".[test]"` | For a cold laptop install: @@ -30,7 +30,7 @@ For a cold laptop install: ```bash python3.12 --version export CODE_MOWER_PYTHON="$(command -v python3.12)" -pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.0 +pipx install --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 command -v code-mower code-mower --version ``` @@ -48,7 +48,7 @@ For a repository that already has generated Code Mower support, follow [Upgrade An Existing Repository](upgrade-existing-repo.md) before copying a new `.code-mower.generated` tree. -`1.2.0` is the supervised-pilot release. To follow a future prerelease line +`1.2.1` is the supervised-pilot release. To follow a future prerelease line instead of pinning this exact build: ```bash diff --git a/docs/v121-release-notes.md b/docs/v121-release-notes.md new file mode 100644 index 00000000..f3520d73 --- /dev/null +++ b/docs/v121-release-notes.md @@ -0,0 +1,52 @@ +# Code Mower v1.2.1 Release Notes + +Code Mower v1.2.1 is a focused reliability release for maintained Claude +release qualification. It preserves the v1.2 supervised-pilot posture and all +existing provider, campaign, gate, and cloud contracts. + +## Claude qualification timing + +The maintained Claude adapter now tells Claude to report each step duration as +a non-negative integer number of seconds, represent measured setup or +serialization outside named checks as an explicit `overhead` step, and set the +top-level duration to the exact arithmetic sum of the emitted step durations. + +The change addresses a failure mode where an otherwise valid qualification +could report an independently measured total that differed from the rounded +step sum. It does not rewrite provider-authored evidence or relax the closed +adoption-result schema. A mismatch still fails closed, and Code Mower still +performs one paid provider invocation with no automatic retry. + +Focused regression coverage proves that an inconsistent result is rejected +after exactly one invocation and that exact integer arithmetic is accepted. +A live maintained-adapter canary against `v1.2.0` passed on its first attempt: +Claude emitted step durations of 3, 12, and 0 seconds and a matching 15-second +total. The exact PR head also passed Claude merge-authority review, Codex +informational review, Gitar, and the Python 3.12 through 3.14 package matrix. + +## Install or upgrade + +With `uv`: + +```bash +uv tool install --python 3.12 --reinstall --refresh-package code-mower code-mower==1.2.1 +code-mower --version +``` + +With `pipx`: + +```bash +CODE_MOWER_PYTHON="$(command -v python3.12)" +PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON" code-mower==1.2.1 +code-mower --version +``` + +Expected version output: `code-mower 1.2.1`. + +## Privacy + +The privacy boundary is unchanged. Campaign adapters parse provider output +transiently and persist only validated `code_mower.adoptionResult.v1` +metadata. Code Mower does not upload source, Jira summaries or descriptions, +issue bodies, comments, attachments, raw diffs, prompts, transcripts, raw +provider output, authentication output, local paths, or secrets. diff --git a/pyproject.toml b/pyproject.toml index ee0e32c9..76f4cded 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "code-mower" -version = "1.2.0" +version = "1.2.1" description = "Multi-reviewer AI code audit orchestration" requires-python = ">=3.12" readme = "README.md" diff --git a/src/code_mower/__init__.py b/src/code_mower/__init__.py index f64d8e29..f0427544 100644 --- a/src/code_mower/__init__.py +++ b/src/code_mower/__init__.py @@ -1,3 +1,3 @@ """Code Mower package.""" -__version__ = "1.2.0" +__version__ = "1.2.1" diff --git a/src/code_mower/templates/workflows/builder-provenance.yml.j2 b/src/code_mower/templates/workflows/builder-provenance.yml.j2 index 0d99d108..4776755b 100644 --- a/src/code_mower/templates/workflows/builder-provenance.yml.j2 +++ b/src/code_mower/templates/workflows/builder-provenance.yml.j2 @@ -8,7 +8,7 @@ permissions: contents: read env: - CODE_MOWER_PACKAGE_SPEC: code-mower==1.2.0 + CODE_MOWER_PACKAGE_SPEC: code-mower==1.2.1 jobs: auto-record: diff --git a/templates/workflows/builder-provenance.yml.j2 b/templates/workflows/builder-provenance.yml.j2 index 0d99d108..4776755b 100644 --- a/templates/workflows/builder-provenance.yml.j2 +++ b/templates/workflows/builder-provenance.yml.j2 @@ -8,7 +8,7 @@ permissions: contents: read env: - CODE_MOWER_PACKAGE_SPEC: code-mower==1.2.0 + CODE_MOWER_PACKAGE_SPEC: code-mower==1.2.1 jobs: auto-record: diff --git a/tests/test_release_hygiene.py b/tests/test_release_hygiene.py index 554feda4..84f699db 100644 --- a/tests/test_release_hygiene.py +++ b/tests/test_release_hygiene.py @@ -65,7 +65,7 @@ class ReleaseHygieneTests(unittest.TestCase): def test_version_is_current_supervised_pilot_release(self) -> None: - self.assertEqual(__version__, "1.2.0") + self.assertEqual(__version__, "1.2.1") def test_dogfood_repo_has_real_root_config(self) -> None: config_path = ROOT / "code-mower.yml" @@ -216,7 +216,7 @@ def test_install_and_upgrade_docs_cover_agent_paths(self) -> None: self.assertIn("Cold Install Vs Upgrade", install) self.assertIn("Switching Between pipx And uv", install) self.assertIn("uv tool install --python 3.12 --reinstall --refresh-package", install) - self.assertIn("code-mower==1.2.0", troubleshooting) + self.assertIn("code-mower==1.2.1", troubleshooting) self.assertNotIn("code-mower==0.8.0b1", troubleshooting) self.assertIn("pipx uninstall code-mower", install) for env_name in ("PIPX_HOME", "PIPX_BIN_DIR", "PIPX_LOG_DIR"): @@ -1100,7 +1100,7 @@ def test_direct_cli_execution_points_to_package_or_dev_wrapper(self) -> None: ) self.assertNotEqual(completed.returncode, 0) - self.assertIn("pipx install code-mower==1.2.0", completed.stderr) + self.assertIn("pipx install code-mower==1.2.1", completed.stderr) self.assertIn("scripts/dev-python -m venv .venv", completed.stderr) self.assertIn(".venv/bin/code-mower", completed.stderr) self.assertNotIn("PYTHONPATH=src", completed.stderr) @@ -3238,10 +3238,10 @@ def test_setup_drift_reports_standalone_pin_states(self) -> None: cases = ( ( - 'CODE_MOWER_STANDALONE_REF="v1.2.0"\n', + 'CODE_MOWER_STANDALONE_REF="v1.2.1"\n', "pass", "matches_running_package", - "v1.2.0", + "v1.2.1", ), ( 'CODE_MOWER_STANDALONE_REF="v0.9.1-beta.1"\n', @@ -3272,12 +3272,12 @@ def test_setup_drift_reports_standalone_pin_states(self) -> None: payload = migration._standalone_pin_drift_summary( repo, - package_version="1.2.0", + package_version="1.2.1", ) self.assertEqual(payload["status"], status) self.assertEqual(payload["reason"], reason) - self.assertEqual(payload["expected_ref"], "v1.2.0") + self.assertEqual(payload["expected_ref"], "v1.2.1") if current_ref is None: self.assertNotIn("current_ref", payload) else: @@ -3298,7 +3298,7 @@ def test_setup_drift_warns_on_non_utf8_standalone_pin(self) -> None: payload = migration._standalone_pin_drift_summary( repo, - package_version="1.2.0", + package_version="1.2.1", ) self.assertEqual(payload["status"], "warn") @@ -3361,7 +3361,7 @@ def test_setup_drift_text_prints_absent_standalone_pin_line(self) -> None: "standalone_pin": { "status": "skip", "reason": "pin_file_absent", - "expected_ref": "v1.2.0", + "expected_ref": "v1.2.1", }, "builder_hint": { "status": "skip", @@ -3373,7 +3373,7 @@ def test_setup_drift_text_prints_absent_standalone_pin_line(self) -> None: rendered = migration.render_setup_drift_text(payload) - self.assertIn("Standalone pin: SKIP pin_file_absent expected=v1.2.0", rendered) + self.assertIn("Standalone pin: SKIP pin_file_absent expected=v1.2.1", rendered) def test_setup_drift_reports_builder_hint_when_builders_omitted(self) -> None: from code_mower import migration @@ -5553,11 +5553,11 @@ def test_package_materializer_can_run_from_extracted_checkout(self) -> None: (output_dir / "src/code_mower/cloud_client/dogfood.py").is_file() ) self.assertIn( - 'version = "1.2.0"', + 'version = "1.2.1"', (output_dir / "pyproject.toml").read_text(encoding="utf-8"), ) self.assertIn( - '__version__ = "1.2.0"', + '__version__ = "1.2.1"', (output_dir / "src/code_mower/__init__.py").read_text( encoding="utf-8" ), @@ -7562,7 +7562,7 @@ def _run_mocked_pip_install( "pip", "install", "--no-cache-dir", - "code-mower==1.2.0", + "code-mower==1.2.1", ] def fake_run_step(*args: object, **kwargs: object) -> subprocess.CompletedProcess[str]: @@ -7629,7 +7629,7 @@ def test_package_install_rehearsal_classifies_package_index_specs(self) -> None: self.assertTrue(code_mower_migration._package_spec_uses_package_index("code-mower")) self.assertTrue( code_mower_migration._package_spec_uses_package_index( - "code-mower==1.2.0" + "code-mower==1.2.1" ) ) self.assertFalse(code_mower_migration._package_spec_uses_package_index(".")) @@ -7638,7 +7638,7 @@ def test_package_install_rehearsal_classifies_package_index_specs(self) -> None: ) self.assertFalse( code_mower_migration._package_spec_uses_package_index( - "git+https://github.com/codemower-ai/code-mower.git@v1.2.0" + "git+https://github.com/codemower-ai/code-mower.git@v1.2.1" ) ) @@ -7648,7 +7648,7 @@ def test_package_install_rehearsal_requires_package_index_opt_in(self) -> None: with self.assertRaisesRegex(ValueError, "--allow-package-index"): code_mower_migration.run_package_install_rehearsal( - package_spec="code-mower==1.2.0", + package_spec="code-mower==1.2.1", work_dir=work_dir, ) @@ -7676,7 +7676,7 @@ def test_package_install_rehearsal_cli_passes_network_opt_ins(self) -> None: [ "package-install-rehearsal", "--package-spec", - "code-mower==1.2.0", + "code-mower==1.2.1", "--allow-package-index", "--upgrade-pip", "--pip-no-cache", @@ -7732,10 +7732,10 @@ def test_release_readiness_reports_package_index_promotion_gate(self) -> None: payload = release_readiness.render_release_readiness(ROOT) self.assertEqual(payload["status"], "pass") - self.assertEqual(payload["version"], "1.2.0") - self.assertEqual(payload["release_tag"], "v1.2.0") - self.assertEqual(payload["alpha_tag"], "v1.2.0") - self.assertEqual(payload["package_index_spec"], "code-mower==1.2.0") + self.assertEqual(payload["version"], "1.2.1") + self.assertEqual(payload["release_tag"], "v1.2.1") + self.assertEqual(payload["alpha_tag"], "v1.2.1") + self.assertEqual(payload["package_index_spec"], "code-mower==1.2.1") check_ids = {check["id"]: check for check in payload["checks"]} self.assertEqual(check_ids["package-version-consistency"]["status"], "pass") self.assertEqual( @@ -7751,9 +7751,9 @@ def test_release_readiness_reports_package_index_promotion_gate(self) -> None: self.assertEqual(check_ids["public-support-redaction-guidance"]["status"], "pass") commands = {action["id"]: action["command"] for action in payload["next_actions"]} urls = {action["id"]: action.get("url", "") for action in payload["next_actions"]} - self.assertIn("--ref v1.2.0", commands["dry-run-release-workflow"]) + self.assertIn("--ref v1.2.1", commands["dry-run-release-workflow"]) self.assertNotIn("--ref main", commands["dry-run-release-workflow"]) - self.assertIn("--ref v1.2.0", commands["publish-testpypi-candidate"]) + self.assertIn("--ref v1.2.1", commands["publish-testpypi-candidate"]) self.assertNotIn("--ref main", commands["publish-testpypi-candidate"]) self.assertIn("publish_testpypi=true", commands["publish-testpypi-candidate"]) self.assertIn("publish_pypi=false", commands["publish-testpypi-candidate"]) @@ -7790,7 +7790,7 @@ def test_release_readiness_fails_on_materialized_package_version_drift( check_ids = {check["id"]: check for check in payload["checks"]} check = check_ids["materialized-package-version-consistency"] self.assertEqual(check["status"], "fail") - self.assertEqual(check["detail"]["source_version"], "1.2.0") + self.assertEqual(check["detail"]["source_version"], "1.2.1") self.assertEqual(check["detail"]["generated_init_version"], "0.0.0") def test_public_support_docs_are_packaged_and_privacy_forward(self) -> None: @@ -7894,20 +7894,20 @@ def test_release_readiness_tag_derivation_supports_release_stages(self) -> None: "v1.0.0-rc.1", ) self.assertEqual( - release_readiness._release_tag_for_version("1.2.0"), - "v1.2.0", + release_readiness._release_tag_for_version("1.2.1"), + "v1.2.1", ) self.assertEqual( - code_mower_versioning.release_tag_for_version("1.2.0"), - "v1.2.0", + code_mower_versioning.release_tag_for_version("1.2.1"), + "v1.2.1", ) def test_public_release_baseline_helpers_derive_announcement_links(self) -> None: self.assertEqual( code_mower_versioning.public_baseline_sentence(__version__), ( - "The current package-index release baseline is `v1.2.0`, " - "with pinned package install spec `code-mower==1.2.0`. " + "The current package-index release baseline is `v1.2.1`, " + "with pinned package install spec `code-mower==1.2.1`. " "Release evidence is recorded on the GitHub release and in the " "first-user install rehearsal." ), @@ -7916,7 +7916,7 @@ def test_public_release_baseline_helpers_derive_announcement_links(self) -> None code_mower_versioning.tagged_doc_url(__version__), ( "https://github.com/codemower-ai/code-mower/blob/" - "v1.2.0/docs/try-in-10-minutes.md" + "v1.2.1/docs/try-in-10-minutes.md" ), ) @@ -7969,12 +7969,12 @@ def test_public_docs_match_current_commands_and_privacy_boundary(self) -> None: readme = (ROOT / "README.md").read_text(encoding="utf-8") sessions = (ROOT / "docs" / "sessions.md").read_text(encoding="utf-8") - release_notes = (ROOT / "docs" / "v12-release-notes.md").read_text( + release_notes = (ROOT / "docs" / "v121-release-notes.md").read_text( encoding="utf-8" ) self.assertIn("Documentation on `main` follows the source on `main`", readme) - self.assertIn("available in `code-mower==1.2.0`", sessions) - self.assertIn("# Code Mower v1.2.0 Release Notes", release_notes) + self.assertIn("available in `code-mower==1.2.1`", sessions) + self.assertIn("# Code Mower v1.2.1 Release Notes", release_notes) self.assertIn("The privacy boundary is unchanged.", release_notes) self.assertLess( readme.index("[v1.1 Release Notes](docs/v11-release-notes.md)"), @@ -7984,6 +7984,10 @@ def test_public_docs_match_current_commands_and_privacy_boundary(self) -> None: readme.index("[v1.1.2 Release Notes](docs/v112-release-notes.md)"), readme.index("[v1.2 Release Notes](docs/v12-release-notes.md)"), ) + self.assertLess( + readme.index("[v1.2 Release Notes](docs/v12-release-notes.md)"), + readme.index("[v1.2.1 Release Notes](docs/v121-release-notes.md)"), + ) def test_current_release_docs_record_package_index_procedure(self) -> None: readme = (ROOT / "README.md").read_text(encoding="utf-8") @@ -8005,15 +8009,15 @@ def test_current_release_docs_record_package_index_procedure(self) -> None: ) current_status = ( - "The current package-index release baseline is `v1.2.0`, with " - "pinned package install spec `code-mower==1.2.0`. Release " + "The current package-index release baseline is `v1.2.1`, with " + "pinned package install spec `code-mower==1.2.1`. Release " "evidence is recorded on the GitHub release and in the first-user " "install rehearsal." ) for text in (readme, current_state, rollout): self.assertIn(current_status, " ".join(text.split())) self.assertIn( - "The current package-index release entrypoint is `code-mower==1.2.0`", + "The current package-index release entrypoint is `code-mower==1.2.1`", public_release, ) self.assertIn("The v1.0 supervised-pilot release includes", public_release) @@ -8023,7 +8027,7 @@ def test_current_release_docs_record_package_index_procedure(self) -> None: ) self.assertIn( - "The current public-release baseline is `v1.2.0`", + "The current public-release baseline is `v1.2.1`", oss_checklist, ) self.assertIn( @@ -8054,7 +8058,7 @@ def test_current_release_docs_record_package_index_procedure(self) -> None: " ".join(first_user.split()), ) self.assertIn("never substitute mutable `main`", first_user) - self.assertEqual(first_user.count(" --ref v1.2.0 \\"), 2) + self.assertEqual(first_user.count(" --ref v1.2.1 \\"), 2) self.assertNotIn(" --ref main \\", first_user) self.assertIn("-f publish_testpypi=true", first_user) self.assertIn("-f publish_pypi=false", first_user) @@ -8066,23 +8070,23 @@ def test_current_release_docs_record_package_index_procedure(self) -> None: first_user, ) self.assertNotIn( - "The latest public-package rehearsal for `v1.2.0` was run", + "The latest public-package rehearsal for `v1.2.1` was run", first_user, ) - self.assertNotIn("TestPyPI is not\npublished for `1.2.0`", first_user) + self.assertNotIn("TestPyPI is not\npublished for `1.2.1`", first_user) for text in (readme, current_state, rollout): self.assertNotIn( - "published on PyPI as `code-mower==1.2.0`", + "published on PyPI as `code-mower==1.2.1`", text, ) self.assertNotIn( "latest 10/10 public-package readiness proof for " - "`code-mower==1.2.0`", + "`code-mower==1.2.1`", text, ) self.assertNotIn( "public PyPI package-install rehearsal from " - "`code-mower==1.2.0`", + "`code-mower==1.2.1`", text, ) self.assertNotIn("beta.52: 10/10 first-user readiness", text) @@ -8382,7 +8386,7 @@ def test_install_docs_cover_supported_adoption_paths(self) -> None: self.assertIn("Python 3.12 or newer", install) self.assertIn('pipx install --python "$CODE_MOWER_PYTHON"', install) - self.assertIn("uv tool install --python 3.12 code-mower==1.2.0", install) + self.assertIn("uv tool install --python 3.12 code-mower==1.2.1", install) self.assertIn( 'PIP_NO_CACHE_DIR=1 pipx install --force --python "$CODE_MOWER_PYTHON"', install, @@ -8476,7 +8480,7 @@ def test_active_docs_use_current_release_language(self) -> None: / "v101-effectiveness-assessment.md", } stale_phrases = ( - "pipx install --python python3.12 code-mower==1.2.0", + "pipx install --python python3.12 code-mower==1.2.1", "Use only after TestPyPI passes.", "future newest betas until 1.0", "during v0.7 adoption", @@ -8776,7 +8780,7 @@ def test_next_steps_includes_cloud_upload_dry_run_after_export(self) -> None: "doctor --adoption --repo codemower-ai/code-mower", doctor_step["command"], ) - self.assertIn("code-mower==1.2.0", package_step["command"]) + self.assertIn("code-mower==1.2.1", package_step["command"]) self.assertIn("--allow-package-index", package_step["command"]) self.assertIn("current published PyPI package", package_step["why"]) self.assertIn("first_user_readiness", package_step["why"])