Skip to content

feat: add the release skill - #23

Merged
OndrejDrapalik merged 5 commits into
mainfrom
feat/release-skill
Aug 26, 2026
Merged

feat: add the release skill#23
OndrejDrapalik merged 5 commits into
mainfrom
feat/release-skill

Conversation

@OndrejDrapalik

Copy link
Copy Markdown
Collaborator

Summary

A project skill at .agents/skills/release/ (registered through .claude/skills/release, the same
symlink convention as every other skill here) that covers the path this repo actually takes to ship:
sweep the pull requests that are genuinely ready, then cut and publish a version.

It exists because the sequence has several traps that are individually small and collectively
expensive, and all of them were hit for real while cutting v0.1.0:

  • mergeStateStatus: BLOCKED on a green PR is the review ruleset wanting one approval, not a defect
    — but a red check is not something --admin should paper over, and the two look similar from the
    outside.
  • package.json, herdr-plugin.toml and the tag must all agree, asserted independently by CI's
    version-check and by the release workflow.
  • An empty CHANGELOG section fails the release after the workflow has installed a cross-compile
    toolchain and built three binaries, with the tag already public.
  • CONTRIBUTING.md step 3 is stale: the workflow wipes tui/prebuilt/ and rebuilds from the tag's
    own source, so there is nothing to build locally.

What's in it

  • SKILL.md — the two phases, with the reasoning rather than a command list, plus the repo's
    specific traps written down.
  • scripts/pr-status.sh — a merge-readiness verdict per open PR: READY / STALE / WAIT /
    HOLD. Two of those are things the GitHub API does not surface on its own. A PR with zero
    checks is HOLD, because absence of evidence is not evidence. And STALE catches a PR whose
    checks passed against a base that has since moved — reported as green and mergeable, while those
    tests never ran against the tree that would actually ship. Fork branches are compared as
    owner:branch, since a bare name silently resolves to nothing and makes an outside contribution
    look fresher than it is.
  • scripts/release-preflight.sh — every pre-tag condition in one pass, reporting all of them
    rather than stopping at the first, so you see whether it is one typo or the wrong branch entirely.

The sharpest trap, which this skill also documents

An open PR's changelog hunk is written against ## [Unreleased]. Once a release renames that
heading, the hunk's context still matches — so the bullets land inside the published version's
notes. Git reports a clean merge, version-check only compares the two version files, and nothing
fails: the shipped release quietly claims things it never contained, and the next release's section
comes out empty and hard-fails the workflow after its tag is public. main is in exactly that state
right now (no [Unreleased] heading), which is how the trap was found. The skill's answer is to keep
an empty heading alive and to check where a merged PR's bullets actually went before tagging.

Test plan

  • pr-status.sh run against the live open PRs — correctly reported both as STALE (2 commits
    behind main, one with 6-day-old checks) where a naive read called them green
  • release-preflight.sh 0.1.0 correctly refused an already-taken tag; 0.2.0 correctly reported
    the missing [Unreleased] heading and the version mismatch
  • Exercised end to end by three dry-run agents against this repo; two skill defects they found
    (the [Unreleased] guidance being backwards, and no staleness detection) are fixed here
  • Next real release run confirms the merge sweep and cut behave as written

@cla-bot cla-bot Bot added the cla-signed label Aug 26, 2026
@OndrejDrapalik

Copy link
Copy Markdown
Collaborator Author

Pushed one more fix, found by using this skill to cut v0.2.0 rather than by reading it.

A fork PR's CI is held without saying so. #21 came from a first-time contributor, so its
workflows sat at action_required until released. The check rollup does not report that — it simply
had fewer entries, in that case only verification/cla-signed. To pr-status.sh as written that was
one check, green, none running, none failed: READY. The single most dangerous shape the script
can produce, since it looks proven and nothing had run.

It now probes the head sha's workflow runs for held ones and returns HOLD with the count, and
SKILL.md says what releasing one actually means — an outsider's code executing in CI, so read the
diff first, then approve and wait for the real checks.

Verified as far as it currently can be: the probe's query returns the right run for a given head sha.
The action_required branch itself is logic-only for now — I had already approved #21's run, so that
state no longer exists to test against. It gets its real exercise on the next fork PR.

@OndrejDrapalik
OndrejDrapalik merged commit cb97c44 into main Aug 26, 2026
11 checks passed
@OndrejDrapalik
OndrejDrapalik deleted the feat/release-skill branch August 26, 2026 13:47
@OndrejDrapalik OndrejDrapalik mentioned this pull request Aug 26, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant