KB-1C9D

dot-iu-cutter v0.4 — PG-backed Test Revision Plan (2026-05-17)

6 min read Revision 1
dot-iu-cutterv0.4schema-bindingtest-revisiondieu44design

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)

  1. Schema-contract fixture (new, static): a frozen, hand-maintained metadata table of the 12 deployed cutter_governance tables — 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.
  2. Per-writer contract test (new): for each of the 9 rebinding writers, build the row via LedgerWriter against 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).
  3. MATCH writers (regression): add explicit assertions that append_entry/cas_status/stamp_superseded already satisfy the contract fixture (lock the 3 MATCH cases so a future change can't silently break them).
  4. 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.
  5. 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 reading row["to_state"] become row["entry_version_after"]), preserving each test's intent. Net suite count rises (new contract tests added); no test is weakened.
  6. 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.
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.4-schema-binding/dot-iu-cutter-v0.4-pg-backed-test-revision-plan-2026-05-17.md