# spec v2 — adap đợt-11 (10 broadcast AI_INFRA 2026-07-18 → 07-21)

> **Supersedes** `spec-adap-dot-11-22-07-2026.md` (v1). v1 **GIỮ NGUYÊN** làm vết audit — CẤM sửa.
> **Gate:** `/fable-clone reviewer` 3-lane `wf_301d3943-144` — **3/3 lane sạch, 0 rỗng**.
> R1 anchor `PASS_WITH_FIXES` (60 neo · 55 khớp · 4 MAJOR) · R2 scope `PASS_WITH_FIXES` (5 mục để lên PASS) · R3 teeth `PASS_WITH_FIXES` (bảng: **2 răng-thật · 4 nửa-răng · 3 nửa-rỗng · 4 rỗng**).
> 🔴 **Đính chính reviewer:** R3 §0 headline ghi "4 răng-thật · 4 nửa-răng · 5 rỗng" — **không khớp bảng của chính nó**. v2 dùng **số từ bảng** (2+4+3+4=13 ✓).

---

## ⓿ DISPOSITION — 20 finding, TỪNG DÒNG (luật-chung #3, cấm báo số tổng)

| # | Finding | Nguồn | Xử |
|---|---|---|---|
| M1 | `settings.json:11` **trỏ nhầm lãnh-thổ** — repo `.claude/settings.json` 330 B, dòng 11 = `]`, 0 hit `model\|opus\|fable`; sự thật ở `~/.claude/settings.json:11` (global, NGOÀI git) | R1 | ✅ **SỬA** — mọi neo ngoài-git mang đường-dẫn đầy đủ (§P4-1). Lead **tự re-verify**: repo 0 hit ✓, global dòng 11 = `"model": "claude-opus-4-8[1m]"` ✓ |
| M2 | `cost-lens:50` **cắt nửa dòng** — rơi *"Khoản ③ áp được cho MỌI nhà"* | R1+R2(O-4c) | ✅ **SỬA** — thêm P3-5 |
| M3 | C11 giẫm knob owner (`session-start.md:135` khai **DP-5 quyền owner cục-bộ**) | R1 | ✅ **SỬA** — thành **O-6**, gỡ khỏi tay em-main |
| M4 | Nhãn *"đo được"* (tool-use 21/23 vs 28/34/35) **0 phản-chứng trên đĩa** | R1 | ✅ **SỬA** — khai nguồn = khối `<failures>` in-session **KHÔNG lưu đĩa** ⇒ hạ nhãn xuống *"quan sát in-session, không tái-lập được"* |
| P-1 | C8 **sai trục + tự mâu thuẫn**: `depth-axis:40` trần áp **tổng-lượt trục SÂU**, spec ép lên `taskList.length` (**width**); và `depth-axis:43` nói *"**không văng lỗi**"* trong khi C8 đòi THROW — trái cả `spec-v1:53` cấm-throw | R2 | ✅ **SỬA** — tách C8a/C8b, **bỏ THROW** |
| P-2 | C6 sweep **hồi-tố toàn corpus** > floor `goi-chot:55` (*"tài-liệu governance **mới**"*) | R2 | ✅ **SỬA** — forward-looking bắt buộc; hồi-tố **time-box** |
| O-1 | `harness-dong-du-vong:46` **khoản ③ tuần-tự trong-vòng** — **0 dòng** trong v1 | R2 | ✅ **SỬA** — thành **P1-6** + C4b |
| O-2 | `goi-chot:38/:66/:73` **nửa sau khoản 2** — SE dùng resume **VÀ** dựa model-pin (`hmw.js:219`) ⇒ phải tự verify override sống qua resume | R2 | ✅ **SỬA** — thành **P4-6** |
| O-3 | khoản ② propose-only **không có dòng disposition** (dù `hmw.js:185` writeGuard nhiều khả năng đã đạt) | R2 | ✅ **SỬA** — bảng 4-dòng/thư-binding |
| O-4a | `hub-tu-danh-gia:27` *"điểm tự-chấm của lead phải để **NGOÀI mọi kênh sub với tới được**"* — 🔴 **FIRE ĐỎ NGAY RUN NÀY** | R2 | ✅ **NHẬN LỖI + SỬA** — xem ⓪ dưới |
| O-4b | `hub-tu-danh-gia:62` cite nửa dòng (nửa kia = *"dùng được ngay ở mọi nhà"*) | R2 | ✅ **SỬA** — P3-6 |
| O-4d | `depth-cost:52` bài-học-1 *"lệnh ép-full-power của owner phải khoá cả chiều MÁY"* | R2 | ✅ **SỬA** — neo vào C8b |
| O-4e | `auto:29-31`+`:46` instrument **tự làm tươi** số-đo-đóng-băng | R2 | ✅ **SỬA** — P2-2 thêm nhánh làm-tươi |
| G-1 | C8 chứa **SỐ** + **đổi CƠ CHẾ** = 2 cột owner (`eval:24`), chưa có trong O-1…O-5 | R2 | ✅ **SỬA** — **O-7** |
| G-2 | C12 ghi **posture TOGGLE** vào `CLAUDE.md` = stale-by-construction (`ultra-off.md:9` xoá marker) + đẻ **ghost-wire mới** | R2+R3 | ✅ **SỬA** — đổi sang **trỏ nơi tra**, không chép giá-trị |
| G-3 | `≤3 file/lane` là số **AI tự đặt** | R2 | ✅ **KHAI** — "AI-tự-đặt, đảo được", không gate |
| T-C6 | C6 **RỖNG HOÀN TOÀN** — literal `"máy sẽ"` trong `docs/governance/` = **0 hit**; họ-diễn-đạt cùng nghĩa = **19 hit NGOÀI tập-đo**; sweep rộng hơn **đã chạy** @wave-3 (3/3 sạch). Fault-inject: cắm câu-hứa-giả → **VẪN XANH** | R3 | ✅ **VIẾT LẠI** |
| T-C11 | C11 **BẤT-KHẢ-THI** — `grep=0` buộc xoá luật owner đang GIỮ (`sleep-…l2.md:52`); fault-inject: đổi `ngày`→`chu-kỳ` → grep=0 → xanh, hành vi y nguyên | R3 | ✅ **VIẾT LẠI** — đo **hành vi**, không đo chữ |
| T-C7 | *"đo wall-clock, ghi số"* **PASS ở MỌI giá trị**; `pause.md:44` đã gọi `powershell.exe` **lọt khe** danh-mục-cấm | R3 | ✅ **VIẾT LẠI** |
| T-mix | C2/C3/C5/C9/C10/C13 nửa-răng/nửa-rỗng | R3 | ✅ **SIẾT** từng mục (§③) |

