# fable-real reviewer — CONG CUOI (verdict spec v2)

> Lenh-A /fable-real reviewer · wf_cb964f83-331 · single deep-pass · RETURN-only.
> Lead ghi (B3). 3 truc: v2-va-du? + HONESTY (lane R4 chet) + GO/NO-GO.

---

VERDICT: GO-WITH-FIXES — v2 đã đóng toàn bộ các đường mất-việc/rewrite-history (không còn tiêu-chí NO-GO), nhưng 3/23 finding thật vẫn STILL-BROKEN + 3 PARTIAL, kèm 2 lỗi honesty cấp C ("v2 vá 19 finding" là over-claim che đúng 5 MAJOR bị rớt; enum 10-class tự nhận "khớp H24 5+5" nhưng đánh rơi 1 dấu-hiệu sàn của broadcast) — phải vá spec-v3 trước khi HMW wave chạy.

---

## TRỤC 1 — Đối chiếu TỪNG finding (đếm lại từ file: R2 = 4C+8M+6m, R3 = 5C+6M+6m ⇒ 23 C+M, KHÔNG phải 19)

| Finding | Trạng thái | Bằng chứng (tự đo 2026-07-15) |
|---|---|---|
| R2-C1 / R3-M1 (ls=14 sai số-học) | **FIXED** | Tự đếm: `ls .claude/agents/*.md`=**13** (12 roster + README) → +2 = 15 glob / 14 sans-README. v2 §2.4(1)+§3.9 dùng đúng bất-biến roster `VALID_ROLES.length==14 AND grep -v README ==14` |
| R2-C2 (anchor số-nhiều) | **FIXED** | Grep `Last updated` trong `.claude/skills` = **0 hit** ✓. Regex v2 `\*\*Status \(post Session \d+ — (\d{4}-\d{2}-\d{2})\)\:\*\*` tự chạy → MATCH `permission-matrix/SKILL.md:16` (`2026-04-30`) + `form-engine/SKILL.md:15` — positive-control bắn được thật |
| R2-C3 (gate⟂cờ tách wave) | **FIXED** (residual nhỏ) | 4-wrapper thật verify: `commands`=18, `hmw.md` NOT-EXIST, `args.run`=0 hit, `fable-real.md` có. Gate+cờ CÙNG 1 COMMIT W2 ✓. Residual: `fable-clone.md` 2-chạm (cờ W2 + GAP#6 W3) vắng bảng xung-đột §3.2; "4 cờ" gồm 1 cái không phải file (raw-invoke) |
| R2-C4 / R3-C5 (gate W0.2 xanh-sẵn / 3 định nghĩa) | **FIXED** | Đo: scoped=**0**, repo=**188** ✓. v2 chốt 1 định nghĩa scoped + khai vacuous + cấm mass rm/checkout + acceptance `--cached`/`--dry-run`; vế "vẫn 0 sau W2" là gate CÓ răng (2 agent .md mới). Cosmetic: dòng 70 nói "W0.2 KHÔNG vào §3.9" nhưng §3.9:245 vẫn có (đã chú vacuous) |
| R2-M1 (nửa-(ii) n-a sai) | **FIXED** | Đọc broadcast wal-defect-fix :58: "wrapper gọi xuống engine dùng-chung" — v2 flip thành ÁP, deliverable 4 chỗ ✓ |
| R2-M2 (lỗ chưa-test precedence) | **FIXED** | Khai vào Nấc-trung-thực + §3.9, acceptance defer phiên lead=Fable, không giả-vờ ✓ |
| R2-M3 (0-hardcode phình scope) | **FIXED** | Thu về "0 số NHỊP hardcode" đúng nguyên-văn broadcast ✓ |
| R2-M4 (scheduler mồ-côi + enum) | **FIXED phần chủ-sở-hữu** / enum sai nội-dung → xem TRỤC 2 C2 | W2 own `memory-budget.json`+`.session-counter.json` ✓; enum chép vào thân spec ✓ nhưng chép **10/11** — rớt 1 class |
| R2-M5 (② + ③d rơi; spawn-probe vắng §3.9) | **FIXED** | ② 14/14/14 + 0.6b registry-probe + §3.9 "RESTART → spawn-probe 14/14 SỐNG" ✓ (đối chiếu broadcast eol :68/:75 ✓) |
| R2-M6 (else "vô-hại") | **FIXED** | Flip thành MÌN NGỦ, bỏ else / fail-loud ✓ (57 trên origin/main tự đếm lại = 57 ✓) |
| R2-M7 (thí-nghiệm quyết-định + L3 caveat) | **FIXED** | W0.6 spawn-probe CRLF (RESTART) + §1.C khôi phục CHƯA-VERIFY + R4 hạ nấc ✓ |
| **R2-M8** (sweep roster sai pattern + file chủ-quản không wave) | 🔴 **STILL-BROKEN** | v2 §2.4(5) = "giữ v1". Tự đo: `hmw.js:9` vẫn "fan-out **9-agent** roster"; `ultra-on.md:24` vẫn heading VALID_ROLES **12-sub** (W2 chỉ thêm cờ, không sync roster); `fable-real.md`/`fable-real-runbook.md` không thuộc wave nào |
| R3-C1 (rebase phá thật) | **FIXED** | 2 nhánh runtime + interlock hook + trap + assert + fault-inject acceptance. Tự đo hôm nay: K=**8**, NONWAL=**0** → nhánh A. Nhưng nhánh B VẪN sẽ chạy tại W6 (range lẫn commit thường) → hở còn lại ghi ở R3-C3 |
| R3-C2 (K stale) | **FIXED** | LUẬT SỐ ĐỘNG + W0.0 + assert `HEAD~K==origin/main`. K drift đo được 4→5→6→**8** trong 1 buổi = chứng minh luật này đúng |
| **R3-C3** (push deadlock) | ⚠️ **PARTIAL** | Chained squash→count→push 1-lượt + re-execute + STOP fail-loud = đúng chữ. NHƯNG cơ chế fold KHÔNG đạt n=0 khi wal: nằm ĐÁY range — mà thiết kế v2 tự tạo ca này: W0.3 "commit-chốt ở W6" để nội dung parked-staged, trong khi `wal-flush.ps1:14-17` (đã đọc) commit **pathspec 3 path** ở turn-boundary kế → toàn bộ nội dung reset-soft thành 1 wal: ĐÁY range; tại W6 NONWAL>0 → nhánh B, luật "todo đầu = pick" giữ wal: đáy sống → recount=1 → re-squash cùng logic → vẫn 1 → **STOP ngay lần dùng thật đầu tiên**. Cộng: W6 = push→adap-report→email nghĩa là cần push #2 cho file report — giữa push#1 và commit report có turn-boundary → wal: đáy range lặp lại. "§5.2 1 lượt" và chuỗi việc W6 chưa tự-mâu-thuẫn về chữ, nhưng chỉ khả thi nếu có luật fold leading-wal: (chưa có) |
| R3-C4 (premise stale / renormalize staging) | **FIXED** | W0.0 phân-loại-ABORT + acceptance `--cached`. Porcelain giờ = **7 untracked broadcast** (WAL sạch, run-folder đã được hook commit) — số của v2 cũng đã stale, đúng như luật v2 tự đặt |
| R3-M2 (STATUS coupling) | **FIXED** | Tự đo: STATUS.md:24 `| Sub-agents | **12** |` có, row `Policies` **không có**, MenuKeys = **54** × Actions 4 = **216** ✓. v2 buộc CÙNG LANDING W2 + thêm row ✓ |
| R3-M3 (TOTAL≥46 close-gate bất-khả) | **PARTIAL** | Gate ≥46-lúc-đóng đã bị GỠ khỏi §3.9 (hết bất-khả) + "PHẢI in TRƯỚC vá" giữ; nhưng không adopt capture-stdout → `runs/<id>/` làm bằng chứng time-anchored — "reviewer chứng-kiến" là neo duy nhất |
| **R3-M4** (Sàn-3 thiếu dual-accept) | 🔴 **STILL-BROKEN** | Tự scan lại runs/: naive = **13** orphan; với dual-accept `harvest/<stage>-synthesis.md` = **8** (7 tồn-đọng + S119) — 5 folder h10/h910 đều có harvest-synth=1. v2 Sàn-3 "giữ v1" = văn bản canonical (sẽ re-author vào `tiep.md` §0) KHÔNG mang mệnh-đề dual-accept (mệnh-đề sống ở `workflows/README.md:19-20` "close-gate chấp nhận CẢ HAI dạng") → wire xong là bão 5 dương-giả. Kèm: W0.5 v2 chốt scope theo **mtime** — đúng phương án R3-m5 đã chứng minh không bền (Dropbox resync rewrite mtime; "closeout cuối" không đo được) → **REGRESSED** ở nhánh này; đáng dùng `git log -1 --format=%cI -- <folder>` so mốc `3fde8af` |
| **R3-M5** (tripwire vỡ đường sống) | ⚠️ **PARTIAL** | Vế wrapper-list + same-commit = fixed (qua R2-C3). Vế ĐIỀU KIỆN tripwire KHÔNG sửa: tự đọc `hmw.js:116` — `const wave = (A.run && A.run.dir) ? A.run : ((A.wave && A.wave.dir) ? A.wave : null)` + `:19` "[legacy alias: args.wave]". Điều kiện v1 `!(A.run?.dir && A.run?.name)` (v2 không đính chính) giết lời gọi `wave:` hợp lệ + đòi `.name` vượt contract `.dir`-only. §3.9 thiếu acceptance "≥3-task kiểu `wave:` vẫn chạy" |
| **R3-M6** (sweep pattern + hmw.js:9) | 🔴 **STILL-BROKEN** | Trùng R2-M8 — đã verify sống cả `hmw.js:9` lẫn `ultra-on.md:24` |

Minors: R3-m5 **REGRESSED** (mtime được chọn làm phương án chính); R3-m6 FIXED (cấm synthesis giả); R2-m3 FIXED qua PA-2b; R2-m1/m4/m5, R3-m1/m3/m4 chưa xử (không chặn wave).

---

## TRỤC 2 — HONESTY (lane R4 chết — trục này chưa ai soi)

**C1 · "v2 vá 19 finding" = over-claim che đúng tập finding bị rớt**
- what: v2:4 + Nấc-trung-thực:275 ghi "R2 FAIL (4C+7M) · R3 FAIL (5C+2M)... 19 finding... v2 vá 19 finding". Đếm từ file: R2 = 4C+**8M** (M1→M8), R3 = 5C+**6M** (M1→M6) ⇒ 23 C+M. Ngay số tự khai cũng lệch nhau (4+7+5+2 = 18 ≠ 19).
- WHY nặng: tập "7M/2M" khớp CHÍNH XÁC tập finding v2 có xử lý — R2-M8, R3-M3/M4/M5/M6 bị rớt không một dòng disposition. Con số đóng vai "đã phủ hết" trong khi 3 finding STILL-BROKEN. Đây là lớp S109 (metadata-count) + S81 (honesty-presentation); văn bản này sẽ thành adap-report gửi hub.
- FIX: bảng disposition 23 dòng (FIXED/PARTIAL/DEFER + lý-do từng dòng); sửa 2 chỗ ghi count. VERIFY: grep "19 finding" = 0; bảng có đủ M8 + R3-M3..M6.

**C2 · Enum 10-class tự nhận "khớp H24 §2(1) 5+5" — SAI, và đánh rơi 1 dấu-hiệu sàn**
- what: v2:168 `flag_classes` = 10. Lane D (`sub-investigator-codebase-D.md:111-117`) = **11 class**, trong đó tách carry thành `carry-dropped`+`carry-overage` là CÓ CHỦ-ĐÍCH (đo được caveat (b)). Broadcast H24 :48-49 đếm 5 dấu-hiệu MISSING: **"một việc rớt khỏi khối work-state so với backlog"** là 1 dấu-hiệu RIÊNG, còn carry (rớt-hẳn/quá-già) là MỘT bullet. v2 giữ carry-tách-đôi NHƯNG bỏ hẳn `workstate-item-dropped` để về 10 rồi tuyên "khớp 5+5" — thành ra lệch CẢ broadcast lẫn lane D.
- WHY nặng: mất đúng class bắt ca F1 của chính SE (S118 chạy 7-spawn mà 0 run-folder = việc rớt khỏi sổ). Enum ĐÓNG nghĩa là 2 vai mới VĨNH VIỄN không được phép phát class này.
- FIX: khôi phục class work-state-drop (11 class, hoặc 10 đúng broadcast bằng cách gộp lại carry — nhưng lane D đã cho lý-do đo-được để tách); xoá câu "khớp 5+5". VERIFY: flag_classes ⊇ {workstate-drop, carry-dropped, carry-aged, owner-specifics, decision-sunk, underfill}.

**M1 · Owner-decisions PA-2: bullet "param `model:` chỉ nhận enum alias" dán nhãn "Đo" nhưng không nêu phép đo** — 2 bullet kia tự verify được (hmw.js:44 ✓; grep full-id ✓ tôi đo lại đúng 5 hit ở 3 file như liệt kê), riêng bullet này là tiền-đề làm PA-2-nguyên-bản thành "BẤT-KHẢ-THI" ⇒ đổi hình-thức một quyết định anh đã chốt. FIX: ghi phương pháp đo (hoặc hạ nấc "theo tài-liệu harness, chưa thử full-id") + 1 câu AskUser xác nhận anh duyệt hình-thức PA-2a/2b trước khi W2 land `TIER2_EXPECTED_FULL_ID`.

**M2 · Hook-interlock chưa được phân loại khung** — v2 xếp R3-side-ref = VƯỢT KHUNG phải request (đúng nguyên-tắc anh S119), nhưng chính v2 sửa `wal-flush.ps1` (thêm skip khi rebase-state) mà không phân loại vs floor N.2 (`harness-11-engine.md:406` — hook "ĐƯỢC làm đúng 2 việc"). Lý-lẽ "interlock bảo vệ chính floor" là tốt — nhưng nguyên-tắc mới nói rõ "dù lý-lẽ tốt". FIX: 1 đoạn phân loại tường-minh (đề xuất: trong-khung vì không thêm hành-vi cấm, chỉ chặn commit lên detached HEAD = chống tự-hủy) + khai ở adap-report; nếu anh muốn chặt: 1 câu ack.

**m ·** (a) "4 cú lật" giữ nguyên nhãn dù v2 đã tự hạ L2→PARTIAL, L3→CHƯA-VERIFY (2/4 đo chắc, 1 treo, L4 là diễn-giải văn bản — hợp lệ vì đích đến là request chứ không tự làm); (b) §3.7 kế thừa "H23 §2(5) n-a ĐÃ THOẢ" = dán nhãn PASS thành n-a (R2-m4) — under-report nấc tuân thủ khi gửi hub; (c) R4-request ghi "W0.6 sẽ trả lời — báo hub sau" trong khi W0.6 chạy TRƯỚC W6 → nên nhét thẳng verdict probe vào request; (d) dòng 70 vs §3.9 tự-mâu-thuẫn chữ "KHÔNG vào §3.9".

**Tỷ lệ claim (mẫu ~30 claim rời tôi re-đo):** ~80% ĐO ĐƯỢC-và-đúng (K/NONWAL/57/0-188/13-18-0hit/54×4/STATUS rows/full-id 5-hit/hook fail-open/regex-match/orphan 8-13...), ~13% SAI — tập trung trọn ở lớp meta-count/coverage (finding-count ×3, enum-khớp ×1), ~7% SUY DIỄN hoặc CHƯA-VERIFY. Điểm sáng thật: 4/5 chỗ CHƯA-VERIFY được khai đúng nấc (L3, precedence, side-ref, hot-reload hmw.js); điểm tối: 2 chỗ SUY DIỄN được trình như ĐO (enum-"khớp", param-alias).

---

## TRỤC 3 — Verdict + FIX BẮT BUỘC trước wave

Không còn đường **mất việc / rewrite-pushed-history**: mass rm+checkout bị cấm, nhánh A + assert `HEAD~K==origin/main` chặn tụt dưới remote, interlock + trap + hard-rule chặn detached-HEAD, không force-push ở đâu, O4 giữ 57. Deadlock hạ cấp thành STOP fail-loud — nhưng STOP này **gần như chắc chắn xảy ra ở W6** nếu không vá fix #3. W0 SOLO: ĐÚNG phải SOLO (phẫu thuật index + reset + restart; fan-out sẽ làm hook commit agent-memory giữa lúc mổ). Owner-decision: không thấy chỗ nào v2 tự quyết CON SỐ/policy của anh; 2 chỗ cần ack tường-minh nêu ở fix #7-#8.

**FIX BẮT BUỘC (spec-v3, không cần chạy lại lane):**
1. **Enum:** khôi phục class work-state-drop + xoá câu "khớp 5+5" (TRỤC 2 C2). Acceptance: flag_classes phủ đủ 5 dấu-hiệu MISSING của broadcast :26/:48-49, carry-tách-đôi khai là mở-rộng lane-D.
2. **Provenance:** bảng disposition 23 C+M + sửa count (TRỤC 2 C1) — cùng nội dung vào adap-report. Acceptance: mỗi finding 1 dòng trạng-thái; "19 finding" = 0 hit.
3. **Luật fold leading-wal: cho §5.2/W6:** (a) W0.3 bỏ "commit-chốt ở W6" — commit-chốt [CLAUDE] NGAY CÙNG TURN với `reset --soft` (gộp luôn edit `wal-flush.ps1` + `.gitattributes`) để đáy range là commit thường; (b) mọi push sau push#1 trong W6 (adap-report...) = write→commit→squash→count→push CHAINED cùng 1 lượt; (c) luật tổng quát: wal: ở đáy range → `reset --soft origin/main` re-commit, KHÔNG rebase. Acceptance: fault-inject cây tạm shape `base + wal + CLAUDE + wal×2` → chained block ra n=0, tree-identical, KHÔNG STOP.
4. **Sàn-3 dual-accept + W0.5 scope:** chép verbatim mệnh-đề C8 (`workflows/README.md:19-20`) vào văn bản canonical Sàn-3 @tiep.md; W0.5 đổi mtime → `git log -1 --format=%cI -- <folder>` so mốc `3fde8af` (2026-07-14T16:29:55+07). Acceptance: scan mới trên cây hiện tại = đúng {S119} sau khi đóng 7; 5 folder h10/h910 im.
5. **Tripwire mirror `:116`:** điều kiện = `const w = (A.run&&A.run.dir)?A.run:((A.wave&&A.wave.dir)?A.wave:null); if (A.taskList.length>=3 && !w) throw` — bỏ đòi `.name` (hoặc nâng contract :116 trong CÙNG edit). Acceptance thêm vào §3.9: ≥3-task kiểu `wave:{dir}` vẫn chạy; thiếu cả hai → throw.
6. **Roster-sweep:** acceptance đổi sang Grep-tool pattern `(12|9)[- ](agent|sub)|roster 12|12 vai|VALID_ROLES[^0-9]*12`; đưa `ultra-on.md:24` (danh sách VALID_ROLES 12→14, CÙNG COMMIT W2 vì là routing-doc), `hmw.js:9` meta 9-agent (gộp vào 1-EDIT W2), `fable-real.md`/`fable-real-runbook.md` vào wave. Acceptance: sau W3 pattern trên 0 hit sống (ngoài lịch-sử/archive).
7. **Bug shell dòng guard W0.3** (`[ -d .git/rebase-merge ] || [ -d .git/rebase-apply ] && {...}`): happy-path (không có dir nào) trả **exit 1** (status của chuỗi ||) → caller check exit-code sẽ báo hỏng giả. Đổi sang dạng `if ... ; then ... ; fi`. Acceptance: chạy block trên repo sạch → exit 0.
8. **2 ack tường-minh:** (a) anh duyệt hình-thức PA-2a/2b (M1); (b) phân loại hook-interlock vs N.2 ghi vào spec + adap-report (M2). Acceptance: owner-decisions có dòng ack / spec-v3 có đoạn phân loại.

Khuyến nghị không-chặn: ghi rõ W0.6 và post-W2 RESTART nối lại bằng `/tiep` (H22 — 2 lần restart nghĩa là wave trải ≥3 phiên CLI); nhét verdict W0.6 vào R4-request thay "báo sau"; 1 dòng "broadcast #7 presence-not-age đã adopt S115" (R2-m1); đổi nhãn "n-a ĐÃ THOẢ"→"đã thoả"; lịch stamp-mark vào W6 (R2-m5); validator W1② chạy glob thay hardcode 12; bổ sung acceptance W0.4 + EOL-assert-scoped-cạnh-push + W6 vào §3.9.

---

## REFUTATION LOG — claim tôi đã thử phá mà KHÔNG phá được

1. **Regex anchor v2** — tấn công em-dash/escape/format: match byte-thật cả 2 positive-control (`permission-matrix/SKILL.md:16`, `form-engine/SKILL.md:15`). ĐỨNG.
2. **"0 full-id sống trong .claude"** — grep lại: đúng 5 hit ở 3 file, đều comment-lịch-sử/outage-path/gỡ-pin như owner-decisions liệt kê. ĐỨNG.
3. **"Scoped EOL = 0 xanh sẵn / repo 188"** — đo lại: 0 / 188. ĐỨNG.
4. **"hmw.md không tồn tại; 18 command; args.run = 0"** — đo lại đủ 3. ĐỨNG.
5. **"Hook fail-open 0 guard"** — đọc `wal-flush.ps1:1-19`: catch{} + exit 0 + không guard rebase. ĐỨNG (và phát hiện thêm: commit **pathspec 3 path** — chính chi tiết này làm lộ lỗ fold ở fix #3).
6. **"8/27 orphan, 7 tồn-đọng"** — scan độc lập: naive 13, dual-accept 8, 5 h10/h910 có `harvest/*-synthesis.md`. Số ĐÚNG; hỏng là mệnh-đề bị rơi khỏi canonical (fix #4).
7. **"57 wal: đã lọt + §5.0 chỉ-đuôi"** — đếm lại 57 ✓; `session-end.md:112-113` verbatim đúng như trích. ĐỨNG.
8. **Nhánh A an toàn với K drift** — thử phá bằng kịch bản K quá lớn/quá nhỏ: assert `HEAD~K==origin/main` + tính runtime chặn cả hai; NONWAL idiom `grep -vc || true` in "0" đúng cả ca all-wal lẫn range rỗng. KHÔNG phá được (lỗ duy nhất còn = leading-wal: tại W6, đã báo ở fix #3).
9. **"Policies = 216"** — `MenuKeys.cs` 54 `public const string` × `Actions[4]` (`:167`) = 216. ĐỨNG.
10. **"Sub-agents row 12 / thiếu row Policies trong STATUS"** — grep: `:24` = **12**, không có Policies. ĐỨNG (fix R3-M2 của v2 là cần thật).

Token cost: ~72K in / ~14K out.