# sub-reviewer-hoi-tu — S149 hội-tụ bookend (ENGINE-ĐẮT /fable-real reviewer)

> Reviewer adversarial — CỔNG CUỐI trước implement. Khung ghi lượt-1 trước khi đọc; bản này = culmination append.
> Đối tượng gate (PIN): `spec-hoi-tu-bookend-24-07-2026.md` · nguồn: `sub-invest-hoi-tu.md` cùng folder.

## VERDICT

**GO-WITH-FIXES** — khung hình B + M1-M8 đúng khuôn sister (đối chiếu nguồn từng mục), ranh owner giữ đúng, nhãn ủy-quyền ghi ĐÚNG khuôn; NHƯNG 1 CRITICAL nằm ngay chỗ spec tuyên bảo-thủ nhất (JUMP "GIỮ NGUYÊN nghĩa" — thực tế bất-khả-đồng-thời với M-1 + bookend), 2 acceptance sẽ FAIL-as-written trên đĩa thật (K5-S140, K1 tự-mâu-thuẫn), 3 caveat của invest bị cắt khỏi spec, và claim "residual 0" lọt 9 hit tên-cũ dạng-ngắn trong luật sống.

## Findings

### A. CRITICAL — FIX-1: M2 × M-1 × M6 bất-khả-đồng-thời trên `class_repeat` (đe doạ trực tiếp dải 3-4 treo)

Bộ ba cam kết của spec không thể cùng đúng:
- **M2** (spec:34): "GIỮ schema `class_repeat` NGUYÊN — không đổi semantics giữa lúc JUMP treo". Semantics hiện tại = **consecutive-AUDIT count có reset-on-clean** (`.session-counter.json` `class_repeat._note`:24 "consecutive-audit repeat count"; reset THẬT đã chạy: S137 "3 class không tái-hiện → reset 0", S140 "gap-decision-sunk 2→0 reset", S143 "view-stale-status 2→0").
- **Ràng M-1** (spec:28): "CẤM wipe-tally-khi-audit-chạy" — đúng bài hub (AI_INFRA `session-end.md:183`: wipe mỗi phiên dưới bookend ⇒ "`k_jump` thành cơ-chế không bao giờ fire được (= prose-ma)").
- **M6** (spec:46): cặp soi-lead VÔ-ĐIỀU-KIỆN 2 đầu phiên ⇒ tần-suất audit từ ~1 lần/2-3 phiên (S140→S143→S146→S148) lên **2 lần/phiên**.

Hệ quả: (a) nếu giữ reset-on-clean (M2) → audit bookend đầu tiên mà class không tái-hiện sẽ **reset dải 3-4 đang treo owner** (gap-owner-specifics 4 · gap-decision-sunk 3 · gap-carry-dropped 3, `_jump_state_S149`:36) = chính hành vi M-1 cấm, jump chết kiểu prose-ma; (b) nếu cấm reset (M-1) → semantics đổi ngầm từ consecutive sang cumulative = vi phạm M2. Hub thoát bằng ĐỔI schema sang sliding-window distinct-sid + prune-on-tick (`h17_cadence.py:263-296`) — đúng cái invest ĐÃ-CÂN-NHẮC-1 bác (đổi thước giữa phép đo). Spec chọn giữ schema nhưng KHÔNG pin cách thoát → implementer sẽ tự chọn semantics thay owner.

**Acceptance FIX-1 (mô tả, không code):** spec phải pin 3 điều trước khi M3/M6 land: (i) đơn-vị sự-kiện tally = **phiên-LOGIC** (kết quả @start+@end gộp thành 1 quyết định tăng/reset per class per phiên — khớp hub đơn-vị sID, `h17_cadence.py:285-288`); (ii) reset-on-clean tối đa 1 lần/phiên và KHÔNG chạy trong phiên land-M6 đầu tiên; (iii) sequence: **owner xử dải 3-4 treo TRƯỚC lần bookend đầu** (hoặc freeze counts tường minh tới khi owner trả lời) — nếu không, máy tự phá bằng-chứng mà spec:28 hứa "KHÔNG tự-retire".

