S146-M3 Claude Nuxt Registries Investigation
S146-M3 — Bao cao Dieu tra Nuxt Registries (Claude)
Agent: Claude Code (Opus 4.6) Ngay: 2026-03-29 Phien ban code: 68d940f (S170D Mission 3.5) Trang thai: CHI DIEU TRA — KHONG SUA CODE
PHAN 0: XAC NHAN PG <-> DIRECTUS (Assembly First)
Bang 1: PG COUNT(*) vs Directus API count
| Collection | PG COUNT(*) | Directus API count | KHOP? |
|---|---|---|---|
| modules | 5 | 5 | YES |
| dot_tools | 152 | 152 | YES |
| tasks | 10 | 10 | YES |
| collection_registry | 145 | 145 | YES |
| workflows | 2 | 2 | YES |
| meta_catalog | 152 | 152 | YES |
| v_registry_counts | 152 | 152 | YES |
KET LUAN: PG COUNT(*) KHOP HOAN TOAN voi Directus API count cho ca 7 collections.
Bang 2: meta_catalog.record_count vs v_registry_counts.record_count
| cat_code | meta_catalog.record_count | v_registry_counts.record_count | v_registry_counts.orphan_count | cross_check | KHOP? |
|---|---|---|---|---|---|
| CAT-ALL | 44413 | 44413 | 0 | KHOP | YES |
| CAT-MOL | 766 | 766 | 0 | KHOP | YES |
| CAT-CMP | 326 | 326 | 0 | KHOP | YES |
| CAT-MAT | 55 | 55 | 0 | KHOP | YES |
| CAT-006 | 152 | 152 | 0 | KHOP | YES |
| CAT-008 | 145 | 145 | 0 | KHOP | YES |
| CAT-009 | 10 | 10 | 0 | KHOP | YES |
KET LUAN: meta_catalog KHOP HOAN TOAN voi v_registry_counts. Nen tang PG <-> Directus DUNG. Van de o Nuxt code.
Bang 3: Phantom CAT codes trong PG
| Code | Ton tai trong meta_catalog? | Ton tai trong v_registry_counts? |
|---|---|---|
| CAT-ORP | KHONG | KHONG |
| CAT-PHA | KHONG | KHONG |
| CAT-SPE | KHONG | KHONG |
| CAT-UNM | KHONG | KHONG |
KET LUAN: 4 phantom codes KHONG ton tai trong PG/Directus. Chung duoc tao boi Nuxt code.
12 CAU TRA LOI BAT BUOC
Cau 1: PG COUNT(*) co KHOP Directus API count cho 7 collections?
CO — KHOP HOAN TOAN. Xem Bang 1 o tren.
Evidence: SSH docker exec postgres psql -U directus -d directus vs curl directus API aggregate count
Cau 2: meta_catalog.record_count co KHOP PG COUNT(*)?
CO cho cac collection da kiem tra. Xem Bang 2.
Cau 3: v_registry_counts.record_count co KHOP meta_catalog.record_count?
CO — KHOP 100%. Ca 152 rows deu khop. cross_check = KHOP cho tat ca.
Cau 4: Nuxt registries/index.vue goi readItems tu collection NAO?
Evidence: web/pages/knowledge/registries/index.vue
| Dong | Collection | Muc dich |
|---|---|---|
| 110 | meta_catalog | Fetch catalog chinh (managed + log entries) |
| 346 | registry_changelog | 10 thay doi gan nhat |
| 355 | meta_catalog (lan 2) | Lay composition_level cho changelog |
| 461 | dot_tools | Dem DOT tools cho coverage row |
| 478 | entity_species | Dem species cho row 7 |
| 484 | birth_registry | Dem governed births cho row 7 |
Ngoai readItems, con goi server API:
| Dong | API | Muc dich |
|---|---|---|
| 190 | /api/registry/composition | Du lieu cot Thanh phan |
| 418 | /api/registry/health | Orphan/Phantom counts (rows 8-9) |
| 430 | /api/registry/unmanaged | Unmanaged count (row 10) |
| 445 | /api/registry/system-issues | System issues (row 11) |
Code nguyen van (fetch chinh — dong 109-119):
const catalog = await $directus.request(
readItems('meta_catalog' as any, {
fields: ['code', 'name', 'entity_type', 'composition_level', 'identity_class', 'record_count', 'active_count', 'orphan_count', 'baseline_count'],
filter: {
identity_class: { _in: ['managed', 'log'] },
registry_collection: { _nnull: true },
status: { _eq: 'active' },
},
limit: -1,
}),
);
Cau 5: Nuxt co doc NHIEU HON 1 collection?
CO — doc 6 collections + 4 server APIs. Nhung day KHONG phai root cause gap doi.
Giai thich: Du lieu chinh (bang registry) chi doc tu meta_catalog (1 collection). Cac collection khac (dot_tools, entity_species, birth_registry) + server APIs chi cung cap du lieu bo sung cho cac cot/rows phu.
Cau 6: Nuxt co code MERGE/CONCAT/SPREAD arrays?
CO — dong 323:
return [...data.summaries, speciesRow, orphanRow, phantomRow, unmanagedRow, systemIssuesRow, ...data.details, coverageRow].map((row, idx) => ({
...row,
stt: idx + 1,
}));
NHUNG day KHONG phai double-count. Giai thich:
- data.summaries = 6 summary rows (CAT-ALL, CAT-MOL, CAT-CMP, CAT-MAT, CAT-PRD, CAT-BLD)
- data.details = ~135 detail rows (individual collections)
- Summary rows la TONG HOP tu details (sum), khong phai copy
Code tinh summary (dong 151-167):
for (const level of levels) {
const levelDetails = managedDetails.filter((d) => d.composition_level === level);
summaries.push({
record_count: levelDetails.reduce((s: number, d: any) => s + d.record_count, 0),
orphan_count: levelDetails.reduce((s: number, d: any) => s + d.orphan_count, 0),
});
}
VAN DE THUC SU — 2 BUG RIENG BIET:
Bug A — Summary rows hien SAI so voi meta_catalog virtual values:
- CAT-ALL tren meta_catalog = 44,413
- CAT-ALL tren UI (Nuxt computed sum) = 33,170
- SAI DO: -11,243
Nguyen nhan: Nuxt tinh CAT-ALL = sum(managed atom-level entries) nhung PG tinh CAT-ALL = tong TAT CA records (ke ca non-atom levels, log entries). Hai con so KHAC NHAU ve ban chat nhung hien thi duoi cung code CAT-ALL.
Bug B — So gap doi ma user bao (77,729 = ~2x44,413):
- KHONG TAI HIEN tren production hien tai (2026-03-29)
- Production hien tai hien CAT-ALL = 33,170
- Kha nang: bug da xay ra o phien ban TRUOC commit 7c4d382 (S170 Mission 1 — pivot_count() replaces counting triggers)
- S170 thay doi data source: TRUOC doc v_registry_counts -> SAU doc meta_catalog
- Neu code cu doc CA v_registry_counts LAN meta_catalog -> cong 2 lan -> doubled
Cau 7: UI hien CAT-ORP, CAT-PHA, CAT-SPE, CAT-UNM — code TAO o dau?
TIM THAY — web/pages/knowledge/registries/index.vue dong 244-304:
// Row 7: Species classification — DONG 246-258
const speciesRow = {
_type: 'summary',
code: 'CAT-SPE', // HARDCODED
name: 'Phan loai loai',
record_count: sd.birthGovCount, // tu birth_registry governed count
};
// Row 8: Orphan — DONG 263-275
const orphanRow = {
_type: 'summary',
code: 'CAT-ORP', // HARDCODED
name: 'Mo coi (Orphan)',
record_count: hd.orphan, // = 5 (so collection co orphan)
orphan_count: hd.totalGap, // = 21,823 (tong |gap| tat ca collections)
};
// Row 9: Phantom — DONG 276-289
const phantomRow = {
_type: 'summary',
code: 'CAT-PHA', // HARDCODED
name: 'Phantom',
record_count: hd.phantom, // = 7 (so collection co phantom)
};
// Row 10: Unmanaged — DONG 290-304
const unmanagedRow = {
_type: 'summary',
code: 'CAT-UNM', // HARDCODED
name: 'Khong quan tri',
record_count: ud.total, // = 122 (62 observed + 60 excluded)
};
Tat ca 4 rows nay duoc INJECT vao bang tai dong 323.
Cau 8: Orphan=21,823 tren UI — CON SO NAY tinh o dau?
Nguon: web/server/api/registry/health.get.ts dong 123:
totalGap: collections.reduce((s, c) => s + Math.abs(c.gap), 0),
Hien thi tai: web/pages/knowledge/registries/index.vue dong 271:
orphan_count: hd.totalGap, // = 21,823
Cong thuc: totalGap = SUM(|gap|) cho tat ca governed collections, trong do:
- gap = source_count - birth_count per collection
- Thanh phan lon nhat: birth_registry collection co gap = 21,181 (21,181 records nhung 0 births)
Van de: birth_registry DANG TU KIEM TRA CHINH MINH. No la governed collection trong species_collection_map, nhung khong ai tao birth records CHO birth_registry. Do do gap = 21,181 -> chiem 97% tong orphan.
Breakdown orphan data (from /api/registry/health):
| Collection | noi_chua | noi_sinh | gap | Status |
|---|---|---|---|---|
| birth_registry | 21,181 | 0 | +21,181 | ORPHAN |
| approval_requests | 165 | 6 | +159 | ORPHAN |
| pivot_definitions | 27 | 0 | +27 | ORPHAN |
| dot_tools | 152 | 435 | -283 | PHANTOM |
| system_issues | 765 | 890 | -125 | PHANTOM |
| meta_catalog | 152 | 174 | -22 | PHANTOM |
| entity_dependencies | 142 | 160 | -18 | PHANTOM |
| Tong | gap |
Cau 9: Nuxt co import pg/postgres/SQL truc tiep?
KHONG. Grep toan bo web/ directory:
grep -r "import.*pg|require.*pg|from 'pg'" web/ -> 0 results
Nuxt chi doc qua Directus SDK (readItems) hoac qua $fetch den Directus API. DUNG kien truc S0-AV.
Cau 10: Nuxt co hardcode CAT codes, so luong co dinh?
CO — cac CAT codes hardcoded trong index.vue:
| Code | Dong | Muc dich |
|---|---|---|
| CAT-SPE | 248 | Species row |
| CAT-ORP | 266 | Orphan row |
| CAT-PHA | 280 | Phantom row |
| CAT-UNM | 294 | Unmanaged row |
| CAT-017 | 311 | System Issues row |
| CAT-ALL..CAT-BLD | 10-17 | VIRTUAL_CODE_LEVEL mapping |
| SYS-CVG | 233 | Coverage row |
Ngoai ra co:
- 6 composition levels hardcoded: atom, molecule, compound, material, product, building (dong 148)
- Composition level display labels/colors hardcoded (dong 51-86)
Khong co so luong co dinh (magic numbers) hardcoded.
Cau 11: Nuxt co logic client-side nao NEN o PG/Directus?
CO — 3 vi pham:
| # | Logic | File:Line | Nen o dau |
|---|---|---|---|
| 1 | Summary row computation (sum record_count per level) | index.vue:148-167 | PG VIEW hoac Directus virtual field — meta_catalog DA CO virtual entries (CAT-ALL etc.) nhung Nuxt KHONG dung |
| 2 | Delta calculation (record_count - baseline_count) | index.vue:127 | PG computed column hoac VIEW |
| 3 | Health totalGap = SUM(abs(gap)) | health.get.ts:123 | Nen la PG function fn_registry_health() thay vi N+1 API calls |
Cau 12: Tu code — DU DOAN UI output, SO VOI UI THAT
Du doan tu code analysis:
Nuxt doc meta_catalog voi filter identity_class IN [managed,log], registry_collection NOT NULL, status=active -> tra ve 138 entries.
Tach managed vs log:
- Managed: 135 entries (identity_class=managed)
- Log: 3 entries (CAT-081 lifecycle_log, CAT-141 measurement_log, CAT-116 pages_blog)
Summary rows tinh tu managed only:
- CAT-ALL (atom): sum of 57 managed atom entries = ~33,170
- CAT-MOL (molecule): sum of 47 managed molecule entries = ~645
- CAT-CMP (compound): sum of 31 managed compound entries = ~326
- CAT-MAT/PRD/BLD: 0 (khong co managed entries o levels nay)
SO VOI UI THAT (production SSR payload 2026-03-29):
| Metric | Du doan tu code | UI that (Nuxt payload) | KHOP? |
|---|---|---|---|
| CAT-ALL record_count | ~33,170 | 33,170 | YES |
| CAT-MOL record_count | ~645 | 645 | YES |
| CAT-CMP record_count | ~326 | 326 | YES |
| CAT-MAT record_count | 0 | 0 | YES |
| CAT-ORP record_count | 5 | 5 | YES |
| CAT-ORP orphan_count | 21,823 | 21,823 | YES |
| CAT-PHA record_count | 7 | 7 | YES |
| CAT-UNM record_count | 122 | 122 | YES |
| CAT-SPE record_count | ~2,099 | 2,099 | YES |
| dot_tools_count | 152 | 152 | YES |
KET QUA: DU DOAN KHOP 100% VOI UI THAT. Dieu tra lan nay DUNG.
BANG BO SUNG
Bang: Vi pham Nguyen tac
| File:Line | Nguyen tac | Code | Muc |
|---|---|---|---|
| index.vue:148-167 | S0-BA (Nuxt=man hinh) | Summary computation client-side | TRUNG BINH — nen dung meta_catalog virtual values truc tiep |
| index.vue:244-304 | S0-AU (Khong hardcode) | 4 phantom CAT codes hardcoded | THAP — intentional design cho health dashboard |
| index.vue:10-17 | S0-AU | VIRTUAL_CODE_LEVEL mapping hardcoded | THAP — can cho routing |
| health.get.ts:90-114 | Scale / N+1 | For loop goi API tung collection | CAO — se cham khi nhieu collections |
Bang: Flow GOC vs HIEN TAI
| Buoc | Flow chuan (S0-AV) | Flow hien tai | Sai o dau |
|---|---|---|---|
| 1. Data source | PG table -> Directus API | PG meta_catalog -> Directus API | DUNG |
| 2. Read | readItems meta_catalog -> lay CAT-ALL.record_count | readItems meta_catalog -> filter managed + sum() | Khong dung pre-computed values |
| 3. Enrich | Khong can | 4 server APIs + 3 readItems calls | Phuc tap hoa |
| 4. Transform | Khong transform | 135+ detail rows + 6 summaries + 5 special rows | Business logic o frontend |
| 5. Render | UTable -> render truc tiep | UTable -> render 147+ rows | DUNG component |
Bang: PG Triggers tren meta_catalog
| Trigger | Status | Ghi chu |
|---|---|---|
| trg_count_meta_catalog | DISABLED | Counting trigger da tat (S170) |
| trg_auto_create_counting | DISABLED | Counting trigger da tat (S170) |
| trg_auto_sync_registry_counts | DISABLED | Sync trigger da tat (S170) |
| trg_refresh_cat_all | ENABLED | Refresh CAT-ALL virtual value |
| trg_refresh_virtual_summaries | ENABLED | Refresh virtual summaries |
| 11 others | ENABLED | Birth, label, guard, etc. |
Bang: Crontab lien quan
| Schedule | Command | Ghi chu |
|---|---|---|
| */10 * * * * | refresh_meta_catalog_from_pivot() | Refresh meta_catalog counts moi 10 phut |
| */10 * * * * | refresh_pivot_results() | Refresh pivot results moi 10 phut |
| 0 */3 * * * | scanner-counts.sh | Integrity scan moi 3h |
| 0 4 * * * | dot-pivot-health | Daily health check |
KET LUAN + DE XUAT
Root Cause chinh xac
VAN DE GAP DOI (user-reported 77,729):
- KHONG TAI HIEN tren production hien tai (2026-03-29). Production hien CAT-ALL = 33,170.
- Kha nang cao: Bug da xay ra o phien ban TRUOC S170 (commit 7c4d382), khi code co the doc tu ca v_registry_counts VA meta_catalog. S170 thay doi data source -> fix implicit.
- HOAC: Data da thay doi (meta_catalog entries duoc phan loai lai).
VAN DE HIEN TAI (2 issues):
-
Summary values SAI so voi meta_catalog: CAT-ALL hien 33,170 nhung meta_catalog CAT-ALL = 44,413. Nuxt TU TINH sum thay vi dung pre-computed value. Sai vi chi sum atom-level managed entries, bo qua log + non-atom.
-
Orphan=21,823 bi inflate: 97% (21,181) den tu birth_registry tu kiem tra chinh minh — structural issue trong species_collection_map.
4 PHANTOM ROWS (CAT-ORP, CAT-PHA, CAT-SPE, CAT-UNM):
- Intentionally hardcoded trong index.vue (dong 244-304)
- Cung cap health/classification dashboard info
- KHONG phai bug — la feature (nhung vi pham S0-AU)
Bao nhieu files can sua (khi duoc duyet)
| Fix | Files | Dong XOA | Dong THEM |
|---|---|---|---|
| Dung meta_catalog virtual values thay vi sum() | 1 (index.vue) | ~20 | ~10 |
| Fix birth_registry self-check | 1 (health.get.ts) hoac PG (species_collection_map) | 0 | ~3 |
| Neu muon XOA phantom rows (CAT-ORP etc.) | 1 (index.vue) | ~60 | 0 |
| Neu muon GIU phantom rows nhung move to PG | 2 (index.vue + PG migration) | ~60 | ~40 |
Risk Assessment
- Fix summary computation: LOW RISK — chi thay doi cach doc, khong anh huong layer 2/3/4
- Fix birth_registry self-check: LOW RISK — chi filter 1 collection khoi health check
- Xoa phantom rows: MEDIUM RISK — E2E tests reference CAT-ORP/PHA/UNM (registries.spec.ts, registries.json contracts)
- Revert ve commit goc (a3d5aaa): MAT toan bo: health rows, species, system issues, changelog, matrix, composition column. GIU gi: basic meta_catalog table. KHONG KHUYEN KHICH revert.