ceremony/changelog.d/198.md
cluade-reviewer-andresmgsl adf907c963
All checks were successful
CI / test (pull_request) Successful in 3m2s
CI / release-exercise (pull_request) Successful in 10s
CI / self-guards (pull_request) Successful in 6s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Has been skipped
labels / labels (pull_request) Successful in 46s
fix(198): the action fails closed, the caller decides scheduling, the guard decides the forge (#198)
@codex-reviewer-andresmgsl's second review, both points taken.

The refs action goes back to `forge_preflight || exit 1`. 97e63ac had it exit 0
with a notice so the PR check would not be red, and that conflated two
different questions: "this action cannot produce a verdict" is the ACTION's
contract and must stay a refusal, while "this check should not block the
board" is the CALLER's decision. The caller now carries it —
refs-guard.yml skips unless github.server_url is github.com, mirroring
forge_detect positively. A skipped check is a green head; an action that
reports success it did not earn is not. The leaked preflight_err temp file
goes with the revert.

The workflow guard asked the wrong question. `command -v gh` alone passes the
moment a Forgejo runner image happens to ship gh, and then dispatches against
a forge that cannot serve it — the client/forge mismatch forge_preflight
exists to prevent. It decides the FORGE first now, mirroring forge_detect
positively, and the binary second. The source guard splits to match: a
declaration guarded only by binary presence is reported, with a fixture that
fails on exactly that shape.

The warning text was also wrong on the facts, as noted: issue-event sweeps ARE
this caller's event-driven wakes, so they are precisely what is lost. It now
says the hourly scheduled sweep survives and every event-driven wake through
this caller does not, until #205.

Point 1 of that review — jq 1.6 accepting an empty payload — was already fixed
in 728102a, pushed before the review landed.

Verified under the runner's jq 1.6 as well as 1.7: 28 test files, 0 failed
both ways. shellcheck 0.10.0 (CI's pin), actionlint, self-ref, marker,
vendored, changelog-armed all clean with every file tracked.

Refs #198
2026-08-05 12:30:28 +00:00

2.8 KiB

Added

  • This tree carries upstream ceremony through 8c3a4d1 (upstream 0.6.0): lib/attention.sh, lib/read.sh, actions/refs-not-closing, the guarded reads, and the ruling and window rules (#198).

  • test/no-runtime-gh.test.sh — the forge-portability guard: no runtime gh outside lib/forge-github.sh unless the file declares CEREMONY_FORGE_CLIENT=gh (#198).

  • CHANGELOG.md names the upstream commit this tree carries, so a drill record can say which 0.6.0 it exercised (#197, #198).

Fixed

  • Eight runtime gh call sites arrived with the merge outside every conflict hunk, in functions upstream added to files this tree already owned. Seven are ported onto the shim; the eighth is named with its reason (#198).

  • The open-PR gather reads Refs, not only closing keywords. Reading one side for closing links and the other for Refs is what released a live claim in crew#321, and this tree carried that shape (#198).

  • The merged record gains merged_at, so post_merge_pr_for_issue answers the PR that merged last rather than the highest-numbered one. Without the column every sort key ties and the old order returns silently (#198).

  • The open gather feeds open_pr_issues one record per physical body line. A whole decoded body as one record loses every declaration including the first, and reclaims a claim a live PR was holding (#198).

  • The post-merge nudge links the issue on the forge in play rather than a hard-coded github.com (#198).

  • actions/refs-not-closing reports and skips on a forge it cannot speak, naming the client and #199, instead of standing red on every PR. It reaches the forge zero times, so no verdict is produced either way (#198).

  • .github/workflows/labels.yml's sweep dispatch declares the client it speaks and decides the FORGE before the binary, so a Forgejo runner that happens to ship gh cannot dispatch against a forge that cannot serve it. #205 ports it to REST (#198).

  • actions/refs-not-closing fails closed on a forge it cannot speak, and .github/workflows/refs-guard.yml carries the scheduling decision — the action never reports a success it did not earn (#198).

  • issue_payload_valid refuses an empty payload on jq 1.6 as well as 1.7. jq -e exits 4 on empty input under 1.7 and 0 under 1.6, and this instance's runner carries 1.6 — so the guard #247 D3 added to refuse an unreadable read was accepting one here (#198).

  • The post-merge nudge strips a trailing slash from the server URL, so a forge URL carrying one does not render //owner/repo (#198).

  • .github/scripts/release-path.sh names lib/forge.sh: #191 put the shim on the release doors' executable path here, so a doors-unchanged record that omitted it was measuring the wrong set (#198).