feat: CI refuses a release PR with no drill record #138

Merged
dan-claude-bot merged 2 commits from feat/drill-gate into main 2026-07-21 16:17:22 +00:00

2 commits

Author SHA1 Message Date
dan-claude-bot
9f8df92484 fix: whitespace is not a drill record, and align the heading grammar with box 2026-07-21 15:53:38 +00:00
dan-claude-bot
2578a570ca feat: CI refuses a release PR with no drill record
CONTRIBUTING has always asked for the full real-hardware drill on a
release. Nothing asserted it, so it was performed exactly as often as a
reviewer remembered to ask — which is never, across every release in the
family, until a reviewer bot finally blocked on it. The gate moves out of
memory and into the tree.

drill/RUNS.md is cast's own run log, starting empty: no fabricated
history, and an honest note that cast has no drill harness script yet —
its legs are run by the documented procedure. The file is the record, not
the instrument.

.github/scripts/drill-recorded.sh reads package.json and asserts that a
bare version has a non-empty '## Release drill — X.Y.Z' section. A -dev
tree has no ship claim and passes trivially. The version is matched
WHOLE via awk field equality, release-notes.sh's fix for the same trap:
0.2.0 is not satisfied by 0.2.0-rc1, or the reverse.

It requires a RECORD, not a PASS. A maintainer waiver is legal and is
itself a section in drill/RUNS.md, so skipping the drill stays possible
and stays a deliberate, reviewable commit rather than an oversight.

The drill itself is ONE orchestrated run over the whole stack: rig
bootstraps a bare host and installs box, box new mints a seed, the seed
calls rig back to converge, and cast's legs run on the result. rig sits
below box and above it, so the repos are mutually recursive rather than
linearly ordered and their releases are not published in a fixed
sequence. The run pins candidate refs (RIG_REPO/RIG_REF at mint time),
so no repo must ship before another can be drilled, and drilling the
candidate is drilling the release — a release diff is the version file
and CHANGELOG.md, nothing executable.

Each repo records its own legs from that run, citing the shared run ID
and the other repos' SHAs. cast never reads box's or rig's drill log to
decide whether cast may ship: a cross-repo lookup degrades to "pass" the
moment it fails to resolve — the unreadable-rollup class.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 15:24:08 +00:00