### ⓪ 🔴 LEAD NHẬN LỖI — anchor ngầm (O-4a), bằng chứng ngôi-thứ-nhất

`hub-tu-danh-gia:27`: *"điểm tự-chấm của lead phải để **NGOÀI mọi kênh sub với tới được** — 'không đưa vào pack' chưa đủ khi sub đọc sổ chung."*

v1 mang sẵn phán quyết của lead (*"SE hiện **FAIL rõ**"* `:67` · *"⇒ **FAIL**"* `:95` · *"→ **SE QUALIFY**"* `:18`) **rồi đưa chính file đó cho reviewer chấm**. Đó là anchor ngầm, và hub vừa phát đúng bài này 3 ngày trước.

**Sửa từ v2:** phán quyết của lead tách khỏi mệnh đề đo được. v2 viết *"đo được: `hmw.js:114-117` = soft-notice, không có clamp cứng"* thay vì *"SE FAIL rõ"*. Kết luận để reviewer tự rút.
🔸 **Khai thật:** vòng review v1 **đã bị anchor**, không sửa ngược được. 3 lane vẫn tìm ra 20 finding kể cả khi bị mồi — nhưng con số đó **không được đọc thành "anchor vô hại"**.

---

## ① TÍNH-NĂNG / ĐỀ-BÀI

Giữ nguyên v1 §① (R2 xác nhận **phân hạng 10/10 đúng ở mức THƯ, 0 ca phóng-đại tầng thư**), **cộng 3 đính chính**:

1. **M2/O-4b/O-4c** — 3 thư nhóm GHI-NHẬN vẫn chứa khoản *"dùng được ngay ở mọi nhà"*: `cost-lens:50` khoản ③ · `hub-tu-danh-gia:62` pattern eval-3-góc + 3 câu kiểm · `depth-cost:52` bài-học-1. **Xếp GHI-NHẬN không có nghĩa bỏ trắng** ⇒ P3-5, P3-6.
2. **O-3** — thư BINDING phải có bảng **4 dòng disposition/thư**, không tuyên "4 khoản" rồi làm 2.
3. **M4** — con số tool-use lane (21/23 vs 28/34/35) đến từ khối `<failures>` + phân tích transcript **in-session**, **KHÔNG lưu đĩa** ⇒ đọc là *quan sát không tái-lập*, không phải *phép đo*.

