dot-iu-cutter v0.4 — PG-backed Test Revision Plan (2026-05-17)
dot-iu-cutter v0.4 — PG-backed Test Revision Plan
Date: 2026-05-17 · DESIGN ONLY (no code/commit/test-run/dry-run/provision). Defines how the test suite and the PG-backed dry-run spec must change once the schema-binding code cycle lands. Constraint D.
1. Why the gap stayed latent (the test hole to close)
The accepted 92/92 unit suite drives the InMemory adapter (dict store) and injected fakes (FakeConn/FakeProvider); no test asserts the produced row's columns against the deployed cutter_governance contract. So LedgerWriter's abstract shape never met the real DDL until a PG-backed dry-run. The revision must add a schema-contract assertion that needs no live DB (stdlib-only, deterministic), plus keep the existing behavioural tests.
2. Unit-test revisions (stdlib only; no DB, no secret)
- Schema-contract fixture (new, static): a frozen, hand-maintained metadata table of the 12 deployed
cutter_governancetables — for each: column set, the NOT-NULL-without-default subset, PK, FK list, UNIQUE list — sourced from this design package's grounding (committed as test data, not read from a live DB at test time). One module, e.g.tests/_schema_contract_fixture.py. - Per-writer contract test (new): for each of the 9 rebinding writers, build the row via
LedgerWriteragainst an instrumented adapter that captures the emitted(table, column-set)and assert: (a) every emitted column ∈ deployed column set; (b) every deployed NOT-NULL-without-default column ∈ emitted columns (or has a deployed default); (c) no forbidden verb. This catches drift structurally without a DB and without the false-negative traps (no string compare of DDL; set-equality on column names). - MATCH writers (regression): add explicit assertions that
append_entry/cas_status/stamp_supersededalready satisfy the contract fixture (lock the 3 MATCH cases so a future change can't silently break them). - Lineage test (SB-DEC-1): assert the real-schema prior-review lookup (
manifest_id ⋈ envelope.source_doc_ref) returns empty for a first review (canonical) and the chained prior on a synthetic re-review — using the InMemory adapter seeded to mimic the deployed columns. - Existing behavioural tests: keep all current
test_phase_contracts/test_real_postgres_adapter/test_security_boundaries/test_state_machine/test_idempotency. Update only the InMemory fixtures whose row dicts change shape (e.g. assertions readingrow["to_state"]becomerow["entry_version_after"]), preserving each test's intent. Net suite count rises (new contract tests added); no test is weakened. - No-secret/no-DB guarantee retained: all new tests stdlib-only, no psycopg3 required, no
.env, no socket — consistent with the accepted suite's discipline.
3. PG-backed dry-run spec revision
- Row-count baseline: the binding is column-level only; it changes no per-phase row count (state-history-and-sweep-mapping-design §1.4/§2; mark-review-cut-verify-binding-plan §2). Therefore verification-plan r3 is preserved unchanged — final 15-row baseline (
decision_backlog_entry=1,decision_backlog_history=5,decision_backlog_dependency=0,decision_backlog_sweep_log=1,manifest_envelope=1,manifest_unit_block=1,review_decision=1,dot_pair_signature=2,cut_change_set=1,cut_change_set_affected_row=1,verify_result=1,canonical_address_alias=0). No r4 needed. - Gate catalogue: G-14…G-25 unchanged. One clarifying addition (optional, non-count): a new structural gate G-26 "deployed-column conformance" — after the run, assert each written row populated only deployed columns and every NN-no-default column is non-null (catalog/
information_schema-based, set-equality, false-negative-safe). This strengthens, does not alter, the verdict; it can be folded into G-15's per-table check. Decision deferred to the post-code command-review refresh (not required for resume). - command-review r1: unchanged (C-01…C-13, gates) — it already defers scenario detail to design-master §5 and counts to the verification plan.
- design-master r1: unchanged.
4. Negative/idempotency (Δ=0) — unchanged
S2/S3-neg/S8/S9/S10/S11 still assert Δ=0 on all 12 tables. The binding does not introduce new writes on the negative paths (fail-closed/rollback semantics are adapter-level, untouched). Idempotency S10: the deterministic cut_change_set.idempotency_key (SB-DEC-6) strengthens the 23505→IdempotencyResume path but does not change MARK replay dedup (which is payload_idempotency_key in phases.mark, unchanged) ⇒ S10 still Δ=0.
5. Verdict (this doc)
- Test revision required but bounded: 1 new static fixture + per-writer contract tests + targeted InMemory-fixture updates; behavioural coverage preserved; stdlib-only; no DB/secret.
- r3 row-count baseline preserved — no r4. Optional non-count G-26 conformance gate may be added at the post-code command-review refresh.
- PG-backed dry-run resumes after the code cycle PASSes, running command-review r1 + verification-plan r3 unchanged.