Files
claude/lib/tests/contract-verifier.test.sh
T
Bastien ChanotandClaude Opus 4.8 6aed5eea8c feat(agents): contract interview include + verifier agent (verify-loops lot 2)
lib/contract-interview.md: mandatory upstream passage for all orchestrators.
Verbatim REQUEST (immutable), proportional questions (complete request =
zero, max 3 one batch), testable criteria + file scope, written to disk
immediately (.claude/tasks/contracts/<date>-<slug>-<HHMM>.md — a context-only
contract dies at compaction). Lifecycle: enrichment only at human gates
([gated] marker, scope micro-gate), supersedes for re-scope, aborted runs
deleted or committed status:aborted — never left dirty. Hand-off = path,
not restatement.

agents/verifier.md: fresh read-only verifier. Reads the contract from disk,
renders VERIFY — VERDICT: CONFORME | ECARTS(n) | ERROR. Blind: never
receives iteration history. PROOF line mandatory (LRN-048), UNVERIFIABLE
never MET, mute verifier never a PASS (retry once fresh, 2nd structural
failure = human escalation). Orchestrator protocol documented in-file
(max 3 iterations, re-verify request before security).

lib/tests/contract-verifier.test.sh: 31 deterministic structure locks on
the load-bearing doctrine clauses — green, shellcheck clean.

Behavioral dogfood (2 fresh subagents on a planted fixture): gap case →
ECARTS(2) exactly as planted (NOT-MET located + out-of-scope flagged);
conform case with injected fake iteration history → CONFORME, noise
ignored, real python spot-check as evidence. Both outputs parse-clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpphkdTosUzokBDNG7PToS
2026-07-03 18:50:28 +02:00

88 lines
3.7 KiB
Bash

#!/usr/bin/env bash
# ============================================================
# Structure locks — contract/verifier pair (verify-loops lot 2)
# Deterministic greps on load-bearing doctrine clauses: an edit
# that silently drops one (blind verifier, PROOF mandatory,
# immutable REQUEST, micro-gate scope enrichment…) reds here.
# ============================================================
set -u
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
LIB="$REPO/lib/contract-interview.md"
AGT="$REPO/agents/verifier.md"
PASS=0; FAIL=0
# Fixed-string lock (UTF-8 punctuation safe)
tf() { # tf <label> <file> <fixed-string>
if grep -qF -- "$3" "$2" 2>/dev/null; then
echo " PASS $1"; PASS=$((PASS+1))
else
echo " FAIL $1 — missing: $3"; FAIL=$((FAIL+1))
fi
}
# Regex lock
tr_() { # tr_ <label> <file> <ERE>
if grep -qE -- "$3" "$2" 2>/dev/null; then
echo " PASS $1"; PASS=$((PASS+1))
else
echo " FAIL $1 — no match: $3"; FAIL=$((FAIL+1))
fi
}
# Negative lock — pattern must NOT match
tn() { # tn <label> <file> <ERE>
if grep -qE -- "$3" "$2" 2>/dev/null; then
echo " FAIL $1 — forbidden match: $3"; FAIL=$((FAIL+1))
else
echo " PASS $1"; PASS=$((PASS+1))
fi
}
echo "── contract-interview.md locks ──"
if [ -f "$LIB" ]; then
echo " PASS lib exists"; PASS=$((PASS+1))
else
echo " FAIL lib missing: $LIB"; FAIL=$((FAIL+1))
fi
tf "verbatim request immutable" "$LIB" "REQUEST (verbatim — IMMUTABLE)"
tf "contracts dir committed path" "$LIB" ".claude/tasks/contracts/"
tf "unique per-run slug" "$LIB" "<YYYY-MM-DD>-<slug>-<HHMM>"
tf "silent when complete" "$LIB" "ZERO questions"
tf "question budget" "$LIB" "max 3 questions"
tf "aborted status" "$LIB" "status: aborted"
tf "never left dirty" "$LIB" "NEVER left dirty"
tf "scope enrichment micro-gate" "$LIB" "micro-gate"
tf "gated marker" "$LIB" "[gated <YYYY-MM-DD>]"
tf "main-loop only" "$LIB" "ORCHESTRATOR MAIN LOOP"
tf "re-scope supersedes" "$LIB" "supersedes:"
tf "hand-off = path not content" "$LIB" "contract PATH, not a restatement"
echo "── verifier.md locks ──"
if [ -f "$AGT" ]; then
echo " PASS agent exists"; PASS=$((PASS+1))
else
echo " FAIL agent missing: $AGT"; FAIL=$((FAIL+1))
fi
tr_ "frontmatter name" "$AGT" "^name: verifier$"
tr_ "tools read-only set" "$AGT" "^tools: Read, Grep, Glob, Bash$"
tn "no write-capable tools" "$AGT" "^tools:.*(Edit|Write|NotebookEdit)"
tf "verdict grammar" "$AGT" "VERIFY — VERDICT: CONFORME | ECARTS(n) | ERROR(<reason>)"
tf "blind — no iteration history" "$AGT" "NEVER receive iteration history"
tf "blind — complete every time" "$AGT" "every verification is complete and blind"
tf "unverifiable is not met" "$AGT" "\`UNVERIFIABLE\` ≠ \`MET\`"
tf "proof mandatory" "$AGT" "\`PROOF\` is MANDATORY"
tf "contract read from disk" "$AGT" "READ it from disk"
tf "checked count equality" "$AGT" "checked count in"
tf "report-only" "$AGT" "Report-only. Never edit"
tf "bash observation only" "$AGT" "OBSERVATION ONLY"
tf "loop bound" "$AGT" "Max 3 iterations"
tf "structural retry then escalate" "$AGT" "2nd structural failure"
tf "mute never a pass" "$AGT" "A mute verifier is NEVER a PASS"
tf "conforme first pass no loop" "$AGT" "proceed straight to the security gate"
tf "reverify order request first" "$AGT" "re-verify the request FIRST"
echo ""
echo "contract-verifier structure locks: $PASS pass, $FAIL fail"
[ "$FAIL" -eq 0 ]