09 — Phantom / Orphan Governance Alignment (Đ31 / Đ19) + Law-Patch Outline
09 — Phantom / Orphan Governance Alignment (Branch I)
Sources: Đ31 System Integrity Law v1.2, Đ29 §V (fn_registry_health), Đ19 Orphan Scanner, live system_issues classes.
1. Is phantom a local Registries concept or a system-wide health concept?
System-wide health concept. It is the symmetric counterpart of orphan (orphan = substrate exists, no registry record; phantom = registry record exists, no/insufficient substrate). It must NOT be defined locally in Registries-Pivot. Đ29 §V already auto-detects one phantom flavour via fn_registry_health() ("nơi chứa vs nơi sinh" per collection). The Registries-Pivot framing (record_count > actual_count) is a candidate signal, not a definition.
2. Which law should define it?
LAW_DEFINITION_GAP — currently none. "Phantom" does not appear in enacted Đ24/Đ26/Đ28/Đ31. Best home: a clause in Đ31 (System Integrity) — it already owns orphan, drift, and the issue_class taxonomy — or a joint Đ26/Đ31 clause (count-integrity side). Recommend Đ31 (GOV-SIV's law).
3. Which governance owner should approve it?
Definition (law clause) → GOV-COUNCIL via council_review (doc_level 1-2 / amend). Detection/operation → GOV-SIV under the new clause. This is exactly the prior "RG4 council decision" routing — correct, central.
4. How should source_model-aware definitions be managed?
The prior work proved phantom is NOT uniformly record > actual:
- model-A (write-race): record momentarily > actual because births tick faster than the actual recount (e.g. CAT-023 birth_registry) → NOT phantom, it is staleness.
- model-B (substrate-absent): registry row whose substrate is a file/object that no longer exists (e.g. CAT-006 dot file:line) → phantom candidate.
The law clause must define phantom per source_model (a
source_modeldiscriminator already conceptually exists in the design). Detection compares stored-vs-LIVE-pivot, not stored-vs-stored (which is blind when both are stale).
5. How should phantom findings enter system_issues / event_outbox?
Reuse: today phantom appears only as apr_phantom_applied (null issue_class). Additive (Đ45 register-before-emit, approval-gated): new issue_types phantom_candidate, phantom_confirmed (issue_class e.g. integrity_fault); new event_types count_integrity.phantom_detected / .cleared. NO new table.
6. What is the cleanup workflow authority?
A phantom is never auto-cleaned by the scanner (Đ31 "phát hiện TRƯỚC, fix SAU"; Đ23 separation-of-powers "1 LÀM, 1 KIỂM TRA, 1 GIÁM SÁT"). Cleanup = a separate governed action: an approval_requests (retire/reclassify) → Đ32 → B-tier DOT removes/repairs. Authority: GOV-COUNCIL/SIV; execution: GOV-DOT.
7. Who can mark something as phantom?
Only an A-tier audit DOT (GOV-SIV) raising a phantom_candidate issue; confirmation to phantom_confirmed requires either the source_model rule firing deterministically or an approval (for ambiguous cases). No human/agent hand-marks via SQL.
8. What prevents false positives?
(a) source_model-aware definition (model-A excluded); (b) Đ31 2-pass verify with grace_seconds (default 60s) for drift/race; (c) compare-vs-live-pivot not vs-stale-stored; (d) leaf-scoped invariant (no rollup double-count). These four together suppress the write-race false positives the prior macros observed.
9. Is orphan already defined sufficiently?
Yes. Orphan is live and governed: Đ19 (Orphan Scanner / Side B), Đ23 (Inverse-Check), Đ29 §V, Đ31 (vector orphan CRITICAL). Live scanners fn_refresh_orphan_col/_dot/_species + fn_birth_onboarding_full_scan + check_registry_coverage → meta_catalog.orphan_count; issues land in system_issues halves thiếu_quan_hệ/thiếu_mã_định_danh (615) + orphan_file (167). No new orphan machinery needed.
10. How should orphan scanner results be governed?
They already are: read-only detection (no approval to raise), Đ31 contract + watchdog, results to system_issues. Acting on an orphan (birth-register or retire) = Đ32 approval (birth_orphan/retire) — which is exactly what the 143 applied birth_orphan requests did (machine auto-apply for low-risk births). Disposition: REUSE.
Proposed LAW PATCH OUTLINE (outline only — NO enactment, NO self-approval)
Status: DRAFT FOR COUNCIL. Author-mode only. Must be enacted via Đ32
council_review(doc_level 1-2) by GOV-COUNCIL + minuted togovernance_audit_log. This audit does NOT enact.
Patch P1 — Đ31 §(new) "Phantom Definition (source_model-aware)"
- Define phantom = a registry/pivot record whose governed substrate is absent, evaluated against the live pivot, per source_model: model-A (write-race) ⇒ NOT phantom (staleness, drift path); model-B (substrate-absent) ⇒ phantom candidate.
- Mandate: detection by A-tier audit DOT only; 2-pass grace verify; leaf-scoped; false-positive guards (4 above).
- Add
meta_catalog.phantom_countcolumn (additive) + promote pivot PIV-302 (DEFER until enacted). - Register issue_types
phantom_candidate/phantom_confirmed+ event_typescount_integrity.phantom_detected/cleared.
Patch P2 — Đ24/Đ29 §(new) "Ungrouped Display Ceiling"
- Define a per-species/per-list MAX ungrouped ceiling (a CEILING, not a target; pagination ≠ grouping). Stored as a reference table (Đ24 INSERT pattern), default 50, smaller allowed. Exceed → emit
CLASSIFICATION_REQUIRED. - Owner: classification domain (GOV-COUNCIL). NO hardcoded 50 in code.
Patch P3 — Đ37/Đ32 §(new) "Object-level governance ownership" (optional, system-wide)
- Either widen
governance_relations.target_typeCHECK to allowcollection/pivot/object(relational ownership edges), OR formally declare that domain-ownership (governance_registry.domain+law_jurisdiction) is the canonical object-binding. Pick ONE, apply system-wide.
Patch P-DRIFT — reconcile enacted Đ37 v3.3 ↔ live schema
- Align column/CHECK vocabulary (
gov_typevstype,created_by_lawvsgoverning_law, relation_type set, enforcement_role set) and decide whether the livecapabilityJSON (can_create/must_not_own) is ratified into Đ37 or removed. This is a pre-existing drift, surfaced here.
Verdict
Orphan = fully central, REUSE. Phantom = correctly council-routed but blocked by a genuine LAW_DEFINITION_GAP + ISSUE_EVENT_GAP; it must be enacted (P1) before PIV-302/phantom_count/cleanup proceed. Threshold = LAW_GAP (P2). Neither phantom nor threshold should be defined locally in Registries-Pivot.