KB-4E09

Báo cáo kỹ thuật — H11 Split Deployment Gap

5 min read Revision 1
bugfix28H11deployment-gapassembly-first

BÁO CÁO KỸ THUẬT — H11 Split Deployment Gap

Phiên: S178 Fix 28 | Ngày: 2026-04-22 Phát hiện bởi: Agent CLI (chạy prompt auto-heal) + Desktop review Mức độ: BLOCKING — chặn auto-heal H11a, có thể chặn cả detect hiện tại


1. VẤN ĐỀ

Đ43 §9.1 (rev 51, Fix 28) đã amend tách H11 → H11a + H11b. Luật enacted, KB docs tạo, queries chạy được. Nhưng bảng system_health_checks trên production vẫn chỉ có 1 row H11 cũ. Không có row H11a, H11b.

Executor dot-hc-executor dispatch theo rows trong system_health_checks. Nó không biết H11a/H11b tồn tại → không bao giờ chạy queries tách biệt → chuông phân biệt "hạ tầng hỏng" (CRITICAL) vs "chưa enrichment" (WARNING) chưa bao giờ hoạt động trên production.

Thêm nữa: row H11 cũ có threshold_config = {"warn_threshold": 0} — có thể không khớp dispatch_sql contract của executor (đòi threshold, comparator, result_field). Nếu đúng → H11 đang silently fail → executor bỏ qua → description coverage hoàn toàn mù.

2. NGUYÊN NHÂN GỐC

Vi phạm NT8 Assembly First: Sửa từ trên xuống thay vì từ dưới lên.

Tầng Đã làm Thiếu
Luật (Đ43 §9.1) ✅ Amend tách H11a/H11b
KB docs (query SQL) ✅ Upload h11a + h11b queries
KB docs (report) ✅ Chạy ad-hoc, đếm H11a=0, H11b=1238
PG (system_health_checks) ❌ CHƯA LÀM INSERT H11a, INSERT H11b, DEACTIVATE H11 cũ
Executor config ❌ CHƯA LÀM threshold_config khớp dispatch_sql contract

Assembly First = PG trước, rồi KB, rồi luật. Chúng ta làm ngược: luật → KB → quên PG.

Tại sao bị sót: §VIII bước 8 giao agent "upload 2 SQL queries KB" — agent hiểu đúng chỉ dẫn (upload KB docs), nhưng prompt không yêu cầu INSERT rows vào system_health_checks. Prompt thiếu, không phải agent sai. Desktop review kết quả cũng không phát hiện vì chỉ kiểm tra "H11a/H11b KB uploads = 2 (200 OK)" mà không verify PG rows.

3. ẢNH HƯỞNG

Hệ quả Mức độ
Chuông H11a (CRITICAL) chưa bao giờ kêu trên production Nghiêm trọng — hạ tầng hỏng mà không ai biết
Chuông H11b (WARNING) chưa bao giờ kêu trên production Trung bình — enrichment tracking mù
H11 cũ có thể silently fail Nghiêm trọng — description coverage hoàn toàn mù
Auto-heal H11a bị block Block — không có row H11a để upgrade detect_and_fix

Hiện tại H11a = 0 findings (đã backfill hết). Nên impact thực tế = 0 ngay bây giờ. Nhưng nếu entity mới lọt (trigger hỏng) → không ai phát hiện.

4. ĐỀ XUẤT GIẢI QUYẾT — Prompt phiên sau gộp 2 việc

Việc 1: Split H11 → H11a + H11b trong PG (PHẢI LÀM TRƯỚC)

  • INSERT row H11a vào system_health_checks: code='H11a', name='Description Basic Missing', executor_type='sql', executor_ref trỏ KB query h11a, severity_on_fail='critical', check_kind='detect_only' (tạm), threshold_config khớp dispatch_sql contract
  • INSERT row H11b: code='H11b', name='Description Detail Missing', executor_type='sql', executor_ref trỏ KB query h11b, severity_on_fail='warn', check_kind='detect_only', threshold_config khớp dispatch_sql contract
  • UPDATE row H11 cũ: is_active = false (không DROP — giữ trace)
  • Verify: executor chạy 1 lần → H11a + H11b dispatch đúng, H11 cũ skip, không silently fail
  • Kiểm tra threshold_config contract: đọc source code dot-hc-executor xem dispatch_sql expect format nào → seed đúng format

Việc 2: Upgrade H11a → detect_and_fix (auto-heal)

  • UPDATE row H11a: check_kind='detect_and_fix', auto_fix_action có giá trị
  • Config gate: dot_config key hc_*_autofix_enabled = 'false' → flip 'true' sau verify
  • Handler trong executor: đọc findings → UPDATE description = '' (dùng PK introspection, KHÔNG hardcode WHERE code =) → trigger auto-gen → caller INSERT PROV-DOT (R2 P9)
  • Test end-to-end

Thứ tự bắt buộc: Việc 1 TRƯỚC Việc 2. Không có phòng H11a trong PG → không thể upgrade.

5. BÀI HỌC

  1. Review kết quả agent phải verify PG rows, không chỉ KB uploads. "200 OK" từ KB API ≠ production sẵn sàng.
  2. Assembly First áp dụng cả khi amend luật: sửa luật xong → verify PG đã có rows tương ứng → rồi mới declare "DONE".
  3. Prompt phải ghi rõ TẤT CẢ tầng cần sửa (PG + KB + executor + luật). Bỏ sót 1 tầng = hệ thống gãy giữa các tầng.

S178 Fix 28 | 2026-04-22