### B. Chấm M1-M8 + hình B (a=khuôn sister · b=acceptance đo được · c=thứ tự)

| Mục | Khuôn sister | Acceptance | Ghi chú |
|---|---|---|---|
| Hình B | ✅ khớp VIPIX `session-start.md:73` (vô-điều-kiện) `:76` (pause/tiep không spawn) `:77`+`:155` (light→stats GIỮ số owner-authority; retire nhãn fire) `:156` (deep giữ counter, lead tự chạy) — đọc trực tiếp | — | key names đúng (`light_every`/`deep_every` memory-budget.json:149-150) |
| M1 | ✅ `session_scaffold.py` 169 dòng đúng; ts=`git log -1 --format=%cI` (:57), idempotent KHÔNG đè (:144-151), template render str.replace (:74-82); `-New`/`-Ensure` = tailor CÓ CĂN (BƯỚC 0.8 session-start.md:89 cấp-số ⟂ tạo-folder @S146) | ⚠️ K1 TỰ-MÂU-THUẪN (xem D-4) | hub trả **exit 0** khi `_context` tồn tại; K1 đòi "exit khác 0" |
| M2 | ✅ cơ-khí-hoá `_contract` sẵn có (.session-counter.json:5-11); OR-guard + squash-benign 3 nhánh khớp contract v2 | ✅ K2 fault-inject 4 ca chạy được | ⚠️ rơi chữ "atomic (temp+move)" của invest M2 — hub `_save_atomic` h17:174-184 (D-3) |
| M3 | ⚠️ "(max-1/class/phiên **structural**)" SAI schema: structural CHỈ có ở distinct-sid-list (h17:286-288); counts-map SỐ TRẦN (commit 2f39a7e) → phải procedural | ✅ K3 đo được | + dính FIX-1 (reset không định nghĩa) |
| M4 | ✅ khuôn `sub-lead-view-S146.md` tồn tại (artifact path legit) | ✅ K4 2-chiều khuôn S95 | ⚠️ thứ tự: M4-luật nên land TRƯỚC/CÙNG M6 — M3 cần vai đưa FLAG→class làm input; land M6 trước M4 = vòng bookend đầu lặp đúng lỗi S148 mất class-tag |
| M5 | ✅ tailor VIPIX `:153` đúng (verdict-line không exit-code, FLAG=CANDIDATE, FP wal: đã biết) | 🔴 K5 positive-control S140 **SAI TRÊN ĐĨA** (D-1) | |
| M6 | ✅ target text tồn tại đúng chỗ: session-start:236 §2.1.8 OVERDUE-gate + session-end:46-47 "theo NHỊP, KHÔNG mỗi phiên" + :114 (j)(ii) AUTO; ring2-audit hiện "*wherever it fires*" (:49,:118) chưa PIN → M6 điền đúng lỗ; carve-out §A1 khớp AI_INFRA session-end:175-176 verbatim | ⚠️ K6 chỉ grep session-start — M6 sửa CẢ session-end §L.b(j) đối xứng, nửa deliverable không đo | |
| M7 | ✅ ghost-wire xác nhận: `grep -rn 'applied-eval' .claude/commands/` = 0 (invest đo, spec K7 chờ ≥1) | ✅ K7 đo được (call-site + selftest 3/3 + nhãn trong output) | |
| M8 | optional, khai đúng citation-trap use⟂mention | ✅ | |

**Thứ tự land** M1+M2+M3 → M6 → M4+M5 → M7 → M8: đúng dependency TRỪ M4 (nên kéo lên trước M6, lý do ở bảng).

### C. Chỗ LỆCH invest → spec — lead cắt mất 3 caveat (đúng câu hỏi đề bài)

