KB-2150

COUNCIL REVIEW Vòng 3 — Điều 35 v4.5 & Điều 36 v3.5 — GPT

12 min read Revision 1
council-reviewround3dieu35dieu36gpt2026-03-31

COUNCIL REVIEW VÒNG 3 — GPT

A. XÁC NHẬN 12 ĐIỂM ĐÃ FIX

Điều 35 v4.5

  1. Fix đúng§9 Bootstrap đã định nghĩa rõ ngoại lệ one-time qua migration PR, đúng tinh thần “ngoại lệ lịch sử” thay vì bypass thường trực.
  2. Fix đúng§2.3 đã tách domain format: coverage dùng domain gốc, dot_tools.domain dùng domain đầy đủ, query LIKE là nhất quán.
  3. Fix đúng§2.1 thêm trigger_type='one-off', chặn false-positive stale cho migration script.
  4. Fix đúng§2.4 chuyển “operation cần tự động” sang allowlist SSOT, không còn suy luận ở check 7.
  5. Fix đúng§8 đã ref rõ Điều 32 cần dedupe key cho APR pending.
  6. Fix đúng§9.3 có grace period 30 ngày cho paired_dot, và last_executed=NOW() khi backfill.
  7. Fix đúng§10 đã tách metrics baseline phase 1 khỏi KPI phase 2; không dùng coverage_pct làm pass/fail sớm.

Điều 36 v3.5

  1. Fix đúng§10 Bootstrap đã đóng thành 5 bước và buộc chạy cùng bootstrap Điều 35.
  2. Fix đúng§5.3 có type pre-check: trùng tên khác type = CRITICAL, KHÔNG sync.
  3. Fix đúng§2.2 thêm lifecycle active → deprecated → retired cho field standard, đúng Luật Bảo toàn.
  4. Fix đúng§5.2 check 12 đã thêm polymorphic integrity scanner.
  5. Fix đúng§10.3 chuyển KB verify thành WARNING khi 4 tầng lõi PASS.
  6. Fix đúng§5.3dry_run=true cho baseline an toàn.
  7. Fix đúng§3 đã khóa thứ tự 11a → 11b → 11c → 11d → 11e.
  8. Fix đúng§11 đã đổi phase-1 metrics thành baseline per group + pilot governed.
  9. Fix đúng§5.2 check 13 đã thêm group↔species consistency.
  10. Fix đúng§8 chốt 1 collection = 1 group, phân loại phụ qua species/labels.

B. TÌM ĐIỂM GÃY CÒN SÓT

ĐIỀU 35 v4.5

B1. Bootstrap PR cụ thể

  • 🔴 1 PR là đúng, nhưng phải chia thành 3 migration blocks trong cùng PR:

    1. schema create/add nullable,
    2. seed/backfill data,
    3. attach FK/CHECK + enable runtime.
      Nếu không chia rõ, rollback logic sẽ mù khi fail giữa chừng. §9.2 đã có thứ tự 7 bước, nhưng chưa nói cách đóng gói migration theo block có thể rerun/idempotent.
  • 🟡 Seed data chưa đủ đặc tả để người triển khai không phải đoán.
    §9.2 Bước 1 nói “seed 11 domain gốc + sub-domains” nhưng không chốt danh sách record tối thiểu cho bootstrap PR. Phase này cần danh sách seed đóng băng, không chỉ mô tả văn xuôi. Nếu không, hai agent có thể seed khác nhau mà đều tưởng đúng.

  • 🟡 Bootstrap DOT set 6 tool là hợp lý nhưng chưa được viết thành danh sách tối thiểu bất biến.
    §9.2 Bước 5 liệt kê 6 DOT, nhưng chưa nói rõ có cần expire hay runner phụ trợ nào nữa không vì Bước 6 đã nêu expire 5AM. Nếu cron expire tồn tại mà DOT tương ứng chưa seed trong bootstrap set thì đây là lệch runtime.

B2. SQL migration cụ thể

  • 🔴 dot_tools.domain phải nullable cho đến sau Bước 3 backfill xong hoàn toàn.
    §9.2 Bước 2 đã nói nullable, đúng. Nhưng chưa nêu rõ field nào không được attach default sai. tier, domain, operation, paired_dot, last_executed, coverage_status đều không nên có default “đẹp giả” ngoài last_executed seed NOW ở §9.3. Nếu set default sớm, metrics baseline sẽ bị ô nhiễm.

  • 🔴 CASE backfill cho 154 DOT sẽ có record không khớp naming convention.
    §5.3 đã thừa nhận naming chỉ là gợi ý. Vì vậy §9.2 Bước 3 cần nói rõ: “unmatched → domain='governance.review' hoặc NULL?” Hiện chưa chốt fallback giá trị lưu DB khi parse fail. Nếu để NULL rồi attach FK/CHECK, migration có thể fail; nếu gán domain bừa thì vi phạm NT-9.

  • 🟡 Rollback strategy khi 5 DOT backfill sai domain chưa thành văn.
    §9.2 Bước 4 attach FK sau clean là đúng, nhưng chưa nói rõ khi FK fail thì rollback cả transaction hay ghi ra report và stop trước attach. Trên production, chiến lược đúng phải là: pre-check query → fail fast trước ALTER TABLE ... ADD CONSTRAINT.

