13 KiB
sub-task-0 — LANE W1-① : scripts/governance-detectors.ps1
Role: implementer · Run: 2026-07-15-S119-adap-6-broadcast · Lane: W1-①
File EDITed (only): scripts/governance-detectors.ps1 (455 → 715 lines, +267/−7)
VERDICT: 3/3 việc DONE · fault-inject PASS 2 chiều · TOTAL FLAGS 42 → 49 · exit 0 · non-ASCII 0
0. 🔴 4 tiền-đề trong TASK-BRIEF SAI so với đĩa (re-verify từ disk, memory feedback_resume_premise_reverify)
| # | Brief nói | Đĩa thật | Bằng chứng | Xử lý |
|---|---|---|---|---|
| P1 | config = .claude/memory-budget.json |
KHÔNG tồn tại. Thật = .claude/agent-memory/memory-budget.json |
find . -iname '*memory-budget*' → ./.claude/agent-memory/memory-budget.json |
Probe 2 path, agent-memory/ TRƯỚC; in path đã resolve |
| P2 | STATUS.md:6 ⇒ in 2026-07-14 |
2026-07-15 |
git show 3fde8af:docs/STATUS.md = 07-14 → commit 4727d16 (hôm nay 11:20:29, S119 doc-update) đổi thành 07-15 |
KHÔNG sửa STATUS (cấm + = bịa). Detector in 07-15 = ĐÚNG |
| P3 | HANDOFF chưa backfill [carry:*] ⇒ 0-fire |
ĐÃ backfill — 7 khoá | grep -o '\[carry:[^]]*\]' docs/HANDOFF.md | wc -l = 8 (7 thật + 1 literal format-spec) |
Vacuous vẫn đúng nhưng lý-do KHÁC (§4) |
| P4 | HANDOFF:5 ≈ 46 735 ký-tự | 46 493 ký-tự (drift nhẹ) | python len() |
Không ảnh hưởng |
⚠️
grep -cđếm DÒNG không đếm occurrence → trên mega-line trả1⇒ dễ kết luận nhầm "chưa backfill". Phảigrep -o … | wc -l.
1. (A) GAP-3 — +2 token canonical
Get-StatusValue cũ resolve 4 token (:154-157). Thêm menu + policy qua map $canonRows (:170-198).
Tên row ĐỌC TỪ ĐĨA, không đoán:
menu→| Menu keys | **54** |=docs/STATUS.md:19✅ tồn tạipolicy→| Policies | **216** |❌ CHƯA có (W2 mới thêm — spec v2:197)
Row thiếu ⇒ FAIL-LOUD + SKIP (không crash, không im-lặng-xanh):
[DETECTOR] MED | docs/STATUS.md | canonical row missing: no '| Policies | **<n>** |' row in
CURRENT STATE -> token 'policy' UNRESOLVED and SKIPPED (scanning nothing, NOT green)
Làm generic cho cả 6 token ⇒ row nào mất cũng kêu (0 flag mới cho 4 token cũ vì row đủ).
stdout thật:
STATUS.md canonical: mig=66 test=509 gotcha=82 table=89 menu=54 policy=MISSING
menu fire 2 flag thật: permission-matrix/SKILL.md:3 + :16 — “~60 menu key” vs canonical 54.
2. (B) Detector title-freshness — H24-1
anchor_patterns[]= MẢNG 2 DẠNG (fix C2 quan trọng nhất của lane):\*\*Last updated:\*\*\s*(\d{4}-\d{2}-\d{2})\*\*Status \(post Session \d+ <EM-DASH> (\d{4}-\d{2}-\d{2})\)\:\*\*
- Em-dash XÁC MINH BYTE, không đoán —
grep … | xxd:6f 73 74 20 53 65 73 73 69 6f 6e 20 36 20e2 80 9420 32 30 32 36…⇒ U+2014 ✔ (không phải hyphen) → build runtime$EM_DASH = U @(0x2014)(thân .ps1 ASCII-only, gotcha #30) grep "Last updated" .claude/skills/= 0 hit ⇒ xác nhận: 1-regex + “không anchor ⇒ bỏ qua” sẽ giết chính positive-control ⇒ W4 bất-khả-thi.
🔴 PARSE NEO-PHẠM-VI — vì sao load-bearing (ĐO THẬT)
docs/STATUS.md:6 = 69 870 ký-tự / 41 date-token. Cả 3 chuỗi cấm đều NẰM TRÊN LINE 6:
| token | nguồn thật |
|---|---|
2026-08-01 |
hạn audit tháng tới = TƯƠNG-LAI |
1987-03-07 |
cắt từ mark-id RC-pqhuy**1987-03-07**-2026-… |
2026-20-42 |
cắt từ mark-id …-**2026-20-42**-… — tháng 20 ngày 42 |
grep -o '[0-9]{4}-[0-9]{2}-[0-9]{2}' | sort | tail → 2026-20-42.
⇒ regex “ngày bất kỳ” lấy max ⇒ mốc-phải = rác/tương-lai ⇒ trái < phải không bao giờ đúng ⇒ 0 flag vĩnh viễn = tự bóp chết positive-control mà vẫn xanh.
⇒ Fix: capture chỉ ngày dính anchor + TryParseExact (loại thẳng tháng-20/ngày-42).
- mốc-phải = MAX ngày-anchor hợp-lệ toàn corpus =
2026-07-15@docs/STATUS.md:6 docs/_archive/LOẠI KHỎI detector này — snapshot đóng-băng có chủ-đích; “resolve = refresh ngày” sẽ phá chính bản ghi lịch-sử ⇒ flag không-thể-giải = nhiễu vĩnh-viễn. 🔴 Loại CỤC-BỘ ($TitleFreshSkip), KHÔNG đụngTest-Excludedglobal → C1/C3 giữ nguyên baseline (nới global = đổi baseline lane khác = vượt quyền). Khai thật: giữ_archivesẽ +2 flag (47→49… thực ra 49→51). Loại đi vẫn đạt ≥46 ⇒ không có mâu thuẫn số/đúng-đắn.
stdout thật:
anchors parsed: 5 doc(s) ; moc-phai (newest governance milestone) = 2026-07-15 from docs/STATUS.md:6
anchor 2026-07-15 docs/STATUS.md:6
anchor 2026-07-15 docs/HANDOFF.md:5
anchor 2026-05-12 docs/rag-setup-plan.md:4
anchor 2026-04-30 .claude/skills/permission-matrix/SKILL.md:16
anchor 2026-04-30 .claude/skills/form-engine/SKILL.md:15
✅ permission-matrix/SKILL.md FIRE (76d behind). KHÔNG sửa file đó (W4 sở-hữu: fire → reviewer chứng-kiến → rồi mới vá).
📌 Cảnh báo cho W4:
docs/changelog/skill-audit-2026-05-late.md:43có phán-quyết audit CŨ ghi đúng anchor này là “section header timestamp historical, KHÔNG drift”. H24/W4 lật lại là đổi-chính-sách có chủ-đích — nhưng nên biết là đang lật, không phải phát-hiện-mới.
3. (C) Detector carry-age — H24-2 (INFORM-only)
M=h24_cadence.light_everyđọc từ.claude/agent-memory/memory-budget.json. 0 số nhịp hardcode.- Shape canonical (owner-decisions Q2):
h24_cadence: { light_every: 6, deep_every: 15, jump_on_class_repeat: 3 } - dòng-carry = đoạn LOGIC: đọc
-Raw, split trên markerNEXT anh|NEXT em→ 45 segment (KHÔNGGet-Content -TotalCount: 12 dòng vật-lý, riêng :5 = 46 493 ký-tự). - Chuỗi tính chỉ trên segment CÓ carry; phiên không phát carry không phá chuỗi; chỉ khoá vắng trên dòng CÓ carry mới reset.
- Charset khoá
[a-z0-9][a-z0-9._-]*loại<⇒ literal[carry:<slug>](câu văn ĐỊNH-NGHĨA quy-ước trong HANDOFF) không bị đếm = tránh TỰ-THAM-CHIẾU (bài học lead W0.4 #1). - Thiếu key ⇒ FAIL-LOUD, không giả-định default.
stdout thật (repo thật, hôm nay):
config resolved: .claude/agent-memory/memory-budget.json
[DETECTOR] MED | .claude/agent-memory/memory-budget.json | h24_cadence missing - W2 chua land
=> carry-age cadence UNRESOLVED, measuring NOTHING (no default is assumed ...)
HANDOFF logic-segments (NEXT anh/em) = 45 ; of those, carry-lines = 1
[inform] carry 's119-wave' streak=1 carry-line(s) ; M unresolved -> NO aged/not-aged verdict (×7 khoá)
🔴 KHAI THẬT — VACUOUS, nhưng lý-do KHÁC brief
Brief nói vacuous vì “chưa backfill”. Sai. Đã backfill 7 khoá. Vacuous vì cấu-trúc:
CHỈ CÓ ĐÚNG 1 dòng-carry (seg#0 =
NEXT anhcủa S119). Backfill chỉ đóng dấu block hiện-tại. ⇒ mọi streak = 1. Với M ∈ {6,15,3} ⇒ 0 fire — kể cả khi W2 land key.
Hệ quả thiết-kế (cần lead quyết): detector đo streak ĐÓNG-DẤU, không đo tuổi thật.
Bằng chứng cụ thể: [carry:tra-bui-relogin] ở seg#0 (S119); mà seg#2 = NEXT anh của S118 nói đúng việc đó (“tra.bui + 6 NV PRO đăng xuất → đăng nhập lại”) nhưng không được đóng dấu ⇒ tuổi thật ≥2 phiên, detector đọc 1.
⇒ Chỉ hết vacuous khi mỗi phiên đóng dấu lại khoá còn mở vào block NEXT mới (hoặc retro-stamp lịch-sử). Nếu không, streak kẹt ở 1 vĩnh-viễn — đây là “xanh từ commit đầu” đúng thứ H24 bảo phải nghi.
4. 🐞 BUG THẬT bắt được (nếu không fault-inject thì SHIP LỖI)
PowerShell tên biến CASE-INSENSITIVE ⇒ $M (cadence) CHÍNH LÀ $m (biến loop foreach ($m in [regex]::Matches(...))).
Match-object ghi đè cadence ⇒ ($null -eq $M) thành false ⇒ rẽ nhầm sang elseif ($n -ge $M) ⇒
Could not compare "1" to "[carry:bvaau]". (×7)
⇒ nhánh FAIL-LOUD (= nhánh SỐNG hôm nay vì M unresolved) BỊ VỠ, [inform] không in ra.
Fix: $M → $CadenceM, loop var $m → $cm (+ comment cảnh báo tại chỗ).
🔴 exit 0 che lỗi này (detector luôn exit 0) ⇒ chỉ đọc exit-code là không phát hiện. Phải đọc stderr.
5. FAULT-INJECT (cây tạm $env:TEMP\gd-fi, chạy -RepoRoot <cây-tạm>)
| Ca | Inject | Kỳ vọng | stdout thật | Verdict |
|---|---|---|---|---|
| FI-1(c) | copy permission-matrix/SKILL.md anchor 2026-04-30 < mốc-phải |
FLAG | [DETECTOR] LOW | .claude/skills/permission-matrix/SKILL.md:16 | title-stale: anchor says 2026-04-30 but newest … 2026-07-15 (76d behind) |
✅ |
| FI-1(d) | sửa anchor → 2026-07-15 |
hết FLAG | title-stale flags after repair = 0 ; moc-phai … from .claude/skills/permission-matrix/SKILL.md:16 |
✅ |
| FI-2 | light_every=1 |
7 FLAG | M = h24_cadence.light_every = 1 (read from config, not hardcoded) → gap-carry-aged FLAGS = 7 |
✅ |
| FI-2 | light_every=2 (biên) |
0 FLAG | [ok] carry 's119-wave' streak=1 < M=2 → gap-carry-aged FLAGS = 0 |
✅ |
| FI-2 | light_every=6 |
0 FLAG | [ok] … streak=1 < M=6 → gap-carry-aged FLAGS = 0 |
✅ |
| FI-3 | probe-garbage.md anchor = 2026-20-42 |
không nhận | probe-garbage adopted as anchor? -> False |
✅ |
| FI-3 | probe-future.md anchor 2026-05-01 + cùng dòng có 2026-08-01 + 2 mark-id |
lấy 2026-05-01 |
anchor 2026-05-01 docs/probe-future.md:3 ; 2026-08-01 -> False ; 2026-20-42 -> False ; 1987-03-07 -> False |
✅ |
FI-2 = bằng chứng acceptance (a): đổi số trong config ⇒ output đổi (7 flag ↔ 0 flag) ⇒ thật sự đọc config, không hardcode. Biên chính xác tại M (1 fire, 2 không).
Anti-Goodhart: gate KHÔNG xanh sẵn — baseline 42, cả 2 detector mới đều fire trên fault-inject và cùng tắt khi gỡ fault.
6. M3 SCOPE — số owner-đã-ký KHÔNG đụng
git diff -U0 → dòng - duy nhất = 6 dòng canonical-resolve tôi tái-cấu-trúc + 1 dòng countPatterns (thêm dấu phẩy). 0 số ngoài-scope bị sửa:
| Hằng-số | Dòng | Trạng thái |
|---|---|---|
$walLineCount -gt 40 (mark RC-…12-07-2026-11-43-45) |
:459 | ✅ nguyên-văn |
$ratio -ge 0.5 -and $ratio -le 2.0 |
:296 | ✅ nguyên-văn |
$maxGotcha + 50 |
:335 | ✅ nguyên-văn |
$liveVariants.Count -ge 2 |
:439 | ✅ nguyên-văn |
7. ACCEPTANCE (tính TỪ SỐ ĐO)
| # | Tiêu chí | Số đo | Verdict |
|---|---|---|---|
| (a) | config-driven; grep memory-budget|ConvertFrom-Json 0 → >0 |
6 hit; FI-2 đổi 1→2 ⇒ 7 flag→0 flag | ✅ PASS |
| (b) | STATUS.md:6 ⇒ in ngày anchor, không ra 3 chuỗi cấm | in 2026-07-15; garbage/future = False ×3 |
⚠️ PASS-có-caveat (literal brief 2026-07-14 STALE 1 commit — 4727d16; §0 P2) |
| (c) | TOTAL ≥ 46 và có dòng permission-matrix/SKILL.md |
49 (42+7); có 3 dòng permission-matrix | ✅ PASS |
| (d) | exit luôn 0 | EXIT CODE = 0 |
✅ PASS |
| (e) | non-ASCII = 0 | 0 byte >127; BOM-less | ✅ PASS |
+7 flag (Compare-Object, không tự đếm tay): policy-row-missing ×1 · menu ×2 · title-stale ×3 · h24_cadence-missing ×1. Dropped flags = NONE ⇒ không phá detector cũ.
8. Cần lead xử (ngoài quyền lane W1-①)
- 🔴 Hợp-đồng chéo W2: W1① đọc
h24_cadence.light_everytại.claude/agent-memory/memory-budget.json. W2 phải land đúng path + sub-key đó, nếu không ① fail-loud vĩnh-viễn. (Spec chỉ ghi basename ⇒ mơ hồ.) - 🔴 W2 nâng Sub-agents 12→14 ⇒ nay
menu/policyđã sống, rowPoliciesphải land CÙNG — nếu không, flagcanonical row missingở lại và mọi derived-doc ghi “14” sẽ bị flag stale-vs-12 (spec v2:176 cảnh báo “detector BÃO ⇒ ≥46 thoả bằng RÁC”). Hôm nay 49 không chứa rác loại đó. - ⚠️ carry-age vacuous cấu-trúc (§3) — cần quy-ước đóng-dấu lại mỗi phiên, nếu không detector vô-dụng dù W2 land.
- ⚠️ Bug tiền-tồn ngoài lane:
:361$userMemDir = 'C:\Users\pqhuy\.claude\projects\…'hardcode tuyệt-đối, KHÔNG derive$RepoRoot⇒ chạy-RepoRoot <cây-tạm>vẫn đọc user-memory thật ⇒ fault-inject C1-wikilink không cô-lập được. Không sửa (ngoài 3 việc được giao + đổi baseline). - ⚠️ Acceptance (b) literal
2026-07-14nên sửa thành “in đúng ngày ở anchor STATUS.md:6” (số tuyệt-đối tự-lão-hoá mỗi lần STATUS đổi ngày).