09 — Legacy Retirement Plan (Branch H)
title: 09 — Legacy Retirement Plan (Branch H) date: 2026-05-31 status: PLAN only — retirement FORBIDDEN this macro
09 — Legacy Retirement Plan (Branch H)
Prepare retirement after the replacement reaches parity. Nothing retired this macro; no
route cutover. Web source is ssh-grep-able at /opt/incomex/docker/nuxt-repo/web (running
image is compiled, source on disk).
Targets + exact file:line violations (grepped live this run)
| target | file:line | violation (Đ28) |
|---|---|---|
| Σ|gap| total | server/api/registry/health.get.ts:123 |
totalGap: collections.reduce((s,c)=>s+Math.abs(c.gap),0) |
| |gap| sort | server/api/registry/health.get.ts:117 |
collections.sort((a,b)=>Math.abs(b.gap)-Math.abs(a.gap)) |
| JS phantom classify | server/api/registry/health.get.ts:~104-110 |
status: gap===0?'KHOP':gap>0?'ORPHAN':'PHANTOM' (source-model-blind) |
| Σ record_count | server/api/registry/raw-counts.get.ts:58 |
`total_records: entries.reduce((s,e)=>s+(e.record_count |
| hardcoded phantom rows | pages/knowledge/registries/index.vue:266-320 |
virtual rows CAT-ORP/CAT-PHA/CAT-UNM/CAT-017 |
| Σ|gap| as orphan | pages/knowledge/registries/index.vue:271 |
orphan_count: hd.totalGap |
| frontend SUM | pages/knowledge/registries/index.vue:162 |
orphan_count: levelDetails.reduce((s,d)=>s+d.orphan_count,0) |
| template hardcode | pages/knowledge/registries/index.vue:595/598 |
v-if="row.code === 'CAT-017'" / 'CAT-SPE' |
| record_count-as-truth | meta_catalog.record_count consumed as authoritative |
replaced by pivot-backed PIV-500 / v_count_integrity |
| old path | /knowledge/registries |
converged onto /knowledge/registries-pivot |
pivot-query.get.ts is the GOOD pattern and is NOT retired.
Replacement condition (parity gate — ALL must hold)
- Six views + PIV-500/301/302/303/311 + parent_code committed (RG1–RG3).
- Read API live (doc 06) and
/knowledge/registries-pivotrender-shell live (RG8). - Acceptance suite green (doc 10): 100% counts pivot-traced, 0 client-side count math.
- CI no-hardcode gate green on the shell.
Redirect / alias plan
- After parity:
/knowledge/registries→ 301/302 redirect (or server alias) to/knowledge/registries-pivot. - Retire
health.get.tsΣ|gap| math and the hardcodedindex.vuevirtual rows (replace with pivot-backed reads); keepraw-counts/countsonly if re-pointed to PIV-500. /api/registry/healthand/api/registry/counts: deprecate behind the new endpoints; keep a thin compatibility shim returning pivot-backed numbers if any external caller depends on them (audit callers first).
Rollback
- Keep a snapshot of the old
index.vue+health.get.ts+ the nginx/route config before cutover. Rollback = restore snapshot + remove redirect. - Cutover is reversible until the old files are deleted (do that only after a soak period).
No-hardcode checks before cutover (CI, doc 12)
grep gate fails the build on: reduce( with + .*gap/record_count, Math.abs(.*gap),
hardcoded CAT-[A-Z0-9] in .vue, localStorage pins. Must be 0 in the converged surface.
User-facing migration note (draft)
"Danh mục hệ thống đã hợp nhất vào Registries-Pivot — số đếm nay 100% từ pivot (PG), không còn tính ở giao diện. Trang cũ tự chuyển hướng. Trạng thái toàn vẹn đếm hiển thị trung thực (hiện FAILED do 3 dòng lệch + 5 dòng chưa đo)."
Verdict
Legacy retirement plan COMPLETE. Exact violations located, parity gate + redirect + rollback + CI checks + migration note defined. Nothing retired; no cutover (RG9, after acceptance).