From 6617889b77a960c58641cd098cf90fa3a7e04722 Mon Sep 17 00:00:00 2001 From: bastien Date: Sun, 27 Sep 2026 21:20:36 +0200 Subject: [PATCH] feat(verifier): floor-guard waivers outside test files need a CLARIFICATIONS ack Security-gate MEDIUM: a self-service floor-guard: allow neutralised the detector in the same commit. User chose strict: the tool prints WAIVED, the contract authorizes, the verifier counts the rest as gaps. BDR-102 amendment. --- CHANGELOG.md | 5 ++++- agents/verifier.md | 9 +++++++-- lib/verify-secure-loop.md | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3befa5c..a251540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,10 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). `floor-guard: allow ` waiver, rc 0/2/3. Mandatory verifier STEP 3 (`agents/verifier.md`), documented under GATE 1 of `lib/verify-secure-loop.md`. Suite `lib/tests/floor-guard.test.sh`: 6 - kinds plus a WAIVED and a CLEAN fixture, each flip-tested. Adapted from agent-skills `constraint-driven-development`. + kinds plus a WAIVED and a CLEAN fixture, each flip-tested. Waivers + outside test files count as gaps unless the contract's CLARIFICATIONS + names them (security-gate MEDIUM, user chose strict). Adapted from + agent-skills `constraint-driven-development`. - **`lib/tests/skill-routing-census.test.sh`** (+ `lib/skill-routing-census.py`) — TF-IDF cosine census of skill-description collisions across the live catalog (routing ambiguity, not naming): top 10 pairs, WARN ≥ 0.50, diff --git a/agents/verifier.md b/agents/verifier.md index a2bd752..c9cdc2d 100644 --- a/agents/verifier.md +++ b/agents/verifier.md @@ -83,12 +83,17 @@ bash ~/.claude/lib/floor-guard.sh -- ... `` = 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. +- `clean` (rc 0) → no unwaived finding; still apply the WAIVED rule below. - ` finding(s), waived` (rc 2) → each `FLOOR : ` 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. + gap. +- `WAIVED :` lines (either rc): on a test file (path + holds `test`, `spec` or `__tests__`) they are informational. Anywhere + else the waiver is self-service by construction, so it is a gap UNLESS + the contract's `CLARIFICATIONS` names that file and the reason — quote + it. The tool prints, the contract authorizes, the verifier counts. - rc 3 (usage error) → a structural failure like a missing contract: retry once (base ref or pathspec likely wrong), a second failure escalates. diff --git a/lib/verify-secure-loop.md b/lib/verify-secure-loop.md index 0e983c5..5bb4fd1 100644 --- a/lib/verify-secure-loop.md +++ b/lib/verify-secure-loop.md @@ -63,7 +63,9 @@ coverage threshold) that an LLM verdict alone can miss or be talked past one line at a time. Its findings fold straight into that same verifier's `ECARTS` count unless the contract's `CLARIFICATIONS` explicitly authorizes the exact weakening; there is no separate gate and no extra dispatch, it -rides this GATE 1 call. +rides this GATE 1 call. A `floor-guard: allow` waiver outside a test file +is a finding too unless the contract's `CLARIFICATIONS` names it: the +waiver is self-service, the contract is human-gated (BDR-102 amendment). Parse its single `VERIFY — VERDICT:` line: