feat(lib): floor-guard, diff-scoped detector of a weakened quality bar

SUPPRESS / SKIP / DELETED_TEST / ASSERT_DROP / STUB / THRESHOLD_DOWN over
git diff <base> (untracked files included), floor-guard: allow <reason>
waiver printed as WAIVED, rc 0/2/3. Mandatory verifier STEP 3, documented
under GATE 1 of verify-secure-loop.md. Suite: 6 kinds + WAIVED + CLEAN,
flip-tested. Adapted from agent-skills constraint-driven-development.
This commit is contained in:
bastien
2026-09-27 20:17:36 +02:00
parent d28c45ed19
commit 2b25cb4704
4 changed files with 439 additions and 10 deletions
+34 -7
View File
@@ -71,7 +71,28 @@ You may re-run a `CHECK:` yourself to settle a doubt (Bash is read-only, and
these commands are observation). You may NOT edit the contract — an evidence
line you disagree with is reported, never rewritten.
## STEP 3 — SCOPE CHECK
## STEP 3 — FLOOR GUARD (mandatory, deterministic)
Run the floor guard over the diff before rendering any verdict — a red or
skipped run here is a structural gap, never a judgment call:
```bash
bash ~/.claude/lib/floor-guard.sh <base> -- <pathspec>...
```
`<base>` = the branch's gitflow base (develop; main for a hotfix/release).
Parse the single `FLOOR GUARD:` line:
- `clean` (rc 0) → no finding, continue to STEP 4.
- `<n> finding(s), <m> waived` (rc 2) → each `FLOOR <KIND> <file>:<line>
<snippet>` line is a gap for STEP 5's `ECARTS` count, UNLESS the
contract's `CLARIFICATIONS` explicitly authorizes that exact weakening —
quote the authorizing sentence in the verdict instead of counting it as a
gap. `WAIVED` lines are informational only, never a gap.
- rc 3 (usage error) → a structural failure like a missing contract: retry
once (base ref or pathspec likely wrong), a second failure escalates.
## STEP 4 — SCOPE CHECK
List the files actually touched (`git diff --name-only` over `DIFF`).
Compare against the contract's `FILE SCOPE`. Report every out-of-scope
@@ -79,7 +100,7 @@ file. Disposition is NOT your call: the orchestrator treats each one as a
gap — the dev removes it or justifies it, and an accepted justification
only enters the contract through a human micro-gate.
## STEP 4 — VERDICT
## STEP 5 — VERDICT
Read the contract's `ABANDON:` lines. An abandoned criterion is `ABANDONED`
— never `MET`, never counted as a gap the dev can close.
@@ -89,11 +110,12 @@ is not:
1. `ERROR(<reason>)` — the contract is missing or unreadable.
2. `ECARTS(n)` — n = count(NOT-MET) + count(UNVERIFIABLE) + count(out-of-scope
files). Surface any abandonment in the same report.
files) + count(unauthorized FLOOR findings from STEP 3). Surface any
abandonment in the same report.
3. `ABANDONED(n)` — zero gaps remain, but n abandonments stand. This is NOT
a pass and NOT a dev loop: it routes straight to the human gate.
4. `CONFORME` — ALL criteria `MET`, zero out-of-scope files, zero
abandonments.
unauthorized FLOOR findings, zero abandonments.
## OUTPUT (exact format — machine-parsed by the orchestrator)
@@ -106,6 +128,8 @@ CRITERIA:
3. <criterion> — UNVERIFIABLE — <reason>
4. <criterion> — ABANDONED — <the reason recorded in the contract>
SCOPE: in-scope <n> files; out-of-scope: <list | none>
FLOOR: clean | <n> finding(s) (<m> waived) — <FLOOR lines, or the
CLARIFICATIONS sentence that authorizes each one | none>
PROOF: read <n> files, ran <cmd → result | nothing>, checked <n>/<n> criteria
```
@@ -123,6 +147,9 @@ PROOF: read <n> files, ran <cmd → result | nothing>, checked <n>/<n> criteria
- `PROOF` is MANDATORY. A `CONFORME` without a `PROOF` line is invalid —
the orchestrator discards it as a structural failure (LRN-048: a pass
must prove it looked).
- STEP 3's floor-guard run is MANDATORY, every dispatch. A `CONFORME` or
`ECARTS` without a `FLOOR` line is a structural failure just like a
missing `PROOF` — the run was skipped, not the diff clean.
- The verdict grammar is load-bearing: exactly one `VERIFY — VERDICT:`
line, spelled exactly as above.
@@ -145,8 +172,8 @@ loop, never here):
lifts the abandonment (the criterion was fixable after all) or accepts
the partial delivery; the run is never reported as fully complete.
- Structural failure (`ERROR(…)`, missing/duplicated VERDICT line,
unparsable output, agent crash, `CONFORME` without `PROOF`) → retry
ONCE with a fresh verifier; a 2nd structural failure → human
escalation. A mute verifier is NEVER a PASS.
unparsable output, agent crash, `CONFORME` without `PROOF` or without
`FLOOR`) → retry ONCE with a fresh verifier; a 2nd structural failure →
human escalation. A mute verifier is NEVER a PASS.
- After a security-gate fix round: re-verify the request FIRST (this
agent), THEN re-verify security — in that order.