Built: 2026-05-06 | Source: /opt/agent/data/postmortems/260506_supervisor_design/ARCHITECTURE-FINAL.md
A deterministic evidence-gate that locks Brian's ability to claim done / fixed / shipped / blocked / "send me X" until verifiable evidence exists in an immutable ledger. Replaces the original Brian R1 LLM-judge proposal (which would have been bypassed semantically). All decisions are deterministic; LLMs only extract claims and classify intent.
Brian may populate task details, but only the harness may bind claims to validators, execute validators, store evidence artifacts, and decide whether a final response is allowed.
Every component below is in service of this sentence. Any future change that violates it is a regression.
Three R1 proposals, three R2 cross-study refinements, one R3 adversarial review.
- Codex R1+R2: evidence-gated state machine; locked final-response capability
- Gemini R1+R2: verify-then-voice loop; deterministic ledger over LLM judge
- Vibe R1+R2: hard interceptor; no prose regeneration; user-collusion audit
- Codex R3 (adversarial): 5 patches → trust boundary model + schema enforcement + raw artifacts + validator binding policy + scoped Day 1
Antigravity R1+R2: async IDE, did not return synchronously. Documented gap.
Jules: substrate mismatch (TUI not chat consultant). Documented; side-fixed jules-delegate.py hardcoded-timeout bug.
/root/.claude/hooks/brian-evidence-ledger.py — PostToolUse hook (per tool call → JSONL + raw artifact + hash chain)/root/.claude/hooks/brian-evidence-gate.py — Stop hook (extract claim phrases → check ledger → BLOCK if unsupported)/opt/agent/scripts/brian_validator.py — runner Brian invokes to assert evidence exists for a claim/root/.claude/system/policies/claim_binding.yaml — claim type → allowed validator classes + min-args policy/root/.claude/system/validators/command_zero_exit.yaml/root/.claude/system/validators/pytest_pass.yaml/root/.claude/system/validators/file_diff_present.yaml/root/.claude/system/validators/fetch_attempt_proof.yaml/root/.claude/system/validators/ladder_exhaustion_proof.yaml (Day 2 stub)/opt/agent/data/agent_runtime/ledger/<session_id>.jsonl — append-only, chain-hashed/opt/agent/data/agent_runtime/artifacts/<session_id>/<seq>/ — raw cmd + stdout + stderr + cwd + manifest* → brian-evidence-ledger.py (5s timeout)brian-evidence-gate.py (8s timeout)brian_validator.py --claim done --validator pytest_pass \
--args '{"target":"tests/test_x.py::test_y","required_runs":3}'
On PASS (exit 0): writes a VALIDATOR_PASS synthetic ledger entry. Subsequent Stop hook on a "done" message will pass.
On FAIL (exit 2): no entry written. Next "done" message gets BLOCKED.
On REFUSED (exit 3): wrong validator for claim, OR weak args — Brian must fix.
brian_validator.py --claim blocked --validator ladder_exhaustion_proof \
--args '{"turn_id":"<id>"}' # Day 2 only — not yet wired
brian_validator.py --claim delegation --validator fetch_attempt_proof \
--args '{"target_keyword":"linkedin_cookie","distinct_routes_attempted":3}'
The runner counts FAILED fetch-tool entries in the ledger matching the keyword.
python3 /tmp/test_evidence_gate.py # 10/10 pass at Day 1 lock
/tmp/test_validator_e2e.sh # 5 steps, ledger → validator → gate
| Asset | Brian | Harness | Jonah | Enforcement |
|---|---|---|---|---|
| Validator YAML | read-only | execute | author | chmod 0444 root:root ✓ |
| Claim-binding policy | read-only | execute | author | chmod 0444 root:root ✓ |
| Evidence ledger | NONE | append-only via hook | audit | hook is sole writer ✓ |
| Raw artifact store | NONE | write via hook | audit | hash-chained ✓ |
| Synthetic VALIDATOR_PASS | NONE | append via runner | audit | runner refuses weak args ✓ |
ladder_exhaustion_proof validator — needs contract loading. Day 2.http_2xx validator — Day 2.command_must_match_objective_keywords — needs contract context. Day 2.| Check | Status |
|---|---|
| settings.json is valid JSON | ✓ verified by python3 -c json.load |
| Both hooks wired into settings.json | ✓ verified by jq |
| Smoke test 10/10 pass (initial) | ✓ executed |
| E2E test 5/5 steps | ✓ executed |
| Validator YAMLs chmod 0444 root:root | ✓ ls -la |
| Hash chain verified across multi-entry ledger | ✓ chain_prev → chain_hash linked in step 1 of E2E |
_is_real_user_prompt skips tool_result entries labeled type:user)| # | File:Line | Defect | Fix |
|---|---|---|---|
| 1 | gate.py extraction-failure exit |
Silent-pass on extraction empty → BLOCK on >50KB transcripts with empty extraction (heuristic distinguishes legit "no text yet") | |
| 2 | gate.py first-claim-only |
find_claim_in_text → find_all_claims_in_text; collect ALL claims, check each, list all violations |
|
| 3 | gate.py unverified VALIDATOR_PASS |
HMAC-SHA256 signing in runner; gate _verify_hmac against /root/.claude/system/secrets/validator_hmac.key (chmod 0400 root) |
|
| 4 | ledger.py + validator.py seq race |
fcntl.flock(LOCK_EX) on per-session lock file LEDGER_ROOT/.{sid}.lock |
|
| 5 | Missing test coverage | Added B10 (multi-claim), B11 (forged VALIDATOR_PASS rejected), B12 (extraction-anomaly heuristic) |
| Suite | Cases | Pass |
|---|---|---|
/tmp/test_evidence_gate.py |
18 | 18/18 |
/tmp/test_validator_e2e.sh |
5 | 5/5 |
Live test in fresh CC session: gate fired correctly but CC sent the "Shipped" message anyway.
Root cause: hook emitted {"systemMessage": ...} which is non-blocking advisory. CC contract for force-regeneration is {"decision": "block", "reason": "..."}.
Fix applied:
- gate.py now emits {"decision":"block","reason":...} on both BLOCK paths (claim violation + extraction anomaly)
- Added stop_hook_active loop guard at top of main() per CC docs "Stop hook runs forever" footgun
- Test assertion strengthened to require BOTH decision:block in stdout AND BLOCK message in stderr
- New regression test P7 (loop guard) — stop_hook_active=True must exempt
| Suite | Cases | Pass |
|---|---|---|
/tmp/test_evidence_gate.py |
19 | 19/19 |
/tmp/test_validator_e2e.sh |
5 | 5/5 |
"Absence of an approved validator for the claimed scope is itself a blocking condition; Brian may report only attempted actions and uncertainty, not completion."