Files
solution-erp/.claude/workflows/runs/2026-07-15-S119-adap-6-broadcast/spec-adap-6-broadcast-15-07-2026-v3-PATCH.md
pqhuy1987 4727d16178 [CLAUDE] Docs: S119 adap 6 broadcast AI_INFRA - dieu tra chieu rong + spec v3 (dung truoc wave)
check-email 6 broadcast moi (H23 model-at-spawn / H24 lead-self-audit / H22 wal-defect-fix
5-san / H22 push-guard / EOL-CRLF agent-registry / owner-sign) - hash 7/7 + tamper 4/4 MATCH.

Pipeline H21: fable-clone invest 5-lane (wf_1f6bd5e2-478, 5/5 clean) -> spec v1 ->
fable-clone reviewer 4-lane (wf_78a84f9b-03e: R2 FAIL 4C+8M, R3 FAIL 5C+6M, R1/R4 chet #53)
-> v2 -> fable-real reviewer cong-cuoi (wf_cb964f83-331: GO-WITH-FIXES + 8 fix + 2 honesty-C)
-> v3 (STILL-BROKEN = 0). Anh chot B: dung tai spec, wave chay phien sau qua /tiep.

Do that: 57 wal: da lot origin/main (hub do duoc 1 -> SE = 57x); nguyen nhan KHONG phai
turn-seam ma la session-end.md:113 SE tu viet "kep sau -> GIU NGUYEN". K troi 3->10/buoi.
v1 SE GAY MAT VIEC (R3 fault-inject: NONWAL=0 -> 0 commit de fixup -> detached HEAD ->
hook fail-open -> abort -> mat worktree = E-029 bang cua sau).

Owner 6 chot: nguyen-tac moi (vuot-khung = request anh + AI_INFRA) / PA-2 = PA-2a hang-so +
PA-2b audit / 6-15-3 / [carry:slug] / KHONG don 57 / fix#8 (a)(b).

0 prod-code, 0 migration, 0 FE. Test 509 giu nguyen (45D + 464I).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:20:29 +07:00

185 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SPEC v3 — PATCH-SET trên v2 (S119, 2026-07-15)
> 🔴 **CÁCH ĐỌC:** worker đọc **v2** (`spec-…-v2.md`) làm thân + **file này** thay-thế các mục ghi rõ dưới. v3 **KHÔNG** lặp lại v2. **v1 = CẤM CHẠY.**
> **Nguồn:** `/fable-real reviewer` cổng-cuối `wf_cb964f83-331` → **GO-WITH-FIXES** (0 tiêu-chí NO-GO; **8 fix BẮT BUỘC** trước wave). Verdict đầy-đủ: `fable-real-final-gate-verdict.md`.
> **Nấc phiên S119:** anh chốt **dừng tại spec v3** — **KHÔNG chạy wave phiên này**. Wave = phiên sau qua `/tiep`.
---
# 0. 🔴 DISPOSITION 23 FINDING (fix #2 — vá lỗi trung-thực C1)
> **Lỗi đã phạm:** v2 ghi *"R2 (4C+**7M**) · R3 (5C+**2M**) … **19 finding** … v2 vá 19"*. **Đếm thật từ file: R2 = 4C+8M · R3 = 5C+6M ⇒ 23 C+M.** Ngay số tự khai cũng không cộng ra (4+7+5+2 = **18 ≠ 19**).
> **Vì sao NẶNG:** tập "7M/2M" **khớp chính xác** tập v2 có xử-lý ⇒ con-số "19" **đóng vai "đã phủ hết"** trong khi **3 finding STILL-BROKEN**. Lớp S109 (metadata-count) + S81 (honesty-presentation). Bảng này = **bằng-chứng-chống-tái-phạm**, và **đi nguyên vào adap-report**.
| # | Finding | v2 | v3 |
|---|---|---|---|
| R2-C1 | `ls=14` sai số-học | ✅ FIXED | — |
| R2-C2 | anchor số-nhiều | ✅ FIXED (gate tự chạy regex → MATCH `permission-matrix:16` + `form-engine:15`) | — |
| R2-C3 | gate⟂cờ tách wave | ✅ FIXED | **fix #6**: `fable-clone.md` 2-chạm vắng §3.2 |
| R2-C4 | gate W0.2 xanh-sẵn | ✅ FIXED | **fix #9(d)**: dòng 70 ⟂ §3.9 tự-mâu-thuẫn |
| R2-M1 | nửa-(ii) n-a sai | ✅ FIXED | — |
| R2-M2 | lỗ chưa-test precedence | ✅ FIXED | — |
| R2-M3 | 0-hardcode phình scope | ✅ FIXED | — |
| R2-M4 | scheduler mồ-côi + enum | ⚠️ PARTIAL (chủ-sở-hữu ✅ / enum **10/11 SAI**) | **fix #1** |
| R2-M5 | ② + ③d rơi | ✅ FIXED | — |
| R2-M6 | else "vô-hại" | ✅ FIXED | — |
| R2-M7 | thí-nghiệm quyết-định + L3 caveat | ✅ FIXED | — |
| **R2-M8** | **sweep roster sai pattern + file không wave** | 🔴 **STILL-BROKEN** (v2 §2.4(5) = "giữ v1") | **fix #6** |
| R2-m1 | broadcast #7 presence-not-age | ⬜ chưa xử | **fix #9(e)** 1 dòng |
| R2-m3 | — | ✅ FIXED qua PA-2b | — |
| R2-m4 | "n-a ĐÃ THOẢ" = under-report | ⬜ chưa xử | **fix #9(b)** |
| R2-m5 | lịch stamp-mark | ⬜ chưa xử | **fix #9(f)** → W6 |
| R3-C1 | rebase phá thật | ✅ FIXED | **fix #7** (bug shell guard) |
| R3-C2 | K stale | ✅ FIXED (K drift **4→5→6→8** = tự chứng minh luật đúng) | — |
| **R3-C3** | **push deadlock** | ⚠️ **PARTIAL** — v2 **tự tạo** ca wal:-đáy-range | **fix #3** 🔴 |
| R3-C4 | premise stale / renormalize staging | ✅ FIXED | — |
| R3-C5 | gate unscoped bất-khả-giữ | ✅ FIXED | — |
| R3-M1 | ls=15 | ✅ FIXED (trùng R2-C1) | — |
| R3-M2 | STATUS coupling | ✅ FIXED | — |
| R3-M3 | TOTAL≥46 bất-khả | ⚠️ PARTIAL (gate đã GỠ; thiếu capture-stdout) | **fix #9(c)** |
| **R3-M4** | **Sàn-3 thiếu dual-accept** | 🔴 **STILL-BROKEN** + **REGRESSED** (v2 chọn mtime) | **fix #4** 🔴 |
| **R3-M5** | **tripwire vỡ đường sống** | ⚠️ **PARTIAL** (wrapper-list ✅ / điều-kiện ❌) | **fix #5** 🔴 |
| **R3-M6** | sweep pattern + `hmw.js:9` | 🔴 **STILL-BROKEN** (trùng R2-M8) | **fix #6** |
| R3-m5 | mtime không bền | 🔴 **REGRESSED** — v2 chọn mtime làm phương-án CHÍNH | **fix #4** |
| R3-m6 | cấm synthesis giả | ✅ FIXED | — |
| R2-m2, R3-m1/m3/m4 | — | ⬜ chưa xử — **không chặn wave**, ghi để không rơi | defer S120 |
**Tổng:** 23 C+M ⇒ **16 FIXED · 4 PARTIAL · 3 STILL-BROKEN** (+1 REGRESSED ở lớp m). v3 đóng **3 STILL-BROKEN + 3 PARTIAL + 1 REGRESSED**.
---
# FIX #1 — Enum 11 class (thay §2.4 "enum ĐÓNG" của v2)
**Lỗi:** v2 chép **10** class rồi tuyên *"khớp H24 §2(1) 5+5"***SAI cả 2 chiều**: lane D có **11** (tách `carry-dropped`/`carry-aged` **có chủ-đích, đo được caveat (b)**); broadcast H24 `:48-49` liệt **"một việc rớt khỏi khối work-state so với backlog"** = **dấu-hiệu RIÊNG**. v2 **bỏ hẳn** `workstate-item-dropped` để về 10 rồi tuyên khớp.
🔴 **Hậu-quả:** 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** ⇒ 2 vai mới **VĨNH VIỄN** không được phát class này.
```json
"lead_self_audit": {
"flag_classes": [
"view-stale-count", "view-stale-status", "view-stale-header",
"view-stale-role-desc", "view-residual-asym",
"gap-workstate-drop", // ← KHÔI PHỤC (broadcast :48 — dấu-hiệu RIÊNG; bắt ca F1 của SE)
"gap-carry-dropped", "gap-carry-aged", // ← tách-đôi = MỞ-RỘNG lane-D (đo được caveat (b)), KHÔNG phải broadcast
"gap-owner-specifics", "gap-decision-sunk", "gap-underfill"
]
}
```
🔴 **XOÁ câu "khớp H24 5+5"** khỏi spec. Nấc đúng: *"5 STALE (khớp broadcast) + **6** GAP = 5 broadcast + **1 mở-rộng lane-D** (carry tách-đôi, lý-do đo-được)"*.
**Acceptance:** `flag_classes``{gap-workstate-drop, gap-carry-dropped, gap-carry-aged, gap-owner-specifics, gap-decision-sunk, gap-underfill}` · `grep "khớp 5+5"` = **0**.
---
# FIX #3 🔴 — Luật fold leading-wal: (thay v2 W0.3 "commit-chốt ở W6" + §2.1 push-guard)
**Lỗi sâu:** v2 **tự tạo** ca chết. W0.3 park nội-dung staged ("commit-chốt ở W6") → `wal-flush.ps1:14-17` 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**.
**v3:**
- **(a)** W0.3 **BỎ** "commit-chốt ở W6". **Commit-chốt `[CLAUDE]` NGAY CÙNG TURN** với `reset --soft` (gộp luôn `wal-flush.ps1` interlock + `.gitattributes`) ⇒ **đáy range = commit thường**.
- **(b)** Mọi push **sau push#1** ở 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**.
---
# FIX #4 🔴 — Sàn-3 dual-accept + W0.5 bỏ mtime (thay v2 §2.1 Sàn-3 + W0.5)
**Lỗi kép:**
1. Văn-bản canonical Sàn-3 (sẽ re-author vào `tiep.md` §0) **KHÔNG mang mệnh-đề dual-accept** — nó đang sống ở `workflows/README.md:19-20` (*"close-gate chấp nhận CẢ HAI dạng"*, C8 migration S71). Wire xong = **bão 5 dương-giả**. Đo: naive = **13** orphan · dual-accept = **8** (7 tồn-đọng + S119) — 5 folder h10/h910 **đều có** `harvest/<stage>-synthesis.md`.
2. **REGRESSED:** v2 chốt W0.5 scope theo **mtime** — đúng phương-án R3-m5 đã chứng minh **không bền** (**Dropbox resync ghi đè mtime**; "closeout cuối" không đo được).
**v3:**
- **Chép VERBATIM** mệnh-đề C8 (`workflows/README.md:19-20`) vào Sàn-3 canonical @`tiep.md` §0.
- W0.5: **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 tồn-đọng · **5 folder h10/h910 IM**.
---
# FIX #5 🔴 — Tripwire mirror `hmw.js:116` (thay v2 §2.1 Sàn-1 điều-kiện)
**Lỗi:** v2 giữ điều-kiện v1 `!(A.run?.dir && A.run?.name)`. Thật (`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 v2 **GIẾT lời-gọi `wave:` hợp-lệ** + **đòi `.name` vượt contract** `.dir`-only.
```js
const w = (A.run && A.run.dir) ? A.run : ((A.wave && A.wave.dir) ? A.wave : null)
if (A.taskList.length >= 3 && !w) throw new Error('H22 Sàn-1: run ≥3 task PHẢI đăng-ký marker (args.run.dir) TRƯỚC khi phóng')
```
(hoặc **nâng contract `:116`** trong **CÙNG edit** — chọn 1, không nửa vời.)
**Acceptance (thêm §3.9):** ≥3-task kiểu `wave:{dir}` **VẪN CHẠY** · thiếu **cả hai****throw**.
---
# FIX #6 — Roster-sweep pattern + file chủ-quản (thay v2 §2.4(5) "giữ v1")
**Lỗi:** pattern sweep của v1/v2 = `grep "12-agent|12 sub"` — nhưng stale THẬT ghi **"9-agent"** ⇒ **pattern không bao giờ bắt được**. Lead tự verify:
- `hmw.js:9` = `'HMW P2 execute (SOLUTION_ERP) — fan-out **9-agent** roster…'` ← stale **từ trước S119** (roster 12, VALID_ROLES 12 từ S110)
- `ultra-on.md:24` = `'## VALID_ROLES (roster SOLUTION_ERP — **12 sub**, đủ roster từ S110)'` ← sẽ stale khi →14
- `fable-real.md` + `fable-real-runbook.md` = **không thuộc wave nào**
**v3:**
- **Pattern (Grep tool):** `(12|9)[- ](agent|sub)|roster 12|12 vai|VALID_ROLES[^0-9]*12`
- **Vào W2 (1-EDIT):** `hmw.js:9` meta + `ultra-on.md:24` danh-sách VALID_ROLES 12→14 (**routing-doc ⇒ CÙNG COMMIT**)
- **Vào W3:** `fable-real.md` + `fable-real-runbook.md`
**Acceptance:** sau W3, pattern trên = **0 hit sống** (ngoài lịch-sử/archive).
---
# FIX #7 — Bug shell guard W0.3 (thay v2 W0.3 dòng guard)
**Lỗi lead tự viết:** `[ -d .git/rebase-merge ] || [ -d .git/rebase-apply ] && { echo …; exit 1; }` ⇒ happy-path (**không có dir nào**) trả **exit 1** (status chuỗi `||`) ⇒ caller check exit-code **báo hỏng GIẢ**.
```bash
if [ -d .git/rebase-merge ] || [ -d .git/rebase-apply ]; then
echo "STOP: rebase state left behind"; exit 1
fi
```
**Acceptance:** chạy block trên repo sạch ⇒ **exit 0**.
---
# FIX #8 — 2 ack tường-minh (🔴 QUYỀN ANH — chờ ký)
## (a) PA-2 hình-thức — **cần anh duyệt trước khi W2 land `TIER2_EXPECTED_FULL_ID`**
Gate bắt đúng: bullet *"param `model:` chỉ nhận enum alias"* trong `owner-decisions` **dán nhãn "Đo" nhưng KHÔNG nêu phép đo**. 2 bullet kia gate tự verify được (`hmw.js:44` ✓ · grep full-id = 5 hit / 3 file ✓); **riêng bullet này là tiền-đề** biến 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**.
🔸 **Hạ nấc trung-thực:** *"theo tài-liệu harness (Agent-tool `model` enum = `sonnet|opus|haiku|fable`), **CHƯA thử truyền full-id để xem có bị từ-chối không**"*.
**⇒ Cần anh xác nhận:** PA-2 thực-thi bằng **PA-2a (hằng-số `TIER2_EXPECTED_FULL_ID`) + PA-2b (`spawn-model-audit.ps1` so resolved-vs-expected)** — thay vì neo-tại-spawn (chưa thử). ⚪ **CHỜ**
## (b) Hook-interlock vs floor N.2 — **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"*). Nguyên-tắc anh nói rõ **"dù lý-lẽ tốt"**.
**Đề-xuất phân loại (lead):** **TRONG KHUNG** — interlock **KHÔNG thêm hành-vi** cho hook; nó **chặn hook tự-hủy** (commit lên detached HEAD = phá chính floor N.2 nó phục-vụ). = **thu hẹp**, không mở rộng. ⇒ khai ở adap-report, **không cần request**.
**Chờ anh ack** (nếu anh muốn chặt hơn → chuyển thành request).
---
# FIX #9 — Nhóm nhỏ (không chặn, gộp 1 pass)
| | Việc |
|---|---|
| (a) | ~~"4 cú lật"~~**"4 phát-hiện: 2 ĐO CHẮC (L1/L4-diễn-giải) · 1 PARTIAL (L2) · 1 CHƯA-VERIFY (L3)"** — v2 đã tự hạ L2/L3 nhưng **giữ nguyên nhãn "4 cú lật"** |
| (b) | `"H23 §2(5) n-a ĐÃ THOẢ"`**`"đã thoả"`** — dán PASS thành n-a = **under-report nấc tuân-thủ** khi gửi hub |
| (c) | W4 capture-stdout detector ra `runs/<id>/` = bằng-chứng time-anchored (thay "reviewer chứng-kiến" làm neo **duy-nhất**) |
| (d) | v2 dòng 70 *"W0.2 KHÔNG vào §3.9"* ⟂ §3.9:245 vẫn có ⇒ **chốt 1** (giữ ở §3.9 + chú "vacuous") |
| (e) | +1 dòng: **broadcast #7 `presence-not-age` ĐÃ adopt S115** (R2-m1 — kẻo hub tưởng SE bỏ sót) |
| (f) | Lịch **stamp-mark** vào **W6** (R2-m5) |
| (g) | W0.6 verdict **nhét thẳng** vào R4-request (thay *"báo hub sau"* — vì W0.6 chạy **TRƯỚC** W6) |
| (h) | Validator W1② chạy **glob** thay hardcode 12 |
| (i) | +acceptance: W0.4 · EOL-assert-scoped cạnh push · W6 |
| (j) | 🔴 **Ghi rõ: W0.6 + post-W2 đều cần RESTART ⇒ wave trải ≥3 phiên CLI ⇒ nối bằng `/tiep`** (H22 — chính cơ-chế phiên này adopt) |
---
# Nấc trung-thực v3
- **Verdict cổng-cuối:** **GO-WITH-FIXES****0 tiêu-chí NO-GO**. Mọi đường **mất-việc / rewrite-pushed-history** đã đóng (mass rm+checkout 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 · 0 force-push · O4 giữ 57). Deadlock **hạ cấp** thành STOP fail-loud — **nhưng STOP gần-như-chắc-chắn xảy ra ở W6 nếu không có fix #3**.
- **W0 SOLO = ĐÚNG phải SOLO** (phẫu-thuật index + reset + restart; fan-out ⇒ hook commit agent-memory **giữa lúc mổ**).
- **Owner-decision:** gate xác nhận **không có chỗ nào v2 tự quyết CON-SỐ/policy của anh**; 2 chỗ cần ack = **fix #8**.
- 🔴 **Tỷ-lệ claim (gate re-đo ~30 claim rời):** **~80% ĐO ĐƯỢC-và-đúng** · **~13% SAI — tập trung TRỌN ở lớp meta-count/coverage** (finding-count ×3, enum-"khớp" ×1) · ~7% suy-diễn/chưa-verify.
**Điểm sáng:** 4/5 chỗ CHƯA-VERIFY khai **đúng nấc** (L3 · precedence · side-ref · hot-reload `hmw.js`).
**Điểm tối:** **2 chỗ SUY DIỄN trình như ĐO** (enum-"khớp" · param-alias).
**Bài học tự-soi:** *lead ĐO tốt; lead ĐẾM VỀ CHÍNH MÌNH thì sai.* Lỗi **không** nằm ở dữ-liệu — nằm ở **tự-tổng-kết độ-phủ**. Đây là lý-do bảng §0 tồn tại.
- **CHƯA VERIFY (giữ nguyên):** đường đọc frontmatter CR-tolerant hay LF-only (**W0.6 quyết**) · precedence spawn-param ⟂ frontmatter (**defer phiên lead=Fable**) · side-ref R3 (lập-luận plumbing) · hot-reload `hmw.js` · **+ MỚI:** param `model:` có từ-chối full-id không (fix #8a).
- **STILL-BROKEN sau v3 = 0** (3 cái đã có fix #3/#4/#5/#6). **PARTIAL còn:** R3-M3 (fix #9c) · R2-m2/R3-m1/m3/m4 (**defer S120, không chặn**).
- **Số trong v2/v3 = ẢNH CHỤP, KHÔNG phải hằng-số.** K đã trôi **3→4→5→6→8** trong 1 buổi ⇒ **LUẬT SỐ ĐỘNG** (W0.0 re-measure) là bắt-buộc, không phải khuyến-nghị.