KB-1C1A
18000x · 02 — Template Versioning Gap Matrix (9 LIVE_READY + 10 GAPs G1..G10; sidecar > column-add)
5 min read Revision 1
iu-corev0.618000xgap-matrixtemplate-versioningsidecar-designlive-discovery
18000x · 02 — Template Versioning Gap Matrix
Method
Live discovery first (per 12000x L1 / 15000x L1 lessons). Surveyed:
pg_procforfn_iu_*template*/fn_iu_*version*information_schema.tablesfor*template*/*version*/*registry*iu_piece_collection.collection_keyfor version suffix patterns (/v1,/v2)iu_collection_template_registrycolumns (mig 031) for version fields
Live findings
Already LIVE_READY (no work needed)
| Capability | Lives where |
|---|---|
| Template marker | iu_collection_template_registry (mig 031) |
| Template→instance lineage | iu_collection_template_instance_lineage (mig 031) |
| Template registry view | v_iu_product_template (mig 031) |
| Template instance view | v_iu_product_template_instance (mig 031) |
| Template register DOT | dot_iu_register_template (15000x) |
| Lineage record DOT | dot_iu_record_template_instance (15000x) |
| Template+Instance mechanism | fn_iu_compose iu_id-reuse branch (12000x Phase F) |
| Text-as-code roundtrip | cutter_agent/iu_core/text_as_code.py (12000x) |
| Manifest digest invariant | fn_iu_collection_manifest_refresh (mig 015) |
GAPs to close in 18000x
| # | Gap | Severity | Resolution |
|---|---|---|---|
| G1 | No durable version chain (predecessor pointer + family identity) | High | Migration 032 sidecar iu_collection_template_version |
| G2 | No queryable version chain view | Med | v_iu_template_version_chain |
| G3 | No register-version DOT | High | dot_iu_register_template_version + fn_iu_collection_register_template_version |
| G4 | No retire-version DOT | Med | dot_iu_retire_template_version + fn_iu_collection_retire_template_version |
| G5 | No cross-template observability view consolidating template + version + instance + digest signals | High | v_iu_template_observability |
| G6 | No template mutation invariant policy documented | Med | 05-mutation-invariants-proof.md |
| G7 | No bulk instance generation at scale > 1 | Med | ops/.../iu_core_18000x_bulk_instances.sql (3 instances) |
| G8 | No bulk text-as-code export driver | Med | cutter_agent/iu_core/bulk_template_export_18000x.py |
| G9 | No internal LIVE event proof (only dry-run at 15000x) | Med | ops/.../iu_core_18000x_piece_event_live_proof.sql (BEGIN/ROLLBACK) |
| G10 | No auto-instantiate-from-event mechanism shown | Med | ops/.../iu_core_18000x_auto_instantiate_proof.sql (sandbox) |
Carry-forward (NOT productized in 18000x, intentional)
| Item | Why deferred | Next macro |
|---|---|---|
| Live (durable) non-dry-run external delivery | Requires external worker beyond constitution scope | ≥19000x |
| Auto-instantiate daemon/cron | Constitution explicitly forbids; sandbox proof only | ≥19000x |
| Template piece mutation propagation policy code | Documented as invariant; mechanism is explicit v(N+1) compose | 19000x |
| Retention enable | Requires 30-day soak per L1 carry-forward | ≥17000x (operator) |
| PR #669 merge / Nuxt deploy | External owners | external |
| Birth-gate PILOT noise (P-pub1/P-pub2 warnings) | Carry-forward from 15000x — noise only, not failures | ≥19000x |
File template (tpl:file:status-report/v1) version chain enrolment |
Single-version family; operator-opt-in via dot_iu_register_template_version when v2 ships |
19000x |
Design decision — sidecar over column-add (per 15000x L1)
| Option | Pros | Cons |
|---|---|---|
A — extend iu_collection_template_registry with template_family/version_seq/previous_collection_id |
Single-table query for versioning | Forces NULL for the 2 existing 15000x rows; leaks versioning concerns into the "is_template" marker; harder rollback when rows exist |
B — new sidecar iu_collection_template_version |
Zero blast radius on 031; clean FK chain mig 031 → mig 032; per-table rollback boundary | Two-table query — mitigated by views |
Decision: B (sidecar). Migration 032.
Validation
After migration 032: runtime/110 D9 PASS at 174 (28+28+63+6+12+21+16). D8_unregistered = 0 rows. R280 PASS at 24 catalog rows, all_resolvable = t.