dot-iu-cutter v0.4 — Schema-Binding Risk & Code-Change Plan (2026-05-17)
dot-iu-cutter v0.4 — Schema-Binding Risk & Code-Change Plan
Date: 2026-05-17 · DESIGN ONLY (no code/commit/dry-run/provision). Defines the bounded code-change surface for the next GPT-gated cycle and the risk register. Nothing here is executed or committed.
1. Code-change surface (for the future "v0.4 LedgerWriter schema-binding CODE" cycle — NOT this phase)
Strictly scoped, additive-in-spirit (no behaviour/flow change, only row-payload binding):
| File | Change | Notes |
|---|---|---|
cutter_agent/ledger.py |
Rebind 9 row-builders: append_history, append_sweep_log, write_manifest_envelope, write_manifest_unit_block, write_review_decision, write_signature, write_cut_change_set, write_affected_row, write_verify_result |
Method signatures/callers unchanged where possible; only the emitted row dict maps to deployed columns per per-writer-mapping-design |
cutter_agent/ledger.py (or new cutter_agent/schema_binding.py) |
Add binding constants/derivations (TOOL_REV, lane→signature_kind, sentinels SB-DEC-3/4, jsonb defaults) | Prefer a small dedicated module so the mapping is reviewable in isolation |
cutter_agent/phases.py |
Thread render_order enumerate index (SB-DEC-5) into write_manifest_unit_block; thread review_decision_id into CUT and manifest_id/review_decision_id into VERIFY (SB-DEC-6); replace InMemory _source_entry virtual filter with the real-schema source_doc_ref join (SB-DEC-1) |
Small, local; flow/guards/state-machine untouched |
tests/ |
Add static schema-contract fixture + per-writer contract tests; update InMemory-fixture row-key assertions whose shape changed | Per pg-backed-test-revision-plan |
cutter_agent/db_adapter.py |
No change | Adapter is correct; _EXEC/_VERIFY_INSERT_TABLES, routing, isolation, append-only guards all already align to deployed table names |
state_machine.py, idempotency.py, canonicalization.py, signing.py, signal.py, cli.py |
No change | Vocabulary/contracts already compatible |
Not in scope (forbidden / unnecessary): any cutter_governance DDL/migration; any GRANT/role change; any new DELETE/TRUNCATE/DDL surface; any production connection; any change to phase order, principal routing, or isolation; ProductionDBAdapter refusal stays verbatim.
2. Schema migration assessment — NOT needed
Every deployed NOT-NULL-without-default column is fillable from a deterministic, semantically-correct in-process source (state vocabulary, principal/lane/tool constants, clock) or absorbed by an existing jsonb column. No runtime semantic is unrepresentable in the deployed schema (it is a strict superset). Constraint C honoured: migration only if a blocker proves the schema cannot represent required semantics — no such blocker found. (If, during the code cycle, a concrete value is found genuinely underivable, that is a new blocker → STOP + report, not a unilateral migration.)
3. Risk register
| ID | Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|---|
| R1 | A deployed NN column's intended semantic is mis-guessed by a constant (e.g. operation_kind, governance_event_kind) |
Med | Med | Mappings are explicit & GPT-reviewed here before code; values are conservative/neutral; contract test asserts presence, GPT asserts correctness |
| R2 | Rebinding silently changes a row count (breaks r3) | Low | High | Design proves count-invariance (binding is column-level); per-writer-mapping + binding-plan §2; contract tests don't add writes; r3 re-verified by the dry-run itself |
| R3 | FK ordering violation inside a phase | Low | High | Intra-phase order pinned (binding-plan §1); FK graph captured from live catalog |
| R4 | UNIQUE collision on cut_change_set.rollback_key/idempotency_key |
Low | Med | Deterministic keys derived from entry_id/change_set_id; single-entry canonical fixture ⇒ no collision; replay converges (23505→RESUME by design) |
| R5 | Test false-negative (string DDL compare, grep -c, schema-qualified names) | Med | Med | Contract test uses set-equality on column-name sets, integer counts via captured ints — explicitly the project's anti-FN discipline |
| R6 | Scope creep into a schema redesign | Low | High | Hard scope table §1; migration forbidden absent a proven representability blocker; GPT-gated cycle boundary |
| R7 | Lineage join (SB-DEC-1) wrong on re-review (out-of-canonical) | Low | Low | Canonical path has no prior (empty join, identical behaviour); re-review explicitly out of canonical scope; covered by a dedicated test |
| R8 | _Secret/redaction or no-prod invariants disturbed by edits |
Low | High | Edits are row-payload only; db_adapter.py untouched; redaction/no-DSN/no-.env invariants unaffected; security-boundary tests retained |
Residual risk class: STANDARD (bounded, column-level, no migration, GPT-gated, count-invariant, strong test net).
4. Code-authoring "r2"? — terminology
GPT asked "whether code authoring r2 is needed". The accepted code is r1 (56d3732, FINAL CODE PASS). The schema binding requires a new code-authoring cycle (call it the LedgerWriter schema-binding code cycle; "r2" of the cutter-agent code). Yes — a code-authoring cycle is required, scoped to §1, GPT-gated (design→code→evidence→GPT PASS), producing a new scoped commit. It is not authored in this design phase.
5. Verdict (this doc)
- Code-authoring cycle: REQUIRED, surface = §1 (≈2 modules + tests;
db_adapter.pyuntouched). - Schema migration: NOT required.
- PG-backed dry-run: resumes after the code cycle PASSes, using command-review r1 + verification-plan r3 unchanged.
- Residual risk: STANDARD. No production write, no migration, count-invariant.