B3. Runtime interactions

  • 🟡 3AM dot-dot-health và 4AM dot-collection-health không đụng trực tiếp, nhưng vẫn có contention ở system_issuesapproval_requests nếu run time kéo dài >1h.
    Trên VPS $8, quét 154 DOT + 138 collections + KB/API checks có thể kéo dài bất thường. Luật chưa có “single-flight” hoặc lock cơ bản để chặn scanner sau chạy khi scanner trước còn sống.

  • 🔴 dot-collection-field-sync event trigger có thể bị bắn 3 lần đồng thời nếu INSERT 3 Tier 2 records trong một phiên.
    §5.3 của Điều 36 có dry_run, nhưng chưa có batching/debounce. Nếu event trigger fire per row, cùng lúc 3 sync jobs sẽ cùng chạm Directus Fields API. Đây là điểm gãy production thật.

  • 🟡 Report files chưa có retention policy.
    Điều 35 §5.1 và Điều 36 §5.2 đều ghi JSON reports theo ngày. Chưa có quy định retention/compress/logrotate. Trên 1 VPS nhỏ, đây là debt vận hành chắc chắn xảy ra.

B4. Kiểm tra chéo Điều 32

  • 🔴 Dedupe key đề xuất ở Điều 32 vẫn CHƯA ĐỦ nếu không có source hoặc issue_signature.
    UNIQUE(request_type, target_collection, target_entity_code) WHERE status='pending' sẽ gộp nhầm hai vấn đề khác nhau trên cùng entity. Ví dụ cùng request_type='reclassify' cho 1 DOT nhưng một APR do dot-dot-health tạo vì unpaired, một APR do scanner khác tạo vì misassigned — key hiện tại không phân biệt được.

  • 🟡 DOT B pending duyệt phụ thuộc SLA review của Desktop nhưng luật chưa gắn timeout xử lý riêng cho new_dot.
    Nếu dùng timeout/expire chung Điều 32, DOT B có thể expire trước khi được duyệt, gây tình trạng PR đã sẵn nhưng APR chết. Cần rule rõ: new_dot có expiry riêng hoặc queue ưu tiên.

B5. Worst-case scenario

  • 🔴 Worst case 1: bootstrap PR merge xong nửa chừng, scanner chạy trên schema trung gian.
    Recovery path chưa được viết thành luật: phải có cờ “bootstrap_in_progress” hoặc đơn giản hơn là cấm cron cho đến sau Bước 7 Verify. Nếu không, dot-dot-health sẽ báo loạn orphan/partial/phantom trên chính giai đoạn bootstrap.

  • 🟡 Worst case 2: retire move file OK nhưng cron delete fail.
    §6.2 yêu cầu xoá cron entry, nhưng chưa có verify nguồn chân lý cron. Nếu cron sống còn file đã move, runtime sẽ spam lỗi. Cần scanner phụ check “cron target tồn tại thật”.

  • 🟡 Worst case 3: last_executed=NOW() seed làm baseline đẹp giả cho cron hỏng lâu nay.
    Đây là fix hợp lý để không phạt quá khứ, nhưng cũng che mất DOT đã chết từ trước bootstrap. Nên chấp nhận, nhưng cần ghi rõ đây là “reset đồng hồ vận hành” chứ không phải bằng chứng DOT khoẻ.


ĐIỀU 36 v3.5

B1. Bootstrap PR cụ thể

  • 🔴 Điều 36 phải nằm trong CÙNG bootstrap PR với Điều 35, nhưng thứ tự liên PR chưa được viết rõ.
    Đúng thứ tự nên là:

    1. seed collection_groups,
    2. seed collection_field_standards,
    3. gán group cho 138 collections,
    4. attach FK collection_registry.group,
    5. health baseline,
    6. field-sync dry_run.
      Nếu chạy dry_run trước khi FK group attach xong, kết quả scope sẽ không đáng tin.
  • 🟡 Seed data cũng chưa đóng băng đủ chi tiết.
    §10.2 nói seed 9 groups + 8 Tier 1 + 3 Tier 2. Về mặt vận hành, con số đủ nhưng cần danh sách record chuẩn trong PR. Nếu không, mỗi agent sẽ tự viết seed hơi khác.

B2. SQL migration cụ thể

  • 🔴 UPDATE collection_registry SET group = CASE ... là bước rủi ro nhất của Điều 36.
    §10.2 Bước 2 nói “dựa trên species + governance_role + naming convention hiện có” và review sample 20 collections trước khi update toàn bộ. Điểm gãy ở đây là: nếu collection_registry đang có NULL/group text cũ không nhất quán, việc CASE map sai sẽ làm Bước 3 FK attach fail toàn cục. Cần pre-check report 138 rows trước khi UPDATE thật.

  • 🔴 Type pre-check đã tốt, nhưng chưa nói rõ conflict report có block riêng theo collection hay block toàn batch.
    §5.3 nói conflict = CRITICAL, không sync. Nhưng nếu 1 collection conflict owner:string vs owner:json, còn 99 collection khác sạch, sync có nên chạy cho 99 collection kia không? Luật chưa chốt. Nếu block toàn batch, production rollout sẽ rất chậm; nếu skip per collection, cần nói rõ.

