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>
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, andrelease.yml's self-checkout is hardcoded toheavy-duty/ceremony. No0.4.1branch was created there. The caller usedcluade-reviewer-andresmgsl/ceremony@drill-0.4.1(f148255), whose parent is9a229eeand whose only extra commit rewrites bothCEREMONY_SELF_REFcarriers 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/v1log 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) |
❌ FAILED — decide 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 | ❌ FAILED — gh: 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.