KB-5151

06 — Count Gap & Drift Decision (Branch E)

4 min read Revision 1
registries-pivotcount-gapdriftCAT-023write-racephantom-candidatesource-model2026-05-31

title: 06 — Count Gap & Drift Decision (Branch E) date: 2026-05-31 net_gap_live: +5,347 (fluctuating, CAT-023-driven)

06 — Count Gap & Drift Decision (Branch E)

Live re-evaluation at run time. Do not "fix" drift by updating counts — no approval covers it. This branch classifies each drift row by source_model and assigns its action to a macro.

Live invariant (leaf set, 160 rows)

Σ record = 2,007,256   Σ actual = 2,001,909   net_gap = +5,347
drift rows = 3   unmeasured = 5   orphan(leaf) = 0   pivot_backed = 21/160

The 3 drift rows sum exactly to net_gap (5,216 + 146 − 15 = 5,347) → invariant closes.

The 3 drift rows (changed since last run)

code registry model record actual gap Δ since last run classification
CAT-023 birth_registry A 990,687 985,471 +5,216 gap grew from +1 → +5,216 model_a_surplus_recheck
CAT-006 dot_tools B 309 163 +146 stable model_b_phantom_candidate
CAT-007 ui_pages B 37 52 −15 stable model_b_unregistered_candidate

What changed and why (the headline)

The entire net_gap move (+132/+148 → +5,347) is CAT-023. birth_registry.record_count (live, trigger-refreshed) grew to 990,687 while actual_count (last full scan) is frozen at 985,471. The gap grows monotonically until the next scan refresh. This was re-observed inside a transaction: when the Branch-C bundle INSERT fired the refresh, PIV-500 jumped 2,007,256 → 2,007,261 (+5 births in ~2 s). This is a model-A live-write race / stale-scan — NOT a phantom.

Per-row action class & macro assignment

row action class what to do macro
CAT-023 write-race / refresh refresh actual_count scan; do NOT treat as phantom; consider live actual_count from PIV-019 instead of a frozen scan Macro 2 (scan cadence)
CAT-006 phantom candidate council/RG4 must define phantom (LAW_DEFINITION_GAP) before any "phantom_count"; 309 registered vs 163 file = 146 candidates Macro 2 → RG4
CAT-007 unregistered register the 15 pages present on disk but absent from ui_pages Macro 2
CAT-1006..1010 scan + register 5 pg_table rows, counts NULL → run a count scan, set registry_collection, then pivot Macro 2

Why blind record > actual is unsafe as a phantom signal (proof)

CAT-023 is record > actual by +5,216 yet is a write-race, not a phantom. CAT-006 is record > actual by +146 and is a phantom candidate. The direction is identical; only source_model distinguishes them (A=live-write/stale-scan vs B=registry-vs-source). The six-object drift_classification is therefore source_model-aware and labelled "candidate" — it never asserts phantom. RG4 owns the authoritative definition.

Decision

  • No count writes this run (no approval). The drift is characterized, not fixed.
  • count_integrity_status = FAILED is the honest live state (3 drift + 5 unmeasured), surfaced — not hidden behind a frontend Σ|gap|.
  • Belongs in Macro 2 (scan cadence + unregistered fixes + phantom-law), not Macro 1.
Back to Knowledge Hub knowledge/dev/reports/architecture/registries-pivot-macro1-ratify-foundation-pivot-drilldown-2026-05-31/06-count-gap-drift-decision.md