04 — Dynamic Parent Graph / Layer Wiring (rehearsed-clean)
04 — Dynamic Parent Graph / Layer Wiring
Result: REHEARSED-CLEAN, APPLY-READY (commit operator-gated)
The graph is made backend-resolvable by populating pivot_definitions.parent_code (an explicit data edge), NOT by registry_group naming convention (which §13 forbids as final backend logic).
The 13 edges (child → parent)
PIV-101 → PIV-001 (Danh mục theo Lớp → meta_catalog Total)
PIV-102 → PIV-001 (Danh mục theo Loại q.lý → meta_catalog Total)
PIV-106 → PIV-001 (Lớp × Loại quản lý → meta_catalog Total)
PIV-201 → PIV-101 (L2 Atom theo loài → theo Lớp)
PIV-202 → PIV-101 (L2 Molecule)
PIV-203 → PIV-101 (L2 Compound)
PIV-204 → PIV-101 (L2 Material)
PIV-205 → PIV-101 (L2 Product)
PIV-206 → PIV-101 (L2 Building)
PIV-104 → PIV-007 (DOT theo Nhóm → DOT Tools Total)
PIV-105 → PIV-009 (Collections theo P.loại → Collections Total)
PIV-103 → PIV-016 (Loài theo Lớp → Loài Total)
MTX-L2-ATOM → MTX-L1-OVERVIEW
Live BEGIN..ROLLBACK rehearsal (net 0 mutation)
pd_hash_before = 1e31696f3cb47d244c578bd9390ca56d (37 rows)
UPDATE 13 (fired trg_pivot_def_refresh; 607ms; clean)
roots 37 → 24 | children 0 → 13 | parents 0 → 6
dangling_edges = 0 | inactive_parent_edges = 0
v_registries_pivot_tree → hierarchy correct (PIV-001 has_children; PIV-101 has_children with 6 L2 kids; etc.)
ROLLBACK
pd_hash_after = 1e31696f3cb47d244c578bd9390ca56d ← identical ⇒ fully reversible
This matches the 05-31 overlay prediction (24/6/0) exactly, now proven on the current 37-row set.
Nodes intentionally left as roots (correct, not gaps)
The remaining ~24 roots are top-level registry totals (one per source_object: PIV-002..006, 008, 010..021, 207, 015, MTX-L1-OVERVIEW). They would sit under PIV-500 grand total — which is PIVOT_MISSING (doc 05). Until PIV-500 exists they are legitimately roots (each is an independent L1 registry total). PIV-207 (approval_requests, giám_sát) and PIV-014 (entity_dependencies, giám_sát) are monitoring totals — candidates for a future giám_sát parent, deferred (no count change needed now).
Why COMMIT is operator-gated (not a failure)
§6 says graph-metadata apply must "update only graph metadata, not count content." The parent_code UPDATE unavoidably fires trg_pivot_def_refresh → a full refresh_pivot_results() + refresh_meta_catalog_from_pivot() (count content). Therefore live commit requires owner acceptance of the count-refresh side-effect → operator step (doc 10). The refresh is the system's own routine, designed, idempotent behavior; the rehearsal proves it is transaction-safe and reversible.
Rollback (one statement)
UPDATE pivot_definitions SET parent_code = NULL
WHERE code IN ('PIV-101','PIV-102','PIV-106','PIV-201','PIV-202','PIV-203',
'PIV-204','PIV-205','PIV-206','PIV-104','PIV-105','PIV-103','MTX-L2-ATOM');