Ba phát hiện lật tiền-đề của v1 (0/12 mục treo · `hmw.js:225` · SE đi trước hub ở positive-control) — R1/R2/R3 **đều xác nhận**, giữ nguyên.

---

## ② CÁCH IMPLEMENT (delta so v1)

### P0 — giữ nguyên
**P0-1** `hmw.js` lane-chết-phải-kêu · **P0-2** luật đóng-gói-lane. R3 chấm **C1 = RĂNG THẬT**, giữ.
🔸 G-3: `≤3 file/lane` = **AI tự đặt, đảo được** (không phải số owner).

### P1 — thêm **P1-6** (vá O-1)
**P1-6. Tuần-tự trong-vòng** (`harness-dong-du-vong:46`, khoản ③ BINDING v1 bỏ sót)
- *"audit **chờ đúng con đo vòng mình xong** (chống chấm bản stale); các vòng khác nhau chạy song song thoải mái"*.
- 🔴 Vì sao KHÔNG vô hại: `hmw.js:175` `parallel()` **không tuần-tự-hoá trong 1 invocation**. Nếu C4 bơm `harness-audit` chung `taskList` với con-ĐO ⇒ audit chấm **bản rỗng** = đúng lỗ thư vá. v1 đã biết tính chất này (`:100`) mà không áp cùng kết luận.
- Cách: audit vòng X chạy ở **invocation hmw SAU** con-đo vòng X.

### P2 — sửa P2-1, mở rộng P2-2
**P2-1 (sửa P-1 + G-1 + O-4d).** Tách 2 trục, **BỎ THROW**:
- **(a) trục SÂU** — `assert tổng-lượt ≤ trần`; trần = **O-2 (owner)**.
- **(b) trục RỘNG** — `depth-axis:43` *"BỎ đào + báo RÕ (**không văng lỗi**, không lặng-thầm bỏ)"* ⇒ **LOUD-skip**, KHÔNG throw. Neo `depth-cost:52` *"cổng-ngân-sách tự hạ được = máy đè lệnh owner"* — SE có `/fable-real` = lệnh owner đích danh, cổng cứng ở fan-out là đúng lớp bệnh thư cảnh báo.
- Trần width hiện `hmw.js:115` = `16` ⇒ **O-7**.

**P2-2 (thêm O-4e).** Bảng cost re-ground **+ nhánh tự-làm-tươi** (`auto:29-31`): khi chính bộ đo báo trôi quá ngưỡng % → đọc lại + cập nhật **ngay trong phiên**, hết vòng "ghi nhận → treo → bàn lại".

### P3 — thêm P3-5, P3-6; sửa P3-2, P3-3
**P3-5 (M2).** `cost-lens:50` khoản ③ — *"suggest **đúng 1 dòng** non-blocking rồi chạy luôn"*, hub khai *"áp được cho MỌI nhà"*.
**P3-6 (O-4b).** `hub-tu-danh-gia:62` pattern **eval-3-góc** (§1) + **3 câu kiểm** (§6) *"dùng được ngay ở mọi nhà"* — gồm cả câu tự soi anchor (§6 câu 2), thứ vừa fire đỏ ở ⓪.
**P3-2 (sửa M3/T-C11).** Distill trigger đếm-thật ⇒ chuyển thành **O-6** (owner) vì `sleep-…l2.md:52` khai *"INFORM 7-ngày **GIỮ** (quyền owner cục-bộ, B1 §3.4)"*. Em-main **KHÔNG** tự gỡ.
**P3-3 (sửa G-2).** discoverability-home: `CLAUDE.md` **trỏ NƠI tra** posture (marker + `/session-start`), **CẤM chép giá-trị ON/OFF** — `ultra-off.md:9` xoá marker ⇒ chép giá-trị = sai ngay lượt sau.

### P4 — thêm P4-6
**P4-6 (O-2).** `goi-chot:73` SELF-CHECK: **grep call-site resume/continue** → SE có dựa vào model-override sống qua resume không? SE thoả tiền-đề (`hmw.js:219` bơm model tại spawn; path-2 `SendMessage-resume` dùng **2 lần hôm nay**). Nếu CÓ dựa ⇒ **đo 1 lần trên env SE** trước khi tiếp tục tin path-2.
🔴 Nếu override không sống qua resume, lane được cứu chạy **model khác mà không ai biết** — đúng `depth-cost:53` *"thử-rồi-chết ≠ chạy-rồi-sạch"*.

