From 1d3d167ac7701c178a29a64e3f9894043b13348c Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Wed, 29 Jul 2026 15:27:46 +0700 Subject: [PATCH] [CLAUDE] Docs: S159-S160 closeout arc-2 "Tong quan quy trinh" - STATUS/HANDOFF arc-2 + gotcha #84 revoker-2-chieu + session-log + tick S160 - STATUS CURRENT: +arc-2 5 dot (bo ten 4-GD chot + rui-ro-co-y-thuc verbatim + revoker) + baseline moi (menu 142, bundle D0sXA0fe/Y6dW_5CM, gate 562) + bo claim "0 prod-code" + Gotchas row 84 - HANDOFF: khoi ARC-2 + risk verbatim + luat khong-SQL-tay-cho-menu + va stale _mind 37,9->69,2% - gotchas: +#84 revoker-2-chieu (data tay prod bi code-path ungated @restart dao nguoc im lang; khuon 3-chan-kieng; lien-quan #75/#76/#82) - session-log S159: 2 nua phien + 5 dot arc-2 + errata + PARK + chot dau viec (anh @S160, 7 slot treo) - counter: tick S160 CLEAN 33->34 (spec KHKK note W1 + diary designer/cicd + _tiep-1 da vao wal-flush 57a4155 theo 4-path hook) Co-Authored-By: Claude Fable 5 --- .claude/governance/.session-counter.json | 13 +++-- docs/HANDOFF.md | 10 +++- docs/STATUS.md | 8 ++- ...0-S159-tong-quan-quy-trinh-arc2-bookend.md | 58 +++++++++++++++++++ docs/gotchas.md | 8 +++ 5 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 docs/changelog/sessions/2026-07-29-1440-S159-tong-quan-quy-trinh-arc2-bookend.md diff --git a/.claude/governance/.session-counter.json b/.claude/governance/.session-counter.json index 8058aca..277e390 100644 --- a/.claude/governance/.session-counter.json +++ b/.claude/governance/.session-counter.json @@ -11,10 +11,10 @@ }, "_tick_invariant_note": "Tick invariant (hub dede7ec5 Delta-1, verbatim): moi LAN-CHOT +1; mot cap dung-noi tang DUNG +1, khong +2, khong +0. SE form = tick-at-entry-gate idempotent-per-label (hub Delta-2 recovery-gate +1 = permitted form) - NET +1/session-label EQUIV hub +1/cap on CLOSED pairs; an OPEN pair is transiently +0 until its entry gate fires (hub blessed, 9a35405b block-1 phep dung-noi). Guard song-con = label-convention (session-start 2.1.8: new conversation = new S\u003cnn\u003e label, NEVER reuse). history[] is append-unbounded BY DESIGN =\u003e absence of a marker = never-happened (safe semantics); IF a FIFO cap is ever added, eviction MUST be handled explicitly (absence-vi-bi-day != absence-vi-chua-xay-ra - log-BOUNDED design-note dede7ec5).", "_seed_honesty": "Seeded UNTICKED on purpose. counter=0 and last_ticked_* = null mean \u0027no tick has ever happened\u0027, which is the truth at S121 - the ritual that performs the tick lands in W3. Seeding a fake first tick here would make the very first cadence reading a lie, and H24 exists to catch exactly that kind of invented number.", - "counter": 33, - "last_ticked_session": "S159", - "last_ticked_head": "bbc39be3abf80285ca11a665a574427bdb2d602c", - "last_ticked_at": "2026-07-28", + "counter": 34, + "last_ticked_session": "S160", + "last_ticked_head": "febe6b1696b834d7b3922866ddcea25768952c08", + "last_ticked_at": "2026-07-29", "last_audit": { "light_at_counter": 27, "deep_at_counter": 25, @@ -171,6 +171,11 @@ "at": "2026-07-28", "session": "S159", "event": "squash-benign (session-counter-tick.ps1 M2, contract fail_loud_on_regress trigger-2 BENIGN branch): counter 32->33, session S158->S159, head 6c263dd->bbc39be. last_ticked_head 6c263dd object EXISTS (cat-file=commit) but NOT reachable (merge-base --is-ancestor exit!=0), counter not regressed => a closeout squash lifted the ticked wal:/session commit out of history (expected drift, not tamper). Trace appended, continue, no owner alarm. Written atomically (temp + Move-Item -Force)." + }, + { + "at": "2026-07-29", + "session": "S160", + "event": "CLEAN tick (session-counter-tick.ps1 M2): counter 33->34, session S159->S160, head bbc39be->febe6b1. Classify-before-tick: no regression (n=160 >= stored n=159); last_ticked_head reachable (merge-base --is-ancestor exit 0). 4 fields updated, 1 history entry appended, written atomically (temp + Move-Item -Force)." } ] } diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index b08e7ea..98002e1 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -2,9 +2,13 @@ > **Tiering rule (S40):** giữ **2-3 session gần nhất**. Cũ hơn → `docs/changelog/sessions/`. Full brief history pre-S40 → `docs/_archive/HANDOFF-preS40-fullhistory.md`. -**🆕 Last updated:** 2026-07-29 (**S159** — phiên-LOGIC **L8**, window 1). Chi tiết = `docs/STATUS.md` dòng CURRENT + run-trace `.claude/workflows/runs/2026-07-29-S159-bookend-open/`. +**🆕 Last updated:** 2026-07-29 chiều (**S159→S160** — phiên-LOGIC **L8**, window-1 `/pause` @14:40 + window-2 `/tiep` closeout). Chi tiết = `docs/STATUS.md` dòng CURRENT + run-trace `.claude/workflows/runs/2026-07-29-S159-bookend-open/` (bookend) + `.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/` (arc-2). -**Tóm S159 (governance-heavy, 0 prod-code):** anh giao 2 việc — **chạy đủ 5 vòng bookend** + **vá 2 chỗ hở spec KHKK** — rồi chốt tiếp *"có giải pháp thì làm luôn, các vòng này tự động luôn"*. Kết quả: 10 vai · 9 spawn + 6 resume · 11 artifact ~231 KB · **5 khoản (49)-(53) thi hành xong**. +**Tóm S159 window-1 = 2 nửa.** **Nửa đầu governance:** anh giao 2 việc — **chạy đủ 5 vòng bookend** + **vá 2 chỗ hở spec KHKK** — rồi chốt tiếp *"có giải pháp thì làm luôn, các vòng này tự động luôn"*. Kết quả: 10 vai · 9 spawn + 6 resume · 11 artifact ~231 KB · **5 khoản (49)-(53) thi hành xong**. **Nửa sau ARC-2 UI SHIP PROD (khối 🆕 dưới)** — dòng "0 prod-code" chỉ đúng nửa đầu. + +**🆕 ARC-2 UI "Tổng quan quy trình" — 5 đợt / 5 commit ship prod trong 1 buổi chiều** (`b5799fc`→`1a47a61`→`2a72695`→`a2bbcb9`→`ea962b1`; cicd 5/5 verdict: PASS · **PARTIAL 8/9** · PASS restart-proof · PASS durability-2 · **PASS 9/9 đợt-5 về kịp trước chốt**): trang tổng-quan fe-user pipeline 4 GĐ + tab strip trên phiếu + menu 4-GĐ đánh số 01-07 + list chi tiết toàn-trình (bỏ KPI/hero theo lệnh anh *"Ồ đẹp đấy, vậy bỏ cái trên đi nhé"*) + menu 6-leaf y-chang-Duyệt-NCC ×7 loại HĐ + `GET /api/contracts/deleted` + sidebar "Tổng quan quy trình" (tên anh đề). **Bộ tên 4-GĐ chốt (lời anh):** ❶ Duyệt NCC · ❷ Kế hoạch ký kết HĐ · ❸ Duyệt hợp đồng (*"Trình ký Hợp đồng đổi thành Duyệt hợp đồng"*) · ❹ Hợp đồng cứng (*"ký cứng -> Hợp đồng cứng"*); nhãn leaf Hdc "- Bảng cứng" theo verbatim anh vẽ (nghi "Bản cứng" — 1 lệnh đổi được, chờ anh). Baseline mới: **menu 142 · bundle admin `D0sXA0fe`/`DWDbm5As`(frozen-hợp-lệ) · user `Y6dW_5CM`/`6YIAufJR` · test 562 giữ · 0 mig**. +🔴 **❹-risk CÓ Ý THỨC (verbatim anh, giữ nguyên văn):** *"đang phát triển → cho hiển thị hết để mọi người góp ý, còn duyệt NCC thì cứ để như cũ"* — menu HĐ public 13/13 role trong khi authz HĐ còn `[Authorize]` trần (lỗ hổng S156 treo chủ-đích *"chỗ hợp đồng cứ từ từ"*, HANDOFF mục "Treo CÓ CHỦ ĐÍCH" dưới); em đã cảnh báo, anh tái khẳng định. **Wave 5 KHKK chạm HĐ ⇒ vẫn phải hỏi lại anh.** +🔴 **Sự cố revoker → gotcha #84 (bài đắt nhất arc):** grant menu SQL tay bị `RevokeTemporarilyHiddenModulesAsync` nhánh [S92] lật **447/494 row** @restart (#423 bắt ở mục-9) → regrant 447 + **gỡ nhánh code** + guard test 2-vế (`StillHiddenKeys`∧`ReopenedKeys` — re-add là CI đỏ) → bền ×3 restart. **Luật: KHÔNG SQL tay cho menu — code-first seeder; comment nêu LUẬT+lệnh grep, CẤM số-đếm** (2 lần trong ngày số-comment thành nợ tự-lan). 🔴 **Ba lần vòng kiểm chặn lead trước khi làm hỏng:** ① `ring2` **D-4** — lead suýt chép `gap-carry-dropped=3` (đơn-vị **trong-phiên**) vào ô tally đang **=7** (**consecutive-audit**) ⇒ **xoá 7 vòng lịch-sử**; *cùng tên ≠ cùng đơn-vị* ② `ring1` thách-CLEAN lật claim *"stray 0 · empty-dir 0"* của H2 → thật **1** + **5→6 đang tăng**, ngay trong run-folder phiên này (0 file, class `agent-cwd-relative-memory-misland` S54) — 🔴 **`git status` MÙ CẤU-TRÚC với thư-mục rỗng** nên post-wave assertion báo sạch *đúng lệnh* mà vẫn sót ⇒ **close-gate phải chạy RIÊNG `find -type d -empty`** ③ `ctx-audit` dùng **mtime** chứng lead ghi `_mind` **sớm 13–54 phút**, ngược `session-start.md:358` — **1 nguyên-nhân gốc sinh 4 triệu-chứng**. ⭐ **Bài đắt nhất phiên — "khâu hỏng là APPEND, không phải phát hiện":** 11 vai diary đóng băng tại đúng commit `11db5ef`; và vì diary đóng băng, `harness-refine` đọc sổ chốt-dừng của **chính nó** **sai 2 vòng** — nó phát hiện **6/6 đề-xuất qua S153+S154+S158 CHƯA từng thi hành**, nên cố ý đề **ít** action. ⇒ Cái hỏng ở khâu **GHI** quay lại làm hỏng khâu **QUYẾT ĐỊNH** = **vòng phản hồi dương**, không phải nợ kỹ-thuật. Đã seed **10/10 diary** on-behalf. ⭐ **Anti-Goodhart đo được:** vá lọc detector ⇒ INFORM **8→14**. **Số xấu đi CHÍNH LÀ bản vá chạy đúng** (3 lane trio + ctx trước đây vô hình với glob `sub-*.md` nên **không bao giờ bị flag**). Nếu chấm bản vá bằng *"flag-count có giảm không"* thì sẽ revert đúng thứ vừa mở mắt cho lưới. @@ -27,7 +31,7 @@ **🔴 NEXT anh @S158 (đánh số — anh trả lời bằng số):** **(42)(43)(44)** — 🔴 **3 slot này đã cấp ở WAL từ S155 nhưng CHƯA BAO GIỜ xuất hiện ở HANDOFF** (lead-stale FLAG-6 @S158: sổ anh đọc dừng ở slot 41 trong khi sổ lead đã tới 44) ⇒ 3 câu dưới đây anh **chưa từng được hỏi**: **(42)** canonRows · **(43)** carry con-trỏ-vs-slug · **(44)** END-line-thành-luật. -~~**(45)** 🔴 **Trần `_mind` — CHẶN cửa `/pause` kế tiếp.**~~ ✅ **RÚT @S159 — BÁO ĐỘNG GIẢ, không cần anh quyết.** `lead-stale-auditor` FLAG-3 (`view-stale-count`, HIGH) + `ring2-audit` tái-dựng 6/6 số: con số **30.305/32.768 B = 92,5%** là của **`_mind-s-7.md`** — file **ĐÃ ĐÓNG BĂNG** cùng phiên-LOGIC L7 (`4169e14`). File **đang hiệu lực** là `_mind-s-8.md` = **37,9%**, dư **20.338 B** — gấp **8,3×** con số trong sổ, thừa sức chứa block kế. **Cửa `/pause` tiếp theo KHÔNG bị chặn.** +~~**(45)** 🔴 **Trần `_mind` — CHẶN cửa `/pause` kế tiếp.**~~ ✅ **RÚT @S159 — BÁO ĐỘNG GIẢ, không cần anh quyết.** `lead-stale-auditor` FLAG-3 (`view-stale-count`, HIGH) + `ring2-audit` tái-dựng 6/6 số: con số **30.305/32.768 B = 92,5%** là của **`_mind-s-7.md`** — file **ĐÃ ĐÓNG BĂNG** cùng phiên-LOGIC L7 (`4169e14`). File **đang hiệu lực** là `_mind-s-8.md` = 37,9% lúc đo @S159 (**69,2% @S160** sau MIND-1/MIND-2 — 22.665/32.768 B, dư 10.103 B; số này TRÔI theo phiên, số sống đọc `mind-check` phép (7), đừng neo literal ở đây). Vẫn thừa chỗ cho block kế. **Cửa `/pause` tiếp theo KHÔNG bị chặn.** 🔴 **Vì sao slot này nguy hiểm hơn một con số sai:** nó xin anh tiêu một **quyết định owner** (nâng khoá `mind_ctx_kb` / vá luật nén) dựa trên số đo của một artifact đã chết. Quyết-định của owner là tài-nguyên hiếm; báo-động-giả tiêu mất một lượt. Class = **tham-chiếu trượt khi L7 `_end` và L8 mở, sổ owner không đi theo**. 🔸 **Giữ phần CÒN ĐÚNG (không vứt cả cụm):** mối lo NỀN là thật — `ctx-verifier` dự báo tường này từ **S156**, và L8 sẽ lớn dần. Cái bị bác là **BỘ SỐ + tính khẩn "cửa kế tiếp"**, không phải câu hỏi thiết kế. Khi `_mind-s-8` thật sự tới ~90% thì mở lại slot mới, đo trên file SỐNG. **(46)** 🔴 **Thước "17,1K" là thước MA — chọn 1 trong 3 ngã** (`harness-refine` A1, nó **cố ý không đặt số** vì số là quyền anh): **(i) WIRE** thêm key `tiers.l1_hot.self_target_bytes` để máy soi được · **(ii) RETIRE** gỡ luật khỏi 5 diary vì thước thật là 25.600 · **(iii) RELABEL** giữ nhưng ghi rõ "advisory". Bằng chứng nó **đang tốn công thật**: `investigator-codebase:58` nén về ~17,1K @S155, **3 ngày sau 20.646 B lại**; áp thước này thì **9/23 vai vượt** trong khi mọi máy in "0 over". diff --git a/docs/STATUS.md b/docs/STATUS.md index f1783e2..1958a83 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,14 +3,16 @@ > **Update rule:** trước khi bắt đầu 1 task → ghi row `🔥 In Progress`. Xong → `✅ Recently Done`. > **Tiering rule (S40):** chỉ giữ **state hiện tại + 3 session gần nhất** ở file này. Session cũ hơn → `docs/changelog/sessions/`. Full history pre-S40 → `docs/_archive/STATUS-preS40-fullhistory.md`. (Tránh over-context — xóa double, không cắt nội dung.) -**🔥 CURRENT (S159, 2026-07-29 — phiên-LOGIC **L8**, window 1: bookend @open **5 vòng ĐỦ** + vá spec KHKK + thi hành 5 khoản owner):** Mig **68** · 89 bảng · **562 test PASS** (45D+517I, đo tươi @S159) · gotcha 83 · counter **33** · roster 23 · 🟢 **RAG service UP** (SE index stale — row RAG chunks đã TÁCH 2 trục). **Governance-heavy, 0 prod-code, 0 mig.** +**🔥 CURRENT (S159→S160, 2026-07-29 — phiên-LOGIC **L8**: window-1 = bookend @open **5 vòng ĐỦ** + vá spec KHKK + thi hành 5 khoản owner + **ARC-2 UI "Tổng quan quy trình" 5 đợt SHIP PROD**; window-2 `/tiep` @S160 = closeout sổ bền + PARK chờ anh):** Mig **68** · 89 bảng · **562 test PASS** (45D+517I, đo tươi @đợt-5 Run #426) · gotcha **84** · counter **34** · roster 23 · **MenuItems prod 142** (root 12 · 38-key 13/13 · 21 key `Ct_*` mới 13/13) · bundle **admin js `D0sXA0fe`/css `DWDbm5As` (frozen-hợp-lệ #69-B)** · **user js `Y6dW_5CM`/css `6YIAufJR`** · 🟢 **RAG service UP** (SE index stale — row RAG chunks đã TÁCH 2 trục). **Nửa đầu governance (0 mig) + nửa sau ARC-2 code 2-app + BE endpoint/seeder — dòng "0 prod-code" của bản trước CHỈ đúng nửa đầu.** ① **Sàn-3 ① kêu ×2** (orphan S155+S157 dạng-4) → anh chốt *"nối cho xong hẳn rồi bootstrap"* → **retro-harvest 2 synthesis**; `harvest-curator` verify độc lập: **12/12 byte-exact · 8/8 verdict nguyên văn · 0 bịa**. ② **ARC spec KHKK:** H5 đóng **2 site** (`N ≥ 6` + 6 tên test W3 · `N ≥ 2` + 2 tên W1 — trước đó `N` thả tự do ⇒ `N=0` vẫn PASS) · H6 đóng **4 site** (HANDOFF ghi 1, lead đếm đầu 3, thật **4** — site-4 `DbInitializer` W2 chỉ lộ khi hỏi *"W1 bỏ `IsVisible=0` rồi thì bật ở W2 còn nghĩa gì?"* ⇒ **grep tìm CHUỖI, chỉ mô-hình nhân-quả tìm HỆ-QUẢ**). ③ **Bookend 5 vòng, 10 vai, 9 spawn + 6 resume, 11 artifact ~231 KB:** V1 tooling 7f + harvest **GATE-FAIL 9f** → `ring1` **40Đ/7T** · V2 stale 5 FLAG (chết #53, **SÀN không phải TỔNG**) + gap 8 FLAG → `ring2` **13Đ/0T** · V3 trio eval **MIXED** → refine 2 action/10 BÁC → audit **42Đ/6T** (re-chạy 15/15 byte-exact) · V4 **`không-nhịp`** (shard 15/15 IM, ring2 xác nhận biên `-gt` qua 4 đường) · V5 floor 43+8 · Phase 3.5 `ctx-audit` **TRUOT 6 FLAG**. ④ 🔴 **Vòng kiểm chặn lead 3 lần:** **D-4** — suýt chép `gap-carry-dropped=3` (đơn-vị trong-phiên) vào tally đang **=7** (consecutive-audit) ⇒ **xoá lịch-sử** · **dư-lượng vật-lý** — `ring1` lật claim *"stray 0 · empty-dir 0"* của H2, thật **1** + **5→6 đang tăng** (`git status` **mù cấu-trúc với thư-mục rỗng**) · **thứ-tự nghi-thức** — `ctx-audit` dùng mtime chứng lead ghi `_mind` **sớm 13–54 phút**, ngược `session-start.md:358`. ⑤ **Thi hành 5 khoản owner (anh: *"có giải pháp thì làm luôn, các vòng này tự động luôn"*):** **(49)** vá **6 site** 2 file LỆNH (cặp H24 = **VÔ-ĐIỀU-KIỆN mỗi bookend**, chỉ `deep` theo nhịp) + nới bất-biến (6) + **thêm phép (10) `thu-tu bookend vs _mind`** (fault-inject **4/4** 2 chiều, gồm ca chống-Goodhart *0 run-folder ⇒ bỏ-qua-CÓ-KHAI, không đọc thành "đạt"*) · **(50)** seed **10/10 diary** on-behalf · **(51)** `_INDEX` header **78→80** + 🔴 **`Run #407` MỒ CÔI** (có trong kho, 0 con-trỏ) đã thêm, sweep lại **0 mồ côi** · **(52)** slot (45) **RÚT — báo động giả** (đo trên `_mind-s-7` đã đóng băng; file sống **37,9%**) · **(53)** vá lọc detector `sub-*.md` → `(sub|harness)-*` ⇒ **INFORM 8→14**, và **số tăng CHÍNH LÀ bản vá chạy đúng** (3 lane trio + ctx trước đây vô hình). ⑥ **`#53`: 7 garble / 10 first-return · 6/6 resume SẠCH · mất 0 B.** Chống-`#53` = **thiết-kế ARTIFACT**, không phải prompt (chứng bền nhất: skeleton 929 B kịp vào git giữa lượt). -→ run-trace `.claude/workflows/runs/2026-07-29-S159-bookend-open/` +⑦ **ARC-2 UI toàn-trình "Tổng quan quy trình" (5 đợt / 5 commit, mỗi đợt qua đủ build+test+reviewer+cicd; khuôn {đợt nhỏ → ship → anh nhìn prod → vẽ tiếp}):** `b5799fc` pipeline 4-GĐ (PASS 9/9) → `1a47a61` tab-strip phiếu + menu 4-GĐ + đánh số 01-07 (**PARTIAL 8/9** — mục-9 lộ revoker, xem ⑧) → `2a72695` gỡ nhánh [S92] khỏi revoker + skeleton menu GĐ2 `Khkk_*`/GĐ4 `Hdc_*` + ComingSoonPage ×2 + REGRESSION-GUARD 2-vế (PASS 9/9 restart-proof 3-chân-kiềng) → `a2bbcb9` bỏ KPI/gần-đây thay bằng list chi tiết toàn-trình + nhãn Hdc "- Bảng cứng" (7 FLAG reviewer fix; PASS 9/9 durability-2) → `ea962b1` menu 6-leaf y-chang-Duyệt-NCC ×7 loại HĐ (21 key `Ct_*_{WfView,Approved,Deleted}`) + **`GET /api/contracts/deleted`** (401-với-control-404) + bỏ hero + sidebar **"Tổng quan quy trình"** (**PASS 9/9** — menu 119→142 = +23 **khớp toán từng đồng**, durability ×3 restart; cicd cứu 1 FALSE-FAIL nhờ luật *control-âm-phải-ĐỘC-QUYỀN*). **Bộ tên 4-GĐ chốt (lời anh):** ❶ **Duyệt NCC** · ❷ **Kế hoạch ký kết HĐ** (đời trước "Đề xuất ký kết hợp đồng" — superseded) · ❸ **Duyệt hợp đồng** (*"Trình ký Hợp đồng đổi thành Duyệt hợp đồng"*) · ❹ **Hợp đồng cứng** (*"ký cứng -> Hợp đồng cứng"*). 🔴 **❹-risk CÓ Ý THỨC (verbatim anh):** *"đang phát triển → cho hiển thị hết để mọi người góp ý, còn duyệt NCC thì cứ để như cũ"* — menu HĐ public 13/13 role trong khi authz HĐ còn `[Authorize]` trần (lỗ hổng S156 treo chủ-đích *"chỗ hợp đồng cứ từ từ"*); đã cảnh báo, anh tái khẳng định. +⑧ **Sự cố revoker → gotcha #84:** grant menu bằng SQL tay bị `RevokeTemporarilyHiddenModulesAsync` (nhánh [S92], ungated @restart) lật **447/494 row** ở Run #423 → xử 2 nhịp: regrant 447 + **gỡ nhánh [S92] khỏi code** + guard test 2-vế (`StillHiddenKeys` false ∧ `ReopenedKeys` true — re-add nhánh là CI đỏ) → bền ×3 restart (38-key 494/494, control âm `Hrm/Off/Personal`=0 chứng revoker còn sống). **Luật: KHÔNG SQL tay cho menu nữa — code-first seeder.** +→ run-trace `.claude/workflows/runs/2026-07-29-S159-bookend-open/` (bookend 11 artifact) + `.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/` (arc-2: run.md + 5 cicd-verify + 3 sub-reviewer + 2 sub-designer + prod-backup/verify = 13 file) **✅ S155→S158 (2026-07-27→28 — phiên-LOGIC L7, **5 cửa-sổ**: PE nút XÓA ship prod → điều tra quy trình sau-CEO → UAT Địa điểm → spec KHKK → **S158 adap `/day` + bookend-close**):** Mig **68** · 89 bảng · **562 test** (45D+517I, đo tươi @S158) · gotcha 83 · counter **32** · bundle admin `8-QYcMOg` / user `DptYR4wL`. ① **PE nút XÓA phiếu ở màn duyệt** (Mig 68 `AddPeAllowApproverDelete`, cờ `AllowApproverDelete` **per-NGƯỜI** — owner chốt (5)): chia **2 ĐỢT** theo lệnh anh vì §F.0 chứng minh quyền xóa **không tới được phiếu đang treo** nếu thiếu lệnh sửa-quy-trình-tại-chỗ; `b1bae77` (nền) + `4464a46` (nút + menu 3 mục + màn "Đã xóa") + `f4494cf` (fix menu sáng nhầm) — **cicd PASS 6/6** lead tự đo @S156 (**D3 giao-tập-ID = 0**: 37 sống ⟂ 9 xóa) · test 532→**562** (+30) ② **A2 quy trình SAU CEO duyệt** (PDF 21 bước, phạm vi **b.7→21** — 🔴 **nguyên văn anh chốt phạm vi:** *"đã xong bước thứ 6 tức CEO duyệt rồi nhé, chưa cần làm gì hết → Bắt đầu đến Project (Ban Chỉ Huy Công trường)"*; `ring2-audit` @S158 M-1 bắt câu này **bốc hơi khỏi mọi bề mặt bền** — `grep -c 'bước thứ 6'` = 0/STATUS + 0/HANDOFF, chỉ còn dẫn xuất `b.7→21` ⇒ nhét lại verbatim cạnh dẫn xuất): `/fable-real investigator-codebase` + `/fable-clone reviewer` **4/4 lane sạch 0 chết, 35 điểm** → verdict **`LAI`** (b.13→21 TÁI DÙNG Contract V2 · b.7→12 DỰNG MỚI) — lõi SỐNG, đổ ở nhãn chi-phí + cách đặt vấn đề; 🔴 **anh ĐẶT TÊN khúc 7→12 = "đề xuất giá trị ký kết hợp đồng"** ⇒ đầu ra = **1 CON SỐ có phê duyệt** ⇒ là **PHIẾU**, không phải thư-mục đính kèm ⇒ Q2 nhánh (c) yếu hẳn, Q6 gần tự trả lời. **CHẶN Q1-Q6 chờ anh** (14 câu); 6 việc sửa bản invest chưa làm (gồm 1 claim SAI SỰ THẬT: "hardcoded fallback" → thật là `ConflictException:115-116` ⇒ HĐ từ phiếu **KẸT CỨNG `ChoDuyet`**) ③ 🔴🔴 **LỖ HỔNG AN NINH PROD phát hiện @S156** (KHÔNG liên quan tính năng mới, gotcha #82 tái phát): `ContractWorkflowService.cs:48-66` nhánh Reject chạy **TRƯỚC MỌI GUARD** + `ContractsController.cs:13` **`[Authorize]` trần DUY NHẤT phủ 22 endpoint ghi** ⇒ mọi user đăng nhập Từ-chối/Trả-lại được **bất kỳ HĐ nào kể cả `DaPhatHanh`**; verify 2 tầng độc lập, đối chứng PE controller có 3 per-action policy. **Anh chốt 07-28: "chỗ hợp đồng cứ từ từ"** ⇒ treo có chủ đích ④ **S157 UAT anh Kiệt "lấy địa chỉ lên luôn"** — chẩn **DATA-không-phải-CODE**: auto-fill `Project.Location` đã wire S59 + chạy đúng cả 4 tầng; ô trống vì **prod 57/62 dự án `Location` NULL** (đo sqlcmd; chỉ 5 dự án có địa chỉ = đúng 5 dòng Excel S55). Anh chốt **"để người dùng tự cập nhật Master data, cái nào không có thì không fill"** ⇒ KHÔNG backfill; vá = cảnh báo amber lộ lý do + trỏ chỗ bổ sung (`6250f39`, 4 file 2-app SHA-mirror). **Deploy Run #419 success 5m40s — cicd PASS 9/9 + lead tự re-curl độc lập KHỚP TỪNG BYTE** (marker 2/2 mỗi app, control âm chứng bundle cũ đã biến mất) ⑤ **`#53` cửa S157 ×1** (`cicd-monitor` tái phạm — return = mẩu transcript, cứu TRỌN 10.666B từ đĩa **nhờ ép ghi-từng-mục-trong-lúc-làm**) · `ctx-verifier` @tiep-3 **CO-CO 10 cờ** (nặng nhất: trần `_mind` dư 110B ⇒ cửa sau nén ≥2 block). → log `changelog/sessions/2026-07-28-0930-S155-S157-pe-delete-bch-invest-diadiem.md` @@ -461,7 +463,7 @@ monthly re-tier mega-line + ef-core SKILL Mig→59 + 3 vocab-fork (2026-07-01 du | Policies | **216** | 🆕 **row MỚI S121** (wave adap-6-broadcast W2 — H24 GAP-3: `governance-detectors.ps1` `Get-StatusValue` resolve canonical TỪ bảng này; **KHÔNG có row ⇒ token `policy` UNRESOLVED ⇒ nửa `policy` của GAP-3 không thể fire** ⇒ detector khai FAIL-LOUD + SKIP, KHÔNG im-lặng-giả-vờ-xanh). 🔴 **DERIVED, KHÔNG độc-lập:** `Policies = |MenuKeys.All| × |MenuKeys.Actions| = 54 × 4 = 216` — sinh runtime ở `src/Backend/SolutionErp.Api/Program.cs:82-89` (`foreach menu → foreach action → opts.AddPolicy($"{menu}.{action}")`), `Actions = ["Read","Create","Update","Delete"]` (`MenuKeys.cs:167`). ⇒ **row này BUỘC đổi CÙNG row `Menu keys`**: thêm 1 menu key ⇒ 55 × 4 = 220; sửa `Menu keys` mà quên `Policies` ⇒ detector flag derived-doc thay vì flag chính chỗ sai. Ground S121 bằng đếm mã-nguồn (`MenuKeys.All` = 54 entry, `public const string` = 54, khớp) — KHÔNG chép số từ spec. ⚠️ `.claude/skills/permission-matrix/SKILL.md` ghi **~240 = STALE** ⇒ W4 vá (🔴 chuỗi H24 §2(4) BẮT BUỘC: detector fire → cổng chứng-kiến → RỒI MỚI vá; vá trước = giết chứng-nhân sống) | | Menu keys | **54** | +1 S69 `Off_Dashboard` (landing Văn phòng số). Prev re-ground S61 (`MenuKeys.cs` const — Mig 50 gỡ 4 `Bg_*` Budget menu cũ). Prev 57 (S58) | | Tests | **562 PASS** | 45 Domain + 517 Infra · 0 fail / 0 skip · **S155 +30** (PE xóa-by-approver: `PeDeleteByApproverTests.cs` + T26/T27 — 🔴 **T27 khoá CẢ LỚP lỗi** *entity-có-cờ-mà-DTO-không-có* bằng reflection [mọi cờ `Allow*` trên entity phải có mặt trên DTO], **fault-inject xác nhận có răng**: tiêm bug ⇒ ĐỎ, khôi phục ⇒ xanh — không phải guard tuyên-bố suông; T26 giữ ĐỎ có chủ ý vì bug production thật, lead vá bằng đảo thứ tự chứ KHÔNG nới assert. Số 562 cross-check 2 nguồn độc-lập: log CI run #417 + `dotnet test` local @S156) · **S147 +4** (`ProjectCodeNormalizationTests` — Trim khi lưu + kiểm-trùng bỏ-dấu-cách; 🔴 **ô canonical này STALE 528/483I suốt S147→S148**, header `:6` và session-log S147 đều ghi 532/487I từ đầu — closeout S147 vá header mà quên ô canonical; H24 `lead-view-auditor` bắt @S148, lead verify 3-nguồn rồi vá) · **S134 +8** (`PePendingAccumulationTests` C1-C8 lũy-kế-TẠM-TÍNH: C1 ChoDuyet+winner vào delta-selected + PriorPes · C2 TuChoi/DaDuyet loại sạch · C3 Nháp list-only KHÔNG cộng tiền [D1] + TraLai vào delta-submitted [D2] · C4 peer-window CreatedAt · C5 delta âm signed · **C6 complementary-no-double-count exact-numbers [ComputeAsync bất động khi thêm peer non-terminal]** · C7 frozen→pending 0/null · C8 D4 changelog `[S134 pending-prior]` positive+contrast) · **S133 +11** (`PeBudgetFreezeTests` freeze-NS-at-DaDuyet: **T0 repro test-before RED→GREEN** [phiếu DaDuyet phải giữ số cũ sau `UpdatePeBudgetPro` — RED bắt 999tr @:184 pre-fix, phiếu đưa tới DaDuyet QUA service finalize mirror `PeApproverFinalizeTests` KHÔNG seed thẳng Phase] + **T1-T9** spec-coverage [snapshot các nhánh finalize + display-gate + 2 terminal-guard chặn sửa NS phiếu đã kết thúc (cả Admin) + backfill] + **site-5 AdminOverride** [reviewer catch — override thẳng → DaDuyet cũng chốt snapshot]) · **S118 +8** (PRO-perm scope-isolation **+4** `ProcurementMasterAccessSeedTests` [reflection no-prod-touch: upgrade-path Suppliers R+C+U + Master-Read · **scope-isolation** DeptManager-riêng vẫn revoke=false · insert-path no-Delete · idempotent] · ReportsController authz **+4** `AuthorizePolicyRegressionTests` [dashboard/export require Reports.Read · my-dashboard KHÔNG action-policy · class-level [Authorize] intact]) · **S117 +6** (PE endsBeforeCeo pointer-aware **+1** `PeFinalizeProjectionTests.ListPe_EndsBeforeCeo_ChoDuyet_PointerAware_PastFinalizeIsFalse` [ChoDuyet con-trỏ QUA cấp finalize → endsBeforeCeo=false, test-before RED→GREEN + EF-subquery translate smoke] · duyệt-theo-khoảng ProMinMax **+5** `PeApprovedPriceFinalizeTests` [happy set Min+Max · min==max boundary lock strict-`>` · thiếu-Max→Conflict not-finalized · min>max→Conflict · single-source+Max→Conflict wire-bug + regression Max=null] · harness `InvokeApply` 4→5 args fix TargetParameterCountException) · **S116 +9** (PE nhập giá âm: T1 ngân-sách-bất-biến khi quote-âm · T2 winnerQuoteTotal signed-sum · T3 submit-guard all-zero-blocked/pure-neg+net-zero-submittable · T4 CCM-net-threshold) · **S114 +9** (PE multi-NCC per hạng mục: `PeSelectWinnerClearTests` delete-invariant +4 [DeleteQuote/DeleteDetail re-derive IsWinner **test-before RED→GREEN** + guard-no-over-clear + UpsertQuote-update-branch coverage] + impl-lane +5 [per-hạng-mục-total · giaTri-single-partial · threshold-crossing · derive-invariant]) · **S113 +19** (Supplier import v2: `SupplierImportV2DedupTests` 13 [dedup MST-primary+Code-backstop T1-T7 · draft-on-import IsPublic · all-or-nothing · LayoutValid re-bake real-token · **null-Code→nháp FIXED** flipped-from-characterization] + `SupplierPublishAndListTests` 6 [publish-guard Code-required→409 · unpublish · list-filter published · DTO IsPublic]) · **S112 +18** (Supplier `SupplierExcelImportServiceTests` +10 [case-collation dedup có-RĂNG SQLite-BINARY-collation-nên-chứng-dedup-ở-SERVICE · fill-nulls-safe · all-or-nothing-abort · parser abs-cell-index/#REF!-null/header-fingerprint · Type-lạ→NCC · Status-emoji-strip] · PE `PeSubmitGuardAndBypassTests` 4-update→A1 [minOwn subordinate-only, pointer-stop] + 8-new [A1-happy · non-contiguous · EDGE-5 non-admin-throw/admin-pass/system-pass · opinion-history log/none]) · Prev 440: **S96 +6** (PE `PeApproverFinalizeTests` +2 [#6 finalize-opt-out→advance-CEO · #7 stale-noti-clear ExecuteUpdate] · `PeSuggestedPriceSetterAuthzTests` +4 [price-lock phase-guard after-submit — PRO/CCM ChoDuyet/DaDuyet→Conflict, Admin-override; +sửa SeedPeAsync default ChoDuyet→DangSoanThao spec-change]) · **S92 +3** (`AdminOnlyModulesRevokeTests` ẩn 5 nhóm menu chỉ Admin — non-Admin revoked-4-cờ / Admin untouched / Pe_* preserved) · **S91 +9** (ChangePassword self-service BE+test) · **S89 +3** (`PeDraftVisibilityTests` IDOR nháp riêng-tư) · **S88 +17** (D1 financials/CEO-notify/HoSoLink null-safe +11 · D2 create-contract multi-winner +6) · **S87 +25** (Mig 58 net +18: `PeMultiWinnerTests` sum + `PeSelectWinnerClearTests` multi-update + `PeSubmitGuardAndBypass` budget=0 + `PeApproverFinalizeTests` 5 auto-finalize [từng 7, −2 khi opt-in→auto rework] + `PeCcmThresholdFinalize`/`PeWorkItemBudget` collateral; Mig 59 +7 `PeCcmBudgetPeriodSetterAuthzTests` role-gate Admin|CCM/budget=0/null-clear) · **S86 +3** (`PeApproverNotifyExcludesDrafterTests` — notify "cần duyệt" loại NGƯỜI TẠO phiếu: drafter-excluded · co-approver-vẫn-nhận · drafter-vẫn-nhận-chuông-kết-quả) · **S85 +18** (PE CV PRO C5 hủy/đổi NCC winner +10 · urgent drafter-self-unset +5 · workflow-preserve bug-class S42 +3 `PeUpdateDraftWorkflowPreserveTests`) · **S83 +2** (PE require-workflow: `PeWorkItemGuardTests` ApprovalWorkflowId `NotEmpty` ×2 validator + submit-guard rewrite test 7/13 `PeSubmitGuardAndBypass` V1-submit-deprecated, no-count-change) · **S77 +10** (+7 `PeSuggestedPriceSetterAuthzTests` ghi chú PRO/CCM Mig 57 absolute-set/role-gate/null-clear/max-1000 · +3 `PeUrgentToggleAuthzTests` rewrite cờ-gấp **BẤT ĐỐI XỨNG** SET=function role / UNSET=function+DeptManager, plain-PRO-unset Forbidden) · **S76 +5** (`PeWorkItemBudgetTests` PRO split: set ProInitial+ProAdjust gồm âm · validator ProInitial≥0/ProAdjust-cho-âm · full=proFull khi CCM empty · full=CCM khi CCM present) · **S74 +5** (`PeWorkItemBudgetTests` §4b CcmNote: set CCM/Admin · null-clear absolute-set · non-priv Forbidden+no-mutate · all-3-persist) · **S73 +28** (PE opt-in finalize spec 6→11 + 10 giá-chốt `PeApprovedPriceFinalizeTests` + 13 setter-authz `PeSuggestedPriceSetterAuthzTests`) · **S69 +20** (Office-golive OfficeModulePermissionSeed 6 + PE PeCcmThresholdFinalize 5 + PeUrgentToggleAuthz 9) · **S67 +23 HRM test-after** (DepartmentTreeTests 8 cycle-guard/rollup + PeHoSoLinkTests 9 absolute-set + HrmProfilePermissionSeedTests 6 reflection-seed) → 286 · S61 +22 `PeWorkItemBudgetTests` −14 `BudgetPolicyTests` −1 → 263 · S60 +14 `PeSubmitGuardAndBypassTests` +2 spec → 256 (Domain 58→45 do drop Budget module tests) | -| Gotchas | **83** | **+S133 #81-EXT** (instance 2 indirect-assignment, KHÔNG số mới: snapshot-NS-at-DaDuyet hook đặt ở finalize choke-point NHƯNG 2 site gán Phase TRỰC TIẾP bypass — admin-override `PurchaseEvaluationWorkflowService.cs:308` `= targetPhase` + seeder `DbInitializer:1323` `= current` → phiếu vào DaDuyet qua 2 đường này KHÔNG snapshot [frozen=0, display rơi về live = đúng bug đang vá]; reviewer adversarial bắt pre-commit, em-main + 3 invocation implement đều sót — cùng bài enumeration-writer #81; meta: field-đích có hook/derive/snapshot ⇒ grep MỌI assignment-site kể cả override/seeder). +1 S126 (**#83** số AGGREGATE session-cumulative tự-lão-hoá — audit COUNTS đổi bởi CHÍNH spawn review sau đó [2/2/0→4/4/0]; outward mời-reproduce = bảng per-lane theo run-id, KHÔNG số tổng; reviewer-gate bắt, em-main-solo sót). +1 S118 (**#82** menu-flag grant ≠ quyền API thật: display-layer [Permission `CanRead`→`GetMyMenuTree` FE-menu] ⟂ API-authz-layer [controller `[Authorize(Policy=)]`] = 2 tầng ĐỘC-LẬP; grant `Suppliers` R+C+U cho PRO nhưng `PUT/DELETE /suppliers` gate `[Authorize(Roles="Admin,CatalogManager")]` → PRO vẫn 403 sửa/xóa NCC [chỉ Publish/Import theo `Suppliers.Update` là ăn]; ngược lại `ReportsController` `[Authorize]` trần → mọi authed-user đọc `dashboard` tài-chính-HĐ ngược S92; fix gate `[Authorize(Policy="Reports.Read")]` per-method + grep controller authz TRƯỚC khi tin hiệu-lực grant; reviewer adversarial bắt, em-main-solo tin menu-flag=quyền thì sót; liên-quan #44). +1 S114 (**#81** derived-invariant re-derive ở write/select NHƯNG SÓT DELETE writer [DeleteQuote/DeleteDetail cascade] → xóa quote-selected cuối của NCC → `Supplier.IsWinner` kẹt stale [Any(IsSelected)=false] → `CreateContract Where(IsWinner)` gom NCC phantom → **HĐ giaTri=0**; fix helper `PeWinnerInvariant.ReSyncAfterQuoteRemovalAsync` gọi sau SaveChanges 2 handler; **enumeration-writer-trong-spec KHÔNG đáng tin** → grep MỌI `.Remove(`/`.Add(`/`=field` chạm entity chứa field-nguồn; chỉ **verify-adversarial-refute** bắt [invest/review/implement đều sót]; cardinality S87/S88 lên tầng mutation-path). +1 S113 (**#80** null-forgiving `!` che NRE trên external-parsed data: `SupplierExcelImportService.NewSupplier` gán `Code = r.Code!.Trim()` → NullReferenceException khi parser trả `null` cho ô cột-4 rỗng [ĐÚNG path R4 "thiếu Mã NCC → nháp"] → confirm nổ 500 CẢ batch dù preview classify New-draft KHÔNG lỗi; sibling `IsPublic=!IsNullOrWhiteSpace(row.Code)` null-safe nhưng NewSupplier thì KHÔNG; empty-string `""` chạy OK nhưng FE round-trip blank→JSON `null` → nổ. Fix `(r.Code ?? "").Trim()`. **Build 0/0 KHÔNG bắt** [`!` tắt nullable-warning]; chỉ test-before-critical bắt. Lesson: `!` null-forgiving trên dữ-liệu-parse-ngoài = mìn, dùng `?? default`). +1 S97 (**#79** backfill soi NHẦM bảng — transition-marker "[Duyệt KẾT THÚC]" nằm ở `PurchaseEvaluationChangelogs.ContextNote` KHÔNG phải `PurchaseEvaluationApprovals` → Mig 60 backfill match 0, phiếu finalize-CCM giữ flag=0 hiện sai "Đã được CEO duyệt"; fix Mig 61 query đúng bảng. PE 2 bảng lịch-sử tách vai [Approvals=ai-duyệt record :745 · Changelogs=chuyển-phase+marker LogTransition :1073]; verify marker-count prod trước khi tin backfill). +1 S97 (**#78** display-flag suy CONFIG thay RUNTIME → nói dối khi instance lệch config: `endsBeforeCeo` từ "workflow CÓ cấp finalize" thay "phiếu NÀY finalize" → phiếu lên CEO báo sai "không qua CEO"; nặng sau S97 default-flip opt-in; fix field runtime `EndedByLevelFinalize` Mig 60. Flag = "instance ĐÃ làm-gì" KHÔNG "config CÓ THỂ"). +1 S96 (**#77** SPA deploy bundle cache-lag: team thấy UI CŨ dù đã deploy + Ctrl+F5 — index.html no-cache ĐÚNG-chuẩn + JS hash-immutable nhưng browser giữ tab-SPA-mở/cache-local → verify bundle prod **BYTE-LEVEL** (curl + grep string-fix trong `/assets/index-.js`) phân-biệt cache-vs-deploy; **incognito = golden-test**; no-service-worker nên clear-site-data đủ). +2 S91 (**#76** deploy render config từ `.example` KHÔNG phải file-gitignored → prod thiếu setting tới khi điền tay · **#75** seed ungated per-code RESURRECT data đã-wipe mỗi restart → gate sau env-flag `DemoSeed:Disabled` + verify-by-restart-thật). +1 S90 (**#74** Chrome-MCP screenshot kẹt SPA-SignalR `document_idle` → PowerShell `CopyFromScreen` + Win32 lọc-process-`chrome.exe`). +2 S85 (**#72** lệch giờ +7h — DateTime lưu UTC nhưng serialize thiếu 'Z' → FE `new Date()`=local → `UtcDateTimeJsonConverter` global ép UTC-with-Z · **#73** UpdateDraft absolute-set CLEAR field SÓT khỏi pattern null-safe = bug-class S42 → guard `if (request.X is not null)`). +1 S78 **#71** (thêm enum value vào entity DÙNG-CHUNG → pollute UI/guard phân-loại theo PROXY-predicate `supplierId===null` thay vì enum tường minh; file-khi-duyệt purpose=5 lẫn "Bảng so sánh" + false-pass submit-guard → grep mọi field-proxy predicate loại value mới + build-verify TỪNG app; em-main grep no-leak bắt trước deploy). +1 S76 **#70** (FE absolute-set echo field anh-em từ server-snapshot + `invalidate()` fire-and-forget → cửa-sổ stale-echo mất-dữ-liệu khi lưu 2 ô liên-tiếp; guard `useIsFetching` gate nút Lưu tới khi refetch land; reviewer workflow bắt, impl self-review sót). +1 S72 **#69** FE bundle-hash non-deterministic + `deploy.yml` rebuild-FE-unconditional → bundle rotate kể cả commit governance (SPA-fallback-200 trap; cicd Run #312). +2 S69: **#67** Tailwind v4 accent palette thiếu stop (teal/violet/amberx/greenx chỉ 50/100/500/600/700; dùng -300 → teal/violet rơi DEFAULT Tailwind sai-hệ, amberx/greenx drop hẳn — build PASS, phải soi dist CSS) · **#68** IDE TS diagnostic giữa background-agent/workflow = snapshot dở-dang (TS server bắn mỗi save), chỉ tin build SẠCH sau-cùng (2× session này: re-skin + PE-FE đều false-alarm). Prev +1 S68 **#66** Tailwind v4 rule element thô `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng utility `text-white` → heading render đen; fix ĐIỂM `text-white!` (important, grep dist confirm), KHÔNG move `@layer` (load-bearing ~30+ heading toàn app). Prev +1 S65 **#65** build csproj con (vd `SolutionErp.Api.csproj`) ≠ `dotnet build SolutionErp.slnx` (gồm tests) → miss test-compile khi đổi chữ ký record command (CreateDepartmentCommand +ParentId) → CI CS7036 FAIL-gated Run #291 (deploy chặn, prod nguyên — test-gate làm đúng việc). Fix: build full slnx trước push BE signature-change. Prev +2 S61: **#63** EF scaffold tự sinh `RenameColumn` SAI-semantics khi drop+add cùng type (test xanh không bắt — SQLite EnsureCreated không replay migration) · **#64** `dotnet ef database update` áp Design-DB 0-rows ≠ Dev-DB → data-migrate `Sql()` chạy thật lần đầu trên prod. Prev +2 S59 (#61 sqlcmd `-f 65001` · #62 rename natural-key UPDATE trước deploy) | +| Gotchas | **84** | **+S159 #84** (revoker-2-chiều: sửa data tay trên prod bị code-path ungated @restart ĐẢO NGƯỢC im lặng — grant menu SQL tay bị revoker [S92] lật 447/494 row; fix = code-first seeder + gỡ nhánh + guard 2-vế + khuôn 3-chân-kiềng; liên-quan #75/#76 chiều seeder). **+S133 #81-EXT** (instance 2 indirect-assignment, KHÔNG số mới: snapshot-NS-at-DaDuyet hook đặt ở finalize choke-point NHƯNG 2 site gán Phase TRỰC TIẾP bypass — admin-override `PurchaseEvaluationWorkflowService.cs:308` `= targetPhase` + seeder `DbInitializer:1323` `= current` → phiếu vào DaDuyet qua 2 đường này KHÔNG snapshot [frozen=0, display rơi về live = đúng bug đang vá]; reviewer adversarial bắt pre-commit, em-main + 3 invocation implement đều sót — cùng bài enumeration-writer #81; meta: field-đích có hook/derive/snapshot ⇒ grep MỌI assignment-site kể cả override/seeder). +1 S126 (**#83** số AGGREGATE session-cumulative tự-lão-hoá — audit COUNTS đổi bởi CHÍNH spawn review sau đó [2/2/0→4/4/0]; outward mời-reproduce = bảng per-lane theo run-id, KHÔNG số tổng; reviewer-gate bắt, em-main-solo sót). +1 S118 (**#82** menu-flag grant ≠ quyền API thật: display-layer [Permission `CanRead`→`GetMyMenuTree` FE-menu] ⟂ API-authz-layer [controller `[Authorize(Policy=)]`] = 2 tầng ĐỘC-LẬP; grant `Suppliers` R+C+U cho PRO nhưng `PUT/DELETE /suppliers` gate `[Authorize(Roles="Admin,CatalogManager")]` → PRO vẫn 403 sửa/xóa NCC [chỉ Publish/Import theo `Suppliers.Update` là ăn]; ngược lại `ReportsController` `[Authorize]` trần → mọi authed-user đọc `dashboard` tài-chính-HĐ ngược S92; fix gate `[Authorize(Policy="Reports.Read")]` per-method + grep controller authz TRƯỚC khi tin hiệu-lực grant; reviewer adversarial bắt, em-main-solo tin menu-flag=quyền thì sót; liên-quan #44). +1 S114 (**#81** derived-invariant re-derive ở write/select NHƯNG SÓT DELETE writer [DeleteQuote/DeleteDetail cascade] → xóa quote-selected cuối của NCC → `Supplier.IsWinner` kẹt stale [Any(IsSelected)=false] → `CreateContract Where(IsWinner)` gom NCC phantom → **HĐ giaTri=0**; fix helper `PeWinnerInvariant.ReSyncAfterQuoteRemovalAsync` gọi sau SaveChanges 2 handler; **enumeration-writer-trong-spec KHÔNG đáng tin** → grep MỌI `.Remove(`/`.Add(`/`=field` chạm entity chứa field-nguồn; chỉ **verify-adversarial-refute** bắt [invest/review/implement đều sót]; cardinality S87/S88 lên tầng mutation-path). +1 S113 (**#80** null-forgiving `!` che NRE trên external-parsed data: `SupplierExcelImportService.NewSupplier` gán `Code = r.Code!.Trim()` → NullReferenceException khi parser trả `null` cho ô cột-4 rỗng [ĐÚNG path R4 "thiếu Mã NCC → nháp"] → confirm nổ 500 CẢ batch dù preview classify New-draft KHÔNG lỗi; sibling `IsPublic=!IsNullOrWhiteSpace(row.Code)` null-safe nhưng NewSupplier thì KHÔNG; empty-string `""` chạy OK nhưng FE round-trip blank→JSON `null` → nổ. Fix `(r.Code ?? "").Trim()`. **Build 0/0 KHÔNG bắt** [`!` tắt nullable-warning]; chỉ test-before-critical bắt. Lesson: `!` null-forgiving trên dữ-liệu-parse-ngoài = mìn, dùng `?? default`). +1 S97 (**#79** backfill soi NHẦM bảng — transition-marker "[Duyệt KẾT THÚC]" nằm ở `PurchaseEvaluationChangelogs.ContextNote` KHÔNG phải `PurchaseEvaluationApprovals` → Mig 60 backfill match 0, phiếu finalize-CCM giữ flag=0 hiện sai "Đã được CEO duyệt"; fix Mig 61 query đúng bảng. PE 2 bảng lịch-sử tách vai [Approvals=ai-duyệt record :745 · Changelogs=chuyển-phase+marker LogTransition :1073]; verify marker-count prod trước khi tin backfill). +1 S97 (**#78** display-flag suy CONFIG thay RUNTIME → nói dối khi instance lệch config: `endsBeforeCeo` từ "workflow CÓ cấp finalize" thay "phiếu NÀY finalize" → phiếu lên CEO báo sai "không qua CEO"; nặng sau S97 default-flip opt-in; fix field runtime `EndedByLevelFinalize` Mig 60. Flag = "instance ĐÃ làm-gì" KHÔNG "config CÓ THỂ"). +1 S96 (**#77** SPA deploy bundle cache-lag: team thấy UI CŨ dù đã deploy + Ctrl+F5 — index.html no-cache ĐÚNG-chuẩn + JS hash-immutable nhưng browser giữ tab-SPA-mở/cache-local → verify bundle prod **BYTE-LEVEL** (curl + grep string-fix trong `/assets/index-.js`) phân-biệt cache-vs-deploy; **incognito = golden-test**; no-service-worker nên clear-site-data đủ). +2 S91 (**#76** deploy render config từ `.example` KHÔNG phải file-gitignored → prod thiếu setting tới khi điền tay · **#75** seed ungated per-code RESURRECT data đã-wipe mỗi restart → gate sau env-flag `DemoSeed:Disabled` + verify-by-restart-thật). +1 S90 (**#74** Chrome-MCP screenshot kẹt SPA-SignalR `document_idle` → PowerShell `CopyFromScreen` + Win32 lọc-process-`chrome.exe`). +2 S85 (**#72** lệch giờ +7h — DateTime lưu UTC nhưng serialize thiếu 'Z' → FE `new Date()`=local → `UtcDateTimeJsonConverter` global ép UTC-with-Z · **#73** UpdateDraft absolute-set CLEAR field SÓT khỏi pattern null-safe = bug-class S42 → guard `if (request.X is not null)`). +1 S78 **#71** (thêm enum value vào entity DÙNG-CHUNG → pollute UI/guard phân-loại theo PROXY-predicate `supplierId===null` thay vì enum tường minh; file-khi-duyệt purpose=5 lẫn "Bảng so sánh" + false-pass submit-guard → grep mọi field-proxy predicate loại value mới + build-verify TỪNG app; em-main grep no-leak bắt trước deploy). +1 S76 **#70** (FE absolute-set echo field anh-em từ server-snapshot + `invalidate()` fire-and-forget → cửa-sổ stale-echo mất-dữ-liệu khi lưu 2 ô liên-tiếp; guard `useIsFetching` gate nút Lưu tới khi refetch land; reviewer workflow bắt, impl self-review sót). +1 S72 **#69** FE bundle-hash non-deterministic + `deploy.yml` rebuild-FE-unconditional → bundle rotate kể cả commit governance (SPA-fallback-200 trap; cicd Run #312). +2 S69: **#67** Tailwind v4 accent palette thiếu stop (teal/violet/amberx/greenx chỉ 50/100/500/600/700; dùng -300 → teal/violet rơi DEFAULT Tailwind sai-hệ, amberx/greenx drop hẳn — build PASS, phải soi dist CSS) · **#68** IDE TS diagnostic giữa background-agent/workflow = snapshot dở-dang (TS server bắn mỗi save), chỉ tin build SẠCH sau-cùng (2× session này: re-skin + PE-FE đều false-alarm). Prev +1 S68 **#66** Tailwind v4 rule element thô `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng utility `text-white` → heading render đen; fix ĐIỂM `text-white!` (important, grep dist confirm), KHÔNG move `@layer` (load-bearing ~30+ heading toàn app). Prev +1 S65 **#65** build csproj con (vd `SolutionErp.Api.csproj`) ≠ `dotnet build SolutionErp.slnx` (gồm tests) → miss test-compile khi đổi chữ ký record command (CreateDepartmentCommand +ParentId) → CI CS7036 FAIL-gated Run #291 (deploy chặn, prod nguyên — test-gate làm đúng việc). Fix: build full slnx trước push BE signature-change. Prev +2 S61: **#63** EF scaffold tự sinh `RenameColumn` SAI-semantics khi drop+add cùng type (test xanh không bắt — SQLite EnsureCreated không replay migration) · **#64** `dotnet ef database update` áp Design-DB 0-rows ≠ Dev-DB → data-migrate `Sql()` chạy thật lần đầu trên prod. Prev +2 S59 (#61 sqlcmd `-f 65001` · #62 rename natural-key UPDATE trước deploy) | | User memory | **31** | +S84 `feedback_derived_flush_execution` (derived→canonical flush = em-main execution KHÔNG gate user-confirm; monitor INFORM-only ≠ cần-anh-duyệt; chỉ ĐỔI-con-số/policy = quyền anh). +S79 `feedback_canonical_spec_over_broadcast` (adap pull canonical-command/§P đừng phỏng-theo broadcast + report-before-stamp dogfood + residual own-diary OK). +S75 `feedback_harness11_engine` (engine governance tự-bảo-trì + gotcha #30-via-Edit + multi-workflow-verify + git-add-specific lesson). re-ground S71 (H1 disk-count: 25 `feedback_*` + 3 `project_*`; STATUS "21" stale từ S64). +S71 `feedback_harness10_run_trace` (run-trace + 3 lesson). Prev +1 S64 `feedback_harness7_outward_writing_quality`; re-grounded S54 base 19 | | Skills | 6 | 3 domain + 3 ops | | Sub-agents | **23** | **+S153 bộ-ba vòng Ctx** (adopt thư `0df10df4` — 🔄 **OWNER-VETO @S153 hub-form 3-vai**: bản đầu (38)(a) 1-vai OWNER-DELEGATED→LEAD-DECIDED, **anh bác cùng ngày** chốt trực tiếp *"Build đủ 3 vai như hub"* qua AskUser = owner chốt THẬT cho quyết này; 🔄 **RENAME cùng phiên theo lệnh anh** *"đặt tên giống hub và sisters để dễ audit"* — tên khai-sinh `ctx-pause-check`/`ctx-reload` → **hub-form `ctx-curator`/`ctx-verifier`** [đo đĩa 3 nhà: hub = curator/verifier/audit · VIPIX = check/reload/chain · hub≠sister ⇒ SE theo HUB-form, tiền lệ rename S149 lead-*]): **`ctx-curator`** vai-1 KIỂM nháp @mỗi-`/pause` (carve-out `pause.md §1` mirror hub O-1(a)) · **`ctx-verifier`** vai-2 ĐỐI-CHIẾU+NẠP-LẠI @mỗi-`/tiep` (dòng `LEAD-PHAI-NHAC-LAI:` = bằng-chứng nội-dung) · **`ctx-audit`** vai-3 SOI-CHUỖI @2-bookend (kiểm-vết vai-1/2, hồi-tố = fallback phiên 1-cửa). Nấc: ctx-audit `file-land + registry-surfaced @S153` cho CẢ 3 vai ctx [🔄 vá @S153 FLAG-6: bản đầu chỉ cấp nấc này cho `ctx-audit` trong khi `hmw.js:42` + writeGuard + README `:27`/`:199`/`:200` chứng 2 vai mới ĐẠT CÙNG nấc — khai THIẾU vẫn là lệch] — spawn-probe ALIVE cả 3 = phiên sau restart T9; hmw VALID_ROLES 20→**23** + writeGuard :228/:235; ⚠️ **roster 23 > `hmw_width.cap` 20** ⇒ full-roster-sweep LOUD-skip 3 lane cuối — số cap = quyền anh, O-7 (câu (40) đang treo). **🔄 RENAME @S149 (anh ratify "OK đồng ý"): 5 vai đổi tên đồng-bộ sister — `tooling-harvest-audit`→`ring1-audit` · `h24-audit`→`ring2-audit` · `sleep-audit`→`ring4-audit` · `lead-view-auditor`→`lead-stale-auditor` · `lead-omission-auditor`→`lead-gap-auditor` (ring* = 2 sister TRÙNG tuyệt đối; lead-* = hub-form, VIPIX-form là prefix). Nấc **NÂNG @cùng-phiên: `registry-listed-in-session`** — harness list 5 tên MỚI + gỡ 5 tên CŨ NGAY TRONG PHIÊN S149 (không restart), **TRÁI phép đo S120/S121 no-hot-reload** (môi trường có thể đã đổi — đây là data-point ĐO ĐƯỢC, không suy). Spawn-probe vẫn CẦN để chứng instantiate (list ≠ spawn được — đúng 0.6b). Tên cũ trong narrative/runs/history = vết lịch-sử, CỐ Ý giữ.** **+S145 🔬 `ring1-audit` (18th sub — round-KIỂM vòng tooling/harvest, C4/C4b adap dot-11 khoản ① `harness-dong-du-vong:51`, owner-decision [2] TÁCH mỗi-vòng-1-con-KHÔNG-gộp). Vai-KIỂM ĐỘC-LẬP đọc OUTPUT H1 `tooling-auditor` (4-mặt freshness) + H2 `harvest-curator` (5-trục integrity), **KHÔNG re-chạy đo**: verdict per-claim ĐẠT/TRƯỢT + falsify ≥2 + **tự tái-dựng ≥1 số CÓ-THỂ-SAI** (đếm `.claude/agents/*.md` vs roster-count H1 · N-harvested/M-spawned) + **thách-CLEAN** (H1 PASS/H2 GATE-0 → mở 1 skill "fresh"+1 sub "harvested" xem thật). 🔴 no-self-exempt ≠ H1/H2 (m-3 S139). **AUTO fire-after-measure @session-end §L.b(g-bis)** — owner-chốt S145 KHÔNG consent-gate (KHÁC trio/H24), fail-safe NO-OP nếu H1/H2 không chạy phiên đó (CẤM ĐẠT-ảo); tuần-tự C4b (invocation SAU con-đo, mtime chứng). Propose-only, backstop = git-diff commit-gate (KHÔNG dựa thiếu-tool `[carry:tools-whitelist-no-teeth]`). `model: opus`+`effort: max`+`memory: project`+`maxTurns: 16`. **Vai #1/3 round-KIỂM** — `ring2-audit` (vòng soi-lead) + `ring4-audit` (vòng nén-ngủ) land dần incremental (§6 broadcast báo-nấc-per-vòng, owner S145). 🔴 **Nấc = executed-file / verified-pending-restart** — registry Agent-tool KHÔNG hot-reload (`agents/README` §Memory discipline — anchor không-số-dòng, vá cite-dòng-trống @S151 per H1 F-3), spawn-probe alive cần **restart CLI**; run-thử-thật @session-end phiên sau. Design-doc: `runs/2026-07-22-S144-adap-dot-11/C4-design-3-vai-kiem.md`.** **+S145 🔬 `ring2-audit` (19th sub — round-KIỂM vòng soi-lead H24, vai #2/3 C4/C4b). Đọc OUTPUT `lead-stale-auditor` + `lead-gap-auditor` (🔴 KIỂM 2 con-đo H24, **KHÔNG soi lead trực-tiếp**) → verdict per-FLAG + tự tái-dựng ≥1 số (flag-count · mở 1 FLAG đối-chứng source · `class_repeat` `.session-counter.json`) + **thách-CLEAN** (H24 báo ít/0 FLAG ⇒ tự soi 1 surface tìm FLAG sót — CLEAN "lead ổn" là ca nguy nhất, khớp H24 §2(1) phép-thử-nhanh). Verify vai H24 KHÔNG tự chế class ngoài enum ĐÓNG `flag_classes`. no-self-exempt ≠ lead-stale/lead-gap (m-3; tên mới @rename S149). AUTO wired `session-end §L.b(j)(ii-bis)` sau cặp H24; fail-safe NO-OP nếu H24 không chạy (nhịp/consent). `maxTurns: 16`.** **+S145 🔬 `ring4-audit` (20th sub — round-KIỂM vòng nén-ngủ, vai #3/3 C4/C4b). Đọc OUTPUT `/sleep-recovery-memory-l2` (`.gist.md` mới + Fidelity verdict + claim giảm-byte) → verdict per-claim + **tự ĐO LẠI byte** archive gốc vs gist (đối-chứng claim) + **thách-CLEAN** (Fidelity 5P/0F ⇒ mở 1 gist đối-chứng `.md` gốc xem có giữ 4-field load-bearing hay nén quá tay) + kiểm bất-biến gist-ADDITIVE (gốc byte-identical). no-self-exempt độc-lập lượt nén (m-3). AUTO wired `sleep-recovery-memory-l2.md Phase 4.5` sau nén; fail-safe NO-OP nếu 0 gist tươi. `maxTurns: 16`.** **+S141/S142 🧪🧭🧮 `harness-eval` + `harness-refine` + `harness-audit` (15th–17th sub — bộ-ba đồng-kiểm HỆ MEMORY, adopt AI_INFRA khuôn 5-câu `58e28bae` khối B, wave adap đợt-9/10; land S141 persona+seed+`hmw.js` VALID_ROLES 14→17, wiring nghi-thức S142 vòng-2 sau khi vòng-1 chết giữa chừng). Read-only INFORM-only propose-only, frontmatter **không khai Write/Edit** — 🔴 nhưng đo S143: **runtime VẪN cấp** (append cuối tool-list, 9/9 vai read-only; nhân-chứng `reviewer` đã Write+Edit thật) ⇒ đây là **tuyên-bố ý-định**, KHÔNG phải chặn-bằng-thiếu-tool; containment thật = single-writer + git-diff commit-gate · `model: opus`+`effort: max`+`memory: project`+`maxTurns: 18`. Trục = **CHÍNH HỆ MEMORY**, chạy **TUẦN TỰ** eval→refine→audit (🔴 CẤM `parallel()` — con KIỂM chạy song song sẽ chấm bản CŨ ⇒ verdict vô-nghĩa): `harness-eval` = con **ĐO** (chỉ trả số nguyên-văn từ instrument, CẤM số-từ-trí-nhớ) ⟂ `harness-refine` = con **ĐỀ-XUẤT** (4 lớp reinject/promote/archive/distill, bắt buộc có mục "đã cân-nhắc→BÁC") ⟂ `harness-audit` = con **KIỂM** (verdict ĐẠT/TRƯỢT per-claim + re-chạy ≥2 số load-bearing; PIN run-folder đích-danh, CẤM tự tìm "run mới nhất"). 🔴 **KHÔNG gộp** với H1 tooling-freshness / H2 harvest-integrity / H24 lead-surface / reviewer diff-code — 4 trục khác nhau. Nghi-thức 2-đầu-phiên **AUTO 1 vòng/phiên GIỮA 2 bookend** (`session-start §2.1.9(a)` canonical + `session-end §L.b(k)(i)` trỏ): owner chốt @S151 — em-main IN 1 dòng trạng-thái rồi CHẠY, KHÔNG chờ gật [🔄 vá @S153 FLAG-4 HIGH: ô này còn khai "consent-gated + anh gật mới chạy" sau khi owner (32) đã lật AUTO, và ngược chính `:466` cùng file; trio đã chạy THẬT 3 vòng S151/S152/S153]; skip → ghi vết WAL `trio: skipped S` (vết-2-lớp, chuỗi skip nhìn thấy được). Budget seed đo TƯƠI `measure-agent-memory.ps1`: eval 1547B · refine 1616B · audit 1513B (l2_*=0 = SEED-STATE đúng, chưa chạy lần nào). 🔸 **Nấc trung-thực = executed-file / verified-pending-restart** — 3 vai CHƯA spawn-probe lần nào (cần restart CLI + anh consent; KHÔNG được đọc thành verified-runtime).** **+S121 👁 `lead-stale-auditor` + `lead-gap-auditor` (13th+14th sub — H24 lead-self-audit, adopt broadcast `2026-07-14-Governance-harness-24`, anh chốt S119 `owner-decisions-15-07-2026`, land S121 wave-W2 `hmw.js` VALID_ROLES 12→14 CÙNG COMMIT roster+STATUS [R3-M2: lệch landing ⇒ C2/B3 flag mọi derived ghi "14" là stale-vs-12 ⇒ detector BÃO trên chính thay đổi của H24]). 2 monitor INFORM-only propose-only, cookie-cutter frontmatter monitor sẵn (`model: inherit` lúc-land [S124 re-pin → `opus`+`effort:max` cùng toàn roster] · `memory: project` · `maxTurns: 18` · 8 tool read-only, **NO Write/Edit**). Trục: `lead-stale-auditor` = **view LỆCH source** (5 class `view-*`) ⟂ `lead-gap-auditor` = **cái BỊ THIẾU** (6 class `gap-*` — +`gap-incident-unrecorded` @S143 owner-duyệt) — 🔴 **KHÔNG gộp** vào tooling-auditor(H1 tooling-freshness)/harvest-curator(H2 harvest-integrity): H24 §2(1) *"gộp là mất tiêu-điểm; cái ta cần là cặp mắt CHỈ dành cho lead"*. Class-flag = **enum ĐÓNG** `lead_self_audit.flag_classes` ở `.claude/agent-memory/memory-budget.json` (11 class = 5+6, vai CẤM tự chế — mở enum là quyền owner). Nhịp = `h24_cadence` cùng file (single-source H24 §2(3) — doc TRỎ key, KHÔNG chép số ⇒ 🔄 **đã GỠ digits `{6/15/3}` @S153** theo `ring2-audit` R-3: chép số ngay cạnh câu cấm-chép-số là **B1-copy** [số vẫn KHỚP canonical nên KHÔNG phải stale — F-6 chống vu-oan]; đọc số sống ở `memory-budget.json → h24_cadence`); 🔄 **HÌNH B @S149**: cặp soi-lead spawn **VÔ-ĐIỀU-KIỆN 2 bookend mỗi phiên** — `light_every` hạ thành **stats-only** (KHÔNG còn cổng bắn), `deep_every` GIỮ cổng nhịp [vá @S153 FLAG-5: ô này còn mô-tả bắn thuần-cadence; đối-chứng hành-vi = cặp chạy @counter 27 với light 1/6 CHƯA tới hạn]; counter `.claude/governance/.session-counter.json` (content-based `last_ticked_head`, KHÔNG blind-increment — hook `wal-flush.ps1` auto-commit `agent-memory/` mỗi turn sẽ làm hỏng đếm mù; đặt ngoài **4 path** hook CÓ CHỦ-ĐÍCH — *hook nới từ 3 lên 4 @S146 khi thêm `.claude/sessions/`; mệnh-đề "governance/ nằm ngoài" đã RE-VERIFY sau khi nới, vẫn đúng*). ✅ **verified-runtime S122** (spawn-probe toàn-roster-KHI-ĐÓ SỐNG post-restart — **N=14 tại thời-điểm S122**, chứng runtime, §Recently-Done S122; 🔸 +3 trio S141 CHƯA nằm trong phép đo này) **+ chạy THẬT S124** (dogfood 2-vai đầu-tiên, owner-triggered @counter 3) **+ S137** (light-audit consent OVERDUE 8/6 → 2 FLAG view-stale-status + 1 FLAG gap-decision-sunk). 🔸 Residual THẬT giữ: đường `hmw.js→agentType` cho 2 vai H24 chưa exercise (Agent-tool path đã chứng; workflow-path chưa) [S137 view-audit lật ⚠️→✅ khớp source, giữ residual]. 🔸 Từ-vựng "view"/"omission" chọn có chủ-đích tránh va-chạm: `governance-detectors.ps1:15` đã sở-hữu `derived-staleness`, và "GAP" quá-tải (`session-end` build-gap · `memory-selfimprove-audit.ps1` CRITERIA+GAP).** **+S107 📄 `office-document` (12th sub — Office document WRITE specialist: docx·xlsx·pptx·pdf + form-engine; floor OD1–OD10; VALID_ROLES hmw.js 9→10; anh giao trực tiếp S107 "Sub chính" Office; ✅ **verified-runtime S107 CÙNG PHIÊN** — registry hot-reload agent MỚI giữa phiên [S27 lesson thu hẹp còn EDIT-agent/command] + spawn-test PASS OD1/OD4/OD5 template thật, model self-report `claude-fable-5` [data-point #5 flip-8]; finding: 2 template `wwwroot/templates` 0-placeholder mẫu-blank).** **worker-tier-pin (owner-decision S124 2026-07-15 — thay all-inherit H8 S66, trước nữa two-tier H4; sub TOÀN-ROSTER pin cứng KHÔNG theo lead; H23-precedence ĐO S126: spawn-param THẮNG hard-pin ⇒ `/fable-real` SỐNG). Lead = **DEFAULT Opus 5 MAX** (thư `9c909007` @S149 (re-stamp 07-25 G-024a; pre `59ce1d0f`); **anh chốt ô canonical hiển-thị DEFAULT-fleet @S151** — *"cần gọi Fable tao chọn đầu mỗi phiên hoặc gọi bằng command fable-real"* ⇒ Fable = anh `/model` đầu phiên HOẶC per-invocation `/fable-real`; runtime thật = BƯỚC 0.6 probe mỗi phiên, KHÔNG ghi sổ mỗi flip — hết class stale-2-flip ring1 bắt @S150). 🧊 Lineage owner-choice/flip-chain FROZEN tới flip-8 (flip-9 S119 Opus-4.8 owner-choice + các lượt /model sau = per-session không enumerate, anti-churn S106):** em main Fable 5 (1M) Max (✅ **Fable RESTORED S98 2026-07-02** — lead self-report `claude-fable-5` + settings `claude-fable-5[1m]`; fallback-Opus H5 S62→S97 kết thúc, H5.6 hoàn tất) ⚠️ **S101 2026-07-03: runtime lead = Opus 4.8** (lead + 2 monitor + WF2 reviewer inherit đều self-report `claude-opus-4-8`; settings vẫn pin `claude-fable-5[1m]` → **Fable unavailable phiên này → H5-fallback tự-kích, revert-free, KHÔNG sửa frontmatter**; "Fable RESTORED S98" = point-in-time KHÔNG phải steady-state — inherit-chain resolve theo availability runtime; ✅ **S102 2026-07-06: Fable VỀ LẠI runtime** — lead + 2 monitor inherit self-report `claude-fable-5` → H5-fallback S101 kết thúc, pattern availability per-session xác nhận [S98 Fable → S101 Opus → S102 Fable → **S103 Opus** → **S104 Opus** (2026-07-06 Fable outage tiếp — S104 lead + 2 monitor spawn self-report `claude-opus-4-8` ×3, H5-fallback revert-free) → ✅ **S105 Fable** (2026-07-07 Fable VỀ lần 3 — lead + 2 monitor self-report `claude-fable-5` ×3, runtime-verified) → ⚠️ **S106 Opus** (2026-07-07 Fable outage lại — lead runtime self-report `claude-opus-4-8`, H5-fallback revert-free; flip-7) → ✅ **S107 Fable** (2026-07-10 Fable VỀ lần 4 — lead + 2 monitor self-report `claude-fable-5` ×3, runtime-verified; flip-8)], BƯỚC 0.6 probe mỗi phiên; per-session KHÔNG steady-state. 🔴 **[§Sub-agents = CANONICAL single-owner flip-chain — S106 gộp per anh-confirm; derived `agents/README §Architecture` · `session-start BƯỚC 0.6` · `session-end §commit-format` trỏ về đây [🔄 vá @S153 FLAG-1: 3 cite số-dòng cũ `:3`/`:37`/`:113` đo lại SAI cả 3 (đúng là `:5`/`:48`/`:315`) — vá bằng BỎ số theo luật đã áp @S151, không ĐỔI số], KHÔNG tự enumerate mỗi flip → chống churn 4-file/flip]**) · **TOÀN roster `model: opus` + `effort: max`** (worker-tier-pin S124; **A2 đo S126:** lane no-tier resolve `claude-opus-4-8` DÙ lead=Fable ⇒ pin ăn runtime, hết inherit-lead; số vai = cột giữa của chính row này — KHÔNG chép lại vào narrative, đó là cách row-14 và narrative-12 lệch nhau từ S121 tới S122; lineage: 7 demoted flip S66 → all-inherit S66–S123 [office-document S107 inherit-born] → pin S124) · effort Max. 10 product/quality + monitor INFORM-only (H1 · H2 · 2×H24 S121 · 3×trio-memory S141 · 3×round-KIỂM `ring1-audit`/`ring2-audit`/`ring4-audit` S145) — **liệt-kê NHÓM, số vai = cột giữa của chính row này**. Nấc H8 = **runtime-verified S98 (2026-07-02)** — spawn-test inherit-chain ×2 monitor self-report `claude-fable-5` (cả đội tự lên Fable khi lead restore, 0 sửa frontmatter — đúng thiết kế all-inherit). Prev two-tier H4 runtime-verified S57bis (spawn-test 2 chiều). | diff --git a/docs/changelog/sessions/2026-07-29-1440-S159-tong-quan-quy-trinh-arc2-bookend.md b/docs/changelog/sessions/2026-07-29-1440-S159-tong-quan-quy-trinh-arc2-bookend.md new file mode 100644 index 0000000..5649012 --- /dev/null +++ b/docs/changelog/sessions/2026-07-29-1440-S159-tong-quan-quy-trinh-arc2-bookend.md @@ -0,0 +1,58 @@ +# S159 (2026-07-29) — Phiên-LOGIC L8 window-1: bookend @open 5 vòng + vá spec KHKK + 5 khoản owner + ARC-2 UI "Tổng quan quy trình" 5 đợt SHIP PROD + +> Window-1 đóng bằng `/pause` @14:40 (lệnh anh *"xong thì /pause nhé"*). Closeout sổ bền chạy ở window-2 (`/tiep` @S160 cùng ngày ~15:00). +> Chi tiết máy-đọc-được: `docs/STATUS.md` dòng CURRENT ①-⑧ + run-trace 2 folder (dưới). File này = bản kể + disposition + errata. + +## Nửa đầu — governance (sáng) + +- **Sàn-3 ① kêu ×2** (orphan S155+S157 dạng-4) → anh chốt *"nối mạch tiếp cho xong hẳn rồi bootstrap"* → retro-harvest 2 synthesis L7; detector về 0-orphan. +- **Bookend @open 5 vòng ĐỦ** (anh chốt chạy đủ): 10 vai · 9 spawn + 6 resume · 11 artifact ~231KB → `runs/2026-07-29-S159-bookend-open/`. Nặng nhất: `ring2` **D-4** chặn lead trước một nước xoá-lịch-sử tally (đơn-vị trong-phiên ≠ consecutive-audit) · `ctx-audit` mtime-proof lead ghi `_mind` sớm 13–54 phút (1 gốc → 4 triệu-chứng) · REGRESSION diary 11 vai đóng băng — khâu hỏng là **APPEND**, không phải phát hiện → seed 10/10 on-behalf. +- **Vá 2 chỗ hở spec KHKK:** H5 đóng **2 site** (`N ≥ 6`+6 tên · `N ≥ 2`+2 tên) · H6 đóng **4 site** (site-4 `DbInitializer` chỉ lộ khi hỏi nhân-quả — *grep tìm CHUỖI, mô-hình nhân-quả tìm HỆ-QUẢ*). +- **5 khoản (49)-(53) thi hành xong** (anh: *"đã có giải pháp rồi thì làm luôn, tao muốn các vòng này tự động luôn"*): vá 6 site 2 file LỆNH (cặp H24 vô-điều-kiện mỗi bookend) + phép (10) mind-check FI 4/4 · seed diary · `_INDEX` cicd +Run #407 mồ-côi · slot (45) RÚT (báo động giả) · vá lọc detector `(sub|harness)-*` ⇒ INFORM 8→14 (**số xấu đi = bản vá chạy đúng**, anti-Goodhart). + +## Nửa sau — ARC-2 UI "Tổng quan quy trình" (chiều, 5 đợt / 5 commit / ~3h) + +Khuôn làm việc: **{đợt nhỏ → ship → anh nhìn prod → vẽ tiếp}** — không phải spec-trước-làm-sau. Mỗi đợt qua đủ build + test + reviewer + cicd. + +| Đợt | Commit | Nội dung | cicd | +|---|---|---|---| +| 1 | `b5799fc` | Trang tổng-quan fe-user: hero pipeline 4 GĐ (designer T1) | PASS 9/9 (#422) | +| 2 | `1a47a61` | Tab strip 4 GĐ trên phiếu + menu 4-GĐ + đánh số 01-07 (anh Kiệt) | **PARTIAL 8/9** (#423 — mục-9 lộ revoker) | +| 3 | `2a72695` | Gỡ nhánh [S92] khỏi revoker + regrant 447 + guard test 2-vế + skeleton menu GĐ2 `Khkk_*`/GĐ4 `Hdc_*` + ComingSoonPage ×2 | PASS 9/9 (#424, restart-proof 3-chân-kiềng) | +| 4 | `a2bbcb9` | Bỏ KPI/gần-đây → list chi tiết toàn-trình (anh: *"hiện theo list chi tiết đàng hoàng"*) + nhãn Hdc "- Bảng cứng" + 7 FLAG reviewer fix | PASS 9/9 (#425, durability-2) | +| 5 | `ea962b1` | Menu 6-leaf y-chang-Duyệt-NCC ×7 loại HĐ (21 key mới) + `GET /api/contracts/deleted` + bỏ hero (anh: *"Ồ đẹp đấy, vậy bỏ cái trên đi nhé"*) + sidebar **"Tổng quan quy trình"** | **PASS 9/9** (#426 — menu 119→142=+23 khớp toán, durability-3, cứu 1 FALSE-FAIL) | + +**Quyết định anh (verbatim, đầy đủ trong `_context-s-8.md` PAUSE-1):** ranh 4-GĐ (b.12∈GĐ2) · ẩn 3 nhóm chưa-public = *"chỉ hiển thị ở trang admin — để tao khỏi nhầm giữa cái đã public và cái đang làm"* · ❹ *"đang phát triển → cho hiển thị hết để mọi người góp ý, còn duyệt NCC thì cứ để như cũ"* (**RỦI-RO CÓ Ý THỨC** — authz HĐ trần S156 treo chủ-đích, đã cảnh báo, anh tái khẳng định) · bộ tên 4-GĐ chốt: **Duyệt NCC · Kế hoạch ký kết HĐ · Duyệt hợp đồng · Hợp đồng cứng** (*"Trình ký Hợp đồng đổi thành Duyệt hợp đồng, ký cứng -> Hợp đồng cứng"*) · *"Thêm chữ bảng cứng vào nhé"* · AskUser *"Chạy cả 2"* (endpoint deleted + matrix HĐ chung — đo `ApplicableType.Contract=3` ⇒ 7 leaf trỏ chung 1 matrix) · *"vậy là tròn 1 quy trình của Solution rồi đấy."* + +**Sự cố revoker → gotcha #84:** grant menu SQL tay bị `RevokeTemporarilyHiddenModulesAsync` [S92] lật 447/494 row @restart. Xử 2 nhịp (regrant + gỡ nhánh code + `StillHiddenKeys`∧`ReopenedKeys`), bền ×3 restart. Luật: **KHÔNG SQL tay cho menu — code-first seeder; comment nêu LUẬT+grep, CẤM số-đếm** (2 lần/ngày số-comment thành nợ: `531` task-id + "chỗ THỨ HAI"). + +**#53 trong arc:** designer ×2 + cicd + reviewer đều có lượt garble first-return — **mất 0 B** nhờ ghi-đĩa-trong-lúc-làm (sub-file là sản phẩm chính; `cicd-verify-ea962b1.md` về kịp PASS 9/9 ngay trước chốt). + +## Window-2 closeout (@S160 `/tiep`, ~15:00) + +- `/tiep` trọn nghi-thức: Sàn-3 5 tín-hiệu kêu ĐÚNG (khớp WAL, không phải sổ-trống-≠-sạch) · tick counter 33→34 (CLEAN) · `NHIP-NO: light 7/6 OVERDUE — /tiep không phải bookend, cặp H24 chạy ở bookend kế` · thư-mới se=0 all=0 (pull-cách 7 ngày = lành, không có gì để kéo) · mind-check **đạt 11/0** · `ctx-verifier` **CO-CO 9 cờ** (nạp-lại 15 dòng; `LEAD-PHAI-NHAC-LAI` giữ đúng). +- Sổ bền: STATUS CURRENT viết lại (arc-2 ⑦⑧ + baseline mới + bỏ claim "0 prod-code") · HANDOFF khối ARC-2 + ❹-risk verbatim + vá số stale `_mind` 37,9%→69,2% · gotcha **#84** · spec KHKK note W1 (tái dùng `Khkk_*`, tiền-đề dark-launch menu ĐẢO, skip-existing) · diary designer entry S159 on-behalf + cicd baseline #426. +- **Curate 2 diary (hook read-limit 24,4KB kêu):** designer 23.570→19.388B (2 entry S69 → `archive/2026-06.md` + `_INDEX` pointer) · cicd 23.678→21.852B (đợt-3 #424 → `archive/2026-07.md`, moved-not-cut verify True ×3). 🔴 **Pointer `_INDEX` cicd cho bản-ghi #424 TREO chờ slot (51-bis)** — index đo tươi **20.313/20.480 = 99,2%, headroom 167B** (HANDOFF ghi 19.958/97,45% đã cũ: +355B do pointer #423 vào cùng commit `wal: pause`). Đích 17,1K của hook KHÔNG ép — đó là thước MA slot (46) chờ anh. +- Re-chạy `governance-detectors` sau khi diary đã commit (HANDOFF NEXT①) — kết quả ghi ở WAL/báo cáo cuối. + +## Errata (FLOW `_context` bất-biến nên đính-chính ở đây) + +1. `_context-s-8.md` PAUSE-1 mục (3) đếm run-folder arc-2 "5 đợt + **3 cicd-verify + 2 sub-reviewer**" — đĩa thật: **5 cicd-verify + 3 sub-reviewer + 2 sub-designer** (+ run.md + 2 prod-txt = 13 file). Con số trong FLOW là undercount lúc viết, không sửa entry. +2. HANDOFF segment S159 (viết @window-1) khai "(governance-heavy, 0 prod-code)" cho cả phiên — đúng nửa đầu, sai nửa sau; đã sửa @closeout. + +## PARK chờ anh (mang sang từ PAUSE-1 + closeout) + +- **FLAG-4** định nghĩa "Đã duyệt" HĐ: phase=9 Đã-phát-hành đang bỏ sót phase-8 đã-qua-BOD; nhãn menu ↔ chip lệch (`run.md:104`). +- **(51-bis)** `cicd-monitor/_INDEX` **99,2% / 167B** (số tươi @S160): (a) split (đã mở lại được) · (b) nâng cap (refine BÁC) · (c) để nguyên. Kèm nợ mới: pointer #424 treo. +- **"Bảng cứng" vs "Bản cứng"** — nhãn theo verbatim anh vẽ; nếu ý là "Bản cứng" thì 1 lệnh đổi. +- **StaticLeaf "Hộp thư"** chưa viết hoa đồng bộ "TỔNG QUAN QUY TRÌNH" — đồng bộ hay để. +- **6 FLAG-L park đợt-4/5** trong `sub-reviewer-diff-dot4.md`/`-dot5.md` (`run.md:87` F6 + `:105` F5–F9). +- Slot cũ giữ nguyên: (42)(43)(44)(46)(47)(48) + nhóm không-chặn-W1 (xem HANDOFF). + +## Chốt đầu việc (@S160, sau báo cáo /tiep) + +> anh: **"OK tạm thời các điều chỉnh vừa rồi ổn. Xem như đóng đầu việc."** + +Disposition: đầu việc **arc-2 + closeout ĐÓNG** theo lời anh. **7 khoản checklist đánh-số KHÔNG được trả lời ⇒ tất cả GIỮ SLOT TREO** (không suy diễn "im lặng = đồng ý" cho bất kỳ khoản nào): (1) FLAG-4 "Đã duyệt" HĐ · (2)=(51-bis) `_INDEX` cicd 99,2%/167B a/b/c + nợ pointer #424 · (3) Bảng↔Bản cứng · (4) Hộp thư hoa · (5) 6 FLAG-L park · (6)=(46) thước 17,1K (dữ kiện mới: hook kêu ×3 @S160) · (7) slot cũ (42)(43)(44)(47)(48). "Tạm thời" trong lời anh = các điều chỉnh có thể còn được rà lại — không phải ratify vĩnh viễn. + +→ Run-trace: `.claude/workflows/runs/2026-07-29-S159-bookend-open/` · `.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/` diff --git a/docs/gotchas.md b/docs/gotchas.md index 2981924..742c965 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -1366,6 +1366,14 @@ for h in resp.points: # ← .points không phải iterable trực tiếp **Fix:** (1) Outward artifact mời-reproduce: trích **bảng per-lane theo run-id** (bất-biến), KHÔNG trích COUNTS tổng; buộc trích tổng → scope rõ "cumulative cả phiên". (2) Internal doc đông-cứng số tổng = ĐÚNG point-in-time nhưng CẤM thừa-kế nguyên-văn ra thư. (3) Biến-thể số-đếm của bài "acceptance literal tự-lão-hoá" (S121). Reviewer-gate G-015 bắt; em-main-solo sót. +### 84. Sửa data tay trên prod bị code-path ungated @restart ĐẢO NGƯỢC im lặng — revoker 2 chiều (Session 159) + +**Triệu chứng:** S159 đợt-2 grant menu 4-GĐ bằng SQL tay trên prod (494 row canread) → deploy kế restart pool → cicd mục-9 đo lại chỉ còn **47/494** (Admin 38 + Procurement 9): `RevokeTemporarilyHiddenModulesAsync` (nhánh ẩn-module [S92], **ungated, chạy MỌI restart**) lật 447 row về `false`. Grant "thành công" sống đúng tới lần restart kế — không lỗi, không log phía người sửa. + +**Cơ chế — 2 CHIỀU của cùng một lớp lỗi:** DbInitializer chạy mỗi boot có cả 2 loại code-path ngược nhau: (a) **seeder grant `skip-existing`** — chỉ insert row THIẾU, KHÔNG nâng row `false` sẵn có ⇒ xóa/hạ tay sẽ KHÔNG được seed lại đúng kỳ vọng "seeder tự chữa" (mặt này là gotcha #75/#76); (b) **revoker ungated** — lật XUỐNG mọi row khớp điều kiện ⇒ grant tay bị nuốt @restart (mặt mới S159). Hệ quả chung: **MỌI thay đổi permission/menu tay trên prod đều tạm thời nếu tồn tại code-path @startup theo hướng ngược** — phải grep DbInitializer cả 2 hướng (Seed* VÀ Revoke*) trước khi tin thao tác tay là bền. + +**Fix:** (1) Đổi trạng thái menu/permission = **code-first qua seeder + deploy**, KHÔNG SQL tay (S159 đợt-3 gỡ nhánh [S92] khỏi revoker rồi mới regrant). (2) Muốn chứng "fix bền": khuôn **3-chân-kiềng** — (i) chứng restart THẬT (`w3wp` StartTime in-window + dòng đầu log mới), (ii) đo chỉ-số đích SAU restart, (iii) **control ÂM chứng checker còn sống** (`Hrm/Off/Personal` non-Admin vẫn =0 ⇒ revoker không bị vô hiệu hoá cả hàm — thiếu vế này thì "fix" bằng cách xoá luôn revoker cũng xanh y hệt). (3) Khoá regression bằng test 2-vế `StillHiddenKeys` (false) ∧ `ReopenedKeys` (true) — re-add nhánh là CI đỏ. (4) Comment quanh seeder nêu **LUẬT + lệnh grep tự-kiểm**, CẤM ghi số-đếm (số thành nợ tự-lan — 2 lần lệch trong 1 ngày @S159). Liên-quan: #75/#76 (chiều seeder re-add), #51 (seed gate), #82 (menu-flag ⟂ API-authz). + --- ## Checklist debug bug mới