| name | aiwfx-release |
| description | Tags a release after an aiwf epic is closed and merged. Determines the semver bump, updates CHANGELOG.md, creates an annotated git tag, runs health checks. The aiwf epic is already `done` at this point โ this skill captures the release act in CHANGELOG and git, not in aiwf state. Use when the user says "cut a release", "let's ship", "ship it", "let's release", "release v1.2", "make a new version", "tag a release", or "publish". Dispatch the `deployer` subagent to run it. Never tags or pushes without explicit human approval. |
aiwfx-release
Tags and publishes a release. aiwf has no released status โ done is the terminal state for an epic. This skill records the release act in the artifacts that downstream consumers see (git tag, CHANGELOG), not in aiwf state.
When to use
An epic has been wrapped (aiwfx-wrap-epic ran, status is done, integration branch merged to mainline). The user says: "release v1.2", "tag a release", "cut a release", "let's release", "let's ship", "ship it", "make a new version", "publish".
If the epic isn't wrapped yet, run aiwfx-wrap-epic first.
Dispatch the deployer subagent to run this ritual rather than executing it inline in the calling session. The deployer agent card already names this skill under "Skills you use" โ dispatching is what lets an aiwf.yaml-configured agents.deployer model/effort tier actually apply, and keeps release mechanics out of whatever session just wrapped the epic. Run inline only when already executing inside the deployer agent's own context, or when the operator explicitly asks to skip delegation.
When dispatched, the two push gates (steps 6 and 7) are executed by the orchestrating session, not by the deployer subagent itself โ a dispatched subagent's own sandboxed tool context has been observed to stall on the network-write phase of git push (reads succeed; the push write hangs) even when the identical command succeeds run directly by the orchestrator. At each push gate, report the exact approved command back to the orchestrating session and wait for it to execute the push and confirm the result, rather than running git push yourself. Running inline (no dispatch), execute each push directly as shown โ there's no separate orchestrator to hand off to.
Gate discipline
Per CLAUDE.md ยง"Working with the user," every mutating action this skill walks you through โ committing the CHANGELOG, creating the tag, pushing commits, pushing the tag โ is its own gate. The standing invariant is one approval per action, no bundling.
A release ritual is the highest-blast-radius sequence aiwf walks you through: a single bundled "tag and push" approval is the difference between a recoverable local mistake and a published artifact every downstream consumer's aiwf upgrade will see. Never collapse tag-creation into tag-push. Never collapse "push the commit" into "push the tag" without naming both in the prompt.
This applies regardless of any cadence pattern inherited from a prior session's summary across /compact.
Workflow
1. Pre-release checks
- On
main (or the project's mainline name).
- Working tree clean.
- All tests pass.
- Build is green.
- CI is green on the last build-relevant commit reachable from HEAD.
Run
gh api "repos/<org>/<repo>/actions/runs?head_sha=$(git rev-parse HEAD)" --jq '.workflow_runs[] | "\(.conclusion // .status) \(.name)"'
to see every workflow run on the current HEAD. If the project's
primary CI workflow isn't in the list, its path filter excluded
HEAD โ typical when HEAD is a markdown-only commit (aiwf promote,
aiwf archive, aiwf edit-body, a docs(changelog): vX.Y.Z prep
commit itself). In that case walk back to the most recent commit
that touches a build input โ the project's source and
dependency-manifest files (e.g. for a Go project,
git log --oneline -- '**/*.go' 'go.mod' 'go.sum' | head -1;
substitute the equivalents for the project's actual language) โ
and verify it ran green via
gh run list --workflow=<workflow-file> --commit <sha> --limit 1.
If any reachable build-relevant commit's most recent run is failure
or anything other than success, stop and resolve before
crossing the Commit gate. The Constraints section asserts
"releases ride on green commits"; this step is where the assertion
binds. A local test-suite pass is necessary but not sufficient โ
lint, vulnerability scanning, and any project-specific jobs also
need to pass at the CI level.
- The epic that justifies this release has
status: done.
If anything is red, stop. Releases ride on green commits.
2. Determine the version
- Check the current version (latest git tag):
git describe --tags --abbrev=0.
- Apply semantic versioning per the project's conventions:
MAJOR โ breaking changes.
MINOR โ new features, backward compatible.
PATCH โ bug fixes only.
- Walk the commits since the last tag and classify them. If any commit suggests a breaking change (banner in the message, breaking-change footer, or just on inspection),
MAJOR is the right bump.
- Confirm the bump with the user. If they want a different version, use that.
3. Update CHANGELOG.md
Add a new release section. Group entries by Added / Changed / Fixed / Removed. Reference the epic and major milestones; keep entries user-observable, not diff-shaped.
## [vX.Y.Z] โ YYYY-MM-DD
### Added
- <user-observable feature> (E-NN, M-NNN)
### Changed
- <observable change>
### Fixed
- <bug fix>
### Removed
- <retired feature>
If the project keeps an [Unreleased] section at the top of CHANGELOG, move its contents into the new release section.
Stage the CHANGELOG. Show the diff.
4. ๐ Commit gate (CHANGELOG)
Show the user the CHANGELOG diff. Propose: docs(changelog): vX.Y.Z.
Stop and wait for "commit" approval.
git commit -m "docs(changelog): vX.Y.Z"
5. ๐ Tag gate
Confirm with the user: "Create annotated tag vX.Y.Z?" Show the commit the tag will point at.
git tag -a vX.Y.Z -m "Release vX.Y.Z: <one-line summary>"
The tag is local-only at this point โ git tag -d vX.Y.Z reverses it cleanly.
6. ๐ Push gate (commit)
Show the local state: the release-prep commit on the release branch. Confirm with the user: "Push the release-prep commit to origin main?"
git push origin main
When running as a dispatched subagent, hand this command back to the orchestrating session to execute rather than running it yourself โ see the handoff note under "When to use." Report the approved command, then wait for the orchestrator to confirm the push landed before continuing to CI verification.
This push is its own gate โ outward and irreversible. The tag push is a separate gate (next step). Per CLAUDE.md's declared-sequence bright line, outward actions are never batched; the two pushes are never collapsed into one approval.
7. ๐ Push gate (tag)
Confirm with the user separately: "Push the tag vX.Y.Z to origin?" Show the tag and the commit it points at.
git push origin vX.Y.Z
When running as a dispatched subagent, hand this command back to the orchestrating session too, same as step 6 โ don't run it from within the subagent's own sandboxed context.
Push is the irreversible boundary. The tag becomes visible to every downstream consumer the moment the push succeeds.
8. Post-release verification
- If CI/CD auto-publishes on tag push (npm, PyPI, container registry, GitHub Release), watch the pipeline. On success, confirm the artifact is consumable.
- Run any project-specific health check (smoke test, canary, rollback drill).
- If a deployment failed: assess whether to rollback the tag (rare โ usually fix-forward is safer). Don't reuse the version number.
9. Optional: link the release to the epic
If the project records release โ epic linkage somewhere (a release notes doc, an external tracker), update it now.
The aiwf epic stays done. There's no separate "released" status โ the git tag and CHANGELOG entry are the durable record of the release.
10. Capture any release-time decision
If a notable release-time decision was made (rolled back, hotfixed, deferred a feature out of the cut), capture it via aiwfx-record-decision.
Constraints
- ๐ Never commit, tag, or push without explicit human approval โ each is its own gate (steps 4, 5, 6, 7); the commit push and the tag push are two separate gates, never bundled.
- Releases run on green commits only. No "release this with the failing test, we'll fix in a patch." Green is CI-green, not just locally-green โ step 1's
gh run list check is where this binds; a local test-suite pass does not substitute for it.
- Versions are immutable. If
vX.Y.Z has a problem, the next release is vX.Y.(Z+1) โ don't move the tag.
- Don't skip CHANGELOG. Future-you and downstream consumers depend on it.
Anti-patterns
- Tagging without checking the diff since the last tag. The bump might be wrong.
- Releasing from a feature branch. Tags are on mainline.
- Auto-publishing on every tag without a confirmation step. The tag-push is the gate; if CI/CD watches it, that's fine, but the tag itself is a deliberate human act.
- Updating the aiwf epic to a "released" status. aiwf doesn't have one.
done is terminal; the release record lives in git history.
Out of scope
Wrapping the epic itself (that's aiwfx-wrap-epic). Authoring release notes for marketing โ CHANGELOG is the truthful record; marketing copy is downstream.