Session Release
Orchestrate a full release cycle: version bump, artifact packaging, and satellite content verification.
Open with one sentence saying what you are about to do and what it will produce.
Non-Negotiables
- Never auto-run builds. Builds often require signing keys, CI pipelines, or Windows/macOS-specific environments. Print the command and wait for the user.
- Never modify lock files manually. Lock files (
package-lock.json,Cargo.lock,pnpm-lock.yaml) are regenerated by the toolchain. Hand-editing corrupts them. - User approves at both gates. Step 3 (build) and Step 6 (satellite updates) require explicit user confirmation, or a standing policy that already covers exactly that action. No proceeding on silence.
- Final version grep must be clean. Before commit, grep the repo for the old version — nothing should remain except in
CHANGELOG.md, lock files, and historical references. - Never skip the satellite scan. The whole point of this skill is to catch the docs site, marketing page, and download modal that still say the old version.
- Never accept a verification verdict without comparing its recorded commit range against the candidate revision. A PASS is evidence about the revision it was recorded against. When they differ, the user decides reuse or rerun explicitly.
- Each release action is authorized on its own. Bumping, packaging, and committing are this skill's work. Tagging, pushing, publishing, deploying, and announcing are separate actions with their own authority, and a release run never performs one because the previous step succeeded.
Core Principle
A release is more than a version bump. Code ships alongside documentation, websites, changelogs, and download pages. This skill ensures nothing is forgotten by:
- Running the project's own release skills (if they exist)
- Scanning for satellite content that may need updating
- Confirming with the user before proceeding at each gate
Prerequisites
- All tests pass (run
/session-post-implementationor the test suite first) - Working tree is clean or changes are committed
- User knows the target version (or will provide it)
- If this release ships a feature with a design doc, a PASS verification artifact exists (run
/session-verifyfirst) and its recorded commit range covers the release candidate, or the user has recorded a reuse decision. Not required for bugfix/refactor releases.
Workflow
Step 1: Pre-flight checks
Verify readiness:
- Git status: Check for uncommitted changes. Warn if dirty.
- Test status: Ask the user to confirm tests pass (or offer to run them).
- Target version: If not provided as argument, ask the user. Validate semver format.
- Verification status: If this release ships a feature that had a design doc (check
.session-flow.json.paths.plans, else a detectedplans/), look for a corresponding_verification/{date}-{label}-verification.mdartifact withVerdict: PASS(orPASS-WITH-CAVEATSif the user accepts the caveats). If the artifact is missing orFAIL, offer to run/session-verifyfirst. Skip for bugfix/refactor releases with no design doc. - Evidence applicability: run the check below on the artifact found in check 4. Skip only when there is no artifact to reuse.
Evidence applicability check
A verdict is evidence about the revision it was recorded against, not about the release candidate.
Read the work item the release ships, when it has one, and re-resolve its authority before going further. Resolve the helper by the one rule for this host (
references/runtime-integration.md) and confirm it answers withdoctor;$ENTRYPOINTis the absolute path it resolves to:python3 -B "$ENTRYPOINT" --project-root "$PROJECT_ROOT" show --seq SEQ-042The item's
evidenceentries name the fingerprint they were gathered against. An entry whose fingerprint differs from the record's currentscope_fingerprintdoes not apply, whatever the artifact says, and an item stillactivebecause its delivery target is unmet is not a shipped outcome. Report either as a gap and let the user decide, exactly as steps 1-5 do for the commit range. Referenced specs are identified by work-root commit; a filename alone dates nothing.Read the artifact's
**Scope:**line --/session-verifywrites it asCommits {sha_first}..{sha_last} on branch {branch}. That is the recorded commit range; take{sha_last}as the verified revision. If the line is absent or unparseable, or the recorded revision is not in this repository, the evidence has no applicability -- offer/session-verifyagainst the candidate and do not proceed on the old verdict.Resolve the candidate revision with
git rev-parse HEADon the branch being released.Compare. The evidence covers the candidate only when the verified revision equals the candidate revision and the recorded branch is the branch being released. Otherwise report the gap using
git rev-list --count {sha_last}..HEADandgit diff --stat {sha_last}..HEAD.When they differ, stop and present: artifact path, verdict, verified revision, candidate revision, commit count between them, and the changed paths. Then ask for one explicit decision -- no default and no proceeding on silence:
- Rerun -- invoke
/session-verifyagainst the candidate. Required when the diff touches source, tests, dependencies, build/packaging, or the design doc the artifact verified. - Reuse -- the user states why the diff cannot change the verified behaviour. Proportionate for documentation, comments, changelog, or satellite-content-only diffs; never inferred from a small diff or a passing test run.
- Rerun -- invoke
Record the outcome. Add a
Verification evidenceblock to the Step 8 commit body and repeat it in the Step 9 summary, naming the artifact path, verified revision, candidate revision, the decision (reuseorrerun), and the user's stated reason verbatim. A reuse decision that was not recorded did not happen.
Step 2: Version bump
Look for a project-specific version bump mechanism:
Detection order:
- Project skill:
/version-bump(check.claude/skills/version-bump/SKILL.md) - Version sync script:
packaging/sync-versions.py,scripts/bump-version.* - Standard tooling:
npm version,cargo set-version,bumpversion,tbump - Manual: Search for version strings across config files
If a project skill exists: Invoke /version-bump <version> and follow its workflow.
If no skill exists: Identify all files containing the current version and update them. Common locations:
package.json/Cargo.toml/pyproject.toml/setup.cfgversion.py/__init__.py/_version.pytauri.conf.json/Info.plist/build.gradle
After bumping, verify consistency by grepping for the old version -- nothing should remain except changelogs and historical references.
Step 3: User gate -- build
The build step often requires the user's environment (signing keys, native toolchains, CI pipelines). Present the build instructions and wait for the user to confirm the build is complete before proceeding.
If a project skill exists (/release-package): it will contain build instructions -- reference them.
If no skill exists: Check for common build commands:
npm run build/pnpm buildcargo build --releasepython -m build/poetry build- CI/CD trigger instructions
Print the build command(s) and ask: "Run the build and let me know when it's done."
Do NOT run builds automatically -- they often need environment setup, signing keys, or manual oversight.
Phase exit criterion: user has explicitly confirmed build completion. Do not proceed to Step 4 on silence or assumed-done.
Step 4: Package release artifacts
Look for a project-specific packaging mechanism:
Detection order:
- Project skill:
/release-package(check.claude/skills/release-package/SKILL.md) - Release scripts:
scripts/release.*,packaging/release.* - Standard tooling:
gh release create,cargo publish,npm publish
If a project skill exists: Invoke /release-package and follow its workflow.
If no skill exists: Identify artifacts and provide manual instructions.
Step 5: Satellite content scan
This is the key differentiator. Scan the repository for content that often needs updating alongside a release but is easy to forget.
Scan for these categories:
5a. Documentation sites
Search for documentation site directories:
Glob patterns: **/docusaurus.config.*, **/mkdocs.yml, **/docs/conf.py, **/.vitepress/config.*, **/astro.config.*, **/book.toml
Common dirs: docs-site/, _docs-site/, docs/, documentation/, website/docs/
If found: Check for version references, outdated screenshots, feature docs that should mention new capabilities.
5b. Marketing / landing pages
Search for website directories:
Glob patterns: **/index.html (in website-like dirs), _website/, website/, landing/, www/
Package.json with vite/next/gatsby in non-app directories
If found: Check for version badges, download links, feature lists, changelog sections.
5c. Changelogs and release notes
Search for:
CHANGELOG.md, CHANGES.md, HISTORY.md, RELEASES.md, NEWS.md
If found: Check if the new version has an entry. If not, draft one from recent git history.
5d. README and badges
Check root README.md for:
- Version badges (shields.io, badgen, etc.)
- Installation instructions referencing specific versions
- Feature lists that may be outdated
5e. Download / distribution files
Search for:
Glob patterns: **/downloads/*, **/dist/*, **/releases/*, latest.json, **/DownloadModal.*, **/download*.tsx
If found: Check if they reference the new version.
5f. API documentation
Search for:
**/openapi.*, **/swagger.*, **/api-docs/
Step 6: User gate -- satellite updates
Present findings as a checklist:
## Release Surface Scan for v{VERSION}
### Needs attention:
- [ ] {item}: {what needs updating} ({file path})
- [ ] {item}: {what needs updating} ({file path})
### Looks current:
- [x] {item}: already up-to-date ({file path})
### Not found (skip):
- {category}: no {type} detected in this repo
Ask the user: "Which of these should we update now? (Enter numbers, 'all', or 'skip')"
Apply the updates the user approves. For each update:
- Make the minimal change needed (version string, link, date)
- Show the diff before applying if the change is non-trivial
- For changelog entries, draft from
git logsince the last tag
Phase exit criterion: every "Needs attention" item has either been updated (with user approval) or explicitly skipped by the user. No silent drops.
Step 7: Final verification
Run a final check:
- Version grep: Search for the OLD version across the repo. Flag any remaining references (excluding changelogs, git history, lock files).
- Build artifacts: Verify expected release artifacts exist (if applicable).
- Satellite content: Spot-check that updated files are consistent.
Step 8: Release commit
If changes were made in steps 5-6, commit them:
release: prepare v{VERSION} for distribution
Step 9: Release instructions
Print a summary of what's ready and what the user needs to do next:
## Release v{VERSION} Ready
### Completed:
- Version bumped across {N} files
- {Artifacts packaged / listed}
- {Satellite content updated}
### Verification evidence:
- Artifact: {path} ({verdict})
- Verified revision: {sha_last} -- candidate revision: {candidate}
- Decision: {reuse | rerun} -- {user's stated reason}
### Next steps -- each its own authorized action:
1. {Push / tag / create GitHub release / publish -- project-specific}
2. {Deploy docs site -- if applicable}
3. {Deploy website -- if applicable}
4. {Announce -- if applicable}
These are printed, not performed. Publishing, tagging, deploying, and announcing carry their own authority and their own rollback story; a completed release commit authorizes none of them.
Execution Notes
- Steps 3 and 6 are user gates -- wait for confirmation, or for the standing policy below, before proceeding
- The reuse-or-rerun decision in Step 1 is a third user gate -- it is the user's call, recorded, not the agent's judgement
- A standing policy already covering this release -- the target version, the satellite targets, the build command -- satisfies the gate it covers: name the policy, say what it authorizes, and go on. Silence never satisfies a gate, and a policy covering the build does not cover the satellite updates
- Escalate the decisions that are actually unknown -- an action outside what the policy covers, a satellite surface nobody decided about, a verdict that no longer applies -- and bring the evidence with the question. Re-asking something already decided is not a safeguard
- Re-resolve the item's authority before each consequential effect, and stop at the boundary of what it covers: a revoked authority blocks the next action, while effects already completed stay recorded and rolling one back needs its own authority
- The satellite scan (Step 5) is intentionally broad -- it's better to flag something unnecessary than to miss something important
- Lock files (
package-lock.json,Cargo.lock,pnpm-lock.yaml) should be regenerated by the build, not manually edited - Exclude from old-version grep:
CHANGELOG.md,*.lock,node_modules/,.git/,target/,build/,dist/
Anti-Patterns
Grepping too aggressively:
- BAD: Flag every occurrence of "0.2.0" including in unrelated constants
- GOOD: Focus on config files, docs, and distribution -- skip test fixtures and historical references
Treating a stored verdict as current:
- BAD: Find
Verdict: PASS, note the tests pass now, and release - GOOD: Compare the artifact's recorded commit range with the candidate revision, and release on old evidence only through a recorded reuse decision
Chain context: see references/workflow-overview.md.