| namespace | aiwg |
| name | flow-release |
| platforms | ["all"] |
| description | Config-driven release orchestration — reads .aiwg/release.config plus optional .aiwg/releases/<plan-id> sidecars and walks the selected release plan's gates |
| triggers | ["help with CI builds or deployment","help me make the build or deployment path safer","start with pipeline safety or release readiness","pipeline safety ci","release flow","flow release","flow-release","run the release flow","run release flow"] |
| commandHint | {"argumentHint":"<version> [--plan <id>] [--channel <stable|rc|beta|alpha|nightly>] [--dry-run] [--skip-uat] [--no-mirror] [--config <path>] [--guidance \"text\"]","allowedTools":"Task, Read, Write, Edit, Bash, Glob, Grep, mcp__git-gitea__*","model":"opus","category":"sdlc-orchestration","orchestration":true} |
Release Orchestration Flow (config-driven)
Declarative Flow source of truth (#1539): the release gate sequence is
defined as a YAML Flow at
agentic/code/frameworks/sdlc-complete/flows/flow-release.playbook.yaml
(with release capabilities under flows/capabilities/). This skill is the
human-readable wrapper over that Flow — it stays for discoverability and
operator guidance, and is a candidate for retirement once discovery surfaces
YAML Flows directly (#1540). Per-gate config still lives in
.aiwg/release.config; the Flow encodes the gate sequence and dependencies.
You are the Core Orchestrator for the project's release sequence.
Your role
You walk the gates declared in .aiwg/release.config, in order, enforcing hard_stop semantics. You do not hard-code which gates exist or what they do — the config does. This is what makes the skill portable across projects with different release policies (a CalVer + npm project like AIWG vs. a SemVer + container-only project will share this skill body but differ entirely in their config).
When the user requests a release:
- Read
.aiwg/release.config (or the path passed via --config). If absent, scaffold a starter copy from the schema at agentic/code/frameworks/sdlc-complete/schemas/flows/release-config.yaml and ask the operator to review before continuing.
- Discover release-plan sidecars under
.aiwg/releases/*.json, .aiwg/releases/*.yaml, and .aiwg/releases/*.yml.
- If
--plan <id> is passed, select that plan.
- If exactly one sidecar exists and no
--plan is passed, select it.
- If multiple plans exist and no plan is selected, halt with an actionable error listing available plan ids.
- If duplicate plan ids exist, halt and require unique ids.
- If no sidecar exists, continue with
.aiwg/release.config as the legacy project-wide plan.
- Report the active release plan before actions. Print the selected plan id, sidecar path, target, and effective delivery mode before executing build, validation, publish, tag, or post-release steps.
- Apply sidecar precedence. When a release plan is active, its
delivery.mode is authoritative for this release and overrides broad project defaults such as direct, pr, or pr-required where they conflict.
- Resolve the target channel from
--channel (default: stable).
- Validate the version against
version_policy.format and the versioning rule (CalVer no-leading-zeros, semver, etc.).
- Walk the selected plan's gates in order. For a sidecar plan, use its
build.commands, validation_gates, publish target policy, and post_release_verification commands. Without a sidecar, walk .aiwg/release.config's gates array. For each gate:
- Skip if
required_for_channels is present and the target channel isn't in it.
- Execute the gate's body (steps, invoke_skill, artifacts, review_diff, actions).
- On failure: if
hard_stop: true, halt and report. If false, log a warning and continue.
- Report with the release tag URL, CI run URL, and tracker actions taken.
Natural language triggers
- "release v2026.5.2"
- "release flow"
- "flow release"
- "flow-release"
- "run the release flow"
- "cut a release"
- "promote to stable"
- "ship it"
- "tag a nightly"
Release plan sidecars
Release plan sidecars are optional per-target release configs stored beside the
main project config:
.aiwg/aiwg.config
.aiwg/release.config
.aiwg/releases/<plan-id>.json
.aiwg/releases/<plan-id>.yaml
.aiwg/releases/<plan-id>.yml
Use sidecars when one repository has independent release tracks, such as an npm
package, documentation site, plugin bundle, container image, or customer-specific
distribution. The schema lives at
agentic/code/frameworks/sdlc-complete/schemas/flows/release-plan.schema.yaml.
Each sidecar can declare:
- release identity:
id, name, and target
- build commands and validation gates
- publish targets and registry/remote details
- artifact, signing, SBOM, and provenance requirements
- docs, changelog, and release-note expectations
- post-release verification commands
delivery.mode, which overrides broad project delivery defaults while that plan is active
Agents must fail closed on missing, ambiguous, or conflicting sidecars. Do not
fall back silently to .aiwg/release.config when the user requested a specific
plan and that plan cannot be resolved.
Config-driven gate semantics
The config schema (release-config.yaml) defines five gate shapes. Each gate has exactly one shape:
Shape 1: steps
Sequential shell commands. Each step has an id, a run template (supports {version}, {tag}, {channel} placeholders), and an expect_exit (default 0).
- name: local-build-test
hard_stop: true
steps:
- id: typecheck
run: npx tsc --noEmit
- id: unit-tests
run: npm test
tolerate_pre_existing_flakes: [test/integration/cli-perf.test.ts]
Execution: run each step in order. Capture stdout/stderr. Compare exit code to expect_exit. If tolerate_pre_existing_flakes is set, treat failures in those test files as warnings (not gate failures) — useful for known-flaky perf tests.
Steps may carry:
required_for_channels (skip when channel not listed)
skip_when_flag (skip when the named CLI flag is present)
depends_on_channel (per-channel variant of the run command)
Shape 2: invoke_skill
Dispatch another AIWG skill via the Task tool. Pass args as input.
- name: doc-sync
hard_stop: true
invoke_skill: doc-sync
args:
direction: code-to-docs
guidance: |
<prose explaining the doc-sync intent>
dry_run_first: true
Execution: spawn a sub-agent invoking the named skill with args. Wait for completion. On failure, apply the gate's hard_stop policy.
Shape 3: tracker (CI poll)
Poll an issue/CI tracker until the workflows referenced complete.
- name: ci-green
hard_stop: true
tracker: gitea
owner: roctinam
repo: aiwg
timeout_seconds: 600
poll_interval_seconds: 30
required_workflows: [ci.yml, validate.yml]
Execution: list recent action runs for the release commit. For each required_workflows entry, wait for status: completed and assert conclusion: success. Fail the gate on timeout or any non-success conclusion.
For Gitea, use mcp__git-gitea__actions_run_read if available. For GitHub, use gh run list/view.
Shape 4: artifacts
Assert release-time files exist (and optionally contain a section).
- name: changelog-and-announcement
hard_stop: true
required_for_channels: [stable]
artifacts:
- path: CHANGELOG.md
section_pattern: '## [{version}]'
- path: 'docs/releases/v{version}-announcement.md'
must_exist: true
Execution: for each artifact, check must_exist (default true) and, if section_pattern is provided, grep the file for the pattern (with {version} interpolated).
Shape 5: review_diff
Surface a diff and prompt the operator.
- name: readme-freshness
hard_stop: false
review_diff:
path: README.md
since_tag: latest-stable
prompt: 'Has the README been reviewed for changes shipping in this release?'
Execution: run git diff <since_tag>..HEAD -- <path> and present to the operator. Wait for explicit acknowledgment before proceeding. With hard_stop: false, a "no" response logs a warning and continues; with hard_stop: true, it halts.
Shape 6: actions (post-release)
Declarative actions for post-release housekeeping.
- name: post-release
hard_stop: false
actions:
- close_imported_issues_with_thanks: true
- update_release_entry: gitea
- update_release_entry: github
skip_when_flag: '--no-mirror'
Each action is interpreted by the skill:
close_imported_issues_with_thanks: true — find issues with the imported label closed by commits in this release, post a thank-you comment on the source tracker, then close on both sides. Mirrors the May-2026 jmagly→roctinam sweep pattern.
update_release_entry: <tracker> — create or update the release entry (Gitea/GitHub) with the announcement body.
Verify publication before closing release-completion issues. After the
release gate pushes the tag and the release workflows run, invoke the
release-publication-verify skill with the tag before the post-release
close-outs. It turns the tag into concrete proof — Gitea/GitHub release assets,
SHA256SUMS + native package checksums, GHCR images, and installer dry-run —
and emits an issue-comment-ready evidence summary distinguishing MISSING from
FAILED proof. Do not close a release-completion issue on assumption; paste the
verifier's evidence into the close comment. Configure what "published" means
via the optional publication_verify block in .aiwg/release.config.
Policy enforcement
The config's policy block applies at every gate:
no_ai_attribution: scan commit message / tag message / announcement body for AI-tool branding. Fail if found.
ci_green_before_done: enforced via the CI gate; never finalize a release on a red CI run.
preserve_pre_release_announcements: false by default — pre-release tags do NOT get announcements (per CLAUDE.md release-channels guidance).
thank_external_reporters: enforced in the post-release action above.
Failure handling
- Pre-tag failures: revert any version-bump commits, restart after fixing the issue.
- Post-tag failures: never delete pushed tags. Increment patch and re-run the flow.
- Gate failures with
hard_stop: true: halt immediately, surface the failure log, do not advance.
- Gate failures with
hard_stop: false: log a warning, continue.
- Supply-chain gate (signed-tag verify) failure: this is the recovery exception to "never delete pushed tags." If
tools/ci/verify-signed-tag.sh rejects the tag (wrong signing key, expired key, missing-from-maintainers.asc), no artifacts are emitted by npm-publish.yml / gitea-release.yml / github-mirror.yml — the bad tag is an empty shell. Recovery: git tag -d <tag>, push delete to both remotes (git push origin :refs/tags/<tag> and git push github :refs/tags/<tag>), then re-cut via tools/release/cut-tag.sh <version> which forces the release key. Document the incident in docs/contributing/versioning.md for the next release.
Apply the anti-laziness recovery protocol (PAUSE→DIAGNOSE→ADAPT→RETRY→ESCALATE) when a gate fails — do not silently bypass with destructive shortcuts like skipping tests or stripping rules.
Tag-cutting must use the wrapper
git tag -a and git tag -s are NOT to be used directly by this skill. The maintainer's global git config typically has tag.gpgsign=true and user.signingkey=<personal-commit-signing-key>, which causes plain git tag invocations to sign with the wrong key — the personal key, not the release key. The supply-chain gate will reject the tag and no artifacts will ship.
Always use tools/release/cut-tag.sh <version> for the tag step. The wrapper:
- Runs 10 pre-tag sanity checks (CalVer shape, package.json + marketplace.json lockstep, CHANGELOG entry, announcement file present, release-signing key present locally AND published in
.gitea/keys/maintainers.asc)
- Signs with
-u <RELEASE_KEY_FINGERPRINT> (defaults to the AIWG release key; override via AIWG_RELEASE_KEY_FINGERPRINT env var for forks)
- Verifies the local signature via
git tag -v before declaring success
- Does NOT push automatically — push is left to the operator so a final sanity step can run
This is the canonical path. Any release config that templates a raw git tag -s is incorrect and must be migrated to call the wrapper.
Defaults when no config exists
If .aiwg/release.config is missing, scaffold one from the schema and ask the operator to review before continuing. The AIWG repo's own config is the reference implementation; new projects can copy it as a starting point.
Owner
Canonical owner: Deployment Manager (agentic/code/frameworks/sdlc-complete/agents/deployment-manager.md).
May delegate to:
- Reliability Engineer — SLO validation in pre-release gates
- Security Architect — for security-sensitive releases
- Technical Writer — for the announcement body
AIWG-specific reference
This repository's .aiwg/release.config declares the gates AIWG uses today:
- local-build-test (typecheck, unit tests, build, UAT for stable)
- ci-green (Gitea workflows on the release commit)
- doc-sync (code-to-docs sync with agentic/ + docs/ scope)
- changelog-and-announcement (CHANGELOG.md + docs/releases/ for stable)
- readme-freshness (diff prompt for stable)
- release (tag, push, mirror, npm dist-tag)
- post-release (tracker close-outs + reporter thanks)
That config IS the AIWG release checklist — what was previously prose in CLAUDE.md is now an executable spec.
Related
- Schema:
agentic/code/frameworks/sdlc-complete/schemas/flows/release-config.yaml
- Release plan schema:
agentic/code/frameworks/sdlc-complete/schemas/flows/release-plan.schema.yaml
- Config:
.aiwg/release.config (per project)
- Release plan sidecars:
.aiwg/releases/<plan-id>.yaml, .yml, or .json
- Rules:
versioning, no-attribution, ci-green-before-done, delivery-policy, anti-laziness
- Skills:
doc-sync (called by gate 3), release-publication-verify (post-tag proof before closing release issues), aiwg-pr (when delivery.mode is pr-required for release prep), aiwg-issue (filing release-blocker issues)
- Doc: CLAUDE.md "Release Documentation Requirements" + "Release Checklist"
Acceptance criteria