Skip to content
Back to skills

Release

ASecurity

Cut an mrw release: gates on merged main, break campaign diffed against the previous tag, a strict vX.Y.Z tag on the MERGE commit with the shape the last tags use, CI publishes, then ONE Status PR naming the tagged SHA, and reinstall the local CLI from the tag. Use when Zy (M in older notes) says "release", "cut", "tag it", or after a served-path change merges. CONTRIBUTING §Releasing owns the tag rule and the Status-names-the-tagged-SHA rule; this is the drill around them.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 22, 2026
developmentgobashgit

Works with

  • cli

Security analysis

A100/100

Scanned October 22, 2026

npx -y skills add atvirokodosprendimai/tool-multipathreadwrite --skill release --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Release?

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

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

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
description: >-
  Cut an mrw release: gates on merged main, break campaign diffed against the
  previous tag, a strict vX.Y.Z tag on the MERGE commit with the shape the last
  tags use, CI publishes, then ONE Status PR naming the tagged SHA, and reinstall
  the local CLI from the tag. Use when Zy (M in older notes) says "release", "cut", "tag it", or
  after a served-path change merges. CONTRIBUTING §Releasing owns the tag rule
  and the Status-names-the-tagged-SHA rule; this is the drill around them.
---

# release — the drill around CONTRIBUTING §Releasing

CONTRIBUTING says two things and both are load-bearing: push a strict `vX.Y.Z`
tag, and the README **Status** line names the **tagged** SHA, never a later
squash. Everything below is the order that satisfies both without a second tag.

## 0. Preconditions

- `git branch --show-current` is `main`, `git status --short` empty, and `main`
  is at the merge commit you are about to tag (`git pull --ff-only origin main`;
  if it will not fast-forward, local `main` carries a stale commit — `git reset
  --hard origin/main`, the way v1.16.0 had to).
- The change that motivates the tag is a **served-path** change (a flag, a
  receipt field, an exit code, a refusal, a stats line). A docs-only merge is
  not a release.

## 1. Gates on the MERGED tree, stand-alone, never piped

Every gate in `AGENTS.md` §Build and check, each on its own, exit code read directly:

```sh
go build -o bin/mrw ./cmd/mrw && go test -timeout 30m ./...; echo TEST:$?
go test -race -timeout 30m ./...; echo RACE:$?
./scripts/contract.sh > /tmp/c.out 2>&1; echo CONTRACT:$?; tail -1 /tmp/c.out
./scripts/static.sh > /tmp/s.out 2>&1; echo STATIC:$?
(cd cmd/opencode/mrw-plugin && npm ci && npm run build && npm test); echo PLUGIN:$?
```

`static.sh` is the dead-code scan the release needs (deadcode, staticcheck U1000): put its tools,
versions and finding count in the tag message, zero included. `-timeout 30m` because `internal/bench`
alone took 504 s on a loaded machine (2026-10-20), near `go test`'s 10-minute default.
The PR's green tick was for a different tree.

## 2. Break campaign, and DIFF it

```sh
MRW=$PWD/bin/mrw bash scripts/break-campaign.sh > /tmp/campaign.raw; echo CAMPAIGN:$?
grep -v 'campaign dir' /tmp/campaign.raw > docs/break/campaign-vX.Y.Z.txt
diff <(grep -o '^\[[^]]*\] exit=[0-9]*' docs/break/campaign-<prev>.txt) \
     <(grep -o '^\[[^]]*\] exit=[0-9]*' docs/break/campaign-vX.Y.Z.txt) && echo NO-EXIT-DIFF
```

59 probes as of v1.32.0. Read CAMPAIGN's status on its own line: piping the script straight into
`grep` reports grep's status, not the campaign's. An exit-code diff is a finding to explain in the tag
message or a reason not to tag; "identical to <prev>" is the sentence the Status
line carries. The campaign file is committed in the Status PR (step 5), not
before the tag — the tag is code, the campaign is evidence about it.

## 3. Tag the MERGE commit with the shape the last tags use

```sh
git tag -a vX.Y.Z <merge-sha> -m "vX.Y.Z — <one line: what a caller sees differently>

<ADR-NNN. The failure it exists to prevent, in two or three sentences.>

<What changed on the served path, flag by flag. Exit codes.>

Contract §NN–§MM. Dead code: deadcode and staticcheck U1000 (static.sh), N findings.
Tagged at <merge-sha> (#PR). Do not retag v<prev> or the README status squash."
git push origin vX.Y.Z
git ls-remote --tags origin vX.Y.Z | cut -c1-7     # the TAG object's sha, not the commit's
```

Read `git show v<prev> -s --format=%b` first and keep the shape. `-X
main.version=$GITHUB_REF_NAME` in CI stamps the tag; a prerelease suffix builds
nothing (the `check` job re-matches with a regex).

## 4. Let CI publish, and confirm

`gh run list --branch vX.Y.Z` → `build` (5 targets) then `release`. Confirm
`gh release view vX.Y.Z --json assets -q '.assets|length'` is **11** (5 raw, 5
archives, `SHA256SUMS.txt`). Do not push anything else while it runs.

## 5. ONE Status PR, after the tag exists

On a branch: README Status → `**Status: stable at vX.Y.Z (date), the tag cut
from \`<merge-sha>\`.** Break campaign for it: [docs/break/campaign-vX.Y.Z.txt],
N probes, exit codes identical to v<prev>.`; CONTRIBUTING's `(\`v<prev>\` is
\`<sha>\`)` example moves with it; add the campaign file. Squash-merge on
`CLEAN`. This commit is NOT tagged — that is the whole point of the rule.

## 6. Reinstall the local CLI from the tag, then smoke it

```sh
git -c advice.detachedHead=false checkout vX.Y.Z
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=vX.Y.Z" -o /tmp/mrw ./cmd/mrw
install -m 0755 /tmp/mrw ~/.local/bin/mrw && git checkout main && mrw version
```

Same flags CI uses. Then one write that exercises the change through the
installed binary — not `bin/mrw` — and read the receipt.

Between releases, after a merge, install from `main` instead, stamped so `mrw version` names the commit:
`go build -ldflags "-X main.version=v<next>-dev+$(git rev-parse --short=8 HEAD)" -o "$(command -v mrw)" ./cmd/mrw`.
This is the one place that says how the local CLI is installed; `~/.claude/CLAUDE.md` points here.

## 7. Write it down

memoryd `fact`, space `tool-multipathreadwrite`: subject `tool-multipathreadwrite.releases`, predicate
`released`, object `vX.Y.Z@<sha>`; and an `open-thread` naming what is left. If the release changed
what AGENTS.md teaches, update the `mrw` skill in memoryd's `craft` space (`update_skill`, its one
store) with the provenance pin moved to this tag — a skill one release behind teaches a plan the
binary now rejects (v8 was two behind) — then mirror it to `.claude/skills/mrw/SKILL.md`.

## What went wrong before, so it does not again

- `git pull` on `main` refused to fast-forward (v1.16.0): a never-landed local
  commit. Reset to origin, do not merge.
- `git rev-parse --short HEAD origin/<branch>` answered "Needed a single revision", and it was read
  as a tracking ref not fetched yet. It fails every time: `--short` verifies ONE revision (found by
  the review of #282). `git ls-remote` asks the remote itself and is the check.
- `gh pr merge --delete-branch` on a parent auto-closes a stacked child PR.
  Status PRs are never stacked; cut them from `main` after the tag.
- Reading an exit code through `| head` returns head's status. The v1.16.0
  field verification did exactly this within an hour of writing the rule.

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.

Comments

Loading comments…

Newsletter

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