release-ironcrew
Prepare, verify, version, and publish an IronCrew release through develop and main with explicit approval gates. Use when the user asks to release, cut a release, ship a version, bump the product vers
SKILL.md.agents/skills/release-ironcrew/SKILL.md
GitHubRelease IronCrew
Use explicit user approval before merges, remote PR changes, commits, pushes, version changes, tags, releases, images, or crates.io publication. Never force-push, rewrite a published commit, or delete a remote tag.
Establish release state
- Require a clean worktree. Record the current branch,
Cargo.tomlandCargo.lockversions, latestv*tag, and divergence from remotedevelopandmain. - Confirm the repository still integrates on
developand releases frommain. A release tag must be an annotated stablevX.Y.Ztag whose commit is reachable frommain. - Stop if unrelated changes would enter the release or version/tag history is inconsistent. Do not repair history destructively.
- List open pull requests targeting
developand summarize mergeability, review state, and CI. Ask before changing remote state.
Release and Docker publication are admitted through versioned
repository_dispatch events so GitHub selects the workflow from the default
branch rather than from a tag commit or caller-selected workflow ref. That
selection is still only repository-level defense in depth. Require reviewed
default-branch controls and a protected release environment before treating
publication as platform-enforced.
IronCrew currently uses an explicit sole-owner authority model: skitsanos is
the trusted root and may approve develop to main, create a stable release
tag, request a release, approve the protected deployment, and rerun it. A
malicious or compromised repository owner is outside this model. Do not dispatch
either workflow until main requires a PR and green CI, the protected release
environment requires deliberate owner self-approval with administrator bypass
disabled, Docker credentials have moved from repository secrets into that
environment, only the owner may create protected v* tags, tag updates and
deletions remain prohibited, immutable releases are enabled, and the documented
non-secret controls have been revalidated.
The owner-only Issues controller is the request channel. It validates an exact
issue and uses its run-scoped GITHUB_TOKEN to create the fixed repository
dispatch, avoiding a standing Contents-write personal token. validate mode is
non-publishing, but it still waits for the protected environment because its
purpose is to prove that enforcement.
Default-branch dispatch does not prevent a tag-capable actor from adding a
different tag-push workflow to an off-main commit. Under the sole-owner model,
only the trusted owner may create v* tags and owner compromise is out of
scope. Record the workflow-execution-policy state, but do not enable a broad
event restriction that breaks CI's intentional push and pull_request
coverage or the Issues request controller without a separately validated
policy design.
Verify and propose
- Prove Cargo freshness with
cargo outdated --root-deps-only,cargo upgrade --dry-run --incompatible, andcargo update --dry-run --verbose, then runcargo audit --deny warnings. Every direct dependency must be current before release. A lower transitive version is acceptable only when the current direct dependency graph pins it exactly; record the upstream constraint and never force an incoherent lockfile. Ask before incompatible major upgrades or audit-policy changes. - Open the official MCP specification index and verify the newest published revision. IronCrew supports only that revision: its strict discovery pin, transports, tests, examples, and docs must move together, with no fallback to the superseded protocol.
- Use
$check-ironcrewto run the complete locally reproducible repository, Rust, Lua, evaluation, PostgreSQL, replica, and release-build gates. Required live tests may not be skipped. Platform-only jobs remain a later CI gate. - Read commits and resolved
IC-NNNentries since the latest tag. Propose a Semantic Versioning bump from behavior, not commit-message prefixes alone. - Draft release notes grouped by area and referencing relevant issue IDs. Wait for the user's version approval.
Cut the release
After approval:
On
develop, update the package version inCargo.toml, refresh the exact root package entry inCargo.lock, and read both back.Rerun the complete gate. Stage only explicit release paths and commit/push only when authorized.
Open or update the
developtomainrelease PR. Wait for green CI, then merge only with explicit sole-owner authorization.Fast-forward local
mainfromorigin/main. Create an annotatedvX.Y.Ztag only on the verified release commit.Prove the tag is reachable from
mainand itsCargo.tomlcontains the same version. Show the evidence and ask before pushing the tag.Push the tag only with explicit approval. Pushing it does not publish a release. After the remote controls above exist, first ask for authorization to exercise the protected environment without publication. Replace the tag in this exact request with the pushed stable tag:
request=$(gh issue create --repo skitsanos/ironcrew \ --title 'IronCrew release request' \ --body '{"target":"release","tag":"vX.Y.Z","mode":"validate"}') gh issue edit "$request" --add-label release-requestThe issue must be open, owner-authored, have the exact title and only the
release-requestlabel, and contain the canonical single-line JSON body shown above. Confirm that the protectedreleaseenvironment required deliberate owner approval and that the run completed without contents-write, OIDC signing, a GitHub release, or registry access. Close the request issue after the downstream run completes. Capture a separately designed denied adversarial canary; the controller'srepository_dispatchalways selects the default-branch workflow and cannot be pointed at an off-main ref.Only after those canaries and a separate explicit publication approval, dispatch the exact release request:
request=$(gh issue create --repo skitsanos/ironcrew \ --title 'IronCrew release request' \ --body '{"target":"release","tag":"vX.Y.Z","mode":"publish"}') gh issue edit "$request" --add-label release-requestA release created with the workflow's
GITHUB_TOKENdoes not cascade into another release-event workflow; Docker promotion remains the separately authorized dispatch below. Monitor.github/workflows/release.yml. It must create the release once and publish the signed OCI archive plus strict image receipt; it must not update an existing release or replace its assets.Docker publication through
.github/workflows/docker-publish.ymlis a separate authorization. It verifies and promotes the tag-owned signed archive rather than rebuilding source. Before any Docker publication, require the exact Docker Hub stable-semver immutability rule and IC-015's recorded non-production replay/conflict/concurrent-latestacceptance. After the protected environment exists, its non-publishing Docker path can be checked with a separate authorization and this exact request; it must not read Docker credentials or touch the registry:request=$(gh issue create --repo skitsanos/ironcrew \ --title 'IronCrew release request' \ --body '{"target":"docker","tag":"vX.Y.Z","mode":"validate"}') gh issue edit "$request" --add-label release-requestIC-015's non-production registry acceptance is resolved, but actual Docker publication remains deferred until this IC-014 control plane is complete and the user separately authorizes production promotion. Then use this exact request:
request=$(gh issue create --repo skitsanos/ironcrew \ --title 'IronCrew release request' \ --body '{"target":"docker","tag":"vX.Y.Z","mode":"publish"}') gh issue edit "$request" --add-label release-requestMonitor the version digest and final
latestdigest against GitHub's current stable release. Publish a crate only with separate authorization too. Do not use this path to backfill a legacy release without the signed OCI archive and receipt; promotion begins with the first release produced by the trusted default-branch release workflow.
If an unpushed local release step is wrong, make a corrective edit or ask for direction. Once anything is pushed, use a forward fix unless the user explicitly authorizes another safe recovery.