--- name: agnes-release-process description: Rules for opening a PR, the CHANGELOG bullet, the release-cut commit, and the post-merge tag + GitHub Release. Use before opening a PR, before merge, when handling a release-cut, and when picking a version bump. --- # Agnes release process Source of truth for the rules in `CLAUDE.md § Release process` and `docs/RELEASING.md`. This skill is invoked by the main agent during planning, by `agnes-reviewer-rules` during review, and by `agnes-releaser` during the release-cut. When the rules below conflict with the master documents above, the master documents win — update this skill. ## When this skill applies - Opening a PR - Reviewing a PR (release-cut implications) - Cutting a release (version bump, CHANGELOG rename) - Post-merge tagging + GitHub Release ## CHANGELOG discipline Every PR that changes **user-visible behavior** MUST add a bullet under `## [Unreleased]` in `CHANGELOG.md`, grouped under Added / Changed / Fixed / Removed / Internal. Breaking changes are prefixed `**BREAKING**`. Doc-only PRs (`docs/**`, README) typically do not need a bullet. Apply judgment based on the diff — if the docs change describes new behavior that should have shipped with a code change, the *code* PR carries the bullet. The CHANGELOG entry is part of the PR that introduces the change — never a follow-up PR. ## Release-cut belongs in the PR If a PR lands the only `[Unreleased]` content since the last release, the release-cut is the **last commit on that PR**: 1. Bump `pyproject.toml` (`version = "X.Y.Z"`). 2. Rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD`. 3. Add a new empty `## [Unreleased]` above it. The release-cut is never a standalone follow-up PR. ## Version bump decision - **Patch** (X.Y.Z+1): default for bug fixes, internal refactors, doc tweaks, small features that do not change documented behavior. - **Minor** (X.Y+1.0): new user-visible features, new APIs, schema migrations that are backwards-compatible. **Ask the user before picking minor.** - **Major** (X+1.0.0): breaking changes, removed APIs, incompatible schema changes. Requires explicit user confirmation. ## Post-merge sequence After the PR with the release-cut is merged to `main`: 1. `git tag vX.Y.Z ` 2. `git push origin vX.Y.Z` 3. `gh release create vX.Y.Z --title "vX.Y.Z" --notes ""` Never tag or release before merge. ## Post-merge auto-rollback On every `main` push, GitHub Actions `release.yml` builds the `:stable` image and a `smoke-test` job pulls it and runs a docker-compose stack. If the smoke test fails: - `rollback-on-smoke-fail` calls `rollback.yml`, which re-points `:stable` to the previous known-good build. - A tracking issue labeled `bug` is opened with the failing image, the commit SHA, the deprecated tag, and the rollback target. Success signal after merge: `smoke-test` green AND `rollback-on-smoke-fail` skipped. If rollback fires, the merge shipped a broken image to GHCR — investigate the tracking issue before any further push. Manual rollback, forced target, and weekly tag-pruning operator commands live in `docs/RELEASING.md`. ## Tests before push Run `.venv/bin/pytest tests/ --tb=short -n auto -q` before every push. Failures in code you touched: fix before pushing. Failures unrelated: confirm they reproduce on a clean branch, note in the PR body, do not block.