Skip to content

W2.B.3 — ComprehensionMismatch event with per-executor diff#53

Draft
TimothyVang wants to merge 2 commits into
feat/W2.B.2-comprehension-gatefrom
feat/W2.B.3-comprehension-mismatch-ledger
Draft

W2.B.3 — ComprehensionMismatch event with per-executor diff#53
TimothyVang wants to merge 2 commits into
feat/W2.B.2-comprehension-gatefrom
feat/W2.B.3-comprehension-mismatch-ledger

Conversation

@TimothyVang

Copy link
Copy Markdown
Owner

Summary

  • Adds Pydantic v2 schema ComprehensionMismatch (and submodel ExecutorEchoDiff) — the ledger payload for the comprehension_check event type.
  • comprehension_gate_node now builds a ComprehensionMismatch on the terminal-concede branch and stores its JSON dump in state["pending_ledger_entry"] for the downstream LedgerEmitter (W2.C.3) to write.
  • Every executor echo received is preserved verbatim — chain-of-custody per CLAUDE.md §9.
  • Schema enforces TZ-aware UTC timestamps (rejects naive datetimes per §3 forensic doctrine), disagreeing_keys min_length=1, and a Crockford-base32 ULID event_id.
  • New verdict/schemas/ulid.py is a ~25-line pure-stdlib ULID generator — avoids a python-ulid direct dep while satisfying ARCHITECTURE.md §5 LedgerEntry contract.
  • TDD: RED test(graph): RED — ComprehensionMismatch schema + gate emission [W2.B.3] → GREEN feat(ledger): ComprehensionMismatch event with per-executor diff [W2.B.3].

Test plan

  • pytest tests/graph/test_comprehension_mismatch.py -v — 7 passed.
  • pytest tests/graph/ -v — 25 passed.
  • ruff check — clean.

Base

This PR targets feat/W2.B.2-comprehension-gate.

TimothyVang added 2 commits May 2, 2026 08:40
Adds tests/graph/test_comprehension_mismatch.py asserting the W2.B.3
contract:

- ComprehensionMismatch Pydantic v2 model in
  verdict.schemas.comprehension_mismatch with fields
  case_id / clarify_iterations_spent / disagreeing_keys / per_executor
  / event_id (ULID) / event_type=\"comprehension_check\" / timestamp_utc
  (TZ-aware required, naive rejected per CLAUDE.md §3 forensic
  doctrine);
- ExecutorEchoDiff submodel preserving each branch's parsed_*
  values verbatim for forensic auditability;
- empty disagreeing_keys is a contradiction in terms — rejected;
- comprehension_gate_node populates state[\"pending_ledger_entry\"]
  with a structured ComprehensionMismatch payload only on the
  terminal-concede branch (after MAX_CLARIFY_ITERATIONS rounds), not
  on intermediate clarify rounds;
- 4-way-consensus path emits NO ledger entry.

RED: ModuleNotFoundError on verdict.schemas.comprehension_mismatch.
GREEN follows.
…B.3]

Adds the ledger payload schema for the comprehension_check event type
emitted when comprehension_gate concedes after MAX_CLARIFY_ITERATIONS
rounds of persistent executor disagreement.

Files:
- verdict/schemas/comprehension_mismatch.py — Pydantic v2 model
  ComprehensionMismatch (event_id ULID + UTC-Z timestamp + case_id +
  clarify_iterations_spent + disagreeing_keys >=1 + per_executor list
  of ExecutorEchoDiff). The TZ-aware timestamp validator rejects naive
  datetimes per CLAUDE.md §3 forensic doctrine; the JSON serializer
  emits the canonical Z suffix the SANS examiner format expects.
- verdict/schemas/ulid.py — minimal pure-Python ULID generator
  (10-char Crockford-base32 timestamp + 16-char randomness, 26 chars
  total). Avoids a python-ulid direct dep; license-clean per §3.8.
- verdict/graph/nodes.py — comprehension_gate_node now builds a
  ComprehensionMismatch on the terminal-concede branch and stores its
  model_dump(mode=\"json\") in state[\"pending_ledger_entry\"] for the
  downstream LedgerEmitter (W2.C.3). Every echo received is preserved
  verbatim — chain-of-custody per CLAUDE.md §9. Empty/malformed echo
  cases populate placeholder ExecutorEchoDiffs rather than dropping
  them silently (ARCHITECTURE.md §1 empty-set rule).
- tests/graph/test_comprehension_mismatch.py — schema round-trip,
  naive-tz rejection, ULID shape, gate-emits-on-concede, gate-omits-
  on-consensus, gate-omits-during-clarify.

Tests: 25 passed (W2.B.1 + W2.B.2 + W2.B.3).
Ruff: clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant