Commit graph

10 commits

Author SHA1 Message Date
codex-bot-andresmgsl
1c3d873bf2 feat: adopt ceremony callers and doctrine 2026-07-23 13:40:44 +00:00
dan-claude-bot
c8150f2d5b fix: issues: write — the fallback PR's --label rides the issues API (labels.yml precedent)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:35:39 +00:00
dan-claude-bot
b89ed144fe fix: pull-requests scope for the door's two PR-API calls; docs catch up
The permission-starvation blocker found on the cast twin (claude-bot,
cast#112 round 4) is identical here: a declared permissions: block zeroes
every unspecified scope, so the decide step's label read and the bump
fallback's gh pr create could only 403 — every genuine ceremony would end
red at the label check. pull-requests: write added with the consumers
named. CONTRIBUTING step 3 and the changelog entry now tell the shipped
story: push-to-main door, event.before interlock, self-re-arm with the
manual path's bump staying the operator's. Re-runs wording nit taken.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:33:41 +00:00
dan-claude-bot
03e1a8c5b7 feat: the release re-arms main — the -dev bump folds into the release act
Operator decision: the post-release bump PR is ceremony debris — a
derivable one-liner with no judgment for a review to add. After tag +
publish, the same job computes X.Y.(Z+1)-dev and pushes it to main
directly (a GITHUB_TOKEN push fires no workflows: no recursion, no red
run); if branch protection refuses, the step opens the bump PR itself,
loudly. #98 is the last hand-made bump.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:04:22 +00:00
dan-claude-bot
89345f7de3 fix: the merge door rides pushes to main — fork PR tokens are read-only
Round-1 blocker (claude + grok): a pull_request run from a public fork
gets a read-only GITHUB_TOKEN — permissions: cannot raise it — and every
ceremony PR this org merges is cross-repo from the bot fork, so the tag
create would 403 after green asserts, red on main per release. The door
now triggers on push to main (in-repo event, full token); the decide step
keeps the first-parent version interlock, and the release label — still
the operator's declared intent — is read via the API off the merge
commit's PR. A transition with no labeled PR behind it refuses. The doors
split on the pushed ref: tags to the tag door, main to the merge door.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:46:03 +00:00
dan-claude-bot
13aa499dad fix: a -dev endstate is always work — the post-release bump must not run red
The four-state table called '-dev but changed' half a ceremony and
refused — but that state IS the mandatory post-release bump PR
(bare -> X.Y.(Z+1)-dev after every release), which would have put a red
run on main once per release, forever. A tree that ends -dev is by
definition not a release: every such merge is work, and no-ops green
with a NOTICE. The red verdicts now guard only bare endstates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:40:48 +00:00
dan-claude-bot
420e8e7f32 fix: the release label's two meanings part ways in a decide step
LABELS.md gives 'release' to release-flow WORK as well as to the ceremony
PR — the PR that added the merge door included. The old assert pair turned
every such merge into a red run on main. The fused decide step reads
VERSION against the merge commit's first parent and answers all states:
-dev unchanged = work, green NOTICE no-op; bare unchanged but already
released = work in the post-release window, same no-op; -dev-but-changed
and bare-unchanged-never-released = half-ceremonies, refused loudly;
bare-and-changed = the ceremony. Later steps gate on its output. Five new
pins in test/release.sh cover each verdict and the gating.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:25:52 +00:00
dan-claude-bot
b58ce5524f feat: merging a release-labeled PR is the release (#96)
The 0.7.0 ceremony exposed the gap: the release PR merged with four
approvals and nothing happened, correctly, because publishing hung off a
separate, manual, silent-when-forgotten tag push — the worst failure
shape, no error and no red X. The ship decision already lives in the
release PR, so the merge now IS the release.

release.yml grows a second door: pull_request closed on main, gated on
merged == true AND the hand-set release label (read from the event
payload — no extra permission). Four asserts, in order, each fail-loud
and creating nothing: VERSION at the merge commit is non--dev; VERSION
changed in this PR (merge vs first parent — the -dev interlock that
kills a mislabeled ordinary PR); the version's CHANGELOG.md section
extracts non-empty via the existing release-notes.sh; and no tag or
release exists yet. Then, in the same job, it creates the tag ref at
the merge commit via the API and publishes with gh release create
--verify-tag. Same-job on purpose: a GITHUB_TOKEN-created tag triggers
no workflows (GitHub's anti-recursion), so the tag door can never fire
off it and double-publish, and the no-existing assert covers a manual
tag racing the merge. The tag-push path stays step-for-step identical
as the documented manual fallback and backfill, gated to the push event
so a closed PR never runs it against a branch ref.

CONTRIBUTING.md's Releases section now reads "the maintainer's merge IS
the release", with the manual tag ritual kept as the fallback.
test/release.sh grep-pins the merged+labeled gate, all four asserts,
the same-job tag+publish, and that the tag-push trigger survives — in
the same daemon-free, fail-closed style.

Fixes #96

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:19:31 +00:00
dan-claude-bot
3122729877 fix: release.yml triggers on every tag, so a mismatch fails loudly
A shape-filtered trigger silently skips the tags it doesn't match — a
habitual v0.7.0 would mint nothing and say nothing. rig's release.yml
(heavy-duty/rig#40) already triggers on '**' and lets the tag==VERSION
assert be the loud gate; align box to that.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 22:18:23 +00:00
dan-claude-bot
dd51b06f3a feat(release): publish the tagged version's changelog section (#83)
On a bare X.Y.Z tag push (the 0.6.0 tag set the no-'v' precedent),
release.yml asserts the tag names the tree's own VERSION — a mismatch
fails loudly and creates NOTHING — then publishes the GitHub release
with that version's CHANGELOG.md section as the body: the curated
prose, not the generated PR list. No assets, because for a pure-bash
tree GitHub's source tarball for the tag IS the package.

The extraction lives in .github/scripts/release-notes.sh, a file of
its own so test/release.sh drives the same code against fixtures and
the real changelog — it refuses a missing or empty section, so a tag
whose release ritual was skipped fails before anything is created.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 22:17:51 +00:00