release
Cut a release the only sanctioned way — SemVer bump from the commit log, a CHANGELOG section, an annotated tag. The only path to a version tag.
What it does
Section titled “What it does”This is the only sanctioned way a version tag gets created. It never invents a version number — it walks every commit since the last tag, classifies each by its Conventional Commits type, and applies whichever bump that history actually earns (a breaking change beats a feature, a feature beats a fix). The changelog section is assembled the same mechanical way, pulled from the commit footers rather than freehand summary, and a commit that should have carried one but didn’t is a hard stop rather than a gap silently papered over. Composing the tag locally and publishing it are two separate moments: nothing pushes to the remote or shows up as a GitHub Release until you explicitly authorize that second step.
/ca:release ["<version>"] | --auto | --dry-runAn explicit version still gets checked against the derived classification; --auto derives it
outright (the default when no version is given); --dry-run runs every check and reports readiness
without composing anything.
Example
Section titled “Example”> /ca:release --dry-run
Working tree clean. Branch: release/prep (not the default branch — OK).Last tag: v2.4.1. Scanning 14 commits since...Classification: 3 feat, 6 fix, 5 chore -> minor bump.Derived version: v2.5.0. Matches plugin manifest? no — manifest still reads 2.4.1, would need updating.Changelog: all 9 feat/fix commits carry a CHANGELOG: footer.Dry run complete — no tag composed. Update the manifest version, then re-run without --dry-run.When to reach for it
Section titled “When to reach for it”Reach for /ca:release once the target branch is clean and its suite is green and you’re ready to
cut a version. Work still in progress lands through /ca:feature or /ca:fix first — a release
aggregates what already passed, it doesn’t chase down anything new.
| Gate | When | Effect |
|---|---|---|
| version derivation | before a tag is composed | the SemVer bump is computed mechanically from Conventional Commits since the last tag — an explicit version that disagrees with that classification blocks rather than being silently adjusted |
| changelog completeness | same phase as version derivation | every feat/fix/perf commit in the release window must carry its own changelog note; a missing one blocks rather than being auto-filled |
| publish authorization | after the tag is composed locally | the tag and the GitHub Release publish together, and only once you explicitly say to |
Related
Section titled “Related”Source
Section titled “Source”Source — plugins/ca/commands/release.md (v2.9.1)
---description: Cut a release the only sanctioned way — SemVer bump from the commit log, a CHANGELOG section, an annotated tag. The only path to a version tag.argument-hint: ["<version>"] | --auto | --dry-run---
# /ca:release — tagged release
The only permitted path to a version tag. A release is a deployment-readiness assertion: the codebase at this SHA satisfies the bar for shipping. `/ca:release` aggregates existing compliance — it does not duplicate it.
## Flow
Routes to the `release` skill. `/ca:release` targets the **`ca`** plugin only (ADR-0007): `LAST_TAG`is the newest `ca` SemVer tag (`v*`, never the sibling `ca-sandbox-v*`), and the release window is the`plugins/ca/`-scoped commit set — a `ca-sandbox` tag or commit never bumps `ca` or lands in itschangelog.
1. **Pre-flight** — working tree clean, on the configured release branch, suite green, no blocking `[CONFIRM-NN]` open, HEAD not produced via `/ca:override`. Identify `LAST_TAG` and the release window.2. **Version bump (SemVer)** — classify every commit in `LAST_TAG..HEAD` by Conventional Commits type and apply the highest-precedence bump (major beats minor beats patch). An explicit version that disagrees with the classification BLOCKS — the bump is never silently up- or downgraded.3. **Changelog** — roll up the `CHANGELOG:` footers from `feat`, `fix`, and `perf` commits into a new section. BLOCK if any `feat`/`fix` commit lacks the footer; never auto-fill it.4. **Tag** — compose the annotated tag. Never push it to a remote without explicit user authorization — publication is a separate decision.
`--dry-run` runs every gate and surfaces the readiness report, then STOPs before composing the tag.
## Arguments
- **`<version>`** (e.g. `"1.2.3"`) — explicit version; Phase 2 still classifies the window and BLOCKs on disagreement.- **`--auto`** — derive the version from the commit log (default when no version is given).- **`--dry-run`** — run all gates, compose nothing. Combines with `--auto` or an explicit version. An explicit version never combines with `--auto` — they are mutually exclusive.
## Routes to
`release` (`${CLAUDE_PLUGIN_ROOT}/skills/release/SKILL.md`).
## When NOT to use
- Tagging an in-progress branch → land work first via `/ca:feature` / `/ca:fix`.- Pushing an already-composed tag → that is a separate user-authorized step.- A changelog only → it is a phase output, not a standalone deliverable.
## Hard gate
MUST NOT compose a tag on a red suite. MUST NOT silently up- or downgrade the SemVer classification —an explicit version that disagrees with the commit log BLOCKS. MUST NOT auto-fill a missing`CHANGELOG:` footer. MUST NOT write to the default branch or force-push. MUST NOT push the tag withoutexplicit user authorization. Any BLOCK may be bypassed only via `/ca:override`.