S146-M4a Pivot Readiness Report (Claude Code)
S146-M4a — Pivot Readiness Report
Agent: Claude Code CLI (Claude Opus 4.6) Ngày: 2026-03-29 Trạng thái: CHỈ KIỂM TRA — KHÔNG SỬA GÌ
STEP 0: CHECKPOINT
- OR version: v7.5 (2026-03-29)
- Merge rule (skills): "CI GREEN" = CHỈ 4 required checks GREEN: Pass Gate, Quality Gate, check-critical-files, Contract Schema Validation. MERGE NGAY khi 4 cái trên xanh. (v4.68)
- Anti-patterns: 12 AP đọc đủ (AP-01 → AP-12). AP-12 đặc biệt liên quan: "Giám sát báo PASS nhưng số sai".
- Assembly Gate Q0: "PG đã giải quyết chưa?" → ĐÃ KIỂM TRA — xem Phần 2.
PHẦN 1: QUOTES HIẾN PHÁP/LUẬT + Ý KIẾN
1A: Hiến pháp (constitution-amendment-measurement.md)
Điều 0-S §3a — Single Provider:
"Mỗi loại nhu cầu = 1 provider duy nhất. Đếm entities →
meta_catalog+refresh_registry_count(). Xác minh đếm →verify_counts()."
Điều 0-S §3b:
"Thêm khách hàng mới = thêm DATA, KHÔNG thêm CODE. Thêm collection mới → thêm 1 row vào meta_catalog. KHÔNG viết trigger mới."
Điều 0-S §5 — Tầm nhìn PG:
"Triggers: ít và ổn định (~20-30). 1 function, nhiều triggers gọi chung. Functions: ít framework functions (~5-10), dùng lại cho mọi luật."
1B: Điều 26 v3.5 (dieu26-new-registries-counting-law-draft.md)
MT2:
"ĐẾM LUÔN ĐÚNG BY DEFINITION (COUNT trực tiếp, không cache)"
MT3:
"SCALE BẰNG DOT, KHÔNG BẰNG CODE"
Bài toán 2 — pivot_definitions schema:
Fields: code, name, source_object, filter_spec (jsonb), group_spec (jsonb), metric_spec (jsonb), registry_group, composition_level, species, parent_code, display_order, is_active, cache_tier, superseded_by, normalized_signature.
pivot_count() — parse JSON → build WHERE: An toàn. DOT validate dễ. Audit rõ ràng.
DOT tools: 4 sửa cũ + 3 mới = 7 (luật nói). Thực tế hiện tại: 2 DOT pivot tools (DOT-113 dot-pivot-declare, DOT-114 dot-pivot-health).
Mission status:
- Mission 0.5: Fix Blockers → (không xác nhận)
- Mission 1: Pivot CHẠY → pivot_definitions + pivot_count() + pivot_results LIVE
- Mission 2: DOT khai báo → dot-pivot-declare + dot-pivot-health LIVE
- Mission 3: VIEW cross-table → PIV-101 đến PIV-106 (cross-table pivots) LIVE
1C: Điều 0-B (composition-level-law.md)
6 lớp cấu tạo:
| Lớp | Tên | Badge |
|---|---|---|
| 1 | Nguyên tử (Atom) | 🟢 |
| 2 | Phân tử (Molecule) | 🔵 |
| 3 | Hợp chất (Compound) | 🟣 |
| 4 | Vật liệu (Material) | 🟠 |
| 5 | Sản phẩm (Product) | 🔶 |
| 6 | Công trình (Building) | 🔷 |
Species (Điều 29 / species-collection-law-draft.md):
"Loài = meta-concept TRƯỚC Điều 24. Không phải facet." Species = meta-entity phân loại, ĐỨNG NGOÀI 6 lớp cấu tạo. Là meta-layer. Registries UI = 7 chiều (6 lớp + 1 species).
1D: ★ Ý KIẾN AGENT — VÊNH / THIẾU / MÂU THUẪN
VÊNH 1: CAT-ALL lệch 176 records.
- CAT-ALL (virtual) = 34,439 nhưng SUM(managed records) = 34,263.
- CAT-MOL (virtual) = 766 nhưng SUM(molecule managed) = 645.
fn_refresh_virtual_summariestính SUM từ managed rows → lẽ ra phải khớp. Nghĩa là có rows managed mà composition_level không đúng, HOẶC virtual rows bị update bởi source khác (ví dụ cron refresh_meta_catalog_from_pivot ghi record_count cho CAT-ALL nhưng nguồn khác).- Vi phạm MT2 ("Đếm đúng by definition") — số lệch = đếm chưa đúng.
VÊNH 2: pivot_definitions.species field TRỐNG trên toàn bộ 27 entries.
- Điều 26 schema có field
speciesnhưng KHÔNG entry nào sử dụng. - Species taxonomy (v1.2) nói "Registries UI = 7 chiều (6 lớp + 1 meta-layer species)" — nhưng thực tế pivot system chưa kết nối species.
VÊNH 3: Cron dot-pivot-health chạy ở đường dẫn SAI.
- Cron:
cd /opt/incomex/deploys/web-test && dot/bin/dot-pivot-health - Nhưng file thực tế nằm ở:
/opt/incomex/dot/bin/dot-pivot-health - VPS log:
/bin/sh: 1: dot/bin/dot-pivot-health: not found - → dot-pivot-health KHÔNG BAO GIỜ CHẠY được qua cron. Vi phạm AP-06 ("Chức năng OK nhưng automation thiếu").
VÊNH 4: DOT tools = 2/7 so với luật.
- Điều 26 nói "4 sửa cũ + 3 mới = 7". Thực tế chỉ 2: dot-pivot-declare + dot-pivot-health.
- Thiếu: dot-pivot-browse, dot-pivot-status, dot-pivot-retire, v.v. (hoặc 5 tools khác luật đề cập chưa rõ tên).
VÊNH 5: Trigger trg_auto_sync_registry_counts DISABLED.
- tgenabled = 'D' → trigger tắt. Nghĩa là khi meta_catalog INSERT → v_registry_counts KHÔNG tự đồng bộ.
THIẾU 1: Không có pivot đếm RIÊNG từng lớp.
- Hiện tại: PIV-101 GROUP BY composition_level → tạo 6 rows trong pivot_results. OK cho cross-table.
- Nhưng KHÔNG có pivot riêng "PIV-ATM: Total atoms" (filter: composition_level=atom). Nghĩa là 7 dòng Registries 2 (6 lớp + 1 species) sẽ cần LẤY DATA TỪ ĐÂU?
- Từ PIV-101 results (đã có) → cần Nuxt query pivot_results WHERE group_values.level = 'atom'
- HOẶC từ meta_catalog virtual rows (CAT-ALL, CAT-MOL, etc.) → đã có nhưng lệch.
THIẾU 2: Không có pivot đếm species.
- Không có pivot nào filter by species hoặc group by species trực tiếp trên entity tables.
- PIV-103 group by composition_level trên entity_species → đếm SỐ LOÀI per lớp, KHÔNG phải đếm CÁ THỂ per species.
MÂU THUẪN 1: Điều 0-B nói 6 lớp nhưng entity_species chỉ biết 4.
- entity_species composition_level: atom=17, compound=6, meta=1, molecule=11. KHÔNG CÓ material, product, building trong entity_species.
- Lớp 4-6 trong Điều 0-B ghi "Chưa" (chưa có entity). Đúng — nhưng PIV-101 group trả building=1, product=1, material=1 từ meta_catalog → đó là virtual rows, KHÔNG phải entities thực.
PHẦN 2: KẾT QUẢ CHẠY THỬ PG
2A: pivot_definitions — 27 entries (26 active, 1 inactive)
| Nhóm | Entries |
|---|---|
| PIV-001 → PIV-021 | 21 "Total" pivots (1 per collection). PIV-020 inactive. |
| PIV-101 → PIV-106 | 6 cross-table pivots (group by level, identity, category, classification, level×identity) |
Composition levels có trong pivots: atom (12), compound (4), molecule (10). KHÔNG CÓ material, product, building.
Species field: TRỐNG trên tất cả 27 entries.
2B: pivot_count() — CHẠY ĐƯỢC, KẾT QUẢ ĐÚNG
pivot_count('PIV-001') = 152, COUNT(*) meta_catalog = 152 ✅ KHỚP
pivot_count('PIV-007') = 152, COUNT(*) dot_tools = 152 ✅ KHỚP
pivot_count('PIV-004') = 2, COUNT(*) workflows = 2 ✅ KHỚP
pivot_count() HOẠT ĐỘNG ĐÚNG cho simple count. JSON filter_spec parse + WHERE build logic chạy đúng.
2C: refresh_meta_catalog_from_pivot() — CHẠY ĐƯỢC
- Function JOIN pivot_count() → pivot_definitions → meta_catalog (qua
registry_collection = source_object) - Chỉ sync pivots có
filter_spec = '{"filters":[]}' AND group_spec = '{"groups":[]}' - Update:
record_count,active_count,last_scan_date - Output: 20 rows. CAT-023 (birth_registry) changed: 21185→21186. Còn lại stable.
- KHÔNG update virtual rows (CAT-ALL, CAT-MOL, etc.) — đó do
fn_refresh_virtual_summariestrigger.
2D: Automation
Cron entries (3):
| Entry | Schedule | Chạy thật? |
|---|---|---|
refresh_meta_catalog_from_pivot() |
*/10 * * * * | ✅ LOG CÓ output (CAT-023 thay đổi) |
dot-pivot-health |
0 4 * * * | ❌ PATH SAI → not found |
refresh_pivot_results() |
*/10 * * * * | ✅ LOG CÓ output (26 entries) |
PG Triggers:
| Trigger | Table | Enabled | Chức năng |
|---|---|---|---|
trg_after_pivot_definitions_change |
pivot_definitions | O (ENABLED) | Gọi trg_pivot_def_refresh() khi INSERT/UPDATE/DELETE |
trg_auto_sync_registry_counts |
meta_catalog | D (DISABLED) | Sync v_registry_counts khi INSERT meta_catalog |
trg_birth_pivot_definitions |
pivot_definitions | O (ENABLED) | Auto birth registry |
trg_birth_pivot_results |
pivot_results | O (ENABLED) | Auto birth registry |
trg_meta_catalog_refresh_views |
meta_catalog | O (ENABLED) | Refresh registry views |
trg_refresh_cat_all |
meta_catalog | O (ENABLED) | Refresh CAT-ALL |
trg_refresh_virtual_summaries |
meta_catalog | O (ENABLED) | Refresh virtual rows (CAT-ALL/MOL/CMP/MAT/PRD/BLD) |
DUAL-TRIGGER:
| Trigger | Loại | Có? | Chạy thật? | Evidence |
|---|---|---|---|---|
| Cron refresh_meta_catalog_from_pivot | #1 scheduled | ✅ | ✅ | Log shows output every 10min |
| PG trigger trg_after_pivot_definitions_change | #2 on-demand | ✅ | ✅ | Enabled, fires on pivot_definitions change |
| Cron dot-pivot-health | Health check | ✅ | ❌ | Path sai, not found |
| Cron refresh_pivot_results | #3 scheduled | ✅ | ✅ | Log shows output |
PHẦN 3: DOT TOOLS ĐÁNH GIÁ
3A: 2 DOT tools tồn tại
dot/bin/dot-pivot-declare(DOT-113)dot/bin/dot-pivot-health(DOT-114)
3B: Đánh giá từng tool
| Tiêu chí | dot-pivot-declare | dot-pivot-health |
|---|---|---|
| Chức năng | INSERT pivot_definitions | Health check 7 items (H1-H7) |
| Mode --single | ✅ --source + --name | N/A |
| Mode --batch | ✅ --auto-from-meta-catalog | N/A |
| Mode --dry-run | ❌ KHÔNG CÓ | ❌ KHÔNG CÓ |
| Idempotent | ✅ ON CONFLICT DO NOTHING + dup check | �� Read-only checks |
| TỰ ĐỘNG? | Có thể chạy tự động qua cron/trigger | Cron TỒN TẠI nhưng PATH SAI |
| Trong cron? | Không (chạy ad-hoc) | Có nhưng path sai → không chạy |
| Đăng ký dot_tools? | ✅ DOT-113 | ✅ DOT-114 |
3C: ★ ĐÁNH GIÁ AUTOMATION
1. Thêm 1 pivot mới → quy trình?
dot-pivot-declare --source <table> --name "<name>" --level <level>→ SSH + gõ lệnh DOT tay.- HOẶC: INSERT trực tiếp vào pivot_definitions → trigger
trg_after_pivot_definitions_changetự refresh. - INSERT 1 dòng → meta_catalog tự cập nhật: ✅ (qua cron mỗi 10 phút HOẶC trigger on-demand).
- Nuxt tự hiện? Phụ thuộc Nuxt UI đọc từ đâu. Nếu Nuxt đọc pivot_results/v_registry_counts → tự hiện sau refresh.
- Kết luận: Semi-automatic. DOT tool phải gõ tay SSH, nhưng SAU INSERT thì pipeline tự chạy.
2. Data thay đổi (thêm 100 atoms) → counting tự cập nhật?
- Cron
refresh_meta_catalog_from_pivot()mỗi 10 phút → YES, tự cập nhật record_count. fn_refresh_virtual_summariestrigger → CAT-ALL/MOL/CMP/etc tự update khi managed record_count thay đổi.refresh_pivot_results()cron → pivot_results table refresh mỗi 10 phút.- Kết luận: ✅ TỰ ĐỘNG sau tối đa 10 phút.
3. Scale test (500 collections)?
- pivot_count() dùng dynamic SQL → iterates qua tất cả active pivots. O(N) queries.
- Với 500 pivots, mỗi lần refresh = 500 COUNT queries. Mỗi query ~1-10ms → ~1-5 giây. Chấp nhận được.
--auto-from-meta-catalogidempotent → thêm collection mới tự có pivot.- Rủi ro: pivot_count() không có timeout/batching. 500 queries trong 1 transaction có thể slow.
3D: DOT registry
DOT-113 | dot-pivot-declare | pivot
DOT-114 | dot-pivot-health | pivot
Đã đăng ký đầy đủ 2/2 tools hiện có. Thiếu 5 tools so với Điều 26 (7 total).
PHẦN 4: KẾT LUẬN — 6 CÂU
4A: Pivot system CHẠY ĐƯỢC cho 7 dòng (6 lớp + species) chưa?
CHƯA HOÀN TOÀN. Cụ thể:
- 6 lớp: PIV-101 GROUP BY composition_level → tạo 6 rows trong pivot_results. Data CÓ nhưng cần Nuxt query đúng. HOẶC dùng meta_catalog virtual rows (CAT-ALL, CAT-MOL, CAT-CMP, CAT-MAT, CAT-PRD, CAT-BLD) — nhưng SỐ LỆCH.
- Species: KHÔNG CÓ pivot nào đếm cá thể per species. PIV-103 chỉ đếm số loài per lớp.
Để tạo 7 dòng Registries 2:
- 6 dòng lớp: Dùng PIV-101 results (đã có) HOẶC meta_catalog virtual rows (cần fix lệch).
- 1 dòng species: Cần pivot mới hoặc query entity_species trực tiếp.
4B: pivot_definitions đã có entry liên quan 6 lớp + species?
- 6 lớp: PIV-101 (Danh mục theo Lớp) — GROUP BY composition_level. Đã có.
- Species: KHÔNG. Không có pivot nào sử dụng
speciesfield. Cần:- Pivot mới GROUP BY species trên entity table, HOẶC
- Sử dụng entity_species table trực tiếp.
4C: Automation ĐẦY ĐỦ chưa?
| Chain | Status |
|---|---|
| INSERT pivot_definitions → meta_catalog tự update | ✅ (trigger + cron) |
| Data thay đổi → counting tự update | ✅ (cron 10min) |
| pivot_results tự refresh | ✅ (cron 10min) |
| dot-pivot-health tự chạy | ❌ PATH SAI |
| v_registry_counts sync từ meta_catalog | ❌ TRIGGER DISABLED |
THIẾU:
- Cron dot-pivot-health path sai → health check KHÔNG chạy.
- trg_auto_sync_registry_counts DISABLED → v_registry_counts có thể stale.
4D: meta_catalog virtual rows
CAT-ALL | Tổng nguyên tử | virtual | atom | active | 34,439 (lệch +176 vs SUM managed)
CAT-MOL | Tổng phân tử | virtual | molecule | active | 766 (lệch +121 vs SUM molecule managed)
CAT-CMP | Tổng hợp chất | virtual | compound | active | 326 (KHỚP)
CAT-MAT | Tổng vật liệu | virtual | material | active | 55 (SUM material managed = NULL → 0 managed nhưng virtual = 55??)
CAT-PRD | Tổng sản phẩm | virtual | product | active | 0 (KHỚP - cả hai 0)
CAT-BLD | Tổng công trình | virtual | building | active | 0 (KHỚP - cả hai 0)
Registries 2 nên dùng rows này? Có thể, nhưng phải FIX LỆCH trước. CAT-ALL lệch 176, CAT-MOL lệch 121, CAT-MAT = 55 mà managed material = NULL (không có managed material entities?).
4E: VÊNH giữa hiến pháp/luật và thực tế
| # | Vênh | Ảnh hưởng Registries 2 |
|---|---|---|
| 1 | CAT-ALL/CAT-MOL lệch vs SUM managed | Nếu dùng virtual rows → số sai |
| 2 | Species không kết nối pivot | Registries 2 dòng species không có data source |
| 3 | dot-pivot-health cron path sai | Không phát hiện lỗi tự động |
| 4 | DOT 2/7 (thiếu 5) | Vi phạm "DOT 100%" nhưng 2 tools hiện tại đủ cho basic ops |
| 5 | trg_auto_sync disabled | v_registry_counts có thể stale |
| 6 | Lớp 4-6 chưa có entities | Registries 2 dòng material/product/building sẽ hiện 0 (chấp nhận được) |
4F: TOÀN BỘ BLOCKERS
| Loại | Blocker | Mức |
|---|---|---|
| PG | CAT-ALL lệch 176, CAT-MOL lệch 121, CAT-MAT = 55 nhưng managed = 0 | 🔴 PHẢI FIX nếu dùng virtual rows |
| PG | Không có pivot đếm cá thể per species | 🟡 Cần thêm pivot hoặc query trực tiếp |
| DOT | dot-pivot-health cron PATH SAI → health check không chạy | 🔴 FIX cron path |
| Automation | trg_auto_sync_registry_counts DISABLED | 🟡 v_registry_counts có thể stale |
| Directus | Không blocker — pivot_definitions + pivot_results serve qua Directus OK | ✅ |
| Nuxt | Chưa kiểm tra — nhưng nếu Nuxt đọc pivot_results/meta_catalog → data flow OK | 🟡 Cần verify |
KẾT LUẬN: CHƯA SẴN SÀNG. 2 blockers ���� (số lệch + cron path), 3 items 🟡 cần xử lý. Sau khi fix → pivot system ĐỦ cho 7 dòng Registries 2.