Skip to content
Back to skills

Release Capcom

ASecurity

Cuts a capcom release: checks the release gate with `go run ./cmd/release status` (pushing the gate commit and waiting for CI when that is all it lacks), drafts the notes with release-notes-capcom, proposes the version and has the owner confirm it, makes the two local release commits with `prepare`, then — after a dry run and one explicit confirmation — runs `publish`, which pushes, waits for the CI-made tag, creates the GitHub release and updates Homebrew, Scoop and winget. Optional argument...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentsgoshellbashgitdatabase

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add airiclenz/capcom --skill release-capcom --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Release Capcom?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Release Capcom
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/airiclenz-release-capcom/badge)](https://www.skillsdirectory.com/skills/airiclenz-release-capcom)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: release-capcom
description: >
  Cuts a capcom release: checks the release gate with `go run ./cmd/release
  status` (pushing the gate commit and waiting for CI when that is all it
  lacks), drafts the notes with release-notes-capcom, proposes the version and
  has the owner confirm it, makes the two local release commits with `prepare`,
  then — after a dry run and one explicit confirmation — runs `publish`, which
  pushes, waits for the CI-made tag, creates the GitHub release and updates
  Homebrew, Scoop and winget. Optional argument vX.Y.Z proposes the version.
  Use for "cut a release", "publish a release", "ship vX.Y.Z". Only drafting
  the notes is release-notes-capcom.
---

# Release capcom — cut and publish a release

## Mission

Turn everything shipped since the last published release — the whole history
before the first one — into a published release: notes the owner approved, a
version the owner confirmed, and every channel converged. The deterministic
work belongs to `go run ./cmd/release`
(ADR 0008: `.capcom/knowledge/decisions/adr-0008.md`, or
`capcom know show "ADR 0008"`); this skill does the judgment and the asking.

The optional argument `vX.Y.Z` (a bare `X.Y.Z` reads the same) is a version
**proposal** — the owner still confirms it in step 4. `VERSION` holds the bare
`X.Y.Z`; the tag is `v` + VERSION.

In this repository this skill and `release-notes-capcom` replace the personal
`cut-release` and `release-notes` skills: those stand aside here, and neither
is run for capcom.

## Boundaries

- **One irreversible step: `publish`.** Everything before it is local and
  undone with `git reset --keep HEAD~2`; everything after it is fixed
  forward, never undone.
- **No bypass.** A blocked gate stops the run, except the one gate fix this
  skill makes itself: step 1a fast-forwards `main` to the gate commit and
  waits for its CI run. Beyond that you never tag, push, create a GitHub
  release, or commit to the tap or the bucket by hand — `publish` does all
  of it, and the tag is made by CI, never by you or `publish`.
- **Ask with the host's user-question tool** (`ask_user`, `AskUserQuestion`,
  or similar) at every *Ask* below, and wait for the answer. No answer, or a
  host without the tool, means stop — never assume consent.
- Needs an authenticated `gh` (`gh auth status`) and a Go toolchain; winget
  also needs `komac`. Shell snippets assume fail-fast hosts (`set -e`,
  `pipefail`): a command that may match nothing carries `|| true` — keep it.

## 1 — Status and resume check (one shell call)

```bash
T="$(git rev-parse --show-toplevel)"; cd "$T"
TMP="${TMPDIR:-${TEMP:-/tmp}}"; S="$TMP/release-capcom-status.json"
go run ./cmd/release status --json > "$S" || true
echo "TMP=$TMP"; echo "VERSION=$(cat VERSION)"; git log -2 --format=%s
```

Read `$S` yourself (it is small). Its keys: `version`, `highestTag`,
`gate.{ok,failures}`, `baseline.{tag,published,range,commits}`,
`steps[].{name,state,detail}`. A missing or unparsable file → stop and relay
the command's error (likely `gh` unauthenticated or no network).

