KB-1607

S146-M4a Pivot Readiness Report (Claude Code)

15 min read Revision 1
s146pivotreadinessreport

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_summaries tí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 species như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_summaries trigger.

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_change tự 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_summaries trigger → 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-catalog idempotent → 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 species field. 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:

  1. Cron dot-pivot-health path sai → health check KHÔNG chạy.
  2. 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.