feat(gates): deterministic floor (GATE 0) under the fresh verifier

GATE 1 is an LLM dispatch and the verifier's mandatory PROOF: line is a line
the verifier writes — nothing structurally stops it being produced without
anything being executed. Nothing deterministic sat between the executor and
that dispatch.

An acceptance criterion can now carry an oracle: indented CHECK: (command),
EXPECT: (success-only marker), EVIDENCE: (slot). lib/gates.sh runs them
fail-closed — MET requires exit 0 AND the marker, so a nonzero process never
passes on its error text carrying the token — and writes the outcome back
into the contract, so the fresh verifier reads evidence as fact rather than
trusting the executor's report.

GATE 0 runs that floor before any verifier is dispatched; a red build sends
the executor back for free, on its own iteration budget. ABANDON: <id>
<reason> turns an impossible criterion into a visible handoff that blocks
CONFORME and routes to the human gate, via the new ABANDONED(n) verdict —
a distinct token because it routes distinctly, never a dev loop. feater and
bugfixer gain a four-pass completion discipline, scoped so a pass can never
widen the contract.

The runner's parse fails closed on partial oracles, duplicate ids,
unindented attributes and runnable criteria with no EVIDENCE: line, and
executes nothing at all when the ledger is malformed. status never executes
and never writes; run always re-executes, since trusting written evidence is
the failure being closed.

Adapted from the unlazy skill (Leonxlnx/unlazy, MIT). Its Stop hook,
approval store, .unlazy/ tree, depth-tree arithmetic and Node checker were
deliberately refused — BDR-083 records each reason.

64 assertions in lib/tests/gates.test.sh, non-execution proved by sentinel
with its own positive control asserted first.
This commit is contained in:
Bastien Chanot
2026-08-24 13:12:38 +02:00
parent 5488c4870f
commit 63310467ca
8 changed files with 826 additions and 20 deletions
+18
View File
@@ -46,6 +46,24 @@ Every choice was made in the plan or is a NEED-DECISION to report.
security/verifier dispatch, editing `.claude/**` or memory registries, user
questions (you cannot ask — report instead), attribution trailers of any kind.
## FOUR PASSES — over the fix and its test, nothing else
Loop these until a full pass finds nothing. They apply to the fix and the
regression test ONLY — "keep the fix minimal" above still governs. They make
the minimal fix COMPLETE; they never widen it.
1. **Complete.** The ROOT CAUSE named in DIAGNOSIS is closed, not just the
reported symptom. No placeholder, no deferred remainder.
2. **Expert reread.** Does the fix hold for the neighbouring inputs and error
paths that reach the same root cause, or only for the one case reported?
3. **Negative control.** Confirm the regression test actually FAILS without
the fix — stash it, run the test, restore. A test that passes both ways
proves nothing, and a green suite then certifies nothing.
4. **Polish.** Naming and comments on what you touched. Nothing else.
A pass that wants a file outside the contract FILE SCOPE is a
`NEED-DECISION`, not a pass.
## OUTPUT — end with exactly this report (your final message)
```