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>
103 lines
5.7 KiB
Markdown
103 lines
5.7 KiB
Markdown
# 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-dev` → `0.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.
|