KB-7DD9

06 — Orphan / Phantom / Unmanaged / Unmonitored / Ghost Policy

5 min read Revision 1
designregistries-pivotorphanphantomunmonitoredghostscannerdieu19dieu23dieu26law-definition-gap2026-05-31

title: 06 — Orphan / Phantom / Unmanaged / Unmonitored / Ghost Policy date: 2026-05-31

06 — Orphan / Phantom / Unmanaged Policy

Each concept: definition · detection · pivot dimension · severity · cleanup trigger · notification target. Reuse existing law where found; mark LAW_DEFINITION_GAP where not.

1. ORPHAN — real object, not visible/governed

  • Def: Đ26 v3.9 / Đ19 — missing birth record OR missing the minimum required relationship set. Two live system_issues halves: thiếu_mã_định_danh (missing ID), thiếu_quan_hệ (missing relations).
  • Detection: fn_birth_onboarding_full_scan (Side B) + fn_refresh_orphan_col/_dot/_speciesmeta_catalog.orphan_count (live Σ=161; CAT-DOT 140, CAT-COL 20, CAT-SPE 1).
  • Pivot dim: by composition_level & species. PIVOT_MISSING: PIV-30x orphan total.
  • Severity: HIGH (Đ23). Cleanup: birth/registration (Side A). Notify: system_issues('thiếu_quan_hệ'|'thiếu_mã_định_danh').

2. PHANTOM — counted/displayed, but no real object ⚠️ LAW_DEFINITION_GAP

  • Status: no phantom law article. De-facto: system_issues('apr_phantom_applied') (1) + the frontend-injected CAT-PHA (=7) computed by gap-math in health.get.ts (an Đ28 violation, not a SoT count).
  • Proposed operational def (PROPOSE): a phantom is a counted unit with no backing real row — record_count > actual_count (the surplus = phantom). Inverse of orphan.
  • Detection: record_count − actual_count where positive, per leaf; live phantom-side rows = 7. No phantom_count column → propose add (doc 05).
  • Pivot dim: composition_level/species. PIVOT_MISSING: PIV-30x phantom. Severity: HIGH (a phantom = a number that lies). Cleanup: recount (refresh_meta_catalog_from_pivot) → if still phantom, investigate stale count / deleted-but-counted rows. Notify: propose system_issues('count_integrity_phantom').

3. UNMONITORED (UNMANAGED) — registered but no scanner watches it

  • Def: Đ23 §4.2 — in meta_catalog but in no DOT-scan scope. Live anchor collection_onboarding_gap (339 open).
  • Detection: meta_catalog ∖ (union of DOT scan scopes). Severity: MED→HIGH. Cleanup: onboard to a DOT/pivot. Notify: system_issues('collection_onboarding_gap').

4. UNREGISTERED — real PG table not in any registry

  • Def: Đ23 §4.2 — public table not in meta_catalog, excl. directus_*/v_*. Detection: information_schema.tablesmeta_catalog.source_location. Severity: HIGH. Cleanup: birth/onboard. Notify: UNREGISTERED TABLE issue.

5. GHOST (cross-store) — exists in one store, deleted in SoT

  • Def: OGV-0 — soft-deleted in PG but vector/Qdrant chunks remain. Detection: PG deleted_at IS NOT NULL ∧ vector point present → needs Qdrant read → DETECTION_DEFERRED (no Qdrant read this session). Notify: system_issues('kb_pg_sync_drift') (82 open, the live analogue). Named here so it is never conflated with phantom.

Nhầm chuồng (mis-stabled) — species/collection misassignment

Entity whose species_collection_map discriminator places it in the wrong collection, or whose composition_level disagrees with its species. Detection: join entity_species×species_collection_map×actual location. Severity: MED. Cleanup: re-classify. Notify: system_issues('sai_lệch_dữ_liệu'). Formal article = LAW_DEFINITION_GAP (propose folding under Đ24/Đ26/Đ29).

Scanner contract (new objects/groups — REUSE)

Auto-detect new species/collections/groups/DOTs/UI-surfaces/workflow-task-form-report from birth_registry, meta_catalog, collection_registry, table_registry, pivot_definitions, species_collection_map, IU/KG. An object that appears with no known registry/list/pivot is classified orphan/unmonitored, surfaced visibly (verification_status=unverified, warning_flags, next_action=register|onboard|propose_pivot), and its count rendered PIVOT_MISSING — never a fabricated number (Đ28). Engine = fn_birth_onboarding_full_scan (+_hc); not executed this session (may write).

Surface integration

Orphan/phantom/unmonitored/unregistered/ghost/drift become warning_flags[] on every node and child-summary counters (doc 03 §C), so the reflection screen shows the health of any layer without expanding it.