CHUOI BAT BUOC (v2 §3.3 + §2.4(4)): fire -> chung-kien -> ROI MOI va -> het fire.
CAM va permission-matrix TRUOC = mat chinh bang-chung detector co rang.
TRUOC (capture ra runs/<id>/W4-detector-fire-15-07-2026.md muc 1-5, fix#9c time-anchored):
MED :3 writes 60 menu but canonical=54
MED :3 writes 240 policy but canonical=216
MED :16 writes 60 menu but canonical=54
LOW :81 writes 48 policy but canonical=216
LOW :16 title-stale anchor 2026-04-30 vs 2026-07-15 (76d)
TOTAL FLAGS: 50 <- khop CHINH XAC du-bao W2 (WAL:17 "49->50, -1 cadence +2 policy")
SAU: permission-matrix 0 FLAG | TOTAL 45 | tut dung 5 | 0 flag moi (do bang `comm`, khong dem mat).
CACH VA = B1 bo so + tro canonical, KHONG doi so (doi so thi lan sau lai stale).
Dung dung loi khuyen detector tu in: "OR replace with pointer '-> docs/STATUS.md'".
CHUOI NHAN-QUA W1<->W2 chung duoc 3 detector doi trang-thai DUNG thiet-ke:
- h24_cadence: "missing => measuring NOTHING" -> "M = light_every = 6 (read from config)"
- spawn-model-audit: "expected constant missing" -> "[OK] claude-opus-4-8 = owner-ratified"
- GAP-3 policy: "policy=MISSING" -> "216" + BAT NGAY permission-matrix:3
=> truoc W2, nua policy KHONG THE fire vi STATUS khong co row Policies => detector IM,
va su im-lang do trong y HET nhu "sach". Detector khong co nguon chuan = do NOTHING.
STALE NANG HON CON-SO (tim duoc luc va, detector count-token KHONG bat duoc):
SKILL.md:20 liet "Budgets root + 3 Bg_*" nhu menu DANG SONG.
Do dia: module Budget XOA tu S61 (Mig 50); 2 hit Bg_ con lai = COMMENT BIA-MO
(MenuKeys.cs:70 + fe-{admin,user}/src/lib/menuKeys.ts:29). Code sach, chi skill con mo-ta.
=> gioi-han detector dem-so: thay "60 != 54" nhung khong thay "4 trong 60 do da bi xoa 60 phien truoc".
DUONG-GIA CAU-TRUC (khai, KHONG sua -- doi hanh-vi detector = quyen anh/W5):
lead-view-auditor.md:45 FIRE title-stale vi bang vi-du cua no chua "2026-04-30" lam MAU
minh-hoa cho class view-stale-header. Cung CO-CHE voi loi da lam acceptance FIX#6 bat-kha-thi
(:47 chua "12 sub ... roster = 14" lam vi-du). 2 detector DOC-LAP, cung 1 file, cung 1 ly-do:
VI-DU VE STALE TRONG Y HET STALE. File dinh-nghia anti-pattern tat-yeu chua mau anti-pattern.
De-xuat (khong tu lam): detector can co-che mien-tru tuong-minh cho khoi vi-du.
LEAD TU BAT 2 LOI @W4:
(a) WAL ghi "permission-matrix 6 dong" -- that la 5 (dong :70 = context, khong phai flag).
Loi dem lan thu 3 trong phien; lan nay bat TRUOC khi thanh claim gui hub.
(b) Suyt claim au canonical: grep tho MenuKeys.cs ra 64 chuoi -> SAI (dem MOI chuoi trong file,
khong phai phan-tu mang All). W2 ground dung: |MenuKeys.All|=54 (:147) x |Actions|=4 = 216.
Lead BO so cua minh, dung so W2. Bai hoc: do bang cong-cu sai con te hon khong do --
vi no ra mot con-so TRONG CO VE do duoc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.5 KiB
W4 — detector-fire evidence (positive-control) · 2026-07-15 S122
🔴 CAPTURE TRƯỚC KHI VÁ. Đây là bằng-chứng time-anchored thay cho "reviewer chứng-kiến" làm neo duy-nhất (spec v3 fix #9(c)). Luật W4 (v2 §3.3 + §2.4(4)):
fire → chứng-kiến → RỒI MỚI vá → hết fire. 🔴 CẤM vápermission-matrixTRƯỚC — vá trước thì detector chạy xong xanh lè và ta mất chính bằng-chứng rằng nó có răng. Lệnh:powershell.exe -ExecutionPolicy Bypass -File scripts/governance-detectors.ps1· exit = 0 (DETECT-only, advisory, không fail build).
1. 🔴 POSITIVE-CONTROL FIRE — permission-matrix/SKILL.md (chạy TRƯỚC mọi sửa đổi)
[DETECTOR] MED | .claude/skills/permission-matrix/SKILL.md:3 | derived-stale: writes 60 menu but canonical=54 | resolve: update to 54 OR replace with pointer '-> docs/STATUS.md'
[DETECTOR] MED | .claude/skills/permission-matrix/SKILL.md:3 | derived-stale: writes 240 policy but canonical=216 | resolve: update to 216 OR replace with pointer '-> docs/STATUS.md'
[DETECTOR] MED | .claude/skills/permission-matrix/SKILL.md:16 | derived-stale: writes 60 menu but canonical=54 | resolve: update to 54 OR replace with pointer '-> docs/STATUS.md'
[DETECTOR] LOW | .claude/skills/permission-matrix/SKILL.md:81 | derived-stale: writes 48 policy but canonical=216 | resolve: update to 216 OR replace with pointer '-> docs/STATUS.md'
[DETECTOR] LOW | .claude/skills/permission-matrix/SKILL.md:16 | title-stale: anchor says 2026-04-30 but newest governance milestone is 2026-07-15 (76d behind)
= 5 FLAG (2 MED + 3 LOW).
🔸 Đính-chính con-số của LEAD: WAL ghi "permission-matrix 6 dòng" — đếm thật = 5 flag. Dòng thứ 6 (:70 anchor 2026-04-30 … SKILL.md:16) là dòng context trong khối tóm-tắt anchor, KHÔNG phải flag. (Lỗi đếm-của-lead, bắt được TRƯỚC khi thành claim gửi hub — nhưng vẫn là lỗi, → adap-report.)
2. ✅ TOTAL = 50 — khớp CHÍNH XÁC dự-báo W2
TOTAL FLAGS: 50
NOTE: DETECT-only lowering net. Exit 0 always (never fails build). FLAGs are advisory.
WAL:17 (W2) dự-báo: "TOTAL 49→50 (−1 cadence, +2 policy)". Đo ra đúng 50. ⇒ hợp-đồng chéo W1↔W2 khép cả hai chiều, đo bằng chính script W1.
3. ✅ Chuỗi nhân-quả W1↔W2 — 3 detector đổi trạng-thái ĐÚNG như thiết-kế
| Detector | TRƯỚC W2 | SAU W2 | Ý-nghĩa |
|---|---|---|---|
h24_cadence |
missing — W2 chưa land ⇒ measuring NOTHING |
M = light_every = 6 (read from config) |
fail-loud tắt đúng lúc key land — không giả-định default |
spawn-model-audit |
expected constant missing |
[OK] claude-opus-4-8 = owner-ratified |
PA-2a hằng-số nhận diện được |
| GAP-3 policy | policy=MISSING |
216 + BẮT NGAY permission-matrix:3 writes 240 but canonical=216 |
🔴 row STATUS Policies land ⇒ detector LẬP TỨC có canonical để so ⇒ lộ stale ẩn 76 ngày |
🔴 Dòng cuối là điểm mấu-chốt: trước W2, nửa policy của GAP-3 KHÔNG THỂ fire vì docs/STATUS.md không có row Policies ⇒ detector không có gì để so ⇒ im lặng, và sự im-lặng đó trông y hệt "sạch". Thêm canonical ⇒ 2 flag mới hiện ra ngay. Bài học: detector không có nguồn chuẩn = detector đo NOTHING, và nó không tự nói cho biết.
4. 🔴 PHÁT-HIỆN NGOÀI SCOPE W4 — vai H24 bị chính detector bắt
[DETECTOR] LOW | .claude/agents/lead-view-auditor.md:45 | title-stale: anchor says 2026-04-30 but newest governance milestone is 2026-07-15 (76d behind)
Đây là DƯƠNG-GIẢ. lead-view-auditor.md:45 chứa **Status (post Session 6 — 2026-04-30):** làm VÍ-DỤ minh-hoạ cho class view-stale-header trong bảng flag-class của chính nó. Detector đọc ngày trong ví-dụ và tưởng là anchor thật của file.
🔴 Cùng CƠ-CHẾ với lỗi đã làm acceptance FIX#6 bất-khả-thi (lead-view-auditor.md:47 chứa "agents/README ghi 12 sub khi roster = 14" làm ví-dụ ⇒ sweep-pattern bắt). Hai detector ĐỘC-LẬP, cùng một file, cùng một lý-do:
Ví-dụ về stale trông y hệt stale. File định-nghĩa anti-pattern tất-yếu chứa mẫu anti-pattern ⇒ mọi detector khớp-mẫu sẽ bắt nó. Đây KHÔNG phải lỗi của vai, cũng KHÔNG phải lỗi của detector — là hệ-quả cấu-trúc của việc dò bằng khớp-mẫu.
Vì sao KHÔNG "sửa" bằng cách đổi ví-dụ: ví-dụ mất tính cụ-thể thì bảng flag-class mất giá-trị dạy-nghề (vai đọc "con-số lệch thực-tế" mà không có mẫu thật thì tự chế class — đúng thứ enum-ĐÓNG sinh ra để chặn). Xử @S122: giữ ví-dụ, khai vào đây + adap-report. Đề-xuất hướng (KHÔNG tự làm — đổi hành-vi detector = quyền anh / W5): detector cần cơ-chế miễn-trừ tường-minh cho khối ví-dụ (vd fenced-block hoặc allowlist path), thay vì bắt lead nhớ né.
🔸 2 flag title-stale KHÁC là THẬT, ngoài scope W4 (không đụng): form-engine/SKILL.md:15 (anchor 2026-04-30) · docs/rag-setup-plan.md:4 (anchor 2026-05-12).
🔸 ef-core-migration/SKILL.md:167/:184 writes 1 migration but canonical=66 = DƯƠNG-GIẢ (cụm "1 migration" trong câu văn) — chính script tự khai: "count-token grep is a soft net — module-local phrases … can false-positive; H18-A ratio-band demotes far-from-canonical counts to LOW = review-not-fail". LOW = đọc-bằng-phán-đoán, không auto-fix.
5. Nấc trung-thực của chính W4
- Detector = DÒ + NÊU CỜ, KHÔNG tự sửa (tầng D6).
exit 0luôn luôn — advisory, không chặn build. - Fire ≠ chứng minh detector tốt — chỉ chứng nó đọc được và có canonical để so. Chất-lượng thật đo ở tỉ-lệ dương-giả (mục 4 = 1 dương-giả cấu-trúc đã lộ).
- Bước kế: vá
permission-matrix→ chạy lại → 5 flag đó PHẢI biến mất (và TOTAL tụt tương-ứng). Nếu vá xong mà vẫn fire ⇒ vá sai chỗ. Nếu TOTAL không tụt đúng số ⇒ có gì đó khác đã đổi ⇒ điều-tra, đừng làm tròn.
6. ✅ SAU KHI VÁ — chu-trình khép, số cộng KHỚP
permission-matrix : 5 FLAG → 0 FLAG
TOTAL : 50 → 45 (tụt ĐÚNG 5)
Flag MỚI xuất-hiện: 0
Diff đo bằng comm (không đếm bằng mắt): đúng 5 dòng biến mất — :3×2 · :16×2 · :81×1 — 0 dòng thêm. ⇒ bản vá không đụng gì ngoài phạm-vi; TOTAL tụt đúng bằng số flag đóng, không phải trùng-hợp làm-tròn.
Cách vá = B1 (bỏ số, trỏ canonical), KHÔNG phải đổi số:
| Dòng | Trước | Sau |
|---|---|---|
:3 description |
~60 menu key … ~240 policy |
bỏ số → "số menu-key · policy canonical → docs/STATUS.md" |
:16 Status |
(post Session 6 — 2026-04-30) + ~60 menu key total |
anchor 2026-07-15 — S122 W4 + trỏ canonical + chỉ ghi HÌNH-DẠNG nhóm, không ghi số |
:81 |
register 48 policy |
register policy {menu}.{action} + khai DERIVED = |MenuKeys.All| × |Actions| |
🔴 Đổi số thì lần sau lại stale — bỏ số thì hết stale vĩnh-viễn. Đây cũng đúng lời khuyên detector tự in: "resolve: update to 54 OR replace with pointer '-> docs/STATUS.md'" — chọn vế sau.
7. 🔴 STALE NẶNG HƠN CON-SỐ (tìm được lúc vá, ngoài 5 flag)
SKILL.md:20 liệt Budgets root + 3 Bg_* (List/Create/Pending) + :23 "Budgets KHÔNG inherit (Bg_ phải grant tay)"* — như menu ĐANG SỐNG.
Đo đĩa: module Budget XOÁ từ S61 (Mig 50). Hai hit Bg_ còn lại trong mã = comment bia-mộ: MenuKeys.cs:70 "[S61 Mig 50] Module Ngân sách cũ (Budgets + Bg_List/Bg_Create/Bg_Pending)" · fe-{admin,user}/src/lib/menuKeys.ts:29 "… XÓA — thay bằng bảng". Code sạch; chỉ skill còn mô-tả.
🔴 Detector count-token KHÔNG bắt được cái này — nó so con-số, mà đây là thực-thể không tồn tại. Skill mô-tả sai suốt S61 → S122. ⇒ giới-hạn của detector đếm-số: nó thấy "60 ≠ 54" nhưng không thấy "4 trong 60 cái đó đã bị xoá 60 phiên trước". Vá @S122 W4 (🧊-mark, giữ bia-mộ để tra-cứu).
8. Lead tự-bắt trong W4 (→ adap-report)
- WAL ghi "permission-matrix 6 dòng" — thật 5. Dòng thứ 6 (
:70) là context trong khối tóm-tắt anchor, không phải flag. (Bắt được TRƯỚC khi thành claim gửi hub — nhưng vẫn là lỗi đếm, lần thứ 3 trong phiên.) - Suýt claim ẩu về canonical: lead grep thô
MenuKeys.csra 64 chuỗi rồi định dùng làm số. SAI — grep đếm mọi chuỗi trong file, không phải phần-tử mảngAll. W2 ground đúng:|MenuKeys.All|= 54 (MenuKeys.cs:147) ×|Actions|4 = 216. ⇒ Lead bỏ số của mình, dùng số W2. Bài học: đo bằng công-cụ sai còn tệ hơn không đo — vì nó ra một con-số trông có vẻ đo được.
Capture @S122 /tiep W4 · mục 1-5 ghi TRƯỚC mọi sửa đổi (TOTAL 50) · mục 6-8 ghi SAU (TOTAL 45) · exit 0 cả 2 lần