1. **Invest-K9 biến mất trọn:** 2 vết @S149 — (a) `memory-budget.json:17` `_drift_check` VẪN ghi "⏳ CHUA CO" trong khi C9 ĐÃ SỐNG (`governance-detectors.ps1:1518` — tự verify) = stale-note; (b) `_fault_inject`:18 đòi re-run 2-chiều trên cap MỚI 20 — chưa có vết chạy. Spec không mang, §4 không khai. → nhét vào K9-spec (sync sau land) hoặc thêm K10.
2. **Invest C-V2 mục "(4) luật diary-seed on-behalf sau VERIFY (GAP-3 ×4)" bị rơi:** GAP-3 (diary vai RỖNG sau chạy) tái ×4, mới nhất @S149 (`h24-audit/` memory RỖNG → vai KIỂM vào mù — .session-counter.json history S149-W3-kiem). Không M nào cover, không nằm §4 → bệnh (i) "đo rồi như chưa đo" claim diệt nhưng nhánh diary còn sống.
3. **Invest-K1 "vết chữ owner ≥1 bề-mặt" bị thay bằng nhãn:** nhãn lead-decided đúng khuôn (xem E) nhưng yêu-cầu vết bền ngoài spec (MARKS/ledger) biến mất — spec:75 chỉ ghi MARKS cho class-map defer, không cho quyết định hình B.

### D. Acceptance FAIL-as-written (đo trên đĩa thật)

1. **K5 (M5 sentinel):** positive-control "S140 PASS" SAI — S140 closeout `b146e2b` chỉ chạm `tooling-auditor/archive/2026-07.gist.md` + `harvest-curator/archive/2026-07.gist.md`, KHÔNG chạm `MEMORY.md` → predicate MEMORY.md (VIPIX nguyên bản + invest M5) sẽ FLAG S140. Đối chứng: S143 `a1e2416` chạm ĐỦ cả 2 MEMORY.md ✓; S146 `8b6df0a` / S147 `5f6c3be` / S148 `932d607` = 0 delta dưới CẢ 2 role-dir (mọi path) → FLAG đúng ✓. **Fix khả thi đã kiểm:** nới predicate thành delta BẤT KỲ dưới `agent-memory/<role>/**` → S140 PASS (2 gist) + S143 PASS + S146-S148 vẫn FLAG (0 hit mọi-path đã kiểm bằng grep không giới hạn MEMORY.md). Ghi rõ deviation-vs-VIPIX + lý do.
2. **K1 (M1 scaffold):** vế 1 "`-Ensure` chạy 2 lần = idempotent (mtime không đổi)" mâu thuẫn vế 3 "CẤM đè: `_context` tồn tại → exit khác 0" nếu cả hai áp cho `-Ensure` (lần 2 luôn rơi vào "_context tồn tại"). Hub: exit **0** + báo idempotent (scaffold.py:144-151). Fix: pin vế-3 cho ca nào (đề nghị: `-New` đụng folder/`_context` đã tồn tại = exit≠0; `-Ensure` gặp `_context` = exit 0 no-op như hub).

### E. Ranh owner — 4 điểm ĐỐI CHIẾU