B3. Runtime interactions

  • 🔴 Field-sync event trigger có nguy cơ N jobs đồng thời cho N INSERT standards.
    Điều 36 đã có dry_run, nhưng chưa có debounce/batch. Nếu seed 3 Tier 2 standards cùng lúc, 3 jobs event-driven sẽ cùng quét 138 collections. Đây là race condition và là điểm gãy thật trên VPS nhỏ.

  • 🟡 4AM dot-collection-health và field-sync event có thể đá nhau.
    Nếu health chạy giữa lúc field-sync đang thêm field, health sẽ ghi false-positive col_missing_* rồi tạo APR sai. Cần lock/mode maintenance hoặc checkpoint “sync in progress”.

  • 🟡 KB verify = WARNING là đúng, nhưng WARNING này có thể tích tụ vô hạn nếu Agent Data degraded kéo dài.
    Chưa có escalation policy: bao nhiêu lần kb_sync_pending liên tiếp thì nâng từ warning lên critical?

B4. Kiểm tra chéo Điều 32

  • 🔴 APR dedupe key hiện tại chưa đủ cho Điều 36 nữa, không chỉ Điều 35.
    Cùng một collection có thể có nhiều APR new_field_standard hoặc reclassify với issue khác nhau. Nếu key thiếu issue_signature hoặc proposed_action_hash, dedupe sẽ gộp nhầm hoặc chặn sai.

  • 🟡 Legacy 3 pha sinh rất nhiều APR auto-approve.
    Nếu Điều 32 không có queue priority hoặc rate limit, backlog APR có thể thành flood và làm khó review của Desktop cho các APR thật sự quan trọng.

B5. Worst-case scenario

  • 🔴 Worst case 1: field-sync thêm classification vào collection live, Directus cập nhật xong nhưng app/UI/cache chưa phản ánh đồng bộ.
    §10.3 chỉ nói KB warning, chưa nói graceful handling cho Directus/Nuxt cache trễ. Nếu user thấy field trống hoặc form lỗi trong vài phút, recovery path là gì? Luật chưa quy định maintenance window hoặc rollout theo pilot collection.

  • 🔴 Worst case 2: bootstrap PR merge xong, sync_field_standards=false gán sai cho 1 group nhạy cảm.
    Khi đó event sync sẽ đẩy field vào collections đáng lẽ phải skip. Recovery hiện mới có lifecycle cho standard field, không có rollback policy cho field đã lỡ thêm hàng loạt ngoài scope.

  • 🟡 Worst case 3: polymorphic integrity check 12 chạy trên dataset lớn có thể đắt nếu không có index (entity_type, entity_id).
    Luật có logic nhưng chưa nhắc index tối thiểu cho polymorphic tables. Đây là điểm gãy performance, không phải logic.


C. PHÁN QUYẾT CUỐI

Phán quyết: SẴN SÀNG CÓ ĐIỀU KIỆN

Điều kiện bắt buộc trước khi ban hành/giao CLI agent triển khai

  1. Bổ sung vào Điều 32 dedupe key đầy đủ hơn: không chỉ (request_type, target_collection, target_entity_code) mà cần thêm issue_signature hoặc source + issue_signature.
  2. Viết thành văn cơ chế chống chạy đồng thời cho:
    • dot-dot-health vs scanner khác
    • dot-collection-health vs dot-collection-field-sync
    • nhiều event sync cùng lúc khi insert nhiều standards
  3. Đóng băng seed bootstrap records trong PR: danh sách 11 domain gốc/sub-domains, 9 groups, 8 Tier 1 + 3 Tier 2, bootstrap DOT set.
  4. Thêm rule “không bật cron/scanner cho đến sau bootstrap verify xong” để tránh báo loạn trên schema trung gian.
  5. Chốt runtime policy cho field-sync conflict scope: conflict block toàn batch hay skip per collection. Em nghiêng về skip-per-collection + report critical.

Vì sao không chấm “Sẵn sàng ban hành” ngay

Không còn lỗi cấu trúc. Bootstrap, metrics, lifecycle, KB warning, type pre-check, polymorphic check đều đã sửa đúng. Phần còn lại là điểm gãy production-level nhỏ nhưng đủ làm fail một phiên triển khai thật: dedupe APR chưa đủ khóa, concurrent jobs chưa có cơ chế chặn, seed bootstrap chưa đóng băng, và scanner có thể chạy sớm hơn bootstrap.

Nếu vá 5 điều kiện trên, em xem cặp Điều 35 v4.5 + Điều 36 v3.5 là đủ an toàn để giao CLI agent triển khai production theo pha.