Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 80b61fa455944d17a7fa5ccb0f8ca39c
Branch: dev/1-p498-gate-switch-coverage
Base: 551375d
At: 2026-11-03T12:36:34Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
Reported-by: FlyBot Product
Surface: policy/ + .github/scripts
Kind: enhancement — derive the gate list instead of repeating it
What happens
policy/gates.json is handwritten. The repository already carries the machine-readable answer: docs/testing-layers.json marks four workflows gate: true (test, merge-gate, enqueue-guard, docker), yet gateFiles names only test.yml among workflows.
Read on live main d90d9359 with the repository's own judge():
merge-gate.mjs→ REFUSED without a signature,merge-gate.yml→ needs none;enqueue-guard.mjs→ REFUSED,enqueue-guard.yml→ needs none;gate-check.mjs, which writes theenqueue-guardcheck run, → needs none.
#2093 added the two rule scripts; the workflows that run them stayed outside, while gates.json's own $comment says "a rule that does not cover its own switch is advice, not a gate".
Red first: 3/3 in Product's probes/gate-switch-coverage.test.mjs, while the existing policy-sign.test.mjs stays 16/16 green; evidence probes/evidence/gate-switch-coverage-d90d9359.txt.
Expected
The list is derived from docs/testing-layers.json: a workflow marked gate: true is a gate file by construction, and each gate workflow is pinned to the scripts it runs from main/base, so the two cannot drift apart again.
Scope
New policy/gates.test.mjs — every gate: true workflow appears in gateFiles, plus three two-way pins (merge-gate.yml → merge-gate.mjs, enqueue-guard.yml → gate-check.mjs/enqueue-guard.mjs/enqueue-rules.mjs, test.yml → policy-sign.mjs). gates.json gains merge-gate.yml, enqueue-guard.yml, gate-check.mjs.
One open question for the implementer to settle with the reviewer: docker.yml is gate: true but absent from gates.json. Include it in this change unless the reviewer says the image build is not a gate; either way the test keeps an explicit table rather than an inference.
Lane: scripts (the L1 suite picks it up), not the client bundle. Because policy/ is itself a gate file, this PR needs one Policy-sign: from the reviewer — the same family as #2099/#2121/#2124.
Dedupe (2026-11-03): #2099 (judge with the pull request's own copy), #2124 (the signing step is not a required context), #2093 (added the two scripts). None proposes deriving the list from docs/testing-layers.json, and none names merge-gate.yml or gate-check.mjs.
Framing
This introduces no new gate. Each file the change adds is already declared a gate by docs/testing-layers.json (gate: true for merge-gate and enqueue-guard) or is the script that writes the enqueue-guard check run; the change removes the second, handwritten copy of that list, which disagreed with the declaration the repository already carries. It makes the list follow the existing declaration — it does not widen what counts as a gate beyond it.
Activity
policy: derive the gate list from docs/testing-layers.json (ThinkFlow…