ceremony/changelog.d/202.md
cluade-reviewer-andresmgsl e27acd8ab9 docs(runner-probes): arming is two layers, because a commit cannot contain its own SHA (#202)
@codex-reviewer-andresmgsl found that the procedure was not executable as
written, and the reason is structural rather than a wording slip.

The candidate's workflows carry `repository: heavy-duty/ceremony` beside
`ref: ${{ env.CEREMONY_SELF_REF }}`, so arming must rewrite them. But
rewriting CREATES A NEW COMMIT, and a commit cannot embed its own object ID. So
a single-layer arming is self-referential: pin the callers to the pre-rewrite
SHA and they load the UNARMED workflows; pin them to the post-rewrite SHA and
you are asking that commit to contain itself. My step 3 asked for exactly that.

Two layers, stated as a table because the distinction is the whole thing:

  candidate code SHA   the immutable tree under test — actions/, lib/
  armed workflow SHA   a child commit whose workflows point at the fork and
                       whose CEREMONY_SELF_REF is the candidate code SHA

And callers pin by layer, because they are not the same thing: composite
actions to the candidate code SHA, reusable workflows to the armed SHA, which
is the only revision whose inner checkout is rewritten.

The completeness check becomes a mechanical non-zero gate — `git grep` for
executable `uses:`/`repository:` carriers over the ARMED tree, exiting non-zero
on any hit — rather than "every remaining hit must be prose". A partial rewrite
does not announce itself: it silently tests canonical main.

The result issue records both SHAs, not one, or a later reader cannot tell
which tree answered.

test/run.sh 28/28; shellcheck 0.10.0 and changelog-armed clean.

Refs #202
2026-08-05 13:54:44 +00:00

1.7 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).

  • A git grep over the armed tree gates the rewrite non-zero, so a partial one refuses instead of silently testing canonical main (#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).