R-404 CLOSED with the ruling; R-417 CLOSED by cause removal; R-418/419/420 filed
gates / gates (push) Successful in 17s

THE RULING WAS NEITHER OPTION AS FRAMED. Both offered answers - narrow the gate, or leave it and
write waivers - argued about the gate, and the gate was never the problem.

DIAGNOSIS, from live source: golden_currency_gate.py never looks at the push. It compares the
controller's newest CHANGELOG heading against this repo's bake evidence and returns the same
verdict whatever you are pushing - correct for a standing invariant, wrong as a push gate. And
controller_gates.py had NO golden-currency entry at all. So the repo where a release happens never
checked, and the repo that cannot create the debt was refused on every push. 18 of the last 24
pushes here touched no code - measured, and the new classifier agrees EXACTLY - most of them by
construction, because the controller's code is in one repo and its register lives in this one. SIX
of those 18 were bake records, so the push that PAYS the debt is itself documents-only: the gate
was blocking its own cure.

Not the waiver its docstring prescribes: that clause was written for a release nobody wants a
golden for. R-417 was a release we DID want a golden for, on a night the runbook forbade baking. A
waiver would have recorded a lie.

RULING: block the push that can create the debt, notify the push that cannot.

The gate's logic, exit codes and wording are BYTE-IDENTICAL. Only the consequence changed, for one
gate, on one kind of push, with a loud ADVISORY block so nothing goes quiet.

R-242's vouch half is amended in place to say it is UNTOUCHED and still open - a baked-but-unvouched
golden still passes both the gate and the new notice. Do not read R-404's closure as closing it.

FILED: R-418 - this runner's docstring listed ELEVEN gates while THIRTEEN were registered;
one-register and closed-register ran undocumented since 2026-08-24. Enumeration fixed here, the
correspondence is still unenforced. R-419 - observations_gate.py accepts an item whose body merely
CONTAINS "NOT-A-FINDING", even in prose disclaiming it; found by accident when a planted test
observation passed and my live validation proved nothing. R-420 - controller_gates.py could not
express a non-blocking gate at all before today.

Register: OPEN 171 -> 172, CLOSED 158 -> 160.
This commit is contained in:
2026-09-01 12:01:10 +02:00
parent 1f74427fd2
commit 1e6c387a0b
6 changed files with 116 additions and 18 deletions
+49
View File
@@ -1,3 +1,52 @@
## push_scope.py v1.0.0 + repo_gates.py --scope — block who can act, notify who cannot (2026-09-01, R-404/R-417)
**No product code, no version bump, no image, and deliberately NO GOLDEN** — creating one would be an
odd way to finish a task about golden debt.
**The diagnosis, because the fix is not a weakening and should not be mistaken for one.**
`golden_currency_gate.py` never looks at the push: it compares the controller's newest CHANGELOG
heading against this repo's bake evidence and returns the same verdict whatever you are pushing.
That is right for a standing invariant and wrong as a push gate. `controller_gates.py` had no
golden-currency entry at all. **So the repo where a release happens never checked, and the repo that
cannot create the debt enforced it on every push** — 18 of the last 24 pushes here touched no code
(measured; the new classifier agrees exactly), most of them by construction, because the controller's
code is in one repo and its register lives in this one. Six of those 18 were bake records, so **the
push that pays the debt is itself documents-only and the gate was blocking its own cure.**
- **`push_scope.py`** — classifies a push `code` or `docs` from an **allow-list** of document paths.
Everything else, including any new top-level directory, is code. **Every uncertainty answers
`code`**: first push (all-zero remote sha), deletion, force-push, merge commit, empty range,
unreadable stdin, absent classifier. Two input modes feed one classifier — `--range` for the hook,
`--files-from` for CI — so there is one definition of "document" and not two. Reasoning goes to
stderr; only the verdict word goes to stdout.
- **`repo_gates.py`** — fifth `exemptible` field (True for `golden-currency` **only**), `--scope=`,
and a new **ADVISORY** verdict printed in its own block after the table. `run_gate` now tees rather
than captures, so the advisory quotes the gate's own numbers instead of re-deriving them. An
unscoped run is byte-identical to before. **`--scope=banana` is refused, not assumed.**
- **`.githooks/pre-push`** — reads git's ref updates from stdin (measured against git 2.47.3:
`<local ref> <local sha> <remote ref> <remote sha>`, one line per ref) and passes the scope through.
Stdin is consumed exactly once, into a variable.
- **`.gitea/workflows/gates.yml`** — the same rule in CI. CI checks out `--depth 1` so it has no
range; the file list comes from the push event payload and feeds the same classifier. Every failure
path writes `code`, so this step can only make CI as strict as it is now, never looser.
**THE GATE ITSELF IS UNTOUCHED** — its logic, exit codes and wording are byte-identical. Only the
consequence changed, and only for one gate, on one kind of push.
**Tests.** `test_push_scope.py` (P1–P5) and `test_repo_gates_scope.py` (R1–R6). **Scenario C — a
documents push with a NON-exemptible gate convicting must still be refused — was written FIRST and
is the acceptance.** Red-proofs run and recorded: swapping the allow-list for a deny-list breaks P3
(all seven unknown paths become documents); marking every gate exemptible breaks R3.
**Proven live on the real hook**, against a throwaway local remote so no test commits reached Gitea:
docs + debt → ADVISORY printed, push accepted; code + debt → refused with today's wording; docs +
debt + a second gate convicting → refused, `CONVICTED: observations` alone. The evidence directory
was moved aside to create the debt and restored afterwards; tree byte-identical, gate green.
**Also fixed here:** this file's own runner docstring listed ELEVEN gates while THIRTEEN were
registered (R-418) — `one-register` and `closed-register` ran on every push undocumented since
2026-08-24.
## closed_register_gate.py v1.0.0 — CLOSED-ITEMS.md holds closed work only (2026-08-31, R-405)
**One row corrected, one gate added, no product code touched.** R-87 ("the restic tier is never