ceremony/drills/0.1.0.md
claude-bot-andresmgsl af48581973 drill: the 0.1.0 record, and the first-release caveat in the doctrine
drills/0.1.0.md — six probes plus (g), run on the disposable scratch repo
against the candidate SHA, every refusal checked for droppings; the pin
deviation (fork ref, CEREMONY_SELF_REF -> candidate SHA in both carriers)
recorded under its own heading per triage's ruling on #11. drills/README.md
gains the first-release caveat that ruling asked for: the first drill can
never take the pure pinned consumer path, and must not fix that by putting
a tag-shaped branch in the canonical ref namespace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:40:38 +00:00

5.7 KiB

0.1.0 — drill record

Run 2026-07-22, by claude-bot-andresmgsl, against the release candidate heavy-duty/ceremony@dbf857a94a7c4b068962efbccc996b41c5e4ab89 (main at the time — the ceremony PR adds only VERSION, the changelog stamp, this record, and a doctrine caveat; no machinery differs between the drilled tree and the released one).

Where: scratch private repo claude-bot-andresmgsl/ceremony-drill-0.1.0, carrying the docs/CONSUMERS.md caller stubs verbatim (modulo the pin deviation below) and a fixture consumer tree in the armed state (VERSION 0.1.0-dev, ## Unreleased on top, drills/). Deleted after this record was written, per drills/README.md: the repo is the evidence's scaffolding, this file is the evidence. Run ids below are kept for the record's own audit trail; they died with the repo.

The deviation: the first release cannot take the pure consumer path

CEREMONY_SELF_REF is "0.1.0" — the ref this drill exists to rehearse creating. Demonstrated live before working around it: the release caller pinned @0.1.0 per the stubs died at workflow resolution before any job started (run 29966400928) — the deadlock #44's bypass solves for ceremony itself, hit from the consumer side, where no bypass can exist.

Ruled on #11 by triage: no 0.1.0 branch on heavy-duty/ceremony — a drill must not leave a hazard in the canonical ref namespace (a branch shadowing the tag every consumer pins) to prove the namespace works. The drill instead pinned the scratch callers to the fork ref claude-bot-andresmgsl/ceremony@drill/0.1.0: the candidate tree with exactly one line changed per pin carrier (release.yml and labels.yml, both — self-ref-check.sh requires the carriers to agree), CEREMONY_SELF_REF: "0.1.0""dbf857a94a7c4b068962efbccc996b41c5e4ab89". Every .ceremony-src byte the doors executed — lib/, actions/, decide — still came from heavy-duty/ceremony at the candidate SHA; the fork supplied orchestration YAML differing by the one line the ceremony stamps each release anyway. From 0.2.0 on, a real tag exists behind every candidate and the pure pinned path drills as written.

The probes

# probe run result
a merge-door ceremony 29966647167 (attempt 1) exactly one release
b mislabeled ordinary PR 29966530098 green NOTICE no-op
c bare-version PR, no label 29966562846 refused, red, created nothing
d re-run of the completed ceremony 29966647167 (attempt 2) refused, red, created nothing
e tag door, manual matching tag 29966718335 published, no bump
f tag door, mismatched tag 29966744675 refused, red, created nothing
g labels bootstrap from nothing 29966488038 taxonomy created

(a) The ceremony. PR release: 0.1.0 — hand-set release label, VERSION 0.1.0-dev0.1.0, changelog stamped ## 0.1.0 — 2026-07-22 with an empty ## Unreleased re-armed above it. Merged. The one run: facts ver='0.1.0' base_ver='0.1.0-dev' labeled='yes'ceremony=yes → tag 0.1.0 created on the merge commit (verified equal to the PR's merge SHA), release 0.1.0 published with the fixture changelog section — verbatim — as its body, and main re-armed to 0.1.1-dev by the run itself. The GITHUB_TOKEN tag create and bump push fired no second run (anti-recursion held: the run list gained nothing after the merge run).

(b) Mislabeled ordinary PR. README-only PR wearing the release label. Green: NOTICE: the version '0.1.0-dev' is -dev and unchanged by this PR — release-flow work under the release label, not a ceremony. Nothing to publish. No tag, no release.

(c) Bare-version PR without the label. The ceremony's two edits, label deliberately absent. Red at decide: the version transitioned ('0.1.0-dev' -> '0.1.0') but no merged, release-labeled PR is behind this commit — a release is a labeled ceremony PR, not a bare push — creating nothing. No tag, no release; main reverted to the armed state afterwards (the revert push itself ran green as a no-op, as it should).

(d) Re-run of the completed ceremony. Re-ran (a)'s run. Red at the nothing-may-exist assert: tag '0.1.0' already exists — this release already happened, or a manual tag won the race; refusing to re-release, creating nothing. Release count still exactly one.

(e) Tag door. Branch with VERSION 0.2.0 and its stamped section; manual 0.2.0 tag pushed at its head (never merged to main). The tag door published release 0.2.0 with that section as its body; the merge door correctly skipped. Main untouched: VERSION stayed 0.1.1-dev — the fallback does not rewrite main.

(f) Mismatched tag. Tag 9.9.9 pushed at main (tree version 0.1.1-dev). Red: tag '9.9.9' does not match the tree's version '0.1.1-dev' — creating nothing. No release, and the operator-facing remediation text printed as designed.

(g) Labels bootstrap from nothing (moved into the drill by triage on #11 — ceremony's own taxonomy already exists, so the scratch repo is the only honest place left to exercise the path every fresh consumer hits first). workflow_dispatch of the scratch labels caller: the reconcile job took the consumer path (.ceremony-src fetched at the candidate SHA), bootstrap=yes, and created the full taxonomy — state, blocker, work-queue, release — plus the consumer-owned scope:fixture row from labels.conf, on a repo that had only GitHub's defaults. Subsequent PR-event runs reconciled without re-upserting, as documented.

Failures

None. Six probes plus (g) behaved exactly as specified, and every refusal path was checked for droppings — no tag and no release exists that a refusal created.