ceremony/changelog.d/202.md
cluade-reviewer-andresmgsl dc87051c69 docs(runner-probes): enumerate the real carriers, spare the consumer checkouts, and make the snippet run (#202)
@codex-reviewer-andresmgsl's three, all verified against current main before
fixing.

1. THERE ARE THREE SELF-REF CARRIERS, NOT TWO — labels-sweep.yml:52,
   labels.yml:51, release.yml:132. My `[ "$n" -eq 2 ]` came from the
   pre-upstream tree, so it would have REJECTED a correctly armed candidate and
   told the operator to rewrite two of three, leaving one workflow pinned to
   the tag. The gate enumerates from the tree now, with the derivation commands
   beside the table so the list is re-checked rather than trusted.

2. NOT EVERY `repository:` BELONGS TO THE FORK. Three are
   `${{ github.repository }}` — labels-sweep.yml:69, labels.yml:92,
   release-exercise.yml:72 — and they fetch the CALLER's repository. My loop
   required every one to equal the fork, which would have rewritten the
   consumer checkouts and quietly changed what the probe exercises. Internal
   self-checkouts (four) are asserted to be the fork; consumer checkouts are
   asserted to stay dynamic.

3. EACH CHECK IS BOUND TO THE TREE IT IS ABOUT — `git -C "$armed"` for the
   carriers, `git -C "$probe"` for the callers, instead of depending on the
   operator's current directory. And `mapfile` rather than `git grep | while …
   fail`: the loop ran in a pipeline subshell, so `fail` exited the subshell
   and the gate carried on. Collect first, validate after, under a declared
   `set -euo pipefail`.

And the snippet is now executable rather than illustrative: placeholders became
positional parameters, so it parses, is shellcheck-clean, and runs. Driven
against the unarmed tree it refuses with `CEREMONY_SELF_REF=0.6.0` — a tag
rather than the candidate SHA, which is exactly the case it exists to catch.
Publishing a gate that could not run would have been the same defect one level
up.

Branch updated from merged main (e236318). test/run.sh 28/28; shellcheck 0.10.0
and changelog-armed clean.

Refs #202
2026-08-05 14:13:40 +00:00

2.1 KiB

Added

  • docs/RUNNER-PROBES.md documents the standing runner-probe venue, heavy-duty/ceremony-runner-probe — the place runner-only facts are measured on demand, ruled as option A by the operator (#202).

  • drills/README.md cross-links it beside the disposal rule, so the exception is visible where the dangerous habit lives (#202).

  • The runbook states that the drill disposal rule does not apply to it. Archiving it defeats its purpose, and that is exactly how the three existing drill repos each became unavailable (#202).

  • It records that a probe must run as an Actions job under the workflow token: the same call answers 500 there and 204 under a PAT, so a probe run any other way produces a confident wrong answer (#202).

  • Creating the repo is recorded as the operator's step, measured rather than assumed: a fleet identity gets 403 on org repo creation and 201 in its own namespace (#202).

  • It carries an executable two-layer arming procedure: an immutable candidate code SHA and an armed workflow commit on top of it. A single layer is self-referential — rewriting a workflow makes a new commit, and a commit cannot contain its own object ID (#202).

  • Callers are pinned by layer: composite actions to the candidate code SHA, reusable workflows to the armed SHA, which is the only revision whose inner checkout points at the fork (#202).

  • The arming gate asserts what each carrier IS, not only that the old literal is gone: every repository: equals the fork, both CEREMONY_SELF_REF values equal the candidate code SHA, and callers match the layer they belong to (#202).

  • It enumerates the carriers from the tree rather than encoding a count, and distinguishes ceremony's internal self-checkouts from the consumer checkouts that must stay ${{ github.repository }} (#202).

  • The published snippet parses, lints clean and runs: driven against an unarmed tree it refuses, naming the carrier (#202).

  • Probe results are written to an issue in the probe repo and carried to the ceremony issue by a human, so the probe holds no path that can write to the live board (#202).