### 🔒 OWNER-GATED — **O-1…O-7** (thêm 2)

| # | Khoản |
|---|---|
| O-1 | Số `min_pending_shards` / `bulk_note_shards` |
| O-2 | Posture trục-sâu + **trần tổng-lượt** |
| O-3 | Gộp hay tách vai-KIỂM 3 vòng còn thiếu |
| O-4 | Ratify ranh `refine ⟂ lead-omission` |
| O-5 | Nhãn model-flip |
| **O-6** 🆕 | **Sleep-trigger 7-ngày → đếm-shard?** — `sleep-…l2.md:52` khai owner **đang GIỮ** có chủ đích. `eval:24` xếp *"đổi cơ chế"* = **owner-quyết-LUẬT**. Em-main CẤM tự gỡ |
| **O-7** 🆕 | **Trần width + cơ chế** (`hmw.js:115` hiện `16`, soft) — số = owner-SỐ; throw-hay-LOUD-skip = owner-LUẬT |

---

## ③ CHECKLIST v2 — đã siết theo R3

**Ký hiệu:** 🦷 răng-thật · ⚙️ đã siết · 🔒 owner-gated

| # | Vai | Deliverable | Acceptance **có răng** |
|---|---|---|---|
| **C1** 🦷 | em-main | `hmw.js` lane-chết-kêu | **Fault-inject 2 CHIỀU**: null→**phải** chứa `lane CHẾT`; sạch→**không được** chứa. R3 chứng: bản giả `log()` vô-điều-kiện **trượt vế âm** ⇒ răng thật. `node --check` exit 0 |
| **C2** ⚙️ | em-main | Luật đóng-gói-lane | ❌ Bỏ `grep -c 'trần lượt'` (đếm chữ). ✅ Đo ở **run KẾ**: 0 lane chết. 🔸 **Khai hạn chế**: C1 chỉ biết `null`, **không phân biệt được NGUYÊN NHÂN** ⇒ "chết vì cháy lượt" hiện **chưa đo được** |
| **C3** ⚙️ | em-main | Khuôn label 4 thành-phần | ✅ **negative-control**: cắm 1 label thiếu {pha·phiên} → phép đọc **phải TRƯỢT**. ✅ **Neo artifact**: label xuất hiện trong `runs/<id>/run.md` (panel ephemeral, không grep được) |
| **C4** ⚙️ | `harness-audit` | Vai-KIỂM 3 vòng | ✅ **Cấm tự-kiểm vòng mình đo** (`m-3 no-self-exempt` S139). ✅ Con số re-check phải là số **CÓ THỂ SAI**, không phải hằng số hiển nhiên |
| **C4b** 🆕 | em-main | Tuần-tự trong-vòng (P1-6) | Audit vòng X ở **invocation hmw SAU** con-đo vòng X. Bằng chứng: 2 run-id khác nhau, mtime audit > mtime đo |
| **C5** ⚙️ | `test-specialist` | Eval phía DÙNG | ✅ **Thêm POSITIVE-control**: id THẬT đã biết → **phải** ra `APPLIED`. 🔴 Thiếu vế này thì matcher **chết** (luôn 0-hit) đạt neg-control **hoàn hảo** |
| **C6** ⚙️🔴 | `reviewer` | Cửa lời-hứa-máy | ❌ **BỎ** neo literal `"máy sẽ"` (tập-đo = **0/19**, fault-inject cắm câu giả **vẫn xanh**). ✅ Tập-đo = **danh sách liệt kê tường minh**, mẫu-số công bố (**19** đo được), mỗi câu 1 dòng disposition. ✅ **positive-control BẮT BUỘC**: cắm 1 câu-hứa-giả vào cây tạm → sweep **phải** nhặt ra. ✅ Tách **use ⟂ mention** (7 hit hiện có đều là *mention*). ✅ Đo **gate đã cài**, không đo *đã quét xong* — `goi-chot:53` *"chặn từ lúc VIẾT"*. ✅ Hồi-tố **time-box** (P-2) |
| **C7** ⚙️ | em-main | Điểm-dừng rẻ | ❌ Bỏ *"ghi số"* (PASS ở mọi giá trị). ✅ **Ngưỡng = O-gated**. ✅ Tập cấm đổi từ liệt-kê sang **bất kỳ tiến-trình ngoài nào** trong đường dừng — 🔴 `pause.md:44` **đã** gọi `powershell.exe nhip-no-probe.ps1`, danh-mục cũ để nó lọt |
| **C8a** 🦷🔒 | em-main | Clamp **trục SÂU** | `assert tổng-lượt ≤ trần`. **BLOCKED-by-O-2** |
| **C8b** ⚙️🔒 | em-main | Ngân-sách **trục RỘNG** | **LOUD-skip**, ❌ **KHÔNG throw** (`depth-axis:43` *"không văng lỗi"*). Fault-inject 2 chiều. **BLOCKED-by-O-7** |
| **C9** ⚙️ | `investigator-codebase` | Bảng cost re-ground + nhánh làm-tươi | ✅ Gỡ mâu thuẫn: **khai thẳng** falsifier `depth-cost:59` **vẫn CHƯA đo được** (đơn-vị thứ ba); C9 chỉ đóng phần **re-ground roster 7→17** + wire nhánh tự-làm-tươi |
| **C10** ⚙️ | trio | Eval-của-eval 4 câu | ✅ Cỡ mẫu **≥3**, **ưu tiên thước CHƯA từng fault-inject** (loại S138/S143 đã xanh). ❌ Bỏ *"mỗi thước có verdict"* khỏi headline (100% do cấu trúc, `eval:32`) |
| **C11** ⚙️🔒 | — | Distill trigger | ❌ **BỎ** `grep 'ngày'=0` (rời-tập-đo: đổi `ngày`→`chu-kỳ` là xanh, hành vi y nguyên; và buộc xoá luật owner đang GIỮ). ✅ Đo **HÀNH VI**: {0 shard chưa-gist, 30 ngày} → trigger **phải IM**; {3 shard, 0 ngày} → **phải KÊU**. **BLOCKED-by-O-6** |
| **C12** ⚙️ | em-main | discoverability-home | ❌ **BỎ** *"CLAUDE.md có dòng nêu posture đang hiệu lực"* (stale-by-construction). ✅ `CLAUDE.md` **trỏ NƠI tra**. ✅ Phép thử **use**: 1 ca dương + 1 ca âm — phiên mới đọc file luật có nói **đúng** posture hiện hành không |
| **C13** ⚙️ | em-main | P4-1…P4-6 | ✅ *"Lý-do-không-làm"* phải kèm **phân loại** {owner-gated · defer-có-ngày · bác-bỏ-có-bằng-chứng} — nếu không = cửa thoát vô hạn |
| **C14** 🆕 | em-main | Bảng disposition per-thư-binding (O-3) | 4 thư BINDING × 4 khoản = **16 dòng**, mỗi dòng {ADOPT · ĐÃ-CÓ+neo · N-A+lý do}. **CẤM** tuyên "4 khoản" rồi làm 2 |
| **C15** 🆕 | em-main | Grep resume call-site (P4-6) | Liệt kê call-site `SendMessage`/resume + verdict 1 dòng *"SE có/không dựa vào model-override sống qua resume"*. Nếu CÓ → đo 1 lần env SE |

### 🔴 Luật chung (v1 giữ 6, thêm 3)

1. Existence-proof tại chỗ · 2. Đo trước khi tuyên · 3. Bảng disposition TỪNG DÒNG · 4. Ghi đĩa TRONG lúc làm · 5. Điểm-dừng phải rẻ · 6. Số của owner — O-1…**O-7** CẤM tự đặt.
7. 🆕 **Neo ngoài-git mang đường-dẫn đầy đủ** (M1 `neo-trỏ-nhầm-lãnh-thổ`).
8. 🆕 **Cite nguyên DÒNG, không cắt nửa** (M2/O-4b/O-4c — 3 ca cùng lớp trong 1 spec).
9. 🆕 **Phán quyết của lead KHÔNG đi vào file sub đọc được** (O-4a `hub-tu-danh-gia:27`).

### Trạng thái khoá

- **Chạy được ngay (không chờ owner):** C1 · C2 · C3 · C4 · C4b · C5 · C6 · C9 · C12 · C13 · C14 · C15
- **BLOCKED chờ owner:** C8a (O-2) · C8b (O-7) · C11 (O-6) · C7-ngưỡng · C10 (nếu đụng số)
