10000x · 08 — Regression matrix + 4 lessons + carry-forward
10000x · 08 — Regression matrix + lessons
Regression matrix (live, post-apply)
| Surface | 9000x baseline | 10000x post | Δ | Status |
|---|---|---|---|---|
| information_unit row count | 163 | 163 | 0 | unchanged |
| iu_vector_sync_point | 152 | 152 | 0 | unchanged |
| iu_three_axis_envelope rows | 163 | 163 | 0 | unchanged |
| iu_split_set | (n/a) | 0 | new+0 | new ledger, never written |
| iu_merge_set | (n/a) | 0 | new+0 | new ledger, never written |
| event_type_registry rows (total) | 15 | 21 | +6 | piece.* seeded |
| dot_iu_command_catalog rows | 17 | 20 | +3 | supersede/split/merge |
| iu_core_iu_chunks Qdrant points | 149 | 149 | 0 | untouched |
| production_documents Qdrant coll | untouched | untouched | 0 | untouched |
| IU Core composer_enabled gate | false | false | 0 | inert |
| IU Core vector_sync_enabled gate | false | false | 0 | inert |
| IU Core delivery_enabled gate | false | false | 0 | inert |
| IU Core structure_ops_enabled gate | false | false | 0 | inert |
| IU Core operator_runtime_enabled gate | false | false | 0 | inert |
| IU Core retention_enabled gate | false | false | 0 | inert |
| iu_create.gateway.mode | enforced | enforced | 0 | unchanged |
| DIEU-28 S1 lifecycle_status | enacted | enacted | 0 | unchanged |
| Mac cron status | green | green | 0 | unchanged |
| PR #669 | open | open | 0 | unchanged (not merged) |
| pytest count | 1232 | 1305 | +73 | new 10000x test file + bumps |
| DOT scan D9 verdict | 7/7 t (146 obj) | 7/7 t (156 obj) | +10 obj | green |
| R280_catalog integrity | 17 / all_resolvable=t | 20 / all_resolvable=t | +3 | green |
All four mutation types are constitutionally reversible (tables drop, functions drop, event_type rows DELETE, catalog rows DELETE).
Lessons (added to memory)
Lesson 1 — cutter_governance.review_decision PK column
The PK is review_decision_id, NOT id. Live sandbox probe caught this in migrations 027/028 before commit:
ERROR: column "id" does not exist
WHERE id = p_review_decision_id
Fix: use WHERE review_decision_id = p_review_decision_id. The analogous cutter_governance.cut_change_set PK is change_set_id. Both were fixed in the same migration files and re-applied (CREATE OR REPLACE is idempotent).
General principle: never assume an id column on a foreign schema table; always run \d <schema>.<table> live before writing the FK probe. The previous macro's pattern in fn_iu_supersede (mig 026) correctly uses review_decision_id — I should have started by matching that pattern instead of writing from memory.
Lesson 2 — dot_iu_command_catalog.target_functions is fn names only
The R280 integrity check probes each target_functions entry against pg_proc.public. Including a table name (e.g. iu_split_set) makes the probe fail with all_resolvable=false. The catalog's target_functions column is named *_functions for a reason — it's a strict pg_proc reference, not a free-form related-objects list.
Fix: dropped iu_split_set / iu_merge_set from the catalog rows; kept only function names.
Lesson 3 — Pre-existing pinning tests need per-macro bumps
12 tests across the suite literally pin counts like ('function',54), '17 governed commands', '146 objects total'. Each macro that bumps the surface must bump the corresponding test literals in the SAME commit, or the suite fails. This is intentional (it locks the catalog to the seed). Convention: each macro PR includes "bump pinning tests" as a regular line item.
Lesson 4 — app.canonical_writer GUC marker resets across function frames
fn_iu_piece_split calls fn_iu_create inside a loop. The GUC marker must be re-set BEFORE every fn_iu_create call (because the inner function changes it to 'fn_iu_create'), and re-set BACK to 'fn_iu_piece_split' after each call so the outer function's INSERT carries the right marker.
Pattern:
PERFORM set_config('app.canonical_writer', 'fn_iu_create', true);
v_create_result := public.fn_iu_create(...);
PERFORM set_config('app.canonical_writer', 'fn_iu_piece_split', true);
The third argument true makes the change LOCAL to the current TX.
Carry-forward
- (10500x?) Add
iu_piece_event_outboxtable + per-fn emit hooks. - (10600x?)
piece_event_handler.pyworker + 8th healthcheck surface. - (later) Optional write-proof of split/merge under explicit governance approval against a freshly minted SCRATCH IU.
- (later) Consider adding
iu_split_set/iu_merge_setas a related_tables column todot_iu_command_catalog(separate fromtarget_functions) so the catalog can express "this DOT touches these tables" without breaking R280.