ceremony/drills/0.4.1.md
cluade-reviewer-andresmgsl abb1c818a3 drill(0.4.1): record the rehearsal — both doors are inoperable here
The drill ran and FAILED, and the record says so. Merge door: lib/facts.sh
reads the release label with `gh api`, the runner image has no gh, the fact
comes back "no", and decide fail-closes on a wrong fact — reproduced twice.
Tag door: clears every gate the merge door fails, then dies at
`gh release create`.

Release count in the scratch repo at the end: 0. Every refusal created
nothing, which is the property the drill exists to check.

drill-recorded wants a record, not a passing result — this is the honest
one, and it says 0.4.1 cannot publish from this instance until facts.sh and
the publish call sites are ported off gh.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 10:44:02 +00:00

4.2 KiB

0.4.1 — drill record

Run 2026-08-04 by cluade-reviewer-andresmgsl against release PR !190 head 9a229ee643291c27dbd404fa97e4dcc7e6ed3b17.

This drill FAILED. Both doors of the release workflow are inoperable on forgejo.heavyduty.builders. The record is written down as the guard requires, and the failure is the finding: 0.4.1 cannot publish from this instance until lib/facts.sh and the publish steps are ported off gh.

Where: disposable private repo heavy-duty/ceremony-drill-0.4.1, armed at 0.4.1-dev with the docs/CONSUMERS.md release caller, a fragment-mode fixture (changelog.d/README.md + one fragment), and a non-blank drill record. Archived at the end; the operator's delete is pending, and per drills/README.md cleanup gates nothing.

Deviations

  • Candidate ref. The pure consumer path cannot resolve CEREMONY_SELF_REF: "0.4.1" before the candidate creates that tag, and release.yml's self-checkout is hardcoded to heavy-duty/ceremony. No 0.4.1 branch was created there. The caller used cluade-reviewer-andresmgsl/ceremony@drill-0.4.1 (f148255), whose parent is 9a229ee and whose only extra commit rewrites both CEREMONY_SELF_REF carriers to that same canonical candidate SHA.
  • Log access. The drill repo was flipped public for ~8 minutes to read job logs — Forgejo's web log route (/{owner}/{repo}/actions/runs/{run}/ jobs/{job}/logs) 404s for a token-authenticated private repo, and the /api/v1 log routes 404 outright. Restored to private, then archived. Recorded because it is a real deviation from "scratch private repo".

Probes

# probe run result
1 merge-door ceremony 12 (and 7, at 0.4.1) FAILEDdecide refused; no tag, no release, main left bare
2 -dev push is a green NOTICE no-op 9, and the fixture push green no-op, nothing created
3 bare version without the release label refuses ⚠️ not run as an independent probe; probe 1 refused through exactly this path, because the label fact read no
4 re-run of a completed ceremony refuses ⚠️ not reachable — no ceremony ever completed to re-run
5 tag-door release from a matching tag 14 FAILEDgh: command not found at publish the release; no release
6 mismatched tag refuses 16 tag '9.9.9' does not match the tree's version '0.4.2' — creating nothing

Release count in the scratch repo at the end: 0. Every refusal path created nothing, which is the one property the drill demands of a refusal.

Finding 1 — the merge door cannot read its own label (lib/facts.sh)

Probe 1, reproduced twice (0.4.1, then 0.4.2 after re-arming):

facts:  ver=0.4.2  base_ver=0.4.2-dev  released=  labeled=no
decide: the version transitioned ('0.4.2-dev' -> '0.4.2') but no merged,
        release-labeled PR is behind this commit — a release is a labeled
        ceremony PR, not a bare push — creating nothing.

The PR was labeled release and was merged. lib/facts.sh derives that fact with gh api "repos/$GITHUB_REPOSITORY/commits/$MERGE_SHA/pulls", and the Forgejo runner image ships no gh. Its own comment says "A failed API call reads as 'no label', which row 5 refuses: fail-closed." — so the guard behaved exactly as designed on a fact that was wrong.

#188 ported the reconcilers and labels-scope onto lib/forge.sh; lib/facts.sh was outside that scope and is still gh-only.

Finding 2 — the tag door cannot publish (gh release create)

Probe 5: the tag matched, the version assert passed, and the job then died at publish the release with gh: command not found (exitcode 127). The tag door has no decide and no label check, so it clears every gate the merge door fails — and then falls at the same missing binary.

Consequence

Merging !190 will run this identical path on heavy-duty/ceremony and refuse, creating nothing. There is no door through which 0.4.1 can publish on this instance today. The fix is the same shape as #188's, one layer out: lib/facts.sh and release.yml's gh release view / gh release create call sites onto forge_*. That is new work, not a re-review of !190.