diff --git a/.claude/WAL.md b/.claude/WAL.md index 470517b..3c12578 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -9,9 +9,10 @@ chain: [x] W0.3 commit 92de58f — ca(0) fire · hook-interlock ĐẶT SAU Set-Location (đặt đầu file = soi nhầm CWD) · chứng RĂNG 2 CHIỀU (a)không-rebase→VẪN commit (b)có-rebase→0 commit+giữ dirty · fault-inject 4 cây tạm: ca2 v2-cũ→REBASE→exit 0 KHÔNG crash nhưng commit gộp thừa-kế msg "wal:"→deadlock XÁC NHẬN [x] W0.4+W0.5 commit 48e0d26 — README:52 gỡ claim STALE (khai 3 đường: hmw.js gate / raw Workflow ❌ / raw Agent ❌ + kẽ CÒN-LẠI) · baseline orphan naive13/dual8/scoped1={S119} khớp CHÍNH XÁC dự-báo FIX #4 [x] W0.6 XONG @S121 sau restart — verdict **CRLF-tolerant** (W0-evidence §7.4/§7.5/§7.6). LF-probe xanh TRƯỚC ⇒ CRLF ăn 4/4 tầng (discovery→parse→spawn→exec); neo = token 45248/45240 lệch 8 = chênh prompt (KHÔNG phải "không báo lỗi"). ⇒ L3 nhánh LF-only-regex **BỊ BÁC** · R4 **HẠ MẠNH KHÔNG rút** (a)+(c) giữ chân riêng, chỉ (b) đổ · 2 probe ĐÃ XOÁ, porcelain sạch probe. Khai chặt: tolerant mức HÀNH-VI, phạm-vi agents/ + 1 build win32; commands//skills//.ps1 CHƯA phủ. 🆕 #53 tái-hiện 2/2 (tool_uses=0 + bịa dòng WAL) — KHÔNG nhiễm verdict (neo = metadata harness) → vào adap-report. nhánh-3 (registry=ảnh-chụp khởi-phiên) xác-nhận LẦN 2 ⇒ memory harness4 thu hẹp @session-end -[!] wf: W1 ĐANG CHẠY — run-id `wf_de36dea9-265` · task-id `wj8l7l61z` · engine **/hmw** RUN-TRACE (KHÔNG raw-Workflow — W0.4 vừa khai raw = kẽ không gate) · 4 lane **role-less** (tránh implementer-backend auto-refuse .ps1) → sub-task-0..3.md · taskList snapshot = run.md §"taskList snapshot — W1". Chết giữa run ⇒ /tiep §4: đọc sub-task-*.md trên ĐĨA (return mất ≠ việc mất) → harvest phần xong → relaunch CẮT-GỌT task còn lại. - 🔸 Sàn-1 LỆCH KHAI THẬT: marker `wf:` này đăng-ký **SAU** phóng (luật = TRƯỚC, run.md:8 positive-assertion @launch). Lead tự mắc @S121 — đi vào adap-report cùng 2 lỗi W0.4. -[ ] W1 phần lead: verify 4 file từ ĐĨA (git diff + chạy thật, KHÔNG tin return) → harvest → W2 GỘP-1-COMMIT (hmw.js 5 hạng-mục + 4 cờ wrapper + 2 agent MỚI + h24_cadence + .session-counter + STATUS Sub-agents 12→14 + row Policies + 🆕 backfill `[carry:*]` HANDOFF ×5 = ORPHAN lead bắt @S121, xem run.md) + RESTART ×2 +[x] W1 XONG @S121 — wf `wf_de36dea9-265` 4/4 lane 0-error (694k tok, 159 tool, 21') · engine /hmw RUN-TRACE (KHÔNG raw-Workflow) · role-less ×4 · containment SẠCH (git status = đúng 4 file đích + 4 sub-task-*.md, 0 rò WAL/agent-memory/STATUS/spec). **LEAD ĐÃ TỰ CHẠY LẠI CẢ 4, KHÔNG tin return:** detectors TOTAL 42→**49** (≥46) + permission-matrix **FIRE** (title-stale 76d) + `menu=54`/`policy=MISSING` fail-loud + exit 0 + **stderr 0** (lane ① tự bắt bug `$M`≡`$m` PS case-insensitive mà `exit 0` CHE — chỉ stderr mới lộ) · eol-check GREEN-BUT-VACUOUS tự khai + **teeth lead tự inject 276 CR → FLAG, gỡ → 0** · wal-recovery **4/4 ca · 30 assert · 0 fail**, có counterfactual tái-hiện DEADLOCK `rebase-exit=0` + assert `sut-has-no-NONWAL-param` bằng **Get-Command reflection** (KHÔNG grep = né tự-tham-chiếu W0.4#1) · spawn-model-audit FAIL-LOUD "expected constant missing (W2 chua land)" + **teeth lead inject `claude-opus-9-9` → FLAG mismatch, sửa → hết**. 4/4 non-ASCII = 0. + 🔴 **2 LỖI LEAD @S121 (đi vào adap-report):** (a) **Sàn-1 LỆCH**: marker `wf:` đăng-ký SAU phóng (luật = TRƯỚC, run.md:8). (b) 🔴 **KHẲNG-ĐỊNH FACT-TRÊN-ĐĨA MÀ KHÔNG ĐO ĐĨA**: lead phán "backfill `[carry:*]` = ORPHAN chưa ai làm" → **SAI**, đã có **7 khoá** từ `4727d16` (S119, đã push). Cơ-chế: rà BẢNG WAVE thấy không ai được giao ⇒ suy ra chưa làm — *"không wave nào sở-hữu" ≠ "chưa có trên đĩa"*. Brief lead còn **4 tiền-đề sai** (config path · STATUS 07-14 vs thật 07-15 · carry · độ-dài) — lane ① re-verify đĩa và vá hết. Bẫy: `grep -c` đếm DÒNG (=1) vs `grep -o|wc -l` đếm occurrence (=8) trên mega-line. +[ ] **GAP THẬT thay claim sai** (lane ① tìm, lead verify đĩa): carry-age **vacuous CẤU-TRÚC** — 45 logic-segment nhưng **carry-lines=1** ⇒ streak≡1 ⇒ **0 fire vĩnh viễn kể cả sau W2**. Chứng: `tra-bui-relogin` chỉ đóng dấu seg#0(S119), mà seg#2(S118) nhắc đúng việc đó KHÔNG dấu ⇒ tuổi thật ≥2, detector đọc 1. ⇒ lỗ = **thiếu nghi-thức RE-STAMP mỗi phiên** (§Q3 = no-retrofit ⇒ chỉ còn đường này) ⇒ **giao W3 `session-end.md`**, KHÔNG phải W2. +[ ] W2 GỘP-1-COMMIT (hmw.js 5 hạng-mục + **PA-2a `TIER2_EXPECTED_FULL_ID='claude-opus-4-8'`** + 4 cờ wrapper + 2 agent MỚI + **`h24_cadence` ĐÚNG PATH = `.claude/agent-memory/memory-budget.json`, sub-key `light_every`** (KHÔNG phải `.claude/memory-budget.json` — hợp-đồng chéo lane ①) + .session-counter + STATUS Sub-agents 12→14 **CÙNG LANDING** row Policies) + RESTART ×2 [ ] W3 SERIAL 5 file (tiep §0 dual-accept VERBATIM C8 → session-start 0.6b+0.7 → session-end §5.2 → fable-clone → agents/README) → W4 detector-fire (PHẢI in permission-matrix/SKILL.md TRƯỚC vá) → W5 harness-11-engine [ ] W6 push (🔴 squash→count→push CHAINED 1 LƯỢT; K runtime, CẤM hardcode) → adap-report ×4 + adap-request R1-R4 + send-email AI_INFRA + stamp-mark @@ -19,5 +20,8 @@ chain: 🔴 2 lỗi lead tự mắc @W0.4 (đã ghi W0-evidence §5, đi nguyên vào adap-report): (a) gate grep-chuỗi chạy trên chính file nó kiểm = TỰ-THAM-CHIẾU (trích claim cũ → FAIL; viết literal regex → FAIL lần 2) (b) meta-count tái-phạm: bảng tự in sẵn "PASS" trong khi số đo nói FAIL ⇒ pass/fail PHẢI TÍNH, cấm nhãn cứng. 🔴 Hook wal-flush.ps1:7 phủ 3 path (.claude/WAL.md · agent-memory/ · workflows/runs/) — KHÔNG phủ .claude/agents/ · broadcasts/ · .gitattributes/scripts/docs. Đáy range HIỆN = commit thường (92de58f) ⇒ mọi wal: sinh sau rơi ca(3) rebase+fixup an-toàn @W6. -next: chờ wf `wf_de36dea9-265` → lead VERIFY 4 file .ps1 từ ĐĨA (chạy thật + fault-inject, KHÔNG tin return — #53 vừa fire 2/2 @W0.6) → harvest → W2 GỘP-1-COMMIT + RESTART ×2 → W3 SERIAL 5 file → W4 → W5 → W6 +next: W1 verify XONG (lead tự chạy 4/4 + teeth 2/2) → **commit W1** → W2 GỘP-1-COMMIT + RESTART ×2 → W3 SERIAL 5 file (**+ nghi-thức re-stamp carry**) → W4 detector-fire (nay CHẮC fire: permission-matrix 3 dòng) → W5 → W6 +🔴 W2 PHẢI SỬA 2 ACCEPTANCE STALE trước khi dùng: (a) `h24_cadence` path THẬT = `.claude/agent-memory/memory-budget.json` (spec chỉ ghi basename ⇒ mơ-hồ; land sai ⇒ ① fail-loud vĩnh viễn). (b) acceptance "STATUS.md:6 in 2026-07-14" **TỰ LÃO-HOÁ ngay trong ngày** (thật = 07-15 sau `4727d16`) ⇒ đổi thành "in ĐÚNG ngày ở anchor STATUS.md:6", cấm literal. +🔴 Bug tiền-tồn NGOÀI lane (lane ① khai, KHÔNG sửa vì đổi baseline): `governance-detectors.ps1` `$userMemDir` **hardcode path tuyệt-đối** `C:\Users\pqhuy\...`, không derive `$RepoRoot` ⇒ `-RepoRoot ` VẪN đọc user-memory THẬT ⇒ fault-inject C1-wikilink KHÔNG cô-lập được. Xử ở W5 hoặc phiên riêng. +📌 W4 cần biết (lane ① khai): `docs/changelog/skill-audit-2026-05-late.md:43` có phán-quyết audit CŨ ghi đúng anchor này là *"historical, KHÔNG drift"* ⇒ H24/W4 đang **LẬT chính-sách có chủ-đích**, KHÔNG phải phát-hiện-mới. Nói đúng nấc khi báo hub. verify: K=$(git rev-list --count origin/main..HEAD) ; git log --format='%s' origin/main..HEAD | tail -1 [đáy range → ca 0/1/2/3; HIỆN = "[CLAUDE] Infra: W0 pre-flight…" = commit thường ⇒ ca(3)] ; git status --porcelain ; ls .claude/agents/_*probe* 2>&1 [PHẢI "No such file" — W0.6 xong, 2 probe đã xoá] ; grep -c "CRLF-tolerant" .claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/W0-evidence-15-07-2026.md [>0 = verdict đã ghi] ; ls scripts/agent-frontmatter-eol-check.ps1 scripts/wal-recovery-test.ps1 scripts/spawn-model-audit.ps1 2>&1 ; ls .claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-*.md 2>&1 [W1 landed?] diff --git a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/run.md b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/run.md index 4c55487..df0b0ce 100644 --- a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/run.md +++ b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/run.md @@ -62,7 +62,27 @@ SE đối ứng **6 broadcast mới** (check-email S119, 7 file copy hash-verify **Phụ-thuộc chéo đã khai với worker:** ①đọc `h24_cadence` từ `memory-budget.json` — key đó **W2 mới thêm** ⇒ ① phải **fail-loud khi thiếu key**, 🔴 CẤM hardcode số nhịp (H24 M3: *"số NHỊP đọc từ config"* — KHÔNG phải "0 số hardcode toàn file"). W1b đọc hằng `TIER2_EXPECTED_FULL_ID` — cũng **W2 mới thêm** (PA-2a) ⇒ cùng luật fail-loud. -🔴 **ORPHAN MỚI phát-hiện @S121 (cùng lớp M4 "v1 để MỒ CÔI"):** owner-decisions §Q3 chốt **backfill `[carry:*]`** cho 5 carry đang sống ở `HANDOFF.md` (binh.le · account-trùng · PE-phân-quyền · BVAAU ×2) — **rà 7 wave: KHÔNG wave nào sở-hữu**. Thiếu backfill ⇒ detector tuổi-carry (lane ①) **không có gì để track** ⇒ **PASS vacuous** (đúng lớp W0.2 đã phải khai thật). ⇒ **giao W2** (cùng owner `.json`/STATUS landing) hoặc W3; **KHÔNG** nhét vào W1 (vỡ file-set disjoint). +🔴 ~~**ORPHAN MỚI @S121:** backfill `[carry:*]` chưa ai làm ⇒ detector tuổi-carry 0-fire~~ — **CLAIM NÀY SAI. LEAD RÚT @S121 sau khi lane ① đo đĩa.** + +### ❌ Lỗi lead @S121 — khẳng-định sự-thật-trên-đĩa mà KHÔNG chạm đĩa (đi vào adap-report) + +| Lead nói (brief + báo anh + run.md) | ĐĨA THẬT | Đo bằng | +|---|---|---| +| HANDOFF **chưa** backfill `[carry:*]` ⇒ orphan | **ĐÃ backfill 7 khoá thật** (+1 literal `[carry:]` = câu định-nghĩa), vào từ **`4727d16`** = closeout S119 **ĐÃ PUSH** | `grep -o '\[carry:[^]]*\]' docs/HANDOFF.md \| sort \| uniq -c` = 8 · `git log -S'[carry:'` = 4727d16 | +| config = `.claude/memory-budget.json` | **KHÔNG tồn tại** — thật = **`.claude/agent-memory/memory-budget.json`** (25KB) | `ls` 2 path | +| acceptance: STATUS.md:6 ⇒ in `2026-07-14` | **`2026-07-15`** — `4727d16` (11:20 hôm nay) đã đổi ⇒ literal STALE **1 commit** | `sed -n '6p' \| grep 'Last updated'` | +| HANDOFF:5 ≈ 46 735 ký-tự | 46 493 **ký-tự** = 50 665 **byte** — 🔸 KHÔNG phải lệch: `wc -c` đếm byte, `len()` đếm char, VN UTF-8 đa-byte. **Không tính lỗi cho sub.** | `wc -c` vs python `len()` | + +🔴 **Cơ-chế lỗi (khác "đo nhầm" — tệ hơn):** lead rà **BẢNG 7 WAVE**, thấy không wave nào được giao việc backfill ⇒ kết-luận **việc chưa làm**. *"Không wave nào sở-hữu"* **≠** *"chưa có trên đĩa"* — S119 đã làm nó **NGOÀI** cấu-trúc wave. ⇒ lead khẳng-định một fact-trên-đĩa **mà chưa hề đo đĩa**. Cùng họ `feedback_resume_premise_reverify` (re-verify tiền-đề từ ĐĨA) — lead tự nhắc mình luật đó ở W0.6 rồi vi-phạm ngay sau đó. +🔸 **Bẫy kỹ-thuật đáng ghi:** `grep -c 'carry:'` trả **1** (đếm **DÒNG**), `grep -o … | wc -l` trả **8** (đếm **occurrence**). Trên mega-line `HANDOFF.md:5` (50 665 byte) hai lệnh lệch **8×** ⇒ ai dùng `-c` sẽ kết-luận "chỉ 1 khoá" và sai y hệt. + +### ✅ GAP THẬT (lane ① tìm ra, lead đã VERIFY ĐĨA) — sâu hơn claim sai + +**carry-age VACUOUS vì CẤU-TRÚC, không phải vì thiếu backfill.** +Đo: `HANDOFF logic-segments (NEXT anh/em) = 45` · **carry-lines = 1** ⇒ **mọi khoá streak = 1** ⇒ với M ∈ {6,15,3} ⇒ **0 fire VĨNH VIỄN, kể cả sau khi W2 land `h24_cadence`**. +🔬 Bằng-chứng detector đo **STREAK-ĐÓNG-DẤU** chứ không đo **TUỔI THẬT**: `[carry:tra-bui-relogin]` chỉ ở **seg#0 (S119)**; nhưng **seg#2** (block S118) nhắc **đúng việc đó** (*"tra.bui + 6 NV PRO đăng xuất → đăng nhập lại"*) mà **KHÔNG được đóng dấu** ⇒ tuổi thật **≥2 phiên**, detector đọc **1**. (lead verify độc-lập bằng python split 45 seg: seg#0 keys=[s119-wave, uat-s117] · seg#2 keys=[] nhưng nhắc tra.bui = True.) +⇒ **Lỗ THẬT = thiếu NGHI-THỨC ĐÓNG-DẤU-LẠI:** không có gì bắt phiên sau re-stamp khoá **còn mở** vào block `NEXT` mới. §Q3 đã chốt **no-retrofit** (cấm truy-ngược) ⇒ đường DUY NHẤT = re-stamp mỗi phiên ⇒ thuộc **`session-end.md` = W3**, KHÔNG phải W2. +⇒ **Giao W3** (session-end §5.2 landing). Cho tới lúc đó, detector khai đúng nấc: `M unresolved -> NO aged/not-aged verdict` (fail-loud, KHÔNG default). ## Nấc / next diff --git a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-0.md b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-0.md new file mode 100644 index 0000000..4a0c543 --- /dev/null +++ b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-0.md @@ -0,0 +1,181 @@ +# 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ải `grep -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ại +- `policy` → `| 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 | **** |' 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): + 1. `\*\*Last updated:\*\*\s*(\d{4}-\d{2}-\d{2})` + 2. `\*\*Status \(post Session \d+ (\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 20 `**`e2 80 94`**` 20 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** đụng `Test-Excluded` global → C1/C3 giữ nguyên baseline (nới global = đổi baseline lane khác = vượt quyền). + Khai thật: giữ `_archive` sẽ +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:43` có 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 marker `NEXT anh|NEXT em` → **45 segment** (KHÔNG `Get-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:]`** (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 anh` củ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 `) + +| 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-①) + +1. 🔴 **Hợp-đồng chéo W2:** W1① đọc **`h24_cadence.light_every`** tạ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ồ.) +2. 🔴 **W2 nâng Sub-agents 12→14** ⇒ nay `menu`/`policy` đã sống, **row `Policies` phải land CÙNG** — nếu không, flag `canonical 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 đó. +3. ⚠️ **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. +4. ⚠️ **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 ` **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). +5. ⚠️ Acceptance (b) literal `2026-07-14` nê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). diff --git a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-1.md b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-1.md new file mode 100644 index 0000000..9a448f0 --- /dev/null +++ b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-1.md @@ -0,0 +1,147 @@ +# sub-task-1 — LANE W1-② — `scripts/agent-frontmatter-eol-check.ps1` + +**Role:** implementer · **Run:** 2026-07-15-S119-adap-6-broadcast · **Lane:** W1-② (WRITE-lane) +**File tạo (DUY-NHẤT):** `scripts/agent-frontmatter-eol-check.ps1` (NEW, 335 dòng) +**VERDICT:** ✅ DONE — script live, PS 5.1 parse sạch, fault-inject 5 ca CÓ RĂNG, exit 0. +🔴 **Nấc trung-thực:** gate trên repo thật = **GREEN-BUT-VACUOUS** (0 CR / 37 file). **KHÔNG tính là thành-tựu.** + +--- + +## 1. Tiền-đề: lý-do tồn-tại của script này VỪA BỊ HẠ CẤP + +W0.6 spawn-probe @S121 ra verdict **CRLF-TOLERANT**: file agent CRLF hoàn-toàn (276 byte CR) spawn ĐỦ 4 tầng +(discovery/parse/spawn/execute), token 45248 (LF) vs 45240 (CRLF) — lệch 8 = chênh chữ trong prompt, KHÔNG do EOL. +⇒ Giả-thuyết "LF-only reader giết registry" **BỊ BÁC bằng thực-nghiệm**. +⇒ Spec v2:159 ra lệnh: *"ra CRLF-tolerant ⇒ validator **HẠ GIÁ-TRỊ** (chỉ còn hygiene) + **KHAI THẬT**"*. + +**Đã tuân:** header `.SYNOPSIS`/`.DESCRIPTION` khai thẳng verdict + số đo + phạm-vi-hẹp. Grep xác nhận **0 hit** +`fatal` / `kill` / `break the registry` theo nghĩa khẳng-định. Trần severity = **MED** (HIGH chỉ dành cho self-broken). + +**Phạm-vi CÒN LẠI của refutation (= lý-do script vẫn sống, nói đúng cỡ):** +behaviour-level only · `.claude/agents/` only · **1 build win32**. **KHÔNG phủ:** `commands/`, `skills/`, hook `.ps1`. + +--- + +## 2. Thiết-kế — 4 quyết-định neo vào bài-học đã có + +| # | Quyết-định | Neo | +|---|---|---| +| 1 | **Byte-reader** `[System.IO.File]::ReadAllBytes`, đếm `0x0D` | `Get-Content` (kể cả `-Raw`) **nuốt/chuẩn-hoá CR** ⇒ check text-level **KHÔNG BAO GIỜ fail được** = vacuous BY CONSTRUCTION. Phụ: không decode text ⇒ gotcha #30 **không với tới phép đo** | +| 2 | **Structural, KHÔNG grep-chuỗi** — đếm `0x0D` trong vùng cắt theo byte-offset | Bài-học W0.4 #1 tự-tham-chiếu: gate grep-chuỗi trích claim cũ vào file ⇒ FAIL trên bản SỬA ĐÚNG. Structural ⇒ **không thể self-match**. Cộng: script ở `scripts/`, quét `.claude/{agents,commands,skills}` ⇒ **path-disjoint** | +| 3 | **Mọi nhãn PASS/GREEN TÍNH TỪ SỐ ĐO**, count bằng glob | Bài-học W0.4 #2 meta-count + spec v3 fix #9h ("validator W1② chạy glob thay hardcode 12") | +| 4 | **Scope CHẶT** 3 thư-mục, **CẤM repo-wide** | repo-wide `i/lf w/crlf` = 188 file (131 EF Migrations) ⇒ acceptance `count==0` toàn-repo = **đường-giá factory**; mass rm+checkout CẤM phiên này (v2 W0.2). 188 = INFORM-only | + +**Severity ladder (hệ-quả CÓ CHỦ-ĐÍCH của refutation):** +- `HIGH` — **chỉ** self-broken (synthetic control fail ⇒ scan vô-nghĩa). **KHÔNG** dùng cho CR finding. +- `MED` — CR trong frontmatter (bề-mặt parser đọc; đúng bề-mặt W0.6 đã probe trên agents/). +- `LOW` — CR chỉ ở body (cùng policy `eol=lf`, xa hot-path hơn). +- `exit 0` LUÔN LUÔN. + +**agents/README.md CỐ Ý nằm TRONG scope** — R2-C1 loại README khỏi **ROSTER count** (nó không phải agent), nhưng +EOL policy là **per-file** ⇒ README bị quản như mọi file khác. 2 luật khác nhau CÓ CHỦ-ĐÍCH; đã ghi comment cấm +"sửa cái này bằng cách copy cái kia". + +**SYNTHETIC CONTROL (khai rõ trong header — v2 ④(a)):** vì W0.6 bác CRLF-fatality ⇒ **KHÔNG còn file-đã-chết THẬT** +làm positive-control tự-nhiên ⇒ dùng 2 buffer in-memory chạy TRƯỚC mỗi lần quét: +`(+)` CRLF synthetic → BẮT BUỘC FmCr>0 · `(-)` LF synthetic → BẮT BUỘC FmCr=0. Fail ⇒ HIGH + `UNTRUSTWORTHY`. +Header khai đúng giới-hạn: *control chứng-minh **READER** chạy đúng; **KHÔNG** chứng-minh CRLF gây hại.* + +--- + +## 3. FAULT-INJECT — 5 ca trên cây tạm `%TEMP%\eol-fi-w1a` (`-RepoRoot`) + +Vật-liệu: copy `.claude/agents/reviewer.md`. Phẫu-thuật byte qua ISO-8859-1 round-trip (bảo-toàn byte tuyệt-đối). + +| Ca | Inject | Kỳ-vọng | Số đo THẬT | Kết | +|---|---|---|---|---| +| **A** | all-LF (baseline) | 0 flag | `TOTAL FLAGS: 0 (scoped files=1, CR=0)` | ✅ | +| **B** | **all-CRLF** (mandated) | MED trên đúng file | `[EOL] MED \| .claude/agents/reviewer.md \| eol-frontmatter-cr: 14 CR ... 262 more in body`; CR=**276** | ✅ **FLAG** | +| **C** | FM-CRLF + body-LF | MED, **BodyCr=0** | `14 CR ... 0 more in body`; CR=14 | ✅ | +| **D** | FM-LF + body-CRLF | **LOW** (không MED) | `[EOL] LOW \| ... eol-body-cr: ... 262 CR`; CR=262 | ✅ | +| **A2** | gỡ lỗi → LF | **hết FLAG** | `TOTAL FLAGS: 0 (CR=0)` | ✅ **HẾT FLAG** | + +**Boundary/anti-Goodhart — C+D chứng-minh region-attribution là THẬT, không phải đếm CR toàn-file:** +`FmCr(C)=14` + `BodyCr(D)=262` = **276** = `TotalCr(B)`. Số-học khớp chéo 3 lần inject. +Độc-lập: driver tự cắt báo `frontmatter = 14 lines` ⇒ khớp `FmCr=14`. + +**Round-trip integrity:** SHA256 bản tạm sau A2 == bản repo gốc +(`4EAF7D3E...07EB` cả 2) ⇒ 4 lần inject **lossless** ⇒ "0 flag" ở A2 KHÔNG phải do file bị nát. + +**🔴 Ca E — chứng-minh chính SYNTHETIC CONTROL có răng (meta-test):** +Lập-luận "green có nghĩa vì control PASS" **vô-giá-trị nếu control không bao giờ fail được**. +⇒ copy script ra temp, sabotage **1 chỗ duy-nhất** (`if ($Bytes[$i] -eq 0x0D)` → `0x00`, needle occurrences=1 = phẫu-thuật +chính-xác), chạy trên cây **SẠCH**: +``` + (+) CRLF synthetic : fm=True FmCr=0 BodyCr=0 expect fm=True,FmCr>0 -> FAIL + (-) LF synthetic : fm=True FmCr=0 BodyCr=0 expect fm=True,FmCr=0 -> PASS +[EOL] HIGH | scripts/agent-frontmatter-eol-check.ps1 (self) | self-broken: synthetic control FAILED ... +RESULT: UNTRUSTWORTHY - the synthetic control FAILED, so the scan above proves nothing. +``` +⇒ Reader mù CR trên cây sạch **KHÔNG ra green** mà ra **UNTRUSTWORTHY**. Không có control, script hỏng sẽ in +"GREEN, 0 flags" **không phân-biệt được** với script chạy đúng. Repo script KHÔNG bị đụng (sabotage trên bản copy; +final run xác nhận lại). Cây tạm đã xoá (`Test-Path = False`). + +--- + +## 4. Chạy trên REPO THẬT — stdout thật + +``` + (+) CRLF synthetic : fm=True FmCr=4 BodyCr=1 expect fm=True,FmCr>0 -> PASS + (-) LF synthetic : fm=True FmCr=0 BodyCr=0 expect fm=True,FmCr=0 -> PASS + .claude/agents scanned=13 frontmatter-CR-files=0 body-only-CR-files=0 CR-bytes=0 + .claude/commands scanned=18 frontmatter-CR-files=0 body-only-CR-files=0 CR-bytes=0 + .claude/skills scanned=6 frontmatter-CR-files=0 body-only-CR-files=0 CR-bytes=0 +TOTAL FLAGS: 0 (scoped files=37, CR bytes measured=0) +RESULT: GREEN-BUT-VACUOUS - 0 CR bytes existed in the scoped set, so this run had nothing to catch. +EXITCODE=0 +``` + +🔴 **KHAI VACUOUS (đúng lệnh, không tính công):** 37/37 file = 0 CR ⇒ **gate XANH SẴN, 0 việc làm** (v2 W0.2 / R2-C4). +Đối-chứng độc-lập TRƯỚC khi viết script: `tr -dc '\r' < f | wc -c` = 0 trên cả 37 file ⇒ **2 nguồn khớp**. +Script **tự in** nhãn `GREEN-BUT-VACUOUS` + "Do NOT bank this as an achievement" ⇒ nấc trung-thực **nằm trong tooling**, +không chỉ trong report. Giá-trị thật = **bắt regression về sau**, KHÔNG phải lần chạy này. +`files with no parseable frontmatter block: 1` = **`.claude/agents/README.md`** (đo, không đoán) — không flag; body-CR vẫn đếm. + +--- + +## 5. Acceptance + +| # | Tiêu-chí | Số đo | Kết | +|---|---|---|---| +| 1 | fault-inject CÓ RĂNG | 5 ca A/B/C/D/A2 + E meta; B flag đúng file, A2 hết flag | ✅ | +| 2 | repo thật 0 flag ở agents/ + khai vacuous | `scanned=13, CR-bytes=0`; nhãn VACUOUS in tự-động | ✅ | +| 3 | grep non-ASCII = 0 · PS 5.1 parse sạch | `LC_ALL=C tr -d '\000-\177'` = **0 byte**; AST `ParseFile` = **0 error** (PS 5.1.26100.8737) | ✅ | +| 4 | header khai đúng nấc W0.6, không bàn 'fatal' | verdict+45248/45240+phạm-vi-hẹp có trong header; trần MED | ✅ | + +**Chứng non-ASCII check có răng (chống vacuous):** cùng lệnh chạy trên `.gitattributes` (có tiếng Việt) = **868 byte** +non-ASCII ⇒ phép đo phân-biệt được, không phải luôn-luôn-0. +⚠️ `grep -P '[\x80-\xff]'` (lệnh trong gotcha #37) **CHẾT** trên môi-trường này: `-P supports only unibyte and UTF-8 +locales`, exit 2 = **lỗi, KHÔNG phải "sạch"** — suýt đọc nhầm exit-code thành PASS. Dùng `LC_ALL=C tr` thay. + +**Self-consistency:** file tự nó `CR = 0`; `git check-attr` ⇒ `text: auto`, `eol: lf` ⇒ chính nó nằm dưới policy nó rao. + +--- + +## 6. Containment + +`git status --porcelain` sau khi xong: +``` +?? scripts/agent-frontmatter-eol-check.ps1 <- CỦA TAO +?? scripts/wal-recovery-test.ps1 <- lane W1-③, KHÔNG phải tao +``` +✅ Đúng 1 file code + 1 file `sub-task-1.md`. KHÔNG git add/commit/push · KHÔNG đụng WAL/agent-memory/CLAUDE/STATUS/spec/run.md +· KHÔNG store_memory/RAG. Cây tạm ngoài repo (được spec lệnh) đã xoá. + +--- + +## 7. Đọng lại + +- **Học:** khi thực-nghiệm BÁC lý-do tồn-tại của một cái gate, đường đúng không phải xoá gate cũng không phải giữ nguyên + giọng cũ — mà **hạ trần severity + khai verdict NGAY TRONG header + thu scope về đúng phần thực-nghiệm CHƯA phủ**. + Tooling tự khai `GREEN-BUT-VACUOUS` thì nấc trung-thực sống-sót qua tay người đọc sau, report thì không. +- **Bất-ngờ 1:** CRLF-hoá `reviewer.md` ra **đúng 276 CR** = con số W0.6 báo ⇒ **đối-chứng độc-lập** vật-liệu probe + (cùng file, cùng byte-delta) — không chủ-đích, rơi ra từ fault-inject. +- **Bất-ngờ 2:** `grep -P` của gotcha #37 **không chạy được** ở đây (locale) và **exit 2 trông như "0 match"** nếu chỉ + liếc — một gate hygiene chống-mojibake **tự nó có thể vacuous-fail-open**. Đã đổi sang `LC_ALL=C tr` + positive control. +- **Bất-ngờ 3:** sandbox chặn `Remove-Item` với path **biến** (báo nhầm `system path 'A:'`); phải `-LiteralPath` chuỗi + tường-minh mới xoá được cây tạm. diff --git a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-2.md b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-2.md new file mode 100644 index 0000000..74a7583 --- /dev/null +++ b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-2.md @@ -0,0 +1,161 @@ +# sub-task-2 — LANE W1-③ — `scripts/wal-recovery-test.ps1` (FIX #3-bis → test CHẠY LẠI ĐƯỢC) + +**VERDICT: PASS** — 4/4 ca chọn đúng nhánh · 30 assert · 0 fail · exit 0. Fault-inject 2 vector chứng RĂNG: control=0 → injected=**1** → reverted=0. Non-ASCII = 0. + +- **File TẠO (duy nhất):** `scripts/wal-recovery-test.ps1` (535 dòng, NEW) +- **Sub-MD:** `.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-2.md` +- **Containment:** `git status --porcelain` → mục duy nhất của em = `?? scripts/wal-recovery-test.ps1`. 4 mục còn lại (`M scripts/governance-detectors.ps1`, `?? scripts/spawn-model-audit.ps1`, `?? scripts/agent-frontmatter-eol-check.ps1`, `?? .../sub-task-1.md`) = lane khác, em **KHÔNG chạm**. 0 git add/commit/push. + +--- + +## 1. Luật được encode (SUT) — `:109-116` + +```powershell +function Select-WalFoldBranch { + param([int]$K, [string]$Bottom) # <<< KHÔNG có $Nonwal — cố ý + if ($K -eq 0) { return 'noop' } + if ($Bottom -match '^wal:') { return 'reset-soft' } + return 'rebase-fixup' +} +``` + +🔴 **NONWAL không phải biến rẽ nhánh** — được neo **BẰNG CẤU TRÚC**, không bằng grep: SUT **không nhận** `$Nonwal` làm param, nên nó *không thể* rẽ theo NONWAL. Assert runtime qua reflection `(Get-Command Select-WalFoldBranch).Parameters.Keys` (`:317-321`). + +> **Vì sao KHÔNG grep:** bài học W0.4 (TỰ-THAM-CHIẾU). Gate grep chuỗi chạy trên chính file nó kiểm → khối comment mô tả luật cũ (`:29-35`) sẽ khiến grep bắt trúng câu trích → FAIL trên bản SỬA ĐÚNG. Reflection soi **đối tượng function sống**, miễn nhiễm với text. + +`Select-WalFoldBranchLegacy` (`:118-122`) giữ lại **CHỈ** làm oracle đối chứng — rẽ theo `NONWAL` đúng như spec v2 `:92`. + +## 2. Chống-tautology: oracle ĐO, không phát-biểu-lại luật + +Bẫy hiển nhiên: assert `SUT(ca2)=='reset-soft'` khi SUT là hàm 3 dòng **cùng file** = phát-biểu-lại luật = vô nghĩa. Cách đóng: + +Mỗi ca chạy **CẢ HAI** nhánh ứng-viên trên **cây độc lập** (`Test-Candidate :263`), rồi **ĐO** hậu-trạng `n(wal: trong origin/main..HEAD)`: + +| ca | cf reset-soft | cf rebase-fixup | oracle | expected lấy từ đâu | +|---|---|---|---|---| +| ca0 | CLEAN (n=0) | CLEAN (n=0) | **INCONCLUSIVE** | spec v3-PATCH — **DEFINITIONAL, khai thật** | +| ca1 | CLEAN (n=0) | **DEADLOCK (n=1)** | **EMPIRICAL** | **ĐO** — chỉ 1 nhánh sống | +| ca2 | CLEAN (n=0) | **DEADLOCK (n=1)** | **EMPIRICAL** | **ĐO** — chỉ 1 nhánh sống | +| ca3 | CLEAN (n=0) | CLEAN (n=0) | **INCONCLUSIVE** | spec v3-PATCH — **DEFINITIONAL, khai thật** | + +🔸 **KHAI THẬT:** ca0/ca3 expected là **DEFINITIONAL** (lấy từ spec, KHÔNG đo được) vì cả 2 nhánh tương-đương trên thước `n(wal:)`. Ở ca3 `reset --soft` **cũng** ra range sạch — spec chọn rebase, không phải vì nhánh kia chết. Script **in thẳng nhãn `DEFINITIONAL`** ra bảng, không giấu. Chỉ **ca1/ca2 là EMPIRICAL**. + +## 3. REGRESSION-GUARD (`:440-473`) — giá trị thật của lane + +Không phải phát-biểu-lại luật; **cả 2 vế đều ĐO trong chính lượt chạy**: + +``` +Replay of W0.3 4.2 - legacy branch (rebase+fixup) executed on a ca2 tree: + rebase-exit = 0 (0 = it SUCCEEDS, which is exactly the hazard) + rebase-state left = False + after: wal: flush 1 + n(wal: in range) = 1 + re-squash (2nd fold) -> n(wal:)=1 [rebase-exit=0] -> fixed point = PERMANENT STOP +``` + +Khớp **từng chi tiết** bằng chứng lead @W0.3 4.2 (`W0-evidence-15-07-2026.md:69-75`): exit 0, không để lại `.git/rebase-merge`, commit gộp **THỪA KẾ message của commit ĐÁY** (`wal: flush 1` — lead ghi `c2c39dc wal: flush 1`). + +🔴 **Điểm mấu chốt:** lỗi này **THÀNH-CÔNG MỘT CÁCH SAI** → test **CẤM** chỉ assert `exit == 0` (nếu thế nó sẽ **PASS trên chính con bug**). Nên assert neo vào **hậu-trạng đo được** `n(wal:)`, không vào exit code. + +**+ Thêm ngoài bằng-chứng lead — fixed-point probe (`:453-460`):** fold **LẦN 2** trên kết quả deadlock → `n(wal:)` **vẫn = 1**. Biến "STOP VĨNH VIỄN" từ tường-thuật → **số đo**: đây là **điểm bất-động**, re-squash không bao giờ thoát. + +4 assert guard: +- `legacy-branch-deadlocks` (`:462`) — ĐO: legacy exit 0 mà `n(wal:)=1` +- `legacy-picks-the-bad-one` (`:468`) — legacy(NONWAL=1) = `rebase-fixup` = đúng nhánh vừa đo là chết +- `sut-rejects-legacy-branch` (`:470`) — **SUT KHÔNG được chọn nhánh vừa đo là chết** ⇒ ai đổi luật về NONWAL → **FAIL** +- `rules-diverge-at-ca2` (`:472`) — 2 luật phải LỆCH ở ca2, nếu không guard thành vô-nghĩa + +## 4. Assert an-toàn (v2 `:260-261`) + +| Assert | Vị trí | Phủ | +|---|---|---| +| `rebase-exit-never-nonzero` | `:398` | main tree **+** cây counterfactual (ca3 in `[0,0]`) | +| `no-rebase-state-left` | `:388` | `.git/rebase-merge` **và** `.git/rebase-apply` ABSENT sau **mọi** bước | +| `cf-no-rebase-state` | `:390` | ABSENT trên **cả 2 cây counterfactual** | +| `headK-eq-origin-pre-reset` | `:402` | `HEAD~K == origin/main` PASS **TRƯỚC** khi reset (`:227-230` abort nếu lệch) | +| `ca2-never-rebases` | `:415` | v3-PATCH: ca2 **KHÔNG** được chạm `git rebase` | +| `git-tree-identical` | `:409` | ca0: ref-state (`for-each-ref` + HEAD) **byte-identical** trước/sau | +| `noop-touched-nothing` | `:407` | ca0: 0 reset, 0 rebase | + +## 5. FAULT-INJECT — 2 vector (bắt buộc, stdout thật ở §7) + +**Vector 1 — `-InjectLegacyRule` (`:69`, built-in, chạy-lại-được):** swap SUT sang legacy → `cases 2/4 PASS | asserts 30 run, 7 failed` → **exit 1**. +**Vector 2 — sửa MÃ NGUỒN thật trên cây tạm + `-RepoRoot `** (đúng dạng spec đòi): copy script sang `$env:TEMP/wal-fi-*/scripts/`, revert `Select-WalFoldBranch` về luật NONWAL (4 phép thay, mỗi phép xác nhận **occurrences = 1** trước khi thay) → chạy → **8 assert FAIL, exit 1** → gỡ lỗi → **4/4 PASS, exit 0**. + +> Vector 2 mạnh hơn: chứng rằng **một lần revert THẬT trong tương lai bị bắt**, không phải chỉ một cờ em tự dựng cho mình. + +**Anti-Goodhart:** gate này **KHÔNG** xanh-sẵn — script là file MỚI, không có "đã xanh trước khi làm gì". Teeth chứng bằng injected=1 ở **cả 2 vector**, không chỉ happy-path. + +## 6. 🔴 2 BUG THẬT script tự bắt (không phải happy-path) + +**(a) Pre/post-state bug — lượt chạy ĐẦU FAIL thật.** Guard tính `$m2 = Measure-Range (ca2-main)` **SAU** khi cây đã fold → đọc nhầm hậu-trạng (`K=1`, bottom = `[CLAUDE] fold re-commit`) → hỏi luật một câu **KHÁC** câu đang test → 2 assert FAIL giả. Fix: `$script:CaseMeasure` chốt số đo **TRƯỚC** fold (`:76-78`, `:345`, `:447-451`). +🔸 Đáng chú ý: bảng in `cases 4/4 PASS` **trong khi** verdict = FAIL — vì `$exitCode` **TÍNH TỪ counter** (`:523-524`), không phải nhãn dán. Đúng bài học META-COUNT @W0.4: nhãn không bao giờ đè số đo. + +**(b) Flaky assert `repo-untouched` — tự bắt lúc audit containment.** Bản đầu assert `HEAD + porcelain` bất-biến trước/sau. Nhưng ĐO: porcelain repo trôi **2 → 5** giữa các lượt chạy vì **lane song song đang ghi**, và Stop-hook `wal-flush.ps1` **commit được** → HEAD trôi. ⇒ assert sẽ **FAIL vì lý-do NGOẠI-SINH**. Hạ xuống **INFO** (`:497-509`); containment giữ **HARD** ở `workdir-outside-repo` (cấu-trúc: mọi cây đều treo dưới `$root`, chứng `$root` ngoài `$RepoRoot` là đủ). +**Chứng bằng ĐO, không bằng lời:** inject concurrency — background job ghi `intruder.txt` vào cây `-RepoRoot` **giữa lượt chạy** → `porcelain 0 -> 1 ; unchanged=False` → **VERDICT PASS, exit 0**. Bản cũ sẽ FAIL ở đúng ca này. + +## 7. STDOUT THẬT + +**Default (`-File scripts/wal-recovery-test.ps1`):** +``` +ca0 base 0 0 noop reset-soft noop DEFINITIONAL PASS +ca1 base|wal:|wal: 2 0 reset-soft reset-soft reset-soft EMPIRICAL PASS +ca2 base|wal:|[CLAUDE] 2 1 reset-soft rebase-fixup reset-soft EMPIRICAL PASS +ca3 base|[CLAUDE]|wal: 2 1 rebase-fixup rebase-fixup rebase-fixup DEFINITIONAL PASS +cases 4/4 PASS | asserts 30 run, 0 failed +VERDICT: PASS DEFAULT-EXIT = 0 +``` + +**Fault-inject vector 2 (cây tạm, `-RepoRoot $fi`):** +``` + occurrences of [param([int]$K, [string]$Bottom)] = 1 (must be 1) + occurrences of [if ($K -eq 0) { return 'noop' }] = 1 (must be 1) + occurrences of [if ($Bottom -match '^wal:') { return 'reset-soft' }] = 1 (must be 1) + occurrences of [return (Select-WalFoldBranch -K $K -Bottom $Bottom)] = 1 (must be 1) +--- (c) RUN INJECTED --- + [FAIL] env | sut-has-no-NONWAL-param | Select-WalFoldBranch params = [K, Bottom, Nonwal] + [FAIL] ca0 | branch-selection | SUT=reset-soft expected=noop (DEFINITIONAL oracle) + [FAIL] ca2 | branch-selection | SUT=rebase-fixup expected=reset-soft (EMPIRICAL oracle) + [FAIL] ca2 | ca2-never-rebases | git rebase NOT invoked on ca2 + [FAIL] ca2 | post-state-clean | n(wal: in origin/main..HEAD) after SUT branch = 1 + [FAIL] grd | sut-rejects-legacy-branch | SUT = rebase-fixup != the measured-deadlock branch + [FAIL] grd | rules-diverge-at-ca2 | SUT=rebase-fixup vs legacy=rebase-fixup +cases 2/4 PASS | asserts 30 run, 8 failed +VERDICT: FAIL INJECTED-EXIT = 1 +--- (d) REMOVE FAULT --- +cases 4/4 PASS | asserts 30 run, 0 failed REVERTED-EXIT = 0 +FAULT-INJECT SUMMARY: control=0 injected=1 reverted=0 +``` +> `[FAIL] ca2 | post-state-clean | n(wal:)=1` = mạnh nhất: luật injected **thật sự rebase** cây ca2-main và **để lại `wal:` trong range** — deadlock đo ngay trên cây SUT. + +**Concurrency boundary:** +``` + [info] RepoRoot HEAD f7ab8c0 -> f7ab8c0 ; porcelain 0 -> 1 ; unchanged=False + [info] delta above is NOT a failure: containment is proven by workdir-outside-repo. +cases 4/4 PASS | asserts 30 run, 0 failed +VERDICT: PASS CONCURRENT-EXIT = 0 +``` + +## 8. Quy-ước .ps1 (gotcha #30/#37) + +| Luật | Trạng thái | Đo | +|---|---|---| +| 1. Thân ASCII-only | ✅ | `NON-ASCII byte count = 0` (quét 24071 byte); no BOM (`first 3 bytes = 60,35,10`) | +| 2. Token VN qua code-point (`U`) | **n/a — KHÔNG cần** | Script chỉ match `^wal:` + `^\[CLAUDE\]` = **thuần ASCII**. Rule 2 chỉ áp khi *"cần token tiếng Việt để MATCH nội dung file đích"*. **KHÔNG** thêm hàm `U` rỗng để làm-màu | +| 3. `-Encoding UTF8` đọc file đích | **n/a** | Không đọc file đích nào; cây git **tự tổng-hợp** từ đầu | +| 4. PS 5.1 only | ✅ | Quét `&&`=0 `\|\|`=0 `??`=0 `-AsHashtable`=0; `PSParser::Tokenize` → **0 parse error**; chạy thật trên **5.1.26100.8737** | +| 5. `param($RepoRoot = ...)` + path derive | ✅ | `:65-69` đúng dạng bắt buộc; 0 đường-dẫn tuyệt-đối hardcode; chạy thật với `-RepoRoot ` | +| 6. Đọc file mẫu trước | ✅ | Đọc trọn `governance-detectors.ps1` (455 dòng); mượn `Write-Section:55`, `param:32-34`, Write-Flag→`Assert-That` | +| EOL | ✅ | `CRLF=0`; `git check-attr` → `text: auto` `eol: lf` (khớp `.gitattributes` W0) | + +## 9. Khác detector — CỐ Ý + +`governance-detectors.ps1:455` = `exit 0` **luôn** (DETECT-only, mandate). File này là **TEST** ⇒ `exit 1` khi fail (`:523-524`, `:535`), `exit 0` khi 4/4. Nhiệm-vụ lane ghi rõ *"đây LÀ test, khác detector"*. + +## 10. 🔸 Khai chặt — giới-hạn + +- **ca0/ca3 = DEFINITIONAL**, không phải đo (§2). Chỉ ca1/ca2 empirical. +- Test phủ **luật rẽ nhánh** FIX #3-bis. **KHÔNG** phủ: interlock hook `wal-flush.ps1` (W0.3 4.3 = fix #8b, ngoài task), `wal:` count-guard §5.2, hành-vi trên **repo thật**. +- Cây tạm dùng `refs/remotes/origin/main` **local giả** — không remote thật, không network. Đúng shape lead đo, nhưng repo thật có thể có yếu-tố khác (worktree bẩn, hook, submodule) **chưa phủ**. +- 1 build git: `git version 2.45.1.windows.1`, win32. Chưa phủ git khác/OS khác. +- `-InjectLegacyRule` là **cửa sau có chủ-đích** (chứng teeth chạy-lại-được). Nó **không** đổi luật ở đường mặc-định (`Get-FoldBranch :124-128`), nhưng vẫn là param công-khai — nếu ai chạy CI **kèm cờ này** thì gate sẽ đỏ. Khai để không ai tưởng là bug. diff --git a/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-3.md b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-3.md new file mode 100644 index 0000000..10089e0 --- /dev/null +++ b/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/sub-task-3.md @@ -0,0 +1,179 @@ +# sub-task-3 — LANE W1b — `scripts/spawn-model-audit.ps1` (PA-2b) + +> **VERDICT: DONE + 2 TIỀN-ĐỀ CỦA LỆNH BỊ ĐO NGƯỢC.** Script land, 6/6 acceptance PASS, fault-inject 11 ca có RĂNG (không chỉ happy-path). +> 🔴 **Hai giả-định trong lệnh giao lane này SAI — đo được, không phải suy-diễn.** Cả hai đều theo hướng **dè-dặt quá mức** (under-claim), nên không tạo "acceptance giả" — nhưng nếu bê nguyên vào adap-report thì **báo sai nấc lên hub**, và W2 sẽ tự trói tay vô cớ. + +- **File TẠO (duy nhất):** `scripts/spawn-model-audit.ps1` — 25.606 byte · 0 byte non-ASCII · no BOM (`3c 23 0a`) · PS 5.1 parse **0 error** · exit **0**. +- **Containment:** `git status --porcelain` ⇒ chỉ `?? scripts/spawn-model-audit.ps1` là của W1b. `git diff -- .claude/workflows/hmw.js docs/STATUS.md .claude/agents/` = **rỗng**. Cây tạm đã xoá. + +--- + +## 0. 🔴 HAI TIỀN-ĐỀ BỊ ĐO NGƯỢC (đọc trước khi dùng lane này) + +### (A) "resolved model rất có thể KHÔNG đo được từ .ps1" — **SAI. ĐO ĐƯỢC, đầy đủ.** + +Lệnh lane dặn: *"NEU KHONG DO DUOC: KHAI THAT … script audit dùng phần ĐO ĐƯỢC (static)"*. Em đi **đo thật** thay vì nhận giả-định. Kết quả: **resolved model được ghi thẳng ra đĩa**, offline, .ps1 đọc được. + +`owner-decisions-15-07-2026.md:60` đã trỏ đúng đường (`…/subagents/workflows/wf_*/agent-*.jsonl`) — đường đó **CÓ THẬT** và **có model**: + +| wf-run (phiên S119 `3d9bec56`) | lane | resolved model | records | +|---|---|---|---| +| `wf_1f6bd5e2-478` (fable-clone invest) | 5 | `claude-opus-4-8` | 45/80/54/60/51 | +| `wf_78a84f9b-03e` (fable-clone reviewer) | 4 | `claude-opus-4-8` | 56/58/66/53 | +| `wf_cb964f83-331` (fable-real reviewer) | 2 | **`claude-fable-5`** | 39/42 | + +Vị trí: `message.model` của record `"type":"assistant"`. +⇒ Script **KHÔNG** phải lùi về static-only. Nó làm **PA-2b THẬT** như owner-decision đặt hàng: `{n dispatch · n explicit · n mismatch}`. +⇒ Bài học: `meta.json` **KHÔNG** có model (`{"agentType":"reviewer","spawnDepth":1}`) — ai chỉ soi meta sẽ kết luận nhầm "không đo được". Model nằm trong `.jsonl`, không nằm trong `.meta.json`. + +### (B) "precedence CHƯA TỪNG ĐƯỢC TEST … chỉ test được ở phiên lead=Fable" — **SAI. ĐÃ TEST RỒI, hôm nay, ngoài ý muốn.** + +Lệnh bắt khai nguyên-văn: *"…CHUA TUNG DUOC TEST … Phep thu phan biet duoc CHI chay duoc trong phien lead=Fable; hom nay lead=Opus => KHONG phan biet duoc => DEFER"*. + +**Chỗ hụt của lập-luận:** nó chỉ xét **chiều `tier:'opus'`**. Điều-kiện phân-biệt thật chỉ là **`họ(spawn-param) ≠ họ(lead)`** — nên **chiều `tier:'fable'` dưới lead=Opus phân biệt ngang hệt**. Và nó **đã chạy**: `wf_cb964f83-331` (`/fable-real reviewer`, cổng-cuối chính phiên này). + +| Yếu tố | Giá trị ĐO ĐƯỢC | Nguồn | +|---|---|---| +| lead model phiên `3d9bec56` | `claude-opus-4-8` — **290/290 record, 0 Fable** | `3d9bec56….jsonl` | +| agentType lane | `reviewer` (agent registry thật) | `agent-*.meta.json` | +| frontmatter lane | `model: inherit` | `.claude/agents/reviewer.md:5` | +| spawn-param | `fable` (`hmw.js:44` `return tier`) | `/fable-real` escape-hatch | +| **RESOLVED** | **`claude-fable-5`** — 2/2 lane | `agent-a5167691d772fad12.jsonl` · `agent-abe4f7938106101ef.jsonl` | + +**Suy ra:** nếu frontmatter `inherit` **thắng** ⇒ resolved phải là lead = `claude-opus-4-8`. **Nó không phải.** +⇒ **spawn-param CÓ hiệu-lực trên agent frontmatter-`inherit`** ⇒ 🔴 **`fix GAP#6` KHÔNG phải NO-OP.** Nỗi lo lớn nhất trong lệnh **đã được gỡ bằng số đo**, không cần defer. + +**Giới-hạn trung-thực (giữ nguyên, không nống):** +1. Đây **không** chứng minh `inherit` **THUA** một cuộc tranh precedence. `inherit` rất có thể nghĩa là *"nghe theo caller"* — khi đó **không hề có tranh chấp**. Hai cách đọc cho **cùng một kết-luận vận-hành** (param có hiệu-lực); dữ-liệu này **không tách được** chúng, và script **không giả vờ tách**. +2. Cái **THẬT SỰ chưa test** = precedence với **frontmatter PIN CỨNG** (dạng hub: 17/17 `model: claude-opus-4-8`). SE có **0 agent pin cứng** (12/12 `inherit`, lệnh anh S66/H8) ⇒ ca đó **không có bằng-chứng**, và **không thể** có ở SE nếu không cố ý tạo. +3. `wf_1f6bd5e2-478` + `wf_78a84f9b-03e` (9 lane `claude-opus-4-8`) **không** phân-biệt được: lead=Opus nên cả 2 giả-thuyết đều tiên-đoán Opus. **Chỉ** `wf_cb964f83-331` mang sức phân-biệt. Đúng như lệnh nói *"hôm nay không phân biệt được"* — **cho chiều opus**. Chiều fable thì được. + +📌 **Đề-xuất cho lead:** câu khai ở `v2:271` cần tách đôi khi vào adap-report — **(A) inherit ⇒ ĐÃ ĐO, param thắng** (kèm run-id + số đo) · **(B) hard-pin ⇒ CHƯA TEST, SE không có ca**. Bê nguyên "CHƯA TỪNG ĐƯỢC TEST" lên hub = **under-report** đúng lớp lỗi `fix #9(b)` vừa bắt (*"dán PASS thành n-a"*, đây là bản đối xứng: dán ĐÃ-ĐO thành CHƯA-TEST). Quyền chốt chữ = lead/anh; em không sửa spec. + +--- + +## 1. Cấu-trúc script (5 section + summary) + +| § | Việc | Nguồn | Đo được? | +|---|---|---|---| +| **A** | PA-2a: hằng `TIER2_EXPECTED_FULL_ID` trong `hmw.js` — tồn-tại? == `claude-opus-4-8`? | `.claude/workflows/hmw.js` | ✅ static | +| **B** | PA-2b: resolved vs expected — `{n dispatch · n explicit · n mismatch}` | `…/wf_*/agent-*.jsonl` | ✅ **đo thật** | +| **C** | Canonical: row `\| Sub-agents \| **N** \|` + marker flip-chain + cross-check đĩa | `docs/STATUS.md:24` | ✅ static | +| **D** | H8 all-inherit: frontmatter `model: inherit` — **glob**, KHÔNG hardcode 12 | `.claude/agents/*.md` | ✅ static | +| **E** | In **mọi lần chạy** các trục KHÔNG-đo-được ⇒ báo-cáo không thể bị đọc quá nấc | — | khai báo | + +### Quyết-định thiết-kế đáng soi + +**(1) Neo CẤU-TRÚC, không grep chuỗi — bài học W0.4 #1 (tự-tham-chiếu).** +`hmw.js:36` **đã sẵn** chứa literal `claude-opus-4-8` trong comment (*"KHÔNG còn demote-pin…"*). Nên acceptance thô ở `v2:269` (*"`TIER2_EXPECTED_FULL_ID` ≥1 hit = claude-opus-4-8"*) nếu code thành **2 grep rời** thì: +> `grep TIER2_EXPECTED_FULL_ID` ≥1 ✓ **AND** `grep claude-opus-4-8` ≥1 ✓ ⇒ **XANH** — kể cả khi hằng-số đang mang `claude-opus-9-9`. + +⇒ Script **bắt giá-trị bằng capture-group** (`TIER2_EXPECTED_FULL_ID\s*=\s*['"]([^'"]+)['"]`) rồi so **giá-trị**. Cái bẫy được **in ra stdout mỗi lần chạy** làm phản-chứng: `anti-vacuous note: naive grep 'claude-opus-4-8' in hmw.js = 1 hit(s) [comment text] -> NOT used as evidence`. + +**(2) `$expected` KHÔNG có default — fail-loud.** Thiếu hằng ⇒ FLAG HIGH `expected constant missing (W2 chua land)` + §B in **`[SKIPPED] … This is NOT a pass`**. Audit mà tự bịa giá-trị nó phải kiểm = tự cấp PASS cho chính mình. + +**(3) 2-key có chủ-đích.** Kỳ-vọng khai **2 nơi**: `hmw.js` (PA-2a) + hằng `$OWNER_RATIFIED_TIER2_FULL_ID` trong script. Sửa lén **một** bên ⇒ FLAG. **Giá phải trả nói thẳng:** anh re-pin thì phải sửa **cả hai** — *chính cái giá đó là phép kiểm*. + +**(4) Path derive 100% từ `$RepoRoot`.** Slug = `$RepoRoot -replace '[:\\/_]','-'` ⇒ `D--Dropbox-CONG-VIEC-SOLUTION-SOLUTION-ERP` (khớp thật). `$TranscriptRoot` từ `$env:USERPROFILE`, **không** hardcode `C:\Users\pqhuy` (khác `governance-detectors.ps1:323`). ⇒ cây tạm tự ra slug lạ ⇒ `[NO-SCOPE]`, **không bịa số**. + +**(5) `mismatch` định-nghĩa hẹp — chống dương-giả.** Alias khoá **HỌ**, không khoá phiên-bản (H23 §2(2)) ⇒ mismatch = *cùng họ `claude-opus-`, khác version*. Lane `claude-fable-5` = **other-family**, KHÔNG phải drift (đó là escape-hatch cố ý). Nếu tính nó là mismatch thì mọi `/fable-real` sẽ báo động giả. + +**(6) KHÔNG dùng `U @(code-point)`.** Quy-ước bắt buộc U() **khi cần match token tiếng Việt**. Mọi neo của lane này **thuần ASCII** (`Sub-agents` · `model: inherit` · `TIER2_EXPECTED_FULL_ID` · `CANONICAL single-owner flip-chain`) ⇒ **không cần** ⇒ nhét U() chết vào cho "giống mẫu" = Goodhart. Thân script vẫn **ASCII tuyệt đối** (rule 1, đo: 0/25.606 byte >127). + +**(7) Glob, không hardcode 12** (fix #9(h) / R2-M3): roster 12→14 ở W2 ⇒ hardcode sẽ **tự già thành FAIL giả** ngay khi W2 land. + +**(8) Mọi verdict TÍNH TỪ SỐ ĐO — bài học W0.4 #2.** Không có nhãn dán cạnh số. Chứng: ca F5 in `frontmatter: 11/12` **và** FLAG — nhãn không thể mâu-thuẫn số vì nhãn **sinh ra từ** số. + +--- + +## 2. Chạy thật trên repo (stdout thật, rút gọn) + +``` +===== A - expected constant (PA-2a, hmw.js) ===== + anti-vacuous note: naive grep 'claude-opus-4-8' in hmw.js = 1 hit(s) [comment text] -> NOT used as evidence +[SPAWN-AUDIT] HIGH | .claude/workflows/hmw.js | expected constant missing (W2 chua land): TIER2_EXPECTED_FULL_ID not declared in hmw.js | resolve: land PA-2a: ... + -> section B comparison will report SKIPPED (no expected value to compare against) + +===== B - resolved model (PA-2b, spawn transcripts) ===== + project slug : D--Dropbox-CONG-VIEC-SOLUTION-SOLUTION-ERP (derived from RepoRoot) + session scope : 95c916ee-253d-4813-8379-f58802d65746 (last write 2026-07-15 12:15) + wf_de36dea9-265/agent-a80fe3808ac6ce234.jsonl [workflow-subagent] -> claude-opus-4-8 (67 record(s)) : SKIPPED (no expected constant) + ... x4 lane ... + COUNTS: 4 dispatch | 4 explicit | 0 mismatch + [SKIPPED] resolved-vs-expected NOT evaluated: section A found no expected constant. + This is NOT a pass. The lanes above are reported raw, uncompared. + +===== C ===== STATUS.md:24 canonical Sub-agents = 12 | [OK] marker | [OK] canonical 12 matches disk (12) +===== D ===== frontmatter: 12/12 agent .md carry 'model: inherit' | [OK] all-inherit holds (12/12) +TOTAL FLAGS: 1 >>> EXIT CODE = 0 +``` + +> 4 lane §B = **chính wave W1 này** (`wf_de36dea9-265` — W1a/W1b/W1c/W1d). Tất cả `claude-opus-4-8`, `agentType=workflow-subagent` (role-less ⇒ inherit lead=Opus) — **khớp H8 all-inherit**, quan sát trực-tiếp. + +--- + +## 3. FAULT-INJECT — 11 ca, cây tạm `$env:TEMP\w1b-faultinject`, `-RepoRoot ` + +Vật-liệu tối-thiểu: `hmw.js` (14.810B) + `STATUS.md` (124.526B) + 13 agent `.md`. + +| Ca | Inject | Kỳ-vọng | **stdout thật** | | +|---|---|---|---|---| +| **F0** | không có hằng (comment `:36` vẫn mang version) | FLAG missing | `HIGH … expected constant missing (W2 chua land)` · `TOTAL FLAGS: 1` | ✅ | +| **F1** 🔴 | hằng = `'claude-opus-9-9'` | **FLAG mismatch** | `HIGH … hmw.js declares 'claude-opus-9-9' but S119 PA-2a ratified 'claude-opus-4-8'` · `TOTAL FLAGS: 1` | ✅ | +| **F2** 🔴 | sửa về `'claude-opus-4-8'` | **hết FLAG** | `[OK] hmw.js expected = 'claude-opus-4-8' = owner-ratified` · **`TOTAL FLAGS: 0`** | ✅ | +| **F3** | `'claude-opus-4-8[1m]'` | FLAG suffix | `MED … carries a '[1m]' context-window suffix` (+HIGH mismatch) · `TOTAL FLAGS: 2` | ✅ | +| **F4** | 2 định-nghĩa lệch nhau | FLAG conflict | `HIGH … declared with 2 different values [claude-opus-4-1 vs claude-opus-4-8]` | ✅ | +| **F5** | `reviewer.md` pin cứng model | FLAG H8 | `MED \| .claude/agents/reviewer.md:5 \| frontmatter pins 'model: claude-opus-4-8'` + **`frontmatter: 11/12`** | ✅ | +| **F6** | STATUS `Sub-agents`=14, đĩa 12 | FLAG stale | `MED … canonical-itself-stale: STATUS Sub-agents=**14** but disk has 12 agent .md` | ✅ | +| **F7** | gỡ hết | 0 FLAG | `TOTAL FLAGS: 0` | ✅ | +| **B1** | transcript giả: lane `claude-opus-9-9` | **FLAG drift** | `HIGH \| wf_fake/agent-a2.jsonl \| alias-drift: resolved 'claude-opus-9-9' … expected 'claude-opus-4-8'` · `COUNTS: 4 dispatch \| 4 explicit \| 1 mismatch` | ✅ | +| **B2** | gỡ lane drift | mismatch=0 | `COUNTS: 3 dispatch \| 3 explicit \| 0 mismatch` · `TOTAL FLAGS: 0` | ✅ | +| **B3** | lane sạch nhưng tool-payload mang `"model":"claude-opus-9-9"` ở **nesting khác** | **KHÔNG** dương-giả | `-> claude-opus-4-8 (1 record(s)) : match` · `0 mismatch` | ✅ | + +### 🔴 F1 = bằng-chứng chống-Goodhart (không phải happy-path) +Ngay trong stdout ca F1: `naive grep 'claude-opus-4-8' in hmw.js = 1 hit(s)`. Nghĩa là ở F1 file có **đồng thời** `TIER2_EXPECTED_FULL_ID` (≥1 hit) **và** `claude-opus-4-8` (≥1 hit, comment `:36`) ⇒ **gate grep-thô sẽ XANH** trên file khai `claude-opus-9-9`. Neo cấu-trúc **FLAG**. Đây là chỗ răng cắn thật. + +### B3 = chứng neo `"message":{"model":` đáng đồng tiền (đo, không phán) +``` +NAIVE hits = 2 -> [claude-opus-9-9, claude-opus-4-8] <- sẽ đẻ MISMATCH GIẢ (HIGH) trên lane sạch +ANCHORED hits = 1 -> [claude-opus-4-8] <- đúng +``` + +### ⚪ Chỗ em ĐỊNH chứng mà KHÔNG chứng được — khai thẳng +Giả-thuyết ban đầu: agent dán snippet transcript vào text ⇒ nhiễm regex. **Đo ra là SAI:** decoy `\"model\":\"claude-opus-9-9\"` trong text ⇒ **naive = anchored = 1 hit `[claude-opus-4-8]`** — JSON escaping tự chặn (sau `model` là `\` chứ không phải `"`). ⇒ Giá-trị của neo **KHÔNG** nằm ở chống-escaping (như em tưởng) mà **chỉ** ở chống **nesting khác** (ca B3). Ghi lại đúng nấc thay vì nống công. + +--- + +## 4. Acceptance (tính từ số đo) + +| # | Tiêu-chí | Số đo | Verdict | +|---|---|---|---| +| 1 | `TIER2_EXPECTED_FULL_ID` — W2 chưa land ⇒ **FAIL-LOUD**, không crash, không im-lặng-xanh | 0 def ⇒ `HIGH … missing (W2 chua land)`; §B `[SKIPPED] … NOT a pass`; exit 0 | **PASS** | +| 2 | 🔴 fault-inject expected giả ⇒ **PHẢI FLAG**; đổi về đúng ⇒ hết FLAG | F1 `TOTAL FLAGS: 1` (mismatch) → F2 `TOTAL FLAGS: 0` | **PASS** | +| 3 | `param -RepoRoot` bắt buộc | `:74` `[string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path` | **PASS** | +| 4 | non-ASCII = 0 · PS 5.1 parse sạch | 0/25.606 byte >127 · parse errors **0** · PSVersion 5.1.26100.8737 · no BOM · 0 `&&`/`\|\|`/ternary/`??` | **PASS** | +| 5 | exit 0 | `>>> EXIT CODE = 0` (mọi ca, kể cả khi có FLAG) | **PASS** | +| 6 | Header khai trục CHƯA-ĐO-ĐƯỢC, không bàn quá nấc | §E in mỗi lần chạy (6 mục) + header khai (i)…(iv) + khối PRECEDENCE | **PASS** | + +**6/6 PASS.** Trong đó (2) và (4) là số **đo**, không phải tường-thuật. + +--- + +## 5. Bàn giao W2 + +1. **PA-2a land:** thêm cạnh `resolveModel` (`hmw.js:~43`): + `const TIER2_EXPECTED_FULL_ID = 'claude-opus-4-8'` — **không** `[1m]` (gotcha #37; script FLAG nếu có). + Land xong: §A `[OK]` · §B chuyển từ `SKIPPED` sang so thật. Ca F2 đã diễn-tập đúng đường này trên cây tạm. +2. **Nếu anh re-pin version:** sửa **cả hai** — `hmw.js` **và** `$OWNER_RATIFIED_TIER2_FULL_ID` (`spawn-model-audit.ps1:~86`). Chỉ sửa một ⇒ FLAG (đúng thiết-kế 2-key). +3. **Roster 12→14:** §C/§D **tự theo** (glob + đọc STATUS). Không có số nào phải sửa tay trong script này. +4. **CI:** `scripts/*.ps1` có trigger (AS-6) ⇒ file này vào path filter. Nó **exit 0 luôn** ⇒ không thể gãy build. +5. 🔴 **Cho R4-request / adap-report:** dùng **§0(A)** (resolved ĐO ĐƯỢC — bác "không đo được") + **§0(B)** (precedence-vs-`inherit` **ĐÃ ĐO**, param thắng, `wf_cb964f83-331`) thay câu "CHƯA TỪNG TEST" ở `v2:271`. Giữ nguyên caveat: **hard-pin vẫn chưa test** + `inherit` có thể là *"nghe theo caller"* chứ không phải *"thua"*. + +## 6. Giới-hạn script tự khai (§E, in mỗi lần chạy) + +1. Spot-check theo quy-ước, **KHÔNG enforcement** — không chặn spawn (H23 §2(4)). +2. **Chỉ phiên hiện-tại** — run cũ có trước quy-ước ⇒ nhiễu, không phải bão lỗi (owner-decisions:64). +3. **KHÔNG** đọc thành *"đã áp đủ sàn"* — chỉ đo **tính tường-minh trong transcript**, không đo độ-phủ tài-liệu (owner-decisions:65). +4. **Hồi-cứu**: đọc model **đã** resolve; **không** tiên-đoán được spawn KẾ. Báo-cáo sạch **không** hứa lần sau không trôi. Đây chính là lý-do H23 §2(4) để nó informational. +5. **CHƯA TEST** — precedence vs frontmatter **pin cứng**: SE có 0 ca (12/12 inherit). +6. **CHƯA THỬ** — param `model:` có từ-chối full-id không (fix #8a). Tài-liệu nói enum alias; **không thử** ở đây.