- **Hình B = OWNER-DELEGATED → lead-decided:** nhãn ghi ĐÚNG — khuôn `hmw_width._ratified_by` TỒN TẠI THẬT (`memory-budget.json:14` verbatim: "KHONG PHAI 'owner chot'… Anh VETO 1 dong bat cu luc nao") — KHÔNG tái phạm bug hmw.js:116 vừa vá. ✅ HELD (kèm note C-3: thiếu yêu-cầu vết bền).
- **Trio GIỮ CONSENT (owner-held #12):** đúng quyết định đứng @S146 (`session-start.md:274` "anh gật mới chạy"); giữ status-quo = KHÔNG lấn quyền. ✅ HELD. NHƯNG spec không khai hệ-quả: cả 2 sister chạy trio vô-điều-kiện (AI_INFRA session-end:170-172 3-wave FULL; VIPIX session-start:80) → đích "chạy như VIPIX/AI_INFRA" (spec:20) KHÔNG đạt trọn với hình này, và vết-skip trio [M4-WAL] ghost-wire (0 dòng `trio:` toàn lịch sử — invest V3) không M nào vá → cần 1 dòng residual trong §4.
- **`_end` #20:** đang chờ anh thật (`docs/HANDOFF.md:21` mục (20) "Anh chốt điều-kiện đóng `_end` thì em sửa 1 chỗ") — spec §4.5 giữ đúng. ✅ HELD.
- **JUMP dải 3-4 KHÔNG tự-retire:** chữ đúng ✅ nhưng FIX-1 cho thấy máy-như-spec sẽ DE-FACTO phá nó — ranh owner bị đe doạ bởi cơ chế, không bởi câu chữ. Kèm: `light_every=6` là số owner-ratified (memory-budget.json:148 Q2 15-07) bị hạ behavior thành stats dưới delegation — có "owner-authority không xoá" + veto-window, chấp nhận được, nên thêm 1 câu tường minh khi trình anh.

### F. Thách-CLEAN "residual 0 · TOTAL 46" — 2 phép độc lập

1. **TOTAL 46:** tự chạy `powershell.exe -File scripts/governance-detectors.ps1` → "**TOTAL FLAGS: 46**" + INFORM-only mới (C6/H24-4/H24-5/C9) = 0. ✅ HELD (số khớp claim).
2. **Residual tên cũ:** full-form (`lead-view-auditor|lead-omission-auditor|h24-audit|sleep-audit|tooling-harvest-audit`) trong commands/ + agents/ + spec = **0 hit**, positive-control tên mới `lead-stale-auditor` CÓ hit (7 file) → phép đo lành. NHƯNG **dạng-ngắn `lead-view|lead-omission` = 9 hit / 4 file LUẬT SỐNG**: `session-end.md:49` ("verify OUTPUT lead-view+lead-omission" = role-ref rõ), `:118`; `agents/README.md:130,:131`; `ring1-audit.md:4,:53`; `ring2-audit.md:4,:37,:63`. `ring2-audit.md` dùng tên MỚI đầu file + tên CŨ cuối file = bất-đối-xứng nội-bộ, đúng class S146-F1 ("residual có người chỉ tận nơi vẫn rớt"). 🔴 Claim "residual 0" (spec:5 + K0) = đúng theo phép-đo-hẹp, LỌT theo nghĩa-sử-dụng → K9/K0-bis phải sweep 9 hit này (đổi sang tên mới hoặc chú thích alias 1 lần).

### G. §0 lead-verify re-check (spec:9-14)

Row 1 (2 reader READ-only): re-run `grep -rl session-counter scripts/` = đúng 2 file ✅. Row 2 (AI_INFRA :110-125): đối chiếu :167-191 session-end khớp verbatim M-1/RETIRED/carve-out ✅. Row 3 (VIPIX :73/:151-157): đọc trực tiếp khớp ✅. Row 4 (`session-scaffold.js`): tồn tại ✅.

## Falsify-log

| # | Phép | Kết quả | Bằng chứng |
|---|---|---|---|
| F1 | Hình B phủ MỌI ca hỏng S144-S149 (tự đếm từ `.session-counter.json` history 11 entry + invest A) | **HELD-lane / BROKE-coverage** | Phân-lane "0 ca do deep-chưa-tới-hạn" ĐÚNG (deep chạy S143@17, mốc kế 32, không ca nào quy cho deep). Nhưng 3 ca KHÔNG M nào cover: GAP-3 diary-rỗng ×4 · trio vết-skip ghost-wire · lũy-kế garble ×27≠33 |
| F2 | Trio GIỮ CONSENT mâu thuẫn đích "chạy như sister" | **HELD-nửa / BROKE-nửa** | Spec KHÔNG lờ (line 27 tường minh owner-held #12) ✅; nhưng hệ-quả residual (bệnh (ii) còn sống nhánh trio) không khai ở §4 ✗ |
| F3 | M2 vs M3 writer race trên `.session-counter.json` | **BROKE-soft** | Không concurrent-race thực (lead sequential single-writer, session-end:308 M-7 add đích-danh); NHƯNG spec đánh rơi "atomic temp+move" (invest M2 có, hub `_save_atomic` h17:174-184) + chữ "structural" sai schema (h17:286-288 vs counts-map SỐ) |
| F4 | JUMP dải 3-4 — spec có chỗ reset/wipe tally? | **BROKE** 🔴 | Mâu-thuẫn tay-ba M2×M-1×M6 (Findings-A): reset-on-clean consecutive (đã chạy thật S137/S140/S143) × bookend 2×/phiên × CẤM-wipe = không đồng-thời thoả; dải 3-4 sẽ bị máy phá hoặc semantics đổi ngầm |
| F5 | Rename residual — grep 5 tên cũ | **BROKE** | Full-form 0 ✅ (positive-control tên mới có hit) nhưng dạng-ngắn 9 hit / 4 file luật sống (Findings-F2) → "residual 0" lọt |
| F6 | (bonus) K5 positive-control trên commit thật | **BROKE** | S140 `b146e2b` = archive-gist-only, không MEMORY.md → sentinel-as-specified FLAG trong khi spec đòi PASS; fix nới predicate đã kiểm khả thi (Findings-D1) |
| F7 | (bonus) §0 lead-verify + TOTAL 46 re-run độc lập | **HELD** | 2 reader đúng · C9:1518 · C10:1577 · TOTAL FLAGS: 46 tự chạy máy |

## KHÔNG CHẮC

1. Template hub `session-context-template.md` 3-block: tin trích verbatim của invest (đọc scaffold.py chính nhưng KHÔNG mở template) — M1 template-SE khớp form S148 cần implementer đối chiếu mẫu sống `session-2/_context-s-2.md` lúc làm.
2. VIPIX `session-end` chưa đọc trực tiếp (kế thừa caveat invest §4.2) — M6 phía @end tailor từ AI_INFRA §4.6; độ tin cao qua cross-ref `:76`/`:85` nhưng chưa nhìn thẳng.
3. Scope chữ "residual 0" của K0 có thể lead CỐ Ý đo full-name-only; nếu vậy finding F5 hạ MAJOR→MINOR nhưng 9 hit vẫn phải sweep (luật sống mixed-name = bẫy reader mới).
4. TOTAL 46 chạy trên working-tree hiện tại (runs/ + broadcasts excluded, 0 self-match) — khớp số claim nhưng tôi KHÔNG so từng detector-component với baseline-set gốc.
5. Hành vi reset-on-clean hiện là QUY-ƯỚC tay (lead làm theo `_note`, chưa có script) — F4 phán trên quy-ước đó; nếu lead@S150 tự ý không reset thì hiện tượng khác nhưng mâu-thuẫn spec vẫn nguyên (máy M2/M3 sẽ phải chọn 1 trong 2).

## ĐÃ CÂN NHẮC RỒI BÁC

1. **"F4 chỉ cần ràng M-1 là đủ, khỏi pin đơn-vị"** — BÁC: M-1 cấm wipe nhưng consecutive-semantics ĐÒI reset-on-clean; cấm reset = đổi semantics (vi phạm M2), giữ reset = phá dải treo. Để mâu-thuẫn treo cho implementer tự xử = lặp đúng chỗ hub chết (session-end:183). Phải pin per-phiên + sequence owner-treo.
2. **"9 hit dạng-ngắn là tên LENS (view/omission) không phải tên VAI, residual-0 vẫn đúng"** — BÁC: `session-end.md:49` "verify OUTPUT lead-view+lead-omission" chỉ OUTPUT của 2 VAI (class thì tên `view-*`/`gap-*` — vẫn giữ, không tính); `ring2-audit.md` tên mới đầu + tên cũ cuối cùng file = bất-đối-xứng nội-bộ S146-F1.
3. **"K5-S140 khỏi sửa spec, implementer tự nới predicate lúc code"** — BÁC: acceptance là HỢP ĐỒNG đo; để nguyên thì hoặc implementer code theo VIPIX-nguyên-bản rồi K5 fail (đổ lỗi qua lại), hoặc tự nới không khai deviation — cả hai đều đúng lớp "acceptance literal tự-lão-hoá" đã có án S109/S121. Đã kiểm fix khả thi 2 chiều rồi mới đề nghị.
