01 — Orphan / Phantom / Unmanaged / Unmonitored / Ghost: Definitions + Scanner Mapping
title: 01 — Orphan / Phantom / Unmanaged / Unmonitored / Ghost — Definitions + Scanner Mapping date: 2026-05-31
01 — Definitions + Scanner Mapping
Reuse-first: the system already carries crisp legal definitions for most of these. Each row gives definition · detection · pivot dimension · severity · cleanup trigger · notification target. Where the law is ambiguous it is marked LAW_DEFINITION_GAP with a proposed operational definition (proposal only, not enacted).
Existing legal anchors (verified live in KB)
- Điều 19 — Luật Kiểm kê Ngược / Orphan Scanner (Side B) (
knowledge/dev/laws/law-19-orphan-scanner.md): Side A = birth registry (prevention); Side B = scan everything → compare against all registries → not-in-registry = ORPHAN. - Điều 26 — orphan definition v3.9 (council consensus): "Một thực thể là orphan khi thiếu birth record HOẶC thiếu tập quan hệ tối thiểu bắt buộc để được nhìn thấy và quản trị trong graph hệ thống." (orphan = missing birth record OR missing the minimum required relationship set to be visible/governed in the graph).
- Điều 23 §4.2 — Inverse-Check (
dot-scanning-system.md): collection inmeta_catalogbut in no DOT-scan scope → UNMONITORED REGISTRY; public table not inmeta_catalog(excl.directus_*/v_*) → UNREGISTERED TABLE; discrepancy>0 →system_issuesseverity=HIGH. - OGV-0 (
orphan-vectorroot-cause report): GHOST = soft-deleted in PG but chunks remain in the vector store (cross-store drift). - Điều 28 — no fabricated/disguised display rows; counts must come from the SoT, not frontend gap-math. (The current
registries/index.vue+api/registry/health.get.tsviolate this:orphan_count = Σ|gap|injected client-side; CAT-PHA=7 / CAT-UNM=122 computed in the API layer.)
The five concepts, mapped
1. ORPHAN — real object, not visible/governed
- Definition: Đ26 v3.9 (above). Two detectable halves, both already live
system_issuestypes:thiếu_mã_định_danh(missing ID / no birth record) andthiếu_quan_hệ(missing minimum relationship set). - Detection: Side-B scan =
fn_birth_onboarding_full_scan; per-dimension refreshfn_refresh_orphan_col/_dot/_speciespopulatemeta_catalog.orphan_count. Live: CAT-DOT orphan_count=140, CAT-COL=20, CAT-SPE=1 (Σorphan=161 across 169 cats). - Pivot dimension: by
composition_leveland byspecies; PIVOT_MISSING: a dedicatedPIV-30x orphan-by-dimensiontotal. Propose. - Severity: HIGH (Đ23).
- Cleanup trigger: birth/registration workflow (Side A) — register the object or retire it via entity-lifecycle.
- Notification target:
system_issues(issue_type='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 usage exists:
system_issues.issue_type='apr_phantom_applied'(1 row) and the frontend-injected CAT-PHA row (=7) — but CAT-PHA is computed by gap-math inhealth.get.ts(an Đ28 violation, not a SoT count). - Proposed operational definition (PROPOSAL ONLY): a phantom is a counted unit with no backing real row — operationally, a
meta_catalogrow (or any displayed count) whererecord_count > actual_count(the surplus = phantom count), i.e. the inverse of orphan. - Detection:
record_count - actual_countwhere positive, per leaf category; live phantom-side rows = 7 (e.g. CAT-023 birth record 980,221 vs actual 943,726 → −36,495; CAT-006 DOT 309 vs 163 → −146). There is nophantom_countcolumn inmeta_catalog→ propose add (additive, design-only). - Pivot dimension: by
composition_level/species. PIVOT_MISSING:PIV-30x phantom. Propose. - Severity: HIGH (a phantom means a displayed number is lying).
- Cleanup trigger: recount/refresh (
refresh_meta_catalog_from_pivot) then, if still phantom, investigate stalerecord_countor deleted-but-counted rows. - Notification target:
system_issues(proposeissue_type='count_integrity_phantom').
3. UNMONITORED (UNMANAGED) — registered but no scanner watches it
- Definition: Đ23 §4.2 — in
meta_catalogbut in no DOT-scan scope. Live anchor:system_issues.issue_type='collection_onboarding_gap'(339 open). - Detection: set-difference meta_catalog ∖ (union of DOT scan scopes). Pivot dimension: by registry_group. Severity: MEDIUM→HIGH. Cleanup: onboard to a DOT/pivot. Target:
system_issues('collection_onboarding_gap').
4. UNREGISTERED — real PG table not in any registry
- Definition: Đ23 §4.2 — public table not in
meta_catalog, excludingdirectus_*/v_*. Detection:information_schema.tables∖meta_catalog.source_location. Severity: HIGH. Cleanup: birth/onboard. Target:system_issues(UNREGISTERED TABLE).
5. GHOST (cross-store) — exists in one store, deleted in SoT
- Definition: OGV-0 — soft-deleted in PG but vector/Qdrant chunks remain. Out-of-scope for the SQL accounting invariant but must be named so it isn't conflated with phantom. Detection: PG
deleted_at IS NOT NULL∧ vector point present (needs Qdrant read — not available read-only this session → markDETECTION_DEFERRED). Target:system_issues('kb_pg_sync_drift')(82 open, the live analogue).
"Nhầm chuồng" (mis-stabled)
Maps to species/collection misassignment: an 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 row location; severity MEDIUM; cleanup = re-classify; target system_issues('sai_lệch_dữ_liệu'). LAW_DEFINITION_GAP for a formal article — propose folding under Đ24/Đ26.
Summary
Orphan, unmonitored, unregistered, ghost, nhầm-chuồng = REUSE existing law + live detection. Phantom = the one genuine definition gap (LAW_DEFINITION_GAP) with a clean record_count > actual_count operational definition and a needed phantom_count column + pivot.