KB-1B8B
O8F implement F2/F3/GAP6 deploy+proof — 04-f3-legb-verify-generalization-result
4 min read Revision 1
dieu44iu-cutterv0.6o8ff3generalizationgovernance-writers
O8F Report 04 — F3 LegB/Verify generalization result (G3)
- macro:
v0.6-o8f-implement-f2-f3-gap6-deploy-proof - date_utc: 2026-05-21 · gate: G3 — implement F3 · result: G3 PASS — F3 CLOSED
1. Realisation decision — new module, v0.5 files frozen
The v0.5-ratified ledger_v2_canonical_cut.py / ledger_v2_canonical_verify.py
recorders are left byte-identical. F3 is delivered as a NEW generic-path
module — cutter_agent/orchestrator/governance_writers.py. This:
- preserves the M1
writer_digestregression (d99a31d4…) trivially — the frozen files cannot drift; - keeps the change strictly inside v0.6 authoring scope — no widening of the v0.5 ratification is required;
- satisfies G3 literally: the generic path carries no hard N=60, while the Constitution-specific constants stay in the frozen v0.5 namespace.
2. governance_writers.py — GenericLegBRecorder / GenericVerifyRecorder
candidate count: driven off live_state["candidate_count"] — any positive N
section histogram: live_state["expected_section_type"] / ["section_type_
cardinality"] — a per-document dict that must sum to N
match-count key: "body_hash_match_count" (the v0.5 "body_hash_match_60"
literal is gone from the generic path)
identity ids: shape-validated as UUIDs (_is_uuid), NOT equality-to-M1
payload_hash: computed from the per-run canonical envelope
row shapes: identical to the live cutter_governance schema (8 leg-B
tables + 2 verify tables) — same column sets as v0.5
once-only: GenericLegBAlreadyRecorded / GenericVerifyAlreadyRecorded
make_governance_writer / make_verify_writer:
(conn, ctx)->dict collaborators for the live adapter's
governance_writer / verify_writer seam.
3. Tests — tests/test_orchestrator_o8f_f3_generic_recorders.py (27 PASS)
T2 generic N: N=3, N=137 accepted; record() N=5 -> 16 inserts
T3 histogram: arbitrary histogram accepted; non-summing rejected;
section_type outside histogram rejected; payload_hash
deterministic + distinct per document
T4 identity: fresh-UUID change_set accepted; non-UUID rejected;
equal tool revisions rejected (SoD)
T5 idempotency: re-record -> GenericLegB/VerifyAlreadyRecorded
T6 fail-closed: missing key / wrong list length / zero count / address
outside doc_prefix all rejected
no-hard-60: module has no PIN_CANDIDATE_COUNT / no "60" literal
T1 anchor: v0.5 recorders still frozen (PIN_CANDIDATE_COUNT==60,
PIN_M1_CHANGE_SET_ID, EXPECTED_SECTION_TYPE intact)
factories: make_governance_writer / make_verify_writer drive the
generic recorders end-to-end
The M1 writer_digest d99a31d4a4be907c510ae15965e9f7bb3387e9e28676e9f32adf463828b1aa28
is re-observed unchanged in the full VPS suite run (v0.5 recorder path).
4. Real-DB rollback-only proof (VPS — PROOF-2)
plan() (no DB): N=7 -> 7 manifest_unit_block + 7 affected_row;
N=60 -> 60 + 60 — generalisation handles non-60.
rollback-only DB: GenericLegBRecorder.record() ran inside a real cutter_exec
transaction — all 8 cutter_governance tables ACCEPTED the
generic INSERTs (status RECORDED, cut_change_set +1 in
txn) — then ROLLED BACK; cut_change_set count returned to
baseline. The real schema accepts the generic row set.
db_write: NONE — transaction rolled back; counts unchanged.
5. Verdict
f3_status: CLOSED — generic recorders built + 27 tests + real-DB
rollback-only proof; no hard N=60 in the generic path; v0.5
historical audit records preserved (frozen recorders untouched).
g3: PASS