**Resume.** When the two subjects read `chore(version): bump version to vX`
then `chore(release): cut vX`, vX is already prepared — whether or not it was
pushed. Say so, take vX as the confirmed version, and go to step 6: the notes
file `<TMP>/release-notes-capcom-vX.md` is reused when it exists (show it and
*Ask* approval as in step 3), else step 2 runs with the argument vX first.

**Gate.** `gate.ok` false — on a resume too — and every `gate.failures`
entry is one of these two → run step 1a, then read `$S` again:

- `gate commit <sha> is not on origin/main: push it first`
- `ci.yml has no successful run for <sha>[ or <sha>…]`

Any other entry (a dirty tree, `origin/main has commits HEAD does not`, a
check that could not run) → **stop**: list every `gate.failures` entry
verbatim. Fixing it is the owner's work; offer nothing that skips it.

Once `gate.ok` is true, print one ledger line: baseline tag and publish date
— or "no release published yet" when `baseline.tag` is empty — commit count,
and highest tag ("none" when `highestTag` is empty).

### 1a — Push the gate commit and wait for CI

The owner has authorized this push: it sends `gate.commit` — never `HEAD`,
which may carry a `VERSION` bump that CI would tag — to `main`, a
fast-forward only. Substitute `GATE_COMMIT_VALUE` with `gate.commit`; drop
the `git push` line when no failure says `push it first`. The watch can take
ten minutes or more: give the call a long timeout, or run it in the
background and wait for it.

```bash
G="GATE_COMMIT_VALUE"
git push origin "$G:refs/heads/main"
R=""; for i in $(seq 1 30); do
  R="$(gh run list --workflow ci.yml --commit "$G" --limit 1 --json databaseId --jq '.[0].databaseId // empty' || true)"
  [ -n "$R" ] && break; sleep 10
done
echo "RUN=$R"; [ -n "$R" ] || exit 1
gh run watch "$R" --exit-status --interval 30 > /dev/null || true
gh run view "$R" --json conclusion,url --jq '.conclusion + " " + .url'
go run ./cmd/release status --json > "$S" || true
```

A rejected push (not a fast-forward), no run after five minutes, or a
conclusion other than `success` → **stop**: relay it (for a red run, the
failed jobs from `gh run view "$R" --log-failed | tail -n 60`). A red run is
the owner's to fix; never re-run it to get past it. Run step 1a at most once
per release.

## 2 — Draft the notes

Read `.agents/skills/release-notes-capcom/SKILL.md` in place and follow it
exactly as its coordinator, with **no** version argument (the version is
chosen from its inventory). Its output is `NOTES_SRC` =
`<TMP>/release-notes-capcom-<baseline tag>..HEAD.md`, or
`<TMP>/release-notes-capcom-first-release.md` when no release is published
yet; its summary states the implied bump, or that the notes cover capcom's
first release. A stop in that skill stops this one.

## 3 — Approve the notes

The notes are already shown in full. *Ask*: approve, request changes, or
abort. On changes, edit `NOTES_SRC` exactly as asked, show the changed lines,
and *Ask* again. Abort → stop; nothing has been written to the repository.

## 4 — Propose and confirm the version

From `highestTag` `v0.M.P` — an empty `highestTag` (no tag yet) reads as
`v0.0.0`:

- **minor** `v0.(M+1).0` when the notes carry a Breaking section or the
  inventory is feature-heavy (new features are the bulk of the rows), and
  always for the first release (no tag yet: `v0.1.0`);
- otherwise **patch** `v0.M.(P+1)` — also the fallback when the inventory
  gives no clear answer.

An argument version replaces the proposal. *Ask* with the proposal first and
the other size second, plus a free-text choice; the owner's answer is final.
A version not strictly above `highestTag` → say `prepare` will refuse it and
*Ask* again. With no tag yet, any well-formed version is above it.

## 5 — Probe the channels and prepare

```bash
go run ./cmd/release status vX.Y.Z --json || true
go run ./cmd/release prepare vX.Y.Z
git log -2 --format=%s
```

From the status JSON, name every `setup-pending` step (`publish` skips it
and still succeeds; a later re-run converges it once the owner's one-time
setup — a missing tap or bucket repository — is done) and every `unknown`
one. `prepare` makes exactly two **local** commits — the CHANGELOG rollup,
then the bare `X.Y.Z` in `VERSION` — and pushes nothing; a refusal writes
nothing — relay it and stop.

## 6 — Write the release notes file (one shell call)

The notes' title still reads `unreleased`; the published copy names the
version. Substitute `NOTES_SRC_VALUE`, `TMP_VALUE` and the version:

```bash
NF="TMP_VALUE/release-notes-capcom-vX.Y.Z.md"
{ printf '# capcom — %s — %s\n' "vX.Y.Z" "$(date +%F)"; tail -n +2 "NOTES_SRC_VALUE"; } > "$NF.tmp" &&
mv "$NF.tmp" "$NF"; head -n 3 "$NF"; echo "NF=$NF"
```

Skip it on a resume that reuses `NF`; the temp file guards `NOTES_SRC` = `NF`.

## 7 — Dry run, then the one confirmation

```bash
go run ./cmd/release publish vX.Y.Z --notes-file "NF_VALUE" --dry-run
```

Show its output in full. Exit 1 means a refusal: while the tag is pending,
the gate is blocked or VERSION at HEAD does not read X.Y.Z; once the tag is
on origin and the release is pending, `ci.yml` has no successful run for the
tag's commit (its gate row reads `CI only`) — relay the reasons and stop
(see *Abort*). Otherwise *Ask* exactly once: "Publish vX.Y.Z? This pushes
main, waits for CI to tag it, creates the GitHub release and updates
Homebrew, Scoop and winget. It cannot be undone." — options *publish* and
*abort*. Anything but *publish* is abort.

## 8 — Publish

```bash
go run ./cmd/release publish vX.Y.Z --notes-file "NF_VALUE"
```

It never prompts and can wait up to `--tag-timeout` (10m) for the CI-made
tag: give the shell call a long timeout, or run it in the background and wait
for it. It prints a step table and exits 1 when a step fails.

**On failure:** relay the table verbatim and name the failed step and its
detail. Once the cause is fixed (by the owner, or by you when the fix is
outside the release — never a hand-made tag, release or channel commit),
re-run the **same** command: `publish` converges, skipping every step its
probe reports done. A re-run needs no new confirmation for the same version.

## Abort

Before `publish` ran: when `git log -2 --format=%s` shows the two `prepare`
commits for vX.Y.Z, undo them with `git reset --keep HEAD~2` and confirm
`VERSION` reads the old version. Never reset anything else. After `publish`
has pushed, nothing is undone: a broken release is fixed with a new version.

## Report

End with the final step table and, in plain words:

- the version, the GitHub release URL and the notes file path;
- each channel's outcome — **winget "submitted" is not published**: the
  pull request to winget-pkgs merges later, outside this run;
- every `setup-pending` channel with the manual command the owner runs to
  clear it (never you), and that re-running `publish vX.Y.Z` afterwards
  converges it:
  - homebrew — create the tap: `gh repo create airiclenz/homebrew-tap --public`;
  - scoop — create the bucket: `gh repo create airiclenz/scoop-bucket --public`;
  - winget — a first `komac submit` failed: relay the kept manifest
    directory and the command `publish` printed for it, verbatim; or the
    first submission's pull request is still open: name it, nothing to run
    but wait for winget's review to merge it;
- the smoke result `publish` ran last; a SKIP is not a pass — say which.

## Hard rules

- Never tag, push, release or update a channel by hand; `publish` alone does,
  apart from step 1a's fast-forward of `main` to the gate commit.
- Never bypass the gate, nor switch versions to get past a failed `publish`.
- The owner confirms notes, version and publish — each via the question tool.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.