Điều 31 M5-FIX Report — Fix Foundation: Layer Consistency + Legacy Classification
ĐIỀU 31 M5-FIX — FIX FOUNDATION
Agent: Claude Code (CLI) | Ngày: 2026-03-24 PR: #587 (web-test — squash merged) Status: Deployed + verified on production
Vấn đề gốc
Điều 31 hạ tầng 80% xong nhưng vận hành 0%. "Cơ quan kiểm tra" hiển thị SAI:
- Layer 1 Dòng 11: critical=738, warning=738 (cả hai = total — BUG)
- Layer 2 summary: CRITICAL=0, WARNING=0 (trước khi fix severity)
- 738 legacy issues: issue_class = null, severity = tiếng Việt
- Runner chạy DRY-RUN (token env không propagate)
Fix 1: Legacy Classification (738 records)
Script: scripts/classify-legacy-issues.py (agent-data-test repo)
| issue_type (cũ) | → issue_class | severity (cũ) | → severity (chuẩn) | count |
|---|---|---|---|---|
| thiếu_quan_hệ | data_fault | cảnh_báo | WARNING | 606 |
| link_hỏng | render_fault | nghiêm_trọng | CRITICAL | 119 |
| thiếu_mã_định_danh | data_fault | cảnh_báo | WARNING | 9 |
| sai_lệch_dữ_liệu | sync_fault | cảnh_báo | WARNING | 2 |
| lỗi_lớp_2 | render_fault | nghiêm_trọng | CRITICAL | 2 |
Kết quả: 738/738 classified, 0 unclassified. source_system set to dot-scanner.
Fix 2: Layer 1 API (system-issues.get.ts)
Bug: Used meta.total_count (UNFILTERED — always returns 738 regardless of filter) + filtered by status=open (nhưng tất cả records = archived).
Fix: Switched to Directus aggregate API (groupBy severity, aggregate count) — same pattern as Layer 2. Accurate severity breakdown.
Before: {all: 738, critical: 738, warning: 738, info: 0}
After: {all: 738, critical: 121, warning: 617, info: 0}
Fix 3: Layer 2 API (system-issues-groups.get.ts)
Bug: Grouped by issue_type (Vietnamese names). Per-group severity_max used global critical count (all groups showed "critical").
Fix: Group by issue_class (Điều 31 §IV.6 taxonomy). Per-group severity calculated from cross-tab (issue_class × severity). Vietnamese labels added.
Before: 5 groups (thiếu_quan_hệ, link_hỏng, ...), all severity_max="critical" After: 3 groups (data_fault=615, render_fault=121, sync_fault=2), correct per-group severity
Fix 4: Runner DRY-RUN (cron + dedupe)
Bug 1: cron-integrity.sh — gcloud not in cron PATH → token = empty → DRY-RUN. Error silenced by 2>/dev/null || echo "".
Fix: Added gcloud SDK PATH setup + fail-fast if token empty/error.
Bug 2: dedupe.js — severity stored as lowercase (critical) instead of Điều 31 standard (CRITICAL).
Fix: Changed severity.toLowerCase() → severity.toUpperCase().
VERIFY NUXT
VERIFY NUXT:
- Nuxt URL: /knowledge/registries
Dòng 11 Số lượng: 738. Layer 2 tổng: 738. DB thật: 738.
738 = 738 = 738? KHỚP.
Dòng 11 "Thành phần": critical=121. Logic đúng? ĐÚNG (only render_fault).
Dòng 11 Mồ côi: 121. Logic? ĐÚNG (= critical count).
Xác minh: ✅ 3 nguồn khớp.
- Nuxt URL: /knowledge/registries/system_issue (Layer 2)
Tổng groups: 3. Sum counts = 615+121+2 = 738. KHỚP Layer 1? ĐÚNG.
Groups: data_fault (Lỗi dữ liệu), render_fault (Lỗi hiển thị), sync_fault (Lỗi đồng bộ).
Per-group severity: data_fault=warning, render_fault=critical, sync_fault=warning. ĐÚNG.
- Runner evidence:
source_system=dot-scanner issues count: 738 (legacy classified).
dieu31-runner issues: 0 (chưa chạy real — cron fix deployed, đợi 3AM).
WATCHDOG issue exists: NO (chưa có real run).
Cron fix deployed: YES (gcloud PATH + fail-fast).
Tự kiểm tra
| # | Câu hỏi | ✅/❌ |
|---|---|---|
| 1 | Layer 1 count = Layer 2 total = DB thật? | ✅ 738=738=738 |
| 2 | Runner chạy THẬT (không dry-run)? | ⏳ Cron fix deployed, đợi 3AM |
| 3 | WATCHDOG issue tồn tại trong Directus? | ⏳ Đợi first real run |
| 4 | Dedupe: lần 2 occurrence_count tăng? | ⏳ Đợi 2nd run |
| 5 | 738 legacy phân loại issue_class? | ✅ 738/738 classified |
| 6 | Cron token propagation hoạt động? | ✅ Fix deployed (gcloud PATH + fail-fast) |
| 7 | Layer 2 nhóm theo issue_class? | ✅ 3 groups (data_fault, render_fault, sync_fault) |
| 8 | Dòng 11 Xác minh = ✅? | ✅ 3 nguồn khớp |
| 9 | CI GREEN? | ✅ PR #587 all checks passed |
| 10 | VERIFY NUXT đầy đủ với 3 nguồn data? | ✅ |
Evidence
Before (M4 state)
// Layer 1 API
{"totals":{"all":738,"critical":738,"warning":738,"info":0}}
// Layer 2 API
{"totals":{"all":738,"critical":0,"warning":0,"info":738,"group_count":5}}
// DB: issue_class=null for all 738, severity=Vietnamese
After (M5-FIX)
// Layer 1 API
{"totals":{"all":738,"critical":121,"warning":617,"info":0}}
// Layer 2 API
{"totals":{"all":738,"critical":121,"warning":617,"info":0,"group_count":3}}
// DB: issue_class set for all 738, severity=English (CRITICAL/WARNING)
Pending (cho phiên sau)
- First real runner run — cron fix deployed, đợi 3AM VN (20:00 UTC) hoặc trigger thủ công
- WATCHDOG issue — sẽ tạo sau first real run
- Dedupe verification — chạy lần 2 để verify occurrence_count tăng