From 57e672f71f81179d8162e3ae2bf1d88b6b3e7548 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 7 Aug 2026 12:25:55 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Docs:=20S179=20closeout=20=E2=80=94?= =?UTF-8?q?=20va=20doi=20STYLE=202=20vong=20(C7=20bat=202=20MAJOR=20trong?= =?UTF-8?q?=20chinh=20ban=20va)=20+=20H24=209=20FLAG=20+=20drift-audit=20t?= =?UTF-8?q?hang?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SUA-1..6b tron 6/6, acceptance C1-C6b 12/12. Vong-2 sua chinh vong-1 sau reviewer C7 (PASS-WITH-8, 3 MAJOR): - Doi ba-cham -> hai-cham la REGRESSION co dieu-kien, KHONG phai cosmetic: chi tuong-duong khi origin/main con ancestor; cay phan-ky thi hai-cham liet ca file CHI CO tren origin/main (= DA PRODUCTION) vao "phan MOI". Thu pham that = git diff mu untracked. Sandbox 2 chieu CONFIRMED. - git status --porcelain | cut -c4- de path RAC (rename in MOT dong "R old -> new"; path co dau cach bi quote). Sandbox: 2/2 MISS; thuoc moi 2/2 OK. - Thuoc CHOT 4/4 site: { git diff --name-only origin/main...HEAD; git diff --name-only HEAD; git ls-files -o --exclude-standard; } | sort -u Bai: chan-doan sai VAN pass acceptance — acceptance do HINH-DANG chuoi, khong do HANH-VI. Lop mo-neo TU-VO-HIEU: con-tro so-dong tro vao CHINH tep chua no tu thoi moi lan sua dau tep (112->118->121 trong 1 phien) => neo TEN, khong neo SO DONG. Ap cho index.css, gotchas.md, PipelineStageFolders. Con-tro verbatim _mind doi ve commit DA PUSH (ee21056/d081681) — ban truoc tro 727a512 nam trong dai squash => tu de con-tro mo-coi. H24 light-audit 9 FLAG, flush 8 o canonical: Mig 71->72 - Gotchas 86->87 - Tests 644->645 (chay that dotnet test: 45 Domain + 600 Infra, 0 fail) - user-mem 59->60 - header S168->S179 - roster 23->26 (go han so theo B1) - HANDOFF dong 4 slot (68)-(71) + E4. "So noi doi theo huong BI QUAN" x3 ca/1 phien (4 slot - E4 - run.md S173) => leo thang lan 3 phai DO LAI TIEN-DE. Kem: 2 NO vong-3 - 2 synthesis ORPHAN (run-chua-gom 2->0) - di-tru cua-so 6 vao _context - keo+ap 2 thu loi-do-luong (BAC Lop 8 CO SO: mtime cum SE 0,7% vs hub 69%) - drift-audit thang PASS_WITH_FLAGS-8 (va 2, con 6) - _mind 99,67%->84,2% - don 9 dir rong - archive-gate strike 1/2. #53: 4/4 vai garble return dau, vot tron 4/4 bang resume-in-session. Mat 0 byte. 0 file code nghiep-vu. Build 2/2 app PASS. Test 645/645. Co-Authored-By: Claude Opus 5 --- .claude/WAL.md | 59 ++++--- .claude/agent-memory/.mfe-state.json | 12 +- .../back-end-reviewer-style/MEMORY.md | 15 ++ .claude/agent-memory/ctx-verifier/MEMORY.md | 2 + .../database-reviewer-style/MEMORY.md | 17 ++ .../front-end-reviewer-style/MEMORY.md | 15 ++ .../agent-memory/lead-stale-auditor/MEMORY.md | 2 + .claude/agent-memory/reviewer/MEMORY.md | 2 + .../agent-memory/tooling-auditor/MEMORY.md | 2 + .claude/agents/README.md | 24 ++- .claude/agents/back-end-reviewer-style.md | 48 ++++- .claude/agents/database-reviewer-style.md | 54 +++++- .claude/agents/front-end-reviewer-style.md | 40 ++++- .claude/governance/.session-counter.json | 13 +- .claude/sessions/session-11/_context-s-11.md | 21 +++ .claude/sessions/session-11/_mind-s-11.md | 165 ++---------------- .claude/sessions/session-11/_tiep-6.md | 7 + .../bookend-open-synthesis.md | 63 +++++++ .../investigate-synthesis.md | 49 ++++++ CLAUDE.md | 4 +- README.md | 2 +- docs/CLAUDE.md | 2 +- docs/HANDOFF.md | 25 ++- docs/STATUS.md | 24 ++- ...026-08-07-1200-S179-doi-style-va-2-vong.md | 71 ++++++++ docs/gotchas.md | 4 +- ...-05-Governance-loi-do-luong-phan-1-va-2.md | 66 +++++++ .../src/components/khkk/KhkkDetailContent.tsx | 2 +- .../src/components/khkk/KhkkWorkflowPanel.tsx | 7 +- .../pipeline/PipelineStageFolders.tsx | 4 +- .../components/pipeline/PipelineTreePanel.tsx | 4 +- fe-admin/src/index.css | 10 ++ .../src/components/khkk/KhkkDetailContent.tsx | 2 +- .../src/components/khkk/KhkkWorkflowPanel.tsx | 7 +- .../pipeline/PipelineStageFolders.tsx | 4 +- .../components/pipeline/PipelineTreePanel.tsx | 4 +- fe-user/src/index.css | 10 ++ 37 files changed, 621 insertions(+), 241 deletions(-) create mode 100644 .claude/agent-memory/back-end-reviewer-style/MEMORY.md create mode 100644 .claude/agent-memory/database-reviewer-style/MEMORY.md create mode 100644 .claude/agent-memory/front-end-reviewer-style/MEMORY.md create mode 100644 .claude/sessions/session-11/_tiep-6.md create mode 100644 .claude/workflows/runs/2026-08-05-S173-bookend-open/bookend-open-synthesis.md create mode 100644 .claude/workflows/runs/2026-08-05-S175-duan-budget-column/investigate-synthesis.md create mode 100644 docs/changelog/sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md create mode 100644 docs/governance/adap-reports/2026-08-05-Governance-loi-do-luong-phan-1-va-2.md diff --git a/.claude/WAL.md b/.claude/WAL.md index fb0057c..52d216b 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -1,38 +1,41 @@ # WAL — auto-generated, không sửa tay -updated: 2026-08-06 | session: S178 (phiên-LOGIC L11, window 6) | branch: main +updated: 2026-08-07 | session: S179 (phiên-LOGIC L11, window 7) | branch: main +closing: S179 @2026-08-07T12:00:00+07:00 -goal: cửa-sổ 6 (S178) — UAT màn KHKK chạy tiếp: **đợt-7 `99370de` đã push, ĐANG chờ deploy verify 2-vế ×2 app**. Engine `SỬA-6` vẫn treo NGUYÊN, chưa vá điểm nào. 🔴 `_mind` **99,67% trần** (dư 163B) ⇒ phải nén MIND-2+3 TRƯỚC `/pause` kế (`ctx-verifier` cờ-2). +goal: cửa-sổ 7 (S179) — anh: ***"OK làm cho xong hết đi nhé"***. **ĐÃ XONG:** `SỬA-1..6b` **6/6** (acceptance 12/12) · H24 light-audit **9/9 FLAG** · 2 NỢ vòng-3 · 2 run-folder ORPHAN · di-trú cửa-sổ 6 · kéo+áp 2 thư · governance (E4 · Carry · 9 dir · A1 strike-1). `_mind` **99,67% → 84,2%** (dư 7.790B, MIND-8 chèn được). 🔴 **CHẶN CUỐI: 3 vai style cần RESTART CLI mới spawn-probe được** — 0 file code nghiệp-vụ bị đụng, toàn governance + comment. chain: -- [x] nối mạch /tiep @S178: Sàn-3 **2/5** tín-hiệu MẠNH kêu (① 2 orphan-run · ⑤ ORPHAN-L) · tick 51→52 · **3 LỆCH** ground-truth (residual đã bị hook commit · cửa thư tái-dựng ĐƯỢC · ORPHAN-L lệch -1 CỐ-HỮU do PAUSE-3 kép) · `_tiep-5.md` cân sổ -- [x] 🧊 **đợt-1..6 cửa-sổ 5 NÉN thành con-trỏ** (đã ship + 6/6 deploy VERIFIED, chi-tiết sống ở `_context-s-11.md` PAUSE-6 mục (1) + 6 commit): `530af22`·`b346b41`·`cd79d1c`·`4704aaf`·`1fa079d`·`ca9208f`. Mốc bundle cuối cửa-sổ 5 = `BG-xXFql`·`DyRJmp0R`. **Mig 72** + backfill 5/5 có mã · test **645/645** · gotcha **#82** vá lệch 2 tầng -- [x] **đợt-7 `99370de`** (S178 — anh: *"giữ lại chỗ chọn hạng mục - số tiền - thêm hủy thôi, bỏ luôn chỗ ghi chú luôn"*): GỠ ô Ghi chú CẢ 2 chỗ (dòng đã có + dòng thêm) · dọn `addNote` + `note` khỏi 2 mutation · vá chú-thích `:556` trỏ vào chính ô vừa gỡ. 🔴 **SUÝT DÍNH BẪY CHUỖI DÙNG CHUNG LẦN 4**: `Ghi chú (tùy chọn)` ở dist = 2 KHÔNG phải gỡ hỏng — `PeWorkflowPanel:869` + `HardCopiesPage:371` cùng dùng; chuỗi phân biệt KHKK là bản **CÓ dấu `…`**. Nguồn 2→0 · dist 0/0 · control dương 2/2. Thao tác append-theo-STT anh mô tả ĐÃ đúng sẵn (`onSuccess setAddFor(null)`+`invalidate`, BE `OrderBy(CreatedAt)`). ✅ **DEPLOY VERIFIED 2-vế ×2 app** `CZzRTDJS`·`D1cL-UbV`: KHKK-placeholder 0/0 · control dương 2/2 ×2 phép · bundle 1,79MB/1,71MB (KHÔNG phải 900B SPA-fallback) -- [x] 🔴 **4 phép đo của LEAD hỏng rồi tự bắt + 1 vượt trần sổ**: ① dò thư quét `../AI_INFRA…` (repo không ở đó ⇒ `all=0` là RỖNG-VÌ-HỎI-SAI-CHỖ) · ② `HEAD~1` ≠ commit-trước-của-mình (hook `wal:` chèn giữa ⇒ so bản mới với CHÍNH NÓ) · ③ đọc DLL sai heap + lệch khung UTF-16 + quoting `\"` không phải PowerShell · ④ kỳ-vọng chuỗi=0 sai **3 lần** (`STT`·`Giá đề xuất`=6·`bg-brand-50/40`=12) vì đều DÙNG CHUNG · ⑤ WAL phình 73/40. **CONTROL DƯƠNG cứu cả 4** +- [x] nối mạch /tiep @**S179** (mở cửa-sổ 7): Sàn-3 **2/5** MẠNH kêu (① 2 orphan-run · ⑤ ORPHAN-L p=6 r=5) — **cả 2 đã được `verify:` dòng 40 TIÊN-ĐOÁN ⇒ khớp, không phải bất-ngờ** · tick 52→**53** (anti-tamper: `ee21056` là ancestor ⇒ không alarm) · probe `light 7/6 OVERDUE · run-chưa-gom 2 · pull-cách 16 ngày` · `ctx-verifier` **CO-CO 14 cờ** · **1 LỆCH** (thước residual mù — xem dòng 14) · `_tiep-6.md` cân sổ +- [x] 🧊 **NÉN**: /tiep @S178 (Sàn-3 2/5 · tick 51→52 · 3 LỆCH · `_tiep-5.md`) + **đợt-1..6 cửa-sổ 5 thành con-trỏ** (đã ship + 6/6 deploy VERIFIED, chi-tiết sống ở `_context-s-11.md` PAUSE-6 mục (1) + 6 commit): `530af22`·`b346b41`·`cd79d1c`·`4704aaf`·`1fa079d`·`ca9208f`. Mốc bundle cuối cửa-sổ 5 = `BG-xXFql`·`DyRJmp0R`. **Mig 72** + backfill 5/5 có mã · test **645/645** · gotcha **#82** vá lệch 2 tầng +- [x] 🧊 **NÉN (an-toàn vì đã DI-TRÚ):** đợt-7 `99370de` (`CZzRTDJS`·`D1cL-UbV`) + đợt-8 `65f73a9` (`CuWgMI7J`·`32bJmjpM`) — cả 2 ship + **deploy VERIFIED 2-vế ×2 app**; chi-tiết đầy đủ + 2 bẫy (chuỗi dùng-chung lần 4 · submit-guard BE `:176` suýt kẹt phiếu vĩnh viễn) nay sống ở `_context-s-11.md` entry `DI-TRÚ-1`. **Nén ĐƯỢC là vì đã có nhà khác — trước S179 nén là mất hẳn.** +- [x] 🔴 **4 phép đo của LEAD hỏng rồi tự bắt + 1 vượt trần sổ**: ① dò thư quét `../AI_INFRA…` (repo không ở đó ⇒ `all=0` là RỖNG-VÌ-HỎI-SAI-CHỖ) · ② `HEAD~1` ≠ commit-trước-của-mình (hook `wal:` chèn giữa ⇒ so bản mới với CHÍNH NÓ) · ③ đọc DLL sai heap + lệch khung UTF-16 + quoting `\"` không phải PowerShell · ④ kỳ-vọng chuỗi=0 sai **3 lần** (`STT`·`Giá đề xuất`=6·`bg-brand-50/40`=12) vì đều DÙNG CHUNG · ⑤ WAL phình 73/40. **CONTROL DƯƠNG cứu cả 4** · ⑥ **LẦN 5**: đích `'dòng chưa gán hạng mục.'`=0 ở prod, ra **1** — **code ĐÚNG, kỳ-vọng SAI** (`:1118` CỐ Ý giữ câu cũ làm nhánh dự-phòng) ⇒ luật: **đặt đích 0 phải hỏi "mình có thật sự xoá HẾT nhánh dùng chuỗi này không"**, không chỉ "còn ai khác dùng" - [x] `/pause` @PAUSE-6: `_pause-6.md` + `_context` PAUSE-6 (🔴 lead chèn NHẦM ĐẦU FLOW — `_context` là mới-nhất-ở-CUỐI, NGƯỢC `_mind`; đã sửa) + MIND-7 (`ctx-curator` bắt **7 điểm**, vá đủ, máy `dat=11 TRUOT=0`) + nén MIND-1 (51.260B→48.884B) + `_snapshot-1` `e1942a5` -- [!] 🔴 **residual-write:** `ctx-curator` GHI 2 tệp `.claude/agent-memory/ctx-curator/` (G-015). 🔴 **ĐÃ ĐỔI TRẠNG-THÁI @S178:** hook nuốt vào `ee21056` ⇒ `porcelain` nay RỖNG, giữ/revert giờ cần **revert-commit** chứ không discard nữa (đúng bẫy timing `session-start.md:285`) -- [!] 🔴 `/fable-real reviewer` `wf_264fb5c2-0db` = `SETUP-REVIEW: SỬA-6` — **6 điểm CHƯA vá cái nào**. Spec: `runs/2026-08-06-S176-doi-style-3-vai/spec-va-doi-style-3-vai-06-08-2026.md` -- [!] 🔴 **SỬA-1 SỐNG-CHẾT:** thước dispatch `origin/main...HEAD` (**ba-chấm**) ⇒ mù uncommitted+untracked ⇒ đội STYLE gate PRE-commit **chết CÂM** (0 spawn, 0 `SKIP-CO-KHAI`). Sửa 4 site → 2-chấm ∪ `porcelain` lọc `??`. 🔴 **Bằng-chứng: cửa-sổ này 12 file đúng địa-phận cả 3 vai, 0 con được gọi** -- [!] 🔴 **SỬA-5a (rẻ nhất):** 3 vai style thiếu dir `agent-memory//` ⇒ vô hình trong đo/budget. Đo lại **3/3 THIẾU CONFIRMED** -- [ ] SỬA-2 phạm-vi chuẩn quá rộng · SỬA-3 miễn-trừ dấu-cao-su · SỬA-4 thách-CLEAN nhánh DAT bẻ được · SỬA-5b vùng mù seam FE↔BE · SỬA-5c `README:67` thiếu nhãn hiệu-lực · SỬA-6a claim chép 4 site · SỬA-6b lead chép luật vào persona (`db:32/34-35/61`·`be:63`·`fe:4`) · 🔴 3 vai style **CHƯA spawn-probe** (registry no-hot-reload, cần restart CLI) -- [ ] 🔴 2 NỢ vòng-3: ① khung thẻ 2 nguồn sự-thật (`index.css:112` ⟂ utility ×2 app) · ② overclaim gotcha #66 **4 site / 2 CHUỖI KHÁC NHAU** -- [ ] 🔴 ghi synthesis cho **2** run-folder ORPHAN (`…S173-bookend-open` · `…S175-duan-budget-column`) · đính-chính `_context` mục "Lead đã flush (a)" — thật ra 1/7, đính chính bằng entry PAUSE-7 -- [ ] E4 vế ➊ · governance (`STATUS:473` 86→87 · 5 slot HANDOFF · `ROTATE vrapp` · Carry 14 slug · slot (70) anchor) · A1 `ring2-audit` 26.440B · drift-audit quá hạn · 9 dir rỗng · STATUS/HANDOFF chưa phản-ánh Mig 72 + 6 đợt S177 -- [ ] kéo thư — 🔴 **@S178 cửa này TÁI-DỰNG ĐƯỢC** (bác câu "không nằm trên đĩa này"): AI_INFRA ở `../../AI_INFRA` (**2 cấp**, lead cũ hỏi `../` = 1 cấp ⇒ đúng lỗi ① RỖNG-VÌ-HỎI-SAI-CHỖ). Đo: **se=0 · all=2 mới** (`…loi-do-luong-phan-1/2`, 2026-08-05). 🔴 4 vế adap-report của `all=6` **CHƯA tái-dựng** ⇒ carry kèm cờ, CẤM lặng bỏ -- [ ] ⚠️ roster **26** > `hmw_width.cap` **20** ⇒ full-roster-sweep LOUD-skip 6 lane cuối. Số cap = quyền anh, O-7 treo -- 🅿️ **PARK (anh @S176) — KHÔNG hỏi lại, KHÔNG tự làm:** cột DỰ ÁN 11 ô · `Project.BudgetTotal` rỗng 61/69 -- 🔴 **GIỮ mã dự án lặp trên từng dòng** — anh chốt 2 lần cùng hướng (lý do: hình dung hạng mục lớn chứa hạng mục con) ⇒ **ĐỪNG hỏi lại** +- [x] ✅ **residual-write `ctx-curator` — ANH CHỐT @S179: GIỮ** (không revert). 2 tệp `.claude/agent-memory/ctx-curator/` (`MEMORY.md` 10.534B + `feedback_machine_blind_classes.md` 7.564B) ở lại HỢP-LỆ; hết là "residual", nay là nội-dung chính-thức của vai. 🔴 G-015 vẫn đúng ở tầng LUẬT (propose-only sub vẫn Bash-write được) — anh tha *ca này*, KHÔNG tha *cơ-chế*; backstop THẬT vẫn là git-diff commit-gate. 🧊 lịch-sử (đã định-đoạt, giữ 1 dòng làm vết): Hook nuốt vào `ee21056` ⇒ cần **revert-commit**, không discard được nữa. 🔴 **@S179 THƯỚC CŨ HỎNG (lệch 1/1):** `ee21056` **ĐÃ PUSH** ⇒ trôi khỏi cửa-sổ `origin/main..HEAD` ⇒ recipe cũ trả **0-hit ĐỌC THÀNH "đã sạch"**. Control dương: 2 tệp còn trên đĩa (`MEMORY.md` 10.534B + `feedback_machine_blind_classes.md` 7.564B). ⇒ **class `thước neo vào cửa-sổ trôi`** — cùng gốc với `HEAD~n` (dòng 38), khác dụng-cụ +- [x] ✅ **`SETUP-REVIEW: SỬA-6` (`/fable-real reviewer` `wf_264fb5c2-0db`) — VÁ TRỌN 6/6 điểm @S179.** Spec: `.claude/workflows/runs/2026-08-06-S176-doi-style-3-vai/spec-va-doi-style-3-vai-06-08-2026.md` (@S179 vá path gãy — thiếu `.claude/workflows/`) +- [x] ✅ **SỬA-1 — VÁ 2 VÒNG @S179, vòng-2 sửa chính vòng-1** (`reviewer` C7 bắt **8 điểm**, 3 MAJOR). Thước CHỐT 4/4 site: `{ git diff --name-only origin/main...HEAD; git diff --name-only HEAD; git ls-files -o --exclude-standard; } | sort -u`. 🔴 **2 lỗi lead tự đẻ ở vòng-1, lead ĐO LẠI SANDBOX: CONFIRMED cả 2** — ① đổi ba-chấm→hai-chấm **KHÔNG vô-hại mà là REGRESSION có điều-kiện**: chỉ tương-đương khi `origin/main` còn ancestor; cây phân-kỳ (sau `git fetch`) hai-chấm liệt cả file **CHỈ CÓ trên origin/main = ĐÃ PRODUCTION** vào 'phần MỚI' (probe: hai-chấm ra `local_only.txt`+`upstream_only.txt`, ba-chấm ra đúng `local_only.txt`) ⇒ **ba-chấm mới ĐÚNG, thủ phạm thật luôn là `git diff` mù untracked** ② `git status --porcelain | cut -c4-` **đẻ path RÁC**: rename in MỘT dòng `R old -> new`, path có dấu cách bị quote (probe **2/2 MISS**; thước mới **2/2 OK**). 🔸 Bài: **chẩn-đoán sai vẫn pass acceptance** — cả 2 lỗi đều lọt qua 12/12 C1-C6b vì acceptance đo HÌNH-DẠNG chuỗi, không đo HÀNH-VI. +- [x] ✅ **SỬA-5a XONG @S179** — 3 dir + `MEMORY.md` (3.555 · 3.607 · 4.075 B). Verify **qua chính instrument** (không chỉ `ls`): `measure-agent-memory.ps1` nay thấy **26 vai**, trong đó **3/3 style có dòng riêng** `l1_hot_bytes` thật +- [x] ✅ **H24 light-audit @S179 (anh OK item-3)** — `lead-stale-auditor` **9 FLAG** (máy-nền 51, giữ 0 → 9 flag đều NGOÀI tập máy). 🔴 **#53 datum S179: 3/3 vai spawn đều garble return đầu** (`lead-stale-auditor` · `reviewer` C7 · +1) — **cả 3 vớt TRỌN bằng `SendMessage` resume-in-session** (nấc 2 thang #53). **Mất 0 byte.** ⇒ nấc-2 nay ăn **3 phiên liên tiếp** (S173 8/8 · S178 · S179 3/3) — hết là may. 🔸 **Câu garble CHỨA FINDING, đừng vứt**: mảnh của C7 là *"a third thước defect"* ⇒ lead biết có cái thứ 3 TRƯỚC khi đọc verdict. **ĐÃ FLUSH 8 ô**: `STATUS` Mig 71→**72** · Gotchas 86→**87** · Tests 644→**645** (🔴 đo bằng CHẠY THẬT `dotnet test`: 45 Domain + **600** Infra, 0 fail — breakdown cũ "599" cũng lệch) · User-memory 59→**60** · header S168→**S179** · `README` roster ×2 site (+3 vai style, **GỠ HẲN** số "roster 23" theo B1 thay vì cập-nhật) · `HANDOFF` đóng **4 slot** (68)(69)(70)(71) — mỗi slot đóng bằng **bằng-chứng ĐĨA** đích danh, KHÔNG bằng trí-nhớ +- [x] ✅ **H24 9/9 FLAG xử xong @S179.** FLAG-7 vá đúng chỗ hỏng = **con-trỏ** (gỡ câu trỏ sang `:6`, cắm dòng mốc-SỐNG L11/S179 + ghi rõ `§In Progress` **stale-by-design** ⇒ giữa phiên đọc WAL, KHÔNG đọc STATUS). FLAG-8 `_mind:63` "3 lần" vs đĩa **5 lần** — 🔴 **CỐ Ý KHÔNG sửa tại chỗ**: MIND-7 là block cũ, luật `_mind` = **block cũ BẤT BIẾN** (ngoại lệ duy nhất là nén) ⇒ đính-chính thuộc về **MIND-8 @/pause kế**, sửa đè là phạm luật để lấy con số đẹp. 🔴 auditor tự khai **9 = SÀN không phải TỔNG** (chưa chạm `gotchas` thân bài · `migration-todos` · `ACTIVE-MARKS` · 24/26 persona) — CẤM đọc phần chưa soi thành sạch +- [x] ✅ **SỬA-2/3/4/5b/5c/6a/6b XONG @S179** — acceptance spec C1-C6b **12/12 PASS** (đo lại bằng lệnh khác). SỬA-2 = 2 rào (`paths-ignore` 7 path chưa từng deploy · cửa-sổ deploy-FAIL ⇒ lùi mốc về commit VERIFIED; DB thêm nấc `__EFMigrationsHistory`) · SỬA-3 miễn-trừ đòi **TRÍCH NGUYÊN VĂN** + bảng hạng MẠNH/VỪA/YẾU (2/3 nguồn do chính lead viết ⇒ con-trỏ trần = dấu cao-su) · SỬA-4 `DAT` đòi **cặp neo `file:line ⇄ file:line`** (spec xếp `db` "đã đạt" nhưng **acceptance C4 đo ra 2/3** — chỗ đạt của `db` là khuôn FLAG, không phải thách-CLEAN) · SỬA-6a claim BE→**phép-đo per-spawn** (🔴 spec liệt 4 site, thật **5** — `README:197` lòi ra nhờ chạy lại C6a) · SỬA-6b ô-chép→con-trỏ, **vá luôn drift THẬT**: `CLAUDE.md:43` ghi *React 18* mà `package.json` là **^19.2.5** +- [ ] 🔴 3 vai style **CHƯA spawn-probe** — registry no-hot-reload, **cần restart CLI** (anh OK item-6). Đã cắm nhãn *"hiệu-lực sau restart CLI"* vào `README:67` (SỬA-5c) nên lệnh gọi không còn nói dối. 🔴 **Cửa-sổ này 8 file `fe-*/src/**` đúng địa-phận FE-style mà KHÔNG gọi được con nào** — đúng ca thước mới sẽ bắt, nhưng vai chưa sống ⇒ ghi `SKIP-CO-KHAI` ở đây thay vì im lặng +- [x] ✅ **2 NỢ vòng-3 XONG + 2 ORPHAN XONG @S179.** ① khung thẻ: 2 `index.css` **byte-identical sẵn** nhưng **KHÔNG TỰ KHAI mirror** ⇒ luật `front-end-reviewer-style §2` (*chỉ đòi mirror ở file TỰ KHAI*) **không gác** ⇒ cắm khối tự-khai vào **cả 2** (sha vẫn khớp `c40eeb98…`). ② overclaim `"đè là vô hiệu"`: sự thật = chỉ thua utility **THƯỜNG**, `!important` (`text-white!`) VẪN thắng — đó đúng là fix #66 tự đề-xuất; vá 4 site 2 biến-thể. 🔴 **Tự gây dời dòng** (khai mirror +6 dòng ⇒ `.card-accent` 112→**118**, `h1-h4` 79→**85**) ⇒ grep consumer ra **site thứ 5** `KhkkDetailContent:438` spec không liệt; vá luôn `gotchas.md` ×2. **4 cặp mirror còn SHA256 identical · build ✅ 2/2 app.** ③ 2 synthesis ORPHAN đã ghi ⇒ khối DUAL-ACCEPT `/tiep §0 ①` **im** + probe `run-chưa-gom 2→0` (2 thước độc-lập) +- [x] ✅ **DI-TRÚ cửa-sổ 6 XONG @S179** — `_context` entry `DI-TRÚ-1` (khai thẳng: ghi ở `/tiep`, KHÔNG phải PAUSE, vì FLOW là append-only @pause-only). Đo lại: `99370de`=3 · `65f73a9`=2 · `CuWgMI7J`=2 hit trong `_context` (trước = **0**) ⇒ WAL squash nay **không còn xoá được** 2 commit ship + 2 deploy VERIFIED + bài "kỳ-vọng chuỗi sai LẦN 5". Kèm đính-chính "Lead đã flush (a)" = **1/7**. 🧊 nội-dung cũ: — `99370de`·`65f73a9`·`CuWgMI7J` đều **0 hit ở `_mind` VÀ `_context`, chỉ sống trong WAL** (control dương `ca9208f`=3/6 · `Mig 72`=2/1 ⇒ grep KHÔNG rỗng). WAL **tái sinh mỗi `/pause`** ⇒ squash là mất hẳn 2 commit ship + 2 deploy VERIFIED + bài "kỳ-vọng chuỗi sai LẦN 5". Chép sang `_context` PAUSE-7 + cấp NHÀ cho quyết-định giữ/revert `ee21056` (cờ-4: đang mở ở WAL `[!]` mà 0 chỗ trong §C/§D) +- [x] ✅ **governance XONG @S179:** `E4` **ĐÓNG — tiền-đề hết đúng** (đo `harness-refine/MEMORY.md` CÓ ĐỦ S163·S168·S169+S170·S172·S173, 15.126B; câu "đóng băng từ S162" lỗi-thời — cùng lớp 4 slot: **sổ nói dối theo hướng BI QUAN**, báo còn nợ khi nợ đã trả ⇒ **leo thang lần 3 phải ĐO LẠI TIỀN-ĐỀ trước**) · **Carry re-stamp @S179** (14 slug, đóng 2 có bằng-chứng: `mind-tran-nen-moi-cua` + `adap-apply-2-thu`; KHÔNG đóng `harvest-no-s168-s171` vì mới có uỷ-quyền chứ chưa gom byte nào) · **9 dir rỗng → 0** (đều là dấu cwd-lúc-spawn, `ring1`/`ring2` đã chứng vô hại) · **A1 `ring2-audit` 26.440B > cap 25.600**: archive-gate `-Apply` ghi **strike 1/2** — 🔴 **KHÔNG tự archive**, gate cố ý đòi 2 lượt over-cap liên tiếp; ép archive giờ = **bẻ chính guard** +- [ ] 🔴 CÒN (**đã đo, CHƯA vá — đừng đọc thành sạch**): ⓐ `ROTATE vrapp` (việc anh) · ⓑ A1 chờ strike-2 · ⓒ **C7 còn 2**: [6] thước use-only C1 giòn theo THỨ-TỰ CHỮ (thủng cả 2 chiều — bất-biến bền hơn: `tổng hit 'origin/main\.\.\.' == số hit trên dòng có 'CẤM'`) · [8] SỬA-6b áp **bất-đối-xứng** (`be:4` còn hardcode `.NET 10`, `db:4` còn `EF Core 10`) + cả 3 persona **CHÉP 7 mục `paths-ignore`** — nay khớp byte nên SAI 0, nhưng thêm 1 path vào `deploy.yml` là **3 file sai cùng lúc** · ⓓ **drift-audit còn 6**: F-2 `permission-matrix` cây thiếu **5 root** đang sống (`Hrm`·`Off`·`Personal`·`ContractCatalog`·`MenuVisibility`) · F-3 nó tự cấm chép số rồi chép `12 root` (bỏ số, đừng đổi) · F-4 dải `§16+` có **4 giá-trị khác nhau** ở 4 surface · F-5 `PROJECT-MAP` (file #3 trong 5-file-đọc-trước) **0 hit** 4 module đang sống, control dương `contract`=31 · F-7 `ef-core-migration` bảng dừng Mig 71 · F-8 `schema-diagram` "91 bảng" vs canonical 97 +- [x] ✅ **kéo + ÁP 2 thư XONG @S179** (anh OK item-4) — `se=0 · all=2` (`loi-do-luong-phan-1/2`). adap-report `docs/governance/adap-reports/2026-08-05-…-phan-1-va-2.md`. 🔴 **KHÔNG adopt trọn gói** — thư tự dặn *"chạy phép thử, ra ngược thì BỎ, đừng làm cho có"*: **Lớp 8 BÁC CÓ SỐ** (cụm mtime lớn nhất SE **14/2.036 = 0,7%** vs hub **69%** ⇒ mtime còn sống ở SE, không cắm luật cấm) · **Lớp 1/3/5/6 ĂN — SE tự giẫm TRONG chính phiên này TRƯỚC khi đọc thư** (hội-tụ độc-lập) · **Lớp 7 CONFIRMED chưa vá** (`governance-detectors.ps1` neo marker người gõ `NEXT anh/em` **5 site**) · Lớp 2/4/9 **chưa đo, khai thẳng**. 🔸 Cửa dò thư từng `all=0` suốt S177-S178 vì **hỏi sai cấp** — đúng Lớp 1 xảy ra trên chính cửa nhận thư về Lớp 1 ⚠️ + roster **26** > `hmw_width.cap` **20** ⇒ LOUD-skip 6 lane cuối; số cap = quyền anh, O-7 treo (anh "OK" @S179 item-5 = **ghi nhận**, CHƯA phải lệnh đổi ⇒ giữ 20) +- 🅿️ **ANH ĐÃ CHỐT — ĐỪNG HỎI LẠI, ĐỪNG TỰ LÀM:** ⓐ PARK (@S176) cột DỰ ÁN 11 ô · `Project.BudgetTotal` rỗng 61/69 — ⓑ **GIỮ mã dự án lặp trên từng dòng** (anh chốt 2 lần cùng hướng; lý do: hình dung hạng mục lớn chứa hạng mục con) - 🔴 **CHƯA ai soi mắt prod** vòng-4/4b (S176) + 6 đợt S177 — kết luận giao diện vẫn là ĐỌC MÃ (gotcha #3) -next: vá **SỬA-1** (4 site, ba-chấm → hai-chấm ∪ `porcelain` lọc `??`) → SỬA-5a → 2/3/4/5b/5c/6a/6b → re-review +next: đọc verdict **C7 re-review** (`reviewer`, chạy nền @S179) → vá điểm nó bắt → **RESTART CLI** rồi spawn-probe 3 vai style (đây là chốt-chặn duy nhất còn lại của đội STYLE) → `ROTATE vrapp` + drift-audit tháng quá hạn → A1 chờ strike-2 verify: -- `curl -s https://admin.solutions.com.vn/ | grep -oE 'index-[A-Za-z0-9_-]+\.js'` → mốc đợt-7 = **`CZzRTDJS`·`D1cL-UbV`**; khác = đợt SAU đã tới -- 🔴 **BÀI MỚI S178 — hash CI ≠ hash dist LOCAL cùng commit**: lead đoán prod sẽ ra `C1x59woX`·`Cn2Ctxap` (dist local `99370de`), thực tế CI ra `CZzRTDJS`·`D1cL-UbV`. ⇒ **CẤM neo "đã deploy" vào hash-khớp-local**; neo đúng = *(a)* hash ĐỔI so prod cũ **+** *(b)* byte-level nội-dung kèm control dương. Nếu đã neo (a)+(b) thì lệch hash local là VÔ HẠI -- 🔴 đo đợt-7 phải dùng chuỗi **`Ghi chú (tùy chọn)…` CÓ dấu `…`** (đích 0). Bản KHÔNG dấu `…` = **control dương phải CÒN 2** (`PeWorkflowPanel:869`+`HardCopiesPage:371` dùng chung — đừng đọc thành gỡ hỏng) -- `grep -rn 'origin/main\.\.\.HEAD' .claude/agents/ | wc -l` → **4** = SỬA-1 CHƯA vá (đích: 0) -- `ls -d .claude/agent-memory/*-reviewer-style 2>/dev/null | wc -l` → **0** = SỬA-5a chưa làm (đích: 3) -- 🔴 residual-write ctx-curator: `porcelain` NAY VÔ DỤNG (hook nuốt) ⇒ đo bằng `git log --name-only origin/main..HEAD | grep ctx-curator` → có = chưa revert (đích: đã quyết giữ/revert) -- 🔴 LUẬT ĐO bundle: `grep -o '' | wc -l`, **KHÔNG** `grep -c`. Chuỗi DÙNG-CHUNG phải hỏi "còn ai dùng nữa không" TRƯỚC khi kết luận · **mọi phép đo kèm CONTROL DƯƠNG** -- 🔴 **so trước/sau bằng SHA ĐÍCH DANH, CẤM `HEAD~n`** (hook `wal:` chèn ở turn-boundary). Bundle CŨ vô dụng (deploy dọn `dist` ⇒ 900B SPA-fallback) +- `curl -s https://admin.solutions.com.vn/ | grep -oE 'index-[A-Za-z0-9_-]+\.js'` → mốc đợt-8 = **`CuWgMI7J`·`32bJmjpM`**; khác = đợt SAU đã tới +- 🔴 **2 LUẬT ĐO còn hiệu-lực từ cửa-sổ 6** (ca thật ở `_context` `DI-TRÚ-1`): ① **hash CI ≠ hash dist LOCAL cùng commit** ⇒ CẤM neo "đã deploy" vào hash-khớp-local; neo đúng = *(a)* hash ĐỔI so prod cũ **+** *(b)* byte-level kèm control dương ② **chuỗi DÙNG-CHUNG**: đo đợt-7 phải dùng `Ghi chú (tùy chọn)…` **CÓ dấu `…`** (đích 0); bản KHÔNG dấu `…` = **control dương phải CÒN 2** (`PeWorkflowPanel:869`+`HardCopiesPage:371`) — đừng đọc thành gỡ hỏng +- 🔴 SỬA-1 **thước USE-ONLY** (vá @S179): `grep -rn 'git diff [^|]*origin/main\.\.\.HEAD' .claude/agents/ | wc -l` → **0** = ĐÃ VÁ. 🧊 thước cũ (`grep 'origin/main\.\.\.HEAD'`, đích 0) nay **DƯƠNG-GIẢ 3** vì chính 3 dòng `CẤM …` trích lại mẫu bị cấm — **citation-trap, use⟂mention**; đo `∪ porcelain` đã cắm: `grep -rc 'git status --porcelain | cut -c4-' .claude/agents/*.md` → 4/4 site +- `ls -d .claude/agent-memory/*-reviewer-style 2>/dev/null | wc -l` → **3** = SỬA-5a XONG (🔄 đảo chiều @S179: trước đây 0=chưa-làm, nay 3=đã-xong — **đọc nhầm chiều là kết luận ngược**) +- 🔴 **SỬA-2..6b** (đích, đo bằng lệnh KHÁC lệnh đã vá): `grep -l 'paths-ignore' .claude/agents/*-reviewer-style.md | wc -l`→**3** · `grep -l 'TRÍCH NGUYÊN VĂN' …`→**3** · `grep -l 'file:line ⇄ file:line' …`→**3** · `grep -c 'HẾT HẠN' back-end-reviewer-style.md`→**≥1** · `grep -c '0 máy style' README.md`→**0** · `grep -c 'React 19 + Vite 8' front-end-reviewer-style.md`→**0** +- 🔴 **mirror FE 4 cặp phải SHA256 IDENTICAL** (S179 sửa comment cả 2 app): `for f in components/khkk/KhkkWorkflowPanel.tsx components/khkk/KhkkDetailContent.tsx components/pipeline/PipelineTreePanel.tsx index.css; do sha256sum fe-{admin,user}/src/$f; done` · con-trỏ dời: `.card-accent`=`index.css:118` · `h1-h4`=`:85` ⇒ `grep -rn 'index\.css:112' fe-admin/src fe-user/src | wc -l` → **0** +- 🔴 **A1 `ring2-audit` KHÔNG được tự archive** — `memory-archive-gate.ps1` đòi **2 lượt over-cap LIÊN TIẾP**; @S179 mới **strike 1/2**. Ép archive giờ = **bẻ chính guard**; chạy lại gate phiên sau để lên strike 2 +- 🔴 **LUẬT ĐO (gộp):** ① bundle dùng `grep -o '' | wc -l`, **KHÔNG** `grep -c` · chuỗi DÙNG-CHUNG phải hỏi "còn ai dùng nữa không" TRƯỚC khi kết luận · **mọi phép đo kèm CONTROL DƯƠNG** ② so trước/sau bằng **SHA ĐÍCH DANH, CẤM `HEAD~n`** (hook `wal:` chèn ở turn-boundary); bundle CŨ vô dụng (deploy dọn `dist` ⇒ 900B SPA-fallback) ③ **CẤM thước neo vào cửa-sổ git đang trôi** (`origin/main..HEAD`) cho vật SỐNG TRÊN ĐĨA — commit được push là thước tự mù (ca S179) - 🔴 verify BE live = grep DLL prod `C:\inetpub\solution-erp\api\SolutionErp.Application.dll` UTF-8 **và** UTF-16 × 2 khung · DB = `sqlcmd -S .\SQLEXPRESS -d SolutionErp -E` (integrated auth, KHÔNG cần mật khẩu) -- `python scripts/session_ctx.py mind-check --session 11` → `dat=11 TRUOT=0 co=0` · 🔴 chạy khối DUAL-ACCEPT `tiep.md §0 ①` → kỳ vọng **2** ORPHAN · `ls .claude/sessions/session-11/` → _context · _mind · _snapshot-1 · _pause-1..6 · _tiep-1..**5** · 🔴 ORPHAN-L VẪN kêu `p=6 r=5` = lệch **-1 CỐ-HỮU** (PAUSE-3 bị PAUSE-4 đè, không `/tiep` xen giữa) — KHÔNG phải việc dở +- `python scripts/session_ctx.py mind-check --session 11` → **`dat=11 TRUOT=0 co=0`** · `_mind` **84,2%** (41.362/49.152 B) · khối DUAL-ACCEPT `tiep.md §0 ①` → **0 ORPHAN** (đã ghi 2 synthesis) · `ls .claude/sessions/session-11/` → `_tiep-1..6` · 🔴 ORPHAN-L nay **p=6 r=6 CÂN** — nhưng `/pause` kế làm p=7 ⇒ **lệch -1 tái xuất là BÌNH THƯỜNG**, không phải việc dở diff --git a/.claude/agent-memory/.mfe-state.json b/.claude/agent-memory/.mfe-state.json index a69c48d..8e6c955 100644 --- a/.claude/agent-memory/.mfe-state.json +++ b/.claude/agent-memory/.mfe-state.json @@ -1,7 +1,7 @@ { "strikes_total": 25, "rca_entries": 16, - "at": "2026-08-05", + "at": "2026-08-07", "warn_baseline": 25, "history": [ { @@ -103,6 +103,16 @@ "strikes_total": 25, "rca_entries": 16, "at": "2026-08-05 11:32" + }, + { + "strikes_total": 25, + "rca_entries": 16, + "at": "2026-08-07 12:22" + }, + { + "strikes_total": 25, + "rca_entries": 16, + "at": "2026-08-07 12:22" } ] } diff --git a/.claude/agent-memory/back-end-reviewer-style/MEMORY.md b/.claude/agent-memory/back-end-reviewer-style/MEMORY.md new file mode 100644 index 0000000..c673ae9 --- /dev/null +++ b/.claude/agent-memory/back-end-reviewer-style/MEMORY.md @@ -0,0 +1,15 @@ +# back-end-reviewer-style Agent — Persistent Memory + +- **S179 (2026-08-07) SINH SỔ — dir này ra đời do SỬA-5a, KHÔNG phải do mày chạy `[LEAD SEED ON-BEHALF; mày CHƯA chạy lần nào — nguồn = đĩa + spec SỬA-6]`:** mày sinh @**S176** (anh chốt đội STYLE 3 vai, lý do đo được: *"mày cứ làm đi làm lại hoài"*), nhưng **3/3 vai style thiếu dir `agent-memory//`** suốt từ đó ⇒ **vô hình với mọi máy đo** (`measure-agent-memory.ps1` enumerate DIRECTORY rồi mới đọc `MEMORY.md` — không dir thì không sinh dòng nào, và **thiếu-vắng trông y hệt sạch**). Vá @S179 = SỬA-5a. + 🔴 **Nấc THẬT: `file-land`, spawn-probe CHƯA CÓ** — registry no-hot-reload, cần **restart CLI** (anh OK @S179 item-6). Đừng đọc dir này thành "đã chạy rồi". + +- **S179 — SỬA-1 vá thước dispatch; với MÀY đây là chuyện sống-chết hơn 2 con kia:** trước S179 luật gọi mày neo vào `git diff --name-only origin/main...HEAD`. Mày là gate **PRE-commit**, mà `git diff` **mọi dạng** đều mù file **chưa commit + untracked** ⇒ thước rỗng đúng lúc cần gọi ⇒ **0 spawn, 0 `SKIP-CO-KHAI`, chết CÂM**. Đo thật: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai mà **0 con được gọi**. + Thước mới (4/4 site): `{ git diff --name-only origin/main..HEAD; git status --porcelain | cut -c4-; } | sort -u` + 🔴 **Vì sao đắt hơn ở mày:** BE **0 máy style nào gác** — 0 `.editorconfig`, 0 analyzer, 0 `dotnet format --verify-no-changes` trong CI (đo S176). FE còn có ESLint đỡ lớp cơ-học; mày **không có gì cả**. ⇒ thước mù nghĩa là **KHÔNG CÒN LỚP NÀO** soi file BE trước khi commit. + 🔴 **Bài học NGƯỢC ĐƠN THUỐC:** đơn cũ ghi *"đổi ba-chấm → hai-chấm ∪ porcelain"*. Đo @S179: hai-chấm và ba-chấm cho **md5 Y HỆT** (`origin/main` là ancestor của HEAD ⇒ merge-base = origin/main) ⇒ vế đổi dấu chấm **KHÔNG sửa được gì**; răng nằm **TRỌN** ở vế `∪ porcelain`. Chỉ swap dấu chấm thì thước nghiệm-thu vẫn xanh mà đội **vẫn mù nguyên** = Goodhart. + 🔴 **Citation-trap:** dòng `CẤM origin/main...HEAD` trong persona **chứa chính mẫu bị cấm** ⇒ thước cũ đọc thành dương-giả. Thước đúng phân biệt **use ⟂ mention**: `grep -rn 'git diff [^|]*origin/main\.\.\.HEAD'` → 0. + +- **Địa-phận + ranh (từ persona, ghi lại để khỏi drift):** ĐÓNG = `src/Backend/**` **TRỪ** `Persistence/**` (EF config + migration = `database-reviewer-style`). Soi **ĐỒNG-NHẤT STYLE + phân-tầng** (.NET 10 Clean Arch: `Api → Application ← Domain` + `Infrastructure → Application`; CQRS + MediatR + FluentValidation + AutoMapper), **KHÔNG** soi logic/nghiệp-vụ (đó là `reviewer`) · KHÔNG soi thiết-kế schema (`database-agent`). Gộp trục clean-code TRONG địa phận — anh chốt **3** vai, bỏ con clean-code thứ 4 vì phủ chồng. + 🔴 **LUẬT LÕI anh giao:** *"các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"*. Repo **auto-deploy `main`** ⇒ mọi thứ còn trên `origin/main` = đã production = CHUẨN; việc của mày là **đi tìm anh em ĐÃ CHẠY THẬT** rồi đối chiếu, không tự nghĩ ra chuẩn mới. + +Tag `[s179, sinh-so-do-SUA-5a, chua-spawn-probe, 0-may-style-gac-BE, nguoc-don-thuoc-2cham-vo-dung, citation-trap-use-mention]` diff --git a/.claude/agent-memory/ctx-verifier/MEMORY.md b/.claude/agent-memory/ctx-verifier/MEMORY.md index 8a093ae..b797368 100644 --- a/.claude/agent-memory/ctx-verifier/MEMORY.md +++ b/.claude/agent-memory/ctx-verifier/MEMORY.md @@ -1,5 +1,7 @@ # ctx-verifier Agent — Persistent Memory +- **S179 (2026-08-07) LƯỢT 10 @`/tiep` window-7 L11 — verdict `CO-CO — 14 cờ` `[LEAD SEED ON-BEHALF; carry `ctx-verifier-no-self-append` **lần 7** — mày khai đúng nợ này ở dòng 15 bản nạp-lại]`:** chuỗi nay **10 lượt**. **Cờ đắt nhất = cờ-3, và nó ĂN THẬT:** cả cửa-sổ 6 (`99370de`·`65f73a9`·`CuWgMI7J`) **0 hit ở CẢ `_mind` LẪN `_context`**, chỉ sống trong WAL — control dương `ca9208f`=3/6 · `Mig 72`=2/1 chứng grep không rỗng. Lead **đo lại độc-lập: CONFIRMED**, rồi ghi entry `DI-TRÚ-1` vào `_context` ⇒ nay `99370de`=3 · `65f73a9`=2 · `CuWgMI7J`=2. **Nếu mày không bắt, một lần `/pause` squash là mất 2 commit ship + 2 deploy VERIFIED + bài "kỳ-vọng chuỗi sai LẦN 5".** Cờ-14 (path spec SỬA-6 thiếu `.claude/workflows/`) lead `ls` đối chứng: not-found vs nhà thật 7.227 B ⇒ vá — **đường DUY NHẤT tới SỬA-6 mà `next:` chạm ngay sau đó**. Cờ-8 số-học trần: `48.989/49.152 = 99,67%`, biên MIND-8 chỉ **296 B** ⇒ lead nén M2+M3+M4 xuống **41.362 B (84,2%)**, dư 7.790 B. Cờ-9 inbound-pointer: lead giữ đúng 3 mốc `Đổi so MIND-2/3/4`. Cờ-10/11/12 (3 ý `{treo-chờ-anh}` đã được anh định-đoạt) — lead ghi vào block nén. 🔸 **Bài cho lượt sau:** cờ-3 là **class "sống độc nhất ở sổ ghi-đè"** — mỗi lượt nên grep 2-3 marker mới nhất của cửa-sổ xem chúng có nhà NGOÀI WAL chưa. Tag `[s179, luot-10, song-doc-nhat-o-WAL, di-tru-cuu-2-commit, path-spec-gay, tran-99-67, seed-on-behalf-lan-7]` + - **S171+S172 (2026-08-04→05) 2 LƯỢT L10 gộp-seed @S172 `[LEAD SEED ON-BEHALF @closeout; carry `ctx-verifier-no-self-append` **lần 5** — S171 chạy 15:47 mà sổ vẫn dừng S168, chính mày bắt datum này @S172 cờ-5]`:** chuỗi thật nay **9 lượt** (S156·S158·S162·S165·S166·S167·S168·S171·S172). ① **S171 `_tiep-2.md` = `NAP-LAI-SAN-SANG — 9 cờ`** (nặng: acceptance `ctx-audit:314` chưa đạt · run.md 3 ô stale · mồi @close "6" vs đĩa 7 — lead vá 2 cái sau ngay). ② **S172 = `NAP-LAI-SAN-SANG — 9 cờ`, return CLEAN 0-garble.** 🔴 **Cờ đắt nhất ②-cờ-2 = nghề grep-control-dương ĂN TIỀN LẦN 2** (sau ca S168 bác "PARK-1..6"): `run.md` S171 **0 hit** cho `cicd`·`deploy`·`push`·`commit`·`998ea55`·`#446/#447` (**6 từ khác nhau**) trong khi control-dương `canPe`=1 **trong chính file đó** ⇒ chứng phép grep không rỗng ⇒ `cicd-verify-998ea55.md` **MỒ CÔI ngay trong run-folder của nó**, ledger dừng `[ ] E` ⇒ **spawn nào PIN `run.md` để nối sẽ KHÔNG thấy việc duy nhất đang dở**. Lead áp liền: PIN thẳng file cicd + ghi cấm-pin-run.md vào WAL. **Bài nâng 1 nấc:** mồ-côi-trong-chính-nhà-mình là class KHÁC con-trỏ-thối — path đúng, file đúng, **chỉ thiếu người trỏ VÀO** (đảo chiều của inbound-pointer S166). ②-cờ-8/9 lớp **số thối**: "thư day-wake 1 món" thật đĩa **5**; "quá hạn 3 ngày" viết 08-04 nay 08-05 = **4** ⇒ **số đếm TƯƠNG-ĐỐI rụng 1 đơn-vị mỗi cửa**. ②-cờ-4 mù-CÓ-LÝ-DO: STATUS §CURRENT còn "S161→S168 L9" (advance @closeout) ⇒ **đừng đọc STATUS làm bản-đồ hiện-hành giữa phiên**. ②-khoản-4 SẠCH 0 cờ: chạm đĩa kiểm 5/5 chú-thích byte khớp (44.830·11.650·13.132·10.156·74.070) — khác ca S156 chú-thích sai. Delta: `mind_ctx_kb`=48 (owner nâng @S167) ⇒ `_mind` 27.519/49.152 = **56,0%**, dư ~2,6 block ⇒ **luật "nén xong trước pause" S166/S168 HẾT hiệu-lực tới ít nhất MIND-4**. Tag `[s171-s172, luot-8-9, grep-control-duong-lan-2, mo-coi-trong-chinh-nha, so-dem-tuong-doi-thoi, STATUS-khong-phai-ban-do-giua-phien, seed-on-behalf-lan-5]` - **S165+S167+S168 (2026-07-31→08-01) 3 LƯỢT L9 gộp-seed @S168 `[LEAD SEED ON-BEHALF @closeout-nợ; nguồn từng lượt ghi trong thân — carry `ctx-verifier-no-self-append` lần 4]`:** ① **@`_tiep-2` S165 = `CO — 9 cờ`** (trần-mind 84,8% · run.md tách K1-K8 · 2-vá-WAL — nguồn `_mind-s-9` MIND-3 §E + `_tiep-2.md`). ② **@`_tiep-4` S167 = `CO — 11 cờ`** (3 áp liền: verify-trỏ-gate-K6 · STATUS-622 · chữ-B4; còn lại vào WAL-notes — nguồn `_context-s-9`:164 PAUSE-4(3); 🔴 **`_tiep-4.md` 211B RỖNG RUỘT không mang verdict** — chính mày bắt lại @S168 thành cờ ⑧). ③ **@`_tiep-5` S168 = `CO — 11 cờ`, return CLEAN 0-garble:** cờ đắt: **④ claim "PARK-1..6 nhà HANDOFF" BỊ BÁC bằng grep 0-hit + control-DƯƠNG (`carry:` = 41 hit chứng lệnh sống)** — nghề grep-với-control-dương thành khuôn · ⑤⑥ MIND-2 gánh **3 inbound-pointer / 22 ý** + số-học trần: MIND-5 vừa, **MIND-6 vượt** ⇒ nén phải xong TRƯỚC pause-6 · ⑧ → **LUẬT: verdict PHẢI vào biên-nhận ngay tại cửa** (lead áp liền @`_tiep-5` dòng 6) · ⑨ con-trỏ `_context:61` **sai-ngay-lúc-viết** (file append-only không thối theo thời gian) — class khác con-trỏ-thối. 🔸 Đính-chính đếm lượt: entry S166 dưới tự ghi "LƯỢT 4" là **thiếu S165** — chuỗi thật S156→S158→S162→S165→S166→S167→S168 = **7 lượt**. Tag `[s165-s167-s168, luot-5-6-7, grep-control-duong, inbound-3-pointer-22-y, verdict-vao-bien-nhan, sai-luc-viet, seed-on-behalf-lan-4]` diff --git a/.claude/agent-memory/database-reviewer-style/MEMORY.md b/.claude/agent-memory/database-reviewer-style/MEMORY.md new file mode 100644 index 0000000..a29a309 --- /dev/null +++ b/.claude/agent-memory/database-reviewer-style/MEMORY.md @@ -0,0 +1,17 @@ +# database-reviewer-style Agent — Persistent Memory + +- **S179 (2026-08-07) SINH SỔ — dir này ra đời do SỬA-5a, KHÔNG phải do mày chạy `[LEAD SEED ON-BEHALF; mày CHƯA chạy lần nào — nguồn = đĩa + spec SỬA-6]`:** mày sinh @**S176** (anh chốt đội STYLE 3 vai, lý do đo được: *"mày cứ làm đi làm lại hoài"*), nhưng **3/3 vai style thiếu dir `agent-memory//`** suốt từ đó ⇒ **vô hình với mọi máy đo** (`measure-agent-memory.ps1` enumerate DIRECTORY rồi mới đọc `MEMORY.md`; không dir thì không sinh dòng nào, và **thiếu-vắng trông y hệt sạch**). Vá @S179 = SỬA-5a. + 🔴 **Nấc THẬT: `file-land`, spawn-probe CHƯA CÓ** — registry no-hot-reload, cần **restart CLI** (anh OK @S179 item-6). Đừng đọc dir này thành "đã chạy rồi". + +- **S179 — SỬA-1 vá thước dispatch; MÀY là con THIỆT NẶNG NHẤT vì hình-dạng công-việc:** trước S179 luật gọi mày neo vào `git diff --name-only origin/main...HEAD -- '*Persistence*'`. Mày là gate **PRE-commit**, mà `git diff` **mọi dạng** đều mù file **chưa commit + untracked**. + 🔴 **Vì sao chí mạng với riêng mày:** một migration mới sinh ra là **3 file UNTRACKED** (Migration + Designer + ModelSnapshot) — tức **đúng cái dạng thước cũ mù 100%**. ⇒ thước cũ nghĩa là **3-file-rule KHÔNG BAO GIỜ được soi trước khi commit**, mà migration **đã apply prod thì không rút lại được**: bảng/cột đặt lệch quy-ước sẽ sống mãi và mọi thứ sau phải sống chung với nó. Fault-inject @S179 chứng thẳng: thả `Persistence/Migrations/__probe_mig__.cs` untracked → thước cũ **0 hit**, thước mới **bắt**; dọn probe → mới **im**. + Thước mới: `{ git diff --name-only origin/main..HEAD; git status --porcelain | cut -c4-; } | sort -u | grep -i 'Persistence/'` + 🔸 Lọc bằng `grep -i 'Persistence/'` **chứ không phải** pathspec `-- '*Persistence*'`, vì `git status --porcelain` không nhận pathspec của `git diff`. + 🔴 **Bài học NGƯỢC ĐƠN THUỐC:** đơn cũ ghi *"đổi ba-chấm → hai-chấm ∪ porcelain"*. Đo @S179: hai-chấm và ba-chấm cho **md5 Y HỆT** (`origin/main` là ancestor của HEAD) ⇒ vế đổi dấu chấm **KHÔNG sửa gì**; răng nằm **TRỌN** ở vế `∪ porcelain`. Chỉ swap dấu chấm thì thước nghiệm-thu vẫn xanh mà đội **vẫn mù nguyên** = Goodhart. + 🔴 **Citation-trap:** dòng `CẤM origin/main...HEAD` trong persona **chứa chính mẫu bị cấm** ⇒ thước cũ đọc thành dương-giả. Thước đúng phân biệt **use ⟂ mention**: `grep -rn 'git diff [^|]*origin/main\.\.\.HEAD'` → 0. + +- **Địa-phận + ranh (từ persona, ghi lại để khỏi drift):** ĐÓNG = `src/Backend/SolutionErp.Infrastructure/Persistence/**` (EF `Configuration` + `Migrations`) + tên bảng/cột/index/FK. Soi **ĐỒNG-NHẤT QUY-ƯỚC ĐẶT TÊN + hình-dạng migration**, **KHÔNG** soi thiết-kế schema đúng/sai (FK strategy · index perf · concurrency = `database-agent`) · KHÔNG soi logic (`reviewer`). Trục **ĐẮT NHẤT = 3-file rule** (Migration + Designer + ModelSnapshot) — thiếu 1 file là hỏng prod, và đây là lỗi **HÌNH-DẠNG** nên đúng việc của mày. + 🔴 **LUẬT LÕI anh giao:** *"các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"* — ở tầng DB luật này **mạnh hơn mọi tầng khác** vì migration đã apply prod thì không rút lại được. + 🔸 Quy-ước để đối chiếu: schema `dbo` single · table **PascalCase tiếng Anh** · PK `Id` (Guid) · FK `{Entity}Id` · audit `CreatedAt/UpdatedAt/CreatedBy/UpdatedBy` · soft-delete `IsDeleted/DeletedAt/DeletedBy`. + +Tag `[s179, sinh-so-do-SUA-5a, chua-spawn-probe, migration-la-3-file-untracked, 3-file-rule, nguoc-don-thuoc-2cham-vo-dung, citation-trap-use-mention]` diff --git a/.claude/agent-memory/front-end-reviewer-style/MEMORY.md b/.claude/agent-memory/front-end-reviewer-style/MEMORY.md new file mode 100644 index 0000000..e5c355f --- /dev/null +++ b/.claude/agent-memory/front-end-reviewer-style/MEMORY.md @@ -0,0 +1,15 @@ +# front-end-reviewer-style Agent — Persistent Memory + +- **S179 (2026-08-07) SINH SỔ — dir này ra đời do SỬA-5a, KHÔNG phải do mày chạy `[LEAD SEED ON-BEHALF; mày CHƯA chạy lần nào — nguồn = đĩa + spec SỬA-6]`:** mày sinh @**S176** (anh chốt đội STYLE 3 vai, lý do đo được: *"mày cứ làm đi làm lại hoài"*), nhưng **3/3 vai style thiếu dir `agent-memory//`** suốt từ đó ⇒ **vô hình với mọi máy đo** (`measure-agent-memory.ps1` enumerate DIRECTORY rồi mới đọc `MEMORY.md` — không dir thì không có dòng nào, và **thiếu-vắng trông y hệt sạch**). Vá @S179 = SỬA-5a. + 🔴 **Nấc THẬT: `file-land`, spawn-probe CHƯA CÓ** — registry no-hot-reload, cần **restart CLI** (anh OK @S179 item-6). Đừng đọc dir này thành "đã chạy rồi". + +- **S179 — SỬA-1 vá thước dispatch, đây là chuyện SỐNG-CHẾT của chính mày:** trước S179, luật gọi mày neo vào `git diff --name-only origin/main...HEAD`. Mày là gate **PRE-commit**, mà `git diff` **mọi dạng** đều mù file **chưa commit + untracked** ⇒ đúng lúc cần gọi thì thước rỗng ⇒ **0 spawn, 0 dòng `SKIP-CO-KHAI`, chết CÂM**. Đo thật: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai mà **0 con được gọi**. + Thước mới (4/4 site): `{ git diff --name-only origin/main..HEAD; git status --porcelain | cut -c4-; } | sort -u` + 🔴 **Bài học NGƯỢC ĐƠN THUỐC — nhớ kỹ, đây là loại bẫy dễ tái phát:** đơn cũ ghi *"đổi ba-chấm → hai-chấm ∪ porcelain"*. Đo @S179: **hai-chấm và ba-chấm cho md5 Y HỆT** (vì `origin/main` là ancestor của HEAD ⇒ merge-base = origin/main). ⇒ vế đổi dấu chấm **KHÔNG sửa được gì**; răng nằm **TRỌN** ở vế `∪ porcelain`. Nếu chỉ swap dấu chấm thì thước nghiệm-thu (`grep 'main...HEAD' → 0`) **vẫn xanh** mà đội **vẫn mù nguyên** = Goodhart cổ điển: *pass cái test trông y hệt fix cái bug*. + 🔴 **Citation-trap kèm theo:** 3 dòng `CẤM origin/main...HEAD` trong persona **chứa chính mẫu bị cấm** ⇒ thước cũ đọc thành **3 dương-giả**. Thước đúng phải phân biệt **use ⟂ mention**: `grep -rn 'git diff [^|]*origin/main\.\.\.HEAD'` (dạng LỆNH THẬT) → 0. + +- **Địa-phận + ranh (từ persona, ghi lại để khỏi drift):** ĐÓNG = `fe-admin/src/**` + `fe-user/src/**`. Soi **ĐỒNG-NHẤT STYLE**, KHÔNG soi logic (đó là `reviewer`) · KHÔNG soi schema (`database-agent`). Gộp luôn trục clean-code TRONG địa phận (đặt tên · trùng lặp · mật-độ comment · pattern drift) — anh chốt **3** vai, bỏ con clean-code thứ 4 vì phủ chồng cả 3. + 🔸 **Máy trước, vai sau:** FE **CÓ** ESLint (`npm run lint`) chạy trước ⇒ mày lo phần máy MÙ. Đây là điểm mày **nhẹ gánh hơn** con BE (BE 0 máy style nào gác). + 🔴 **LUẬT LÕI anh giao:** *"các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"*. Ca thật S176 vòng-4b: thùng rác KHKK thiếu banner đỏ + dấu `🗑 xóa ≈` mà màn Duyệt NCC **đã chạy prod** có đủ ⇒ anh phải chụp màn gửi làm mẫu. Một lượt làm lại **đáng lẽ không cần**. + +Tag `[s179, sinh-so-do-SUA-5a, chua-spawn-probe, nguoc-don-thuoc-2cham-vo-dung, citation-trap-use-mention, may-truoc-vai-sau-eslint]` diff --git a/.claude/agent-memory/lead-stale-auditor/MEMORY.md b/.claude/agent-memory/lead-stale-auditor/MEMORY.md index eee404d..2dcd877 100644 --- a/.claude/agent-memory/lead-stale-auditor/MEMORY.md +++ b/.claude/agent-memory/lead-stale-auditor/MEMORY.md @@ -1,5 +1,7 @@ # Lead-View-Auditor Agent — Persistent Memory +- **S179 (2026-08-07) @open — `LEAD-STALE: 9 FLAG`, máy-nền 51 giữ 0 `[LEAD SEED ON-BEHALF]`:** **9/9 FLAG đều NGOÀI tập máy phán được** — đó là chỗ vai người còn giá trị. Lead vá **8 ô**: FLAG-1 `view-stale-status` 4 slot HANDOFF (68)-(71) mang dấu 🔴 mở suốt S173→S179 dù **đã ratify + land @S172** (`git log -1 -- HANDOFF` = `3a6eb92`, **0 commit chạm suốt quãng**) · FLAG-2/3 roster 23 vs đĩa **26** ở 2 site `README` · FLAG-4 Tests 644 (lead **chạy thật** `dotnet test` ra **45+600=645**, breakdown cũ "599" cũng lệch) · FLAG-5 Mig 71→**72** + Gotchas 86→**87** · FLAG-6 header CURRENT S168→**S179** · FLAG-9 user-mem 59→**60**. FLAG-7 lead vá **đúng chỗ hỏng = CON-TRỎ** (`§In Progress` tự nó stale-by-design, cái đứt là con-trỏ giải-cứu trỏ vào ô cũng đã ô-nhiễm). FLAG-8 lead **CỐ Ý KHÔNG vá** (`_mind:63` nằm trong block cũ BẤT BIẾN — sửa đè để lấy số đẹp là phạm luật; đính chính thuộc MIND-8). 🔴 **#53:** return đầu **garble giữa câu**, vớt trọn bằng `SendMessage` resume — mảnh garble vẫn mang datum thật (`TOTAL 51 / 2 HIGH`). 🔸 **Bài:** *"đã đính chính TRONG PHIÊN" ≠ "đã LAND trên đĩa"* — chính lỗi 4-slot này đã được `run.md` S173 khai là "lead đã đính chính", mà đĩa nói không. Tag `[s179, 9-flag-ngoai-may, 4-slot-song-6-phien, tests-do-that-645, con-tro-cuu-ho-dut, #53-resume, seed-on-behalf]` + - **S173 (2026-08-05) @open bookend L11-w1 — `LEAD-STALE: 11 FLAG (SAN, khong phai TONG) + 1 INFORM + 7 VERIFIED-CLEAN` (`view-stale-count` 5 · `view-stale-status` 4 · `view-stale-header` 2; HIGH 1/MED-HIGH 2/MED 4/LOW-MED 1/LOW 3) `[LEAD SEED ON-BEHALF — INFORM-only, single-writer = lead (B3)]; nguon `runs/2026-08-05-S173-bookend-open/sub-lead-stale-open-S173.md` 27.244 B, 11/11 dung khuon C11`:** 🔴 **FLAG-4 (HIGH)** `6730eb4` land 5 slot vao **6 nha MAY** (`pause.md`·`session-end.md`·`memory-budget.json`·`.session-counter.json`·`h24-signal-write.ps1`·`.mfe-state.json`) va **0 nha SO** — `grep -c HANDOFF` = **0**, `grep -c "✅"` trong khoi `HANDOFF:9-25` = **0**. **Lan thu 4 lien tiep cung hinh dang** (S162·S166·S172·S173): *so dung o noi lead lam viec, so cua owner giu ban cu* — va lan nay **da tieu mot luot quyet-dinh cua owner THAT**. `ring2` tai-dung **HELD 4/4** (suyt phan BROKE vi diary cua chinh no ghi nguoc dau ⇒ **luat moi: claim chuoi ≥3 ky CAM cham bang diary**). 🔴 **FLAG-10** diem mu **tu-quy-chieu**: persona cua CHINH VAI NAY `.claude/agents/lead-stale-auditor.md:45` day "canonical `STATUS.md:19` = 54" trong khi canonical la `:471` = **113**; tien-de vi-du (`CLAUDE.md` ~60) **0 hit** tren dia. Luat bat phai soi file nay nam **cach cho vi-pham 12 dong**. **FLAG-8/9** khai "da va 4 site @S172" nhung dia chi **2/4** (`:102` `DUE hom nay` + `:442` `8d qua han` con nguyen); 3/3 con-tro `HANDOFF:` chet vi file **chen segment len DAU** (+40 dong) ⇒ **moi con-tro so-dong viet cho luot nay chac chan thoi o luot sau**. **INFORM-1** do lai `find -type d -empty` = **4** (bac claim "0" cua `lead-gap`) nhung **co y KHONG nang thanh FLAG** (return vai ngang hang, chua vao so nao) ⇒ nhuong turf `ring2` — **ky-luat dung**. 🔴 **`ring2` bat 1 nac ✅ SAI:** khai coverage `STATUS` = ✅ CHAM, that chi **3,5% (30/853 dong)**, va dung vung bi ✅ che giau 1 FLAG that: `STATUS:672` mang nhan **L8** khi dang **L11** trong khi khoi ganh 4 viec song. Coverage tu khai thung 4/4 trung thuc (chua cham ACTIVE-MARKS · migration-todos · WAL/_mind; 19/23 persona moi grep so-cung) ⇒ **11 = can-duoi**. Tag `[s173, 11-flag-san, lan-4-lien-tiep-may-khong-so, tu-quy-chieu-persona-minh, con-tro-so-dong-tu-thoi, nac-clean-sai-che-flag-that, chuoi-3-ky-cam-cham-bang-diary]` - **S172 (2026-08-05) @close bookend L10-w4 — `9 FLAG (SÀN, không phải TỔNG) + 1 ESCALATE + 11 VERIFIED-CLEAN` · `view-stale-count` 6 · `view-stale-status` 2 · `view-residual-asym` 1 · SEV HIGH 1/MED 4/LOW 4 `[LEAD SEED ON-BEHALF @closeout M9 — vai INFORM-only, single-writer = lead (B3 VERIFY→APPEND)]; nguồn `runs/2026-08-05-S172-bookend-close/sub-lead-stale-close-S172.md` 27.633 B + return`:** 🔴 **FLAG-1 (HIGH) đắt gấp đôi:** `STATUS:479` giữ bundle đời cũ trong khi artifact của chính lead hôm đó đo live `Ajv-MaCz`/`YsXRkBSR` + chứng 2 hash cũ **rơi về `text/html`**. (a) `STATUS:6` cố ý KHÔNG chép số mà trỏ *"canonical ở :479"* ⇒ **con-trỏ B1 nhắm vào ô nhiễm**; (b) chính ô đó **tự viết quy trình cập nhật của nó** (*"nguồn = cicd-verify lượt kế"*) — lượt kế đã đáp, **0 người thi hành**. **Lần thứ hai cùng ô** (S166 F-2). `ring2` F-2 HELD bằng **nguồn NGOÀI repo**. 🔴 **ESCALATE-1 — gặp ca KHÔNG xếp được vào enum ĐÓNG và TỪ CHỐI ép-vừa** (đúng thứ bị TRƯỢT @S162 FLAG-16): lead tuyên *"role thường có đủ Read+Update"* dựa trên 2 tài-khoản mà slot (64) khai **cả hai mang vai cấp riêng**, 0/2 user trần ⇒ nhánh *"vai thường KHÁC vẫn 403"* (hình dạng gốc #85) chưa loại. Báo verbatim + đề nghị *"sửa câu chữ HOẶC mở enum"*; `ring2` phán **đủ cho CA, không đủ cho CLASS**. 🔴 **Sợi chỉ rút ra:** lead **ĐO rất tốt**; trượt nằm ở **quãng đường từ phép đo VỀ SỔ** — số đúng dừng ở artifact, còn `STATUS:479` (owner đọc) và WAL (`/tiep` nạp) giữ số đợt trước. **Lần thứ ba liên tiếp cùng hình dạng** (S162 · S166 · S172). **Khai coverage thủng, cấm đọc thành sạch:** chưa chạm `gotchas.md`/`migration-todos.md`/`ACTIVE-MARKS.md`/21-23 persona ⇒ **9 là SÀN**; `ring2` chấm: khai-thủng làm số **MẠNH hơn**, dùng được chiều cận-dưới, cấm chiều độ-phủ. Tag `[s172, flag1-canonical-o-nhiem-lan-2, tu-choi-ep-vua-enum, do-tot-chep-so-kem, 9-la-san]` diff --git a/.claude/agent-memory/reviewer/MEMORY.md b/.claude/agent-memory/reviewer/MEMORY.md index 971972b..612dcce 100644 --- a/.claude/agent-memory/reviewer/MEMORY.md +++ b/.claude/agent-memory/reviewer/MEMORY.md @@ -1,5 +1,7 @@ # Reviewer Agent — Persistent Memory +- **S179 (2026-08-07) C7 re-review sau vá SỬA-1..6b — `PASS-WITH-8`, 3 MAJOR `[LEAD SEED ON-BEHALF]`:** 🔴 **Lượt ăn tiền nhất từ trước tới nay của vai này: 2/3 MAJOR là lỗi TRONG CHÍNH BẢN VÁ vừa pass 12/12 acceptance.** [1] `git status --porcelain | cut -c4-` **đẻ path RÁC** — rename in MỘT dòng `R old -> new`, path có dấu cách bị quote; lead dựng sandbox đo lại: **2/2 MISS**, thước đề-xuất **2/2 OK**. [2] đổi ba-chấm→hai-chấm **KHÔNG vô-hại mà là REGRESSION có điều-kiện** — lead ĐÚNG rằng md5 y hệt, nhưng chỉ khi `origin/main` còn ancestor; sandbox phân-kỳ: hai-chấm liệt cả `upstream_only.txt` (= ĐÃ PRODUCTION) vào "phần MỚI", ba-chấm ra đúng. ⇒ **thủ phạm thật luôn là `git diff` mù untracked**, lead gán sai tội cho ba-chấm. [3] khối MIRROR lead vừa viết mang số `:112` trong khi chính 6 dòng đó đẩy thành 118 — **mỏ-neo TỰ-VÔ-HIỆU ngay lúc viết**; lead vá thành `:118` thì 3 dòng vá đẩy tiếp thành 121 ⇒ **sửa gốc = bỏ số dòng, neo TÊN SELECTOR**. [4] census "8/9 khoá" của lead THIẾU — §D gốc 25 mục, **3 ý đóng im lặng**, 1 trong 3 (`Đợt B — NỘI DUNG từng mục`) **0 hit ở cả `_mind` lẫn `_context`**. [5] con-trỏ verbatim `ca9208f` sai (thiếu 4.636 B) ⇒ lead vá **per-block**: `d081681` cho MIND-1, `727a512` cho 3 block S179, đối chứng từng cái resolve ra bản CHƯA nén. 🔸 **Bài đắt nhất:** *chẩn-đoán sai vẫn pass acceptance* — cả 2 MAJOR lọt vì acceptance đo **HÌNH-DẠNG chuỗi**, không đo **HÀNH-VI**. 🔴 #53 garble, resume vớt trọn; mảnh garble mang "a third thước defect" ⇒ lead biết có cái thứ 3 trước khi đọc verdict. Tag `[s179, C7, bat-loi-trong-ban-va, ba-cham-dung-hai-cham-regression, cut-c4-path-rac, moc-neo-tu-vo-hieu, acceptance-do-hinh-dang-khong-do-hanh-vi]` + - **S171 (2026-08-04) — 3 lane lens ĐỐI-KHÁNG (`/fable-clone reviewer` ×3), **cả 3 CHẾT hết-giới-hạn nhưng ĐĨA CỨU 74.070 B** `[LEAD HARVEST HOI-TO @S172 — no mo tu closeout truoc; owner slot (71) chot 'gom va sleep thi auto, tu quyet'. Nguon = artifact tren dia, KHONG suy dien]; nguồn `runs/2026-08-04-S171-khkk-ui-mirror-pe/sub-reviewer-lens-{feasibility,regression,fidelity}-s171.md` 26.461 + 24.432 + 23.177 B`:** **feasibility 8 ĐẠT / 6 BROKE** — mở đầu bằng **tự bác giả-thuyết của chính lane** (*'chỉ ghi 1 nhánh' = SAI; claim D-2 HELD, ≥9 chỗ ghi → thật 10*); bắt **trích-dẫn hỏng dạng nhẹ**: `WorkflowService.cs:552` **không trỏ vào cái gì cả** (call-site thật `:485`/`:554`, định-nghĩa ở file KHÁC) nhưng **nội dung claim vẫn HELD** ⇒ *cite sai ≠ claim sai*, phải tách. **regression 8 ĐẠT / 4 BROKE / 10 bỏ-sót** — phát hiện nặng nhất: **A-6 kiểm SAI KHOÁ ⇒ lỗ thủng NGAY TRONG hàng rào bảo-vệ R-4** (bắt `canPe`); R-4 HELD nhưng *lý-do bản invest đưa QUÁ THÔ*. **fidelity DỞ** (§6+§8 trống, `VERDICT=?`) — lead derive ≈12/6/3; bảng N-1→N-4 đối chiếu **từng claim bằng lệnh dán kèm**: N-1 tự phân loại 35 dòng ⇒ khớp 27/6/2 · N-2 khớp chính xác `:106/:125/:249` · **N-3 HELD về THỨ TỰ nhưng lệch con số hình-thức** (chỉ 3 hit `title="N.` vì Section 2 dùng template-literal đếm động, Section 4 là `
` trần) — 🔴 **chính bẫy này sau đó lead tự dẫm** (grep `'
APPEND)]; nguon `runs/2026-08-05-S173-bookend-open/sub-tooling-auditor-open-S173.md` 26.838 B`:** ① skill 6+23+19 **0-delta** · ② roster **23/23 khop CA 5 be-mat** · ③ plugin 18/15/3 **0-delta 3 phien**; ④ docs DRIFT. 🔴 **F-1** `STATUS:473` `Gotchas | 86` SAI — ground-truth `gotchas.md` = **87** (87 anchor, max `:1389` #87 @S172); `STATUS:6` DUNG. O `:473` la **dau chuoi B1** (CLAUDE.md + skills/README tro ve) ⇒ **3 be-mat sai theo**. 🔴 **F-2** commit `6730eb4` land 5 slot ratify (68·69·70·71·72) ma **KHONG cham `docs/HANDOFF.md`** (`grep -c HANDOFF` = **0**) ⇒ ca 5 con nguyen duoi `🔴 CHO ANH @S172`, 0 gach. **Ca that: da LUA CHINH LEAD** — lead bao owner "5 slot cho anh" roi phai dinh chinh giua phien. 🔴 **F-3** enum mo 11→12 ma `hmw.js:33` con "11 class", `lead-stale-auditor.md:39/:41/:45-49` con "5 class" — **`ring1` bat SOT be-mat LIVE thu 6** (`agent-memory/ring2-audit/MEMORY.md:25`, duoi `## 🎯 Role baseline` = **nap moi spawn**) ⇒ F-3 that = **3 file / 5 site**, khong phai 2/4. **Probe-1** slot (72) het hieu-luc CA 3 ve (`session-end.md:68-70` da go nac "khai chet" · owner da OK · so nay 12/13=92% khong phai 11/13). **Probe-2** monthly drift-audit **CHUA CHAY** — lan cuoi `881783c` 2026-07-01. 🔴 **TRUOT rieng (ring1 bat):** so "20 commit" **khong tai-dung duoc** (that: 89 total / 21 non-wal) vi `git log --since=` **PRUNE IM LANG 22 commit**, trong do **3 cai la `[CLAUDE]` that** ⇒ **cam dung `--since` lam nguon dem**; ket-luan van song vi ring1 quet lai tren tap day du. Tag `[s173, f2-land-may-khong-land-so, dau-chuoi-b1-3-be-mat, since-prune-im-lang, enum-3-file-5-site]` - **S168 (2026-08-01) @close — `PASS_WITH_FLAGS-7`: ① skill / ② roster / ③ plugin SỐ đều PASS (**23=23=23=23**, plugin 0-delta 18/15/3) nhưng ④ **docs DRIFT-FOUND** `[LEAD HARVEST HOI-TO @S172 — no mo tu closeout truoc; owner slot (71) chot 'gom va sleep thi auto, tu quyet'. Nguon = artifact tren dia, KHONG suy dien]; nguồn `runs/2026-08-01-S168-bookend-close/sub-tooling-auditor-close-S168.md` 17.719 B`:** Vào bằng `/tiep` (window-6 L9), **không có bookend @open** ⇒ diff-vs-last lấy mốc = **S162 @close** (entry L1 gần nhất của chính vai) + commit S167 — nghề chọn-mốc-khi-thiếu-@open này giữ dùng tiếp. 3 drift: HANDOFF **trễ 1 cửa-sổ** · còn **hỏi câu owner ĐÃ chốt và ĐÃ ship** · luật fixture-TEST mới **0 bề mặt bền**. 🔴 **Cái đắt nhất: 1 vá-đổi-đường-dẫn SÓT 6 SITE CÙNG LỚP** — đúng bài `được-chỉ-1-chỗ ⇒ grep CẢ LỚP`, và **chính vai này tái phạm @S172** (vá `skills/README:20` mà không quét `:90` cùng file ⇒ `ring1-audit` A40 chấm TRƯỢT). ⇒ bài học đã ghi mà vẫn lặp ⇒ **cần phép máy, không phải trí nhớ**. Tag `[s168, pass-with-flags-7, moc-khi-thieu-bookend-open, sot-6-site-cung-lop, tai-pham-S172]` diff --git a/.claude/agents/README.md b/.claude/agents/README.md index fcfae76..1610c7d 100644 --- a/.claude/agents/README.md +++ b/.claude/agents/README.md @@ -24,7 +24,7 @@ ## 🎯 Architecture -> ⓘ **Diagram dưới = 7 core lane (pre-S47 snapshot) — KHÔNG phải roster hiện-hành.** Roster THẬT = 7 core (diagram) + 🩷 frontend-designer (S47) + 🔵 database-agent (S52) + 📄 office-document (S107) + 🟫 tooling-auditor H1 + ⬜ harvest-curator H2 (2026-06-07 Harness 1) + 🔷 lead-stale-auditor + 🔶 lead-gap-auditor (**H24, S121 W2**) + 🧪 harness-eval + 🧪 harness-refine + 🧪 harness-audit (**trio-memory, S141**) + 🔬 ring1-audit + 🔬 ring2-audit + 🔬 ring4-audit (**round-KIỂM ×3, S145 — C4/C4b TÁCH mỗi-vòng-1-con: vòng tooling/harvest · soi-lead H24 · nén-ngủ**) + 🔎 ctx-curator + 🔎 ctx-verifier + 🔎 ctx-audit (**bộ-ba vòng Ctx lớp trí-nhớ MỀM `_mind`, S153 — adopt `0df10df4`, OWNER-VETO hub-form 3-vai: vai-1 nháp@mỗi-pause [carve-out §1] · vai-2 đối-chiếu+nạp@mỗi-tiep · vai-3 chuỗi@2-bookend**) — xem skill matrix + decision tree + tool grant dưới. Số vai canonical → [`docs/STATUS.md`](../../docs/STATUS.md) §Sub-agents. (Cosmetic ASCII chưa vẽ lại — H1 tooling-auditor flag drift này @session-start.) +> ⓘ **Diagram dưới = 7 core lane (pre-S47 snapshot) — KHÔNG phải roster hiện-hành.** Roster THẬT = 7 core (diagram) + 🩷 frontend-designer (S47) + 🔵 database-agent (S52) + 📄 office-document (S107) + 🟫 tooling-auditor H1 + ⬜ harvest-curator H2 (2026-06-07 Harness 1) + 🔷 lead-stale-auditor + 🔶 lead-gap-auditor (**H24, S121 W2**) + 🧪 harness-eval + 🧪 harness-refine + 🧪 harness-audit (**trio-memory, S141**) + 🔬 ring1-audit + 🔬 ring2-audit + 🔬 ring4-audit (**round-KIỂM ×3, S145 — C4/C4b TÁCH mỗi-vòng-1-con: vòng tooling/harvest · soi-lead H24 · nén-ngủ**) + 🔎 ctx-curator + 🔎 ctx-verifier + 🔎 ctx-audit (**bộ-ba vòng Ctx lớp trí-nhớ MỀM `_mind`, S153 — adopt `0df10df4`, OWNER-VETO hub-form 3-vai: vai-1 nháp@mỗi-pause [carve-out §1] · vai-2 đối-chiếu+nạp@mỗi-tiep · vai-3 chuỗi@2-bookend**) + 🎨 front-end-reviewer-style + ⚙️ back-end-reviewer-style + 🗄️ database-reviewer-style (**ĐỘI STYLE ×3, S176 — anh chốt trực-tiếp, lý-do đo được "mày cứ làm đi làm lại hoài"; địa-phận RỜI theo glob diff, trục ĐỒNG-NHẤT ⟂ `reviewer` ĐÚNG-SAI**) — xem skill matrix + decision tree + tool grant dưới. Số vai canonical → [`docs/STATUS.md`](../../docs/STATUS.md) §Sub-agents. (Cosmetic ASCII chưa vẽ lại — H1 tooling-auditor flag drift này @session-start.) > 🔴 **Bài S143 — enumeration TÊN cũng lão-hoá, và grep-theo-SỐ không bắt được:** sweep roster wave S141–S142 đặt acceptance là `grep "roster 14|14/14|14 folder|14 vai"` → 0 hit ⇒ tuyên bố sạch. Nhưng đúng 2 dòng tự xưng là bản gốc về roster — dòng NÀY ("Roster THẬT") và `:225` ("VALID_ROLES … ĐỦ roster") — **liệt kê TÊN, không chứa con số nào** ⇒ lọt lưới, giữ 14 vai qua cả wave. **Acceptance cho lần sau: ĐẾM PHẦN TỬ trong mọi enumeration rồi so canonical, đừng so hình-dạng chuỗi.** ``` @@ -64,11 +64,21 @@ - Test → **`test-specialist`** dedicated (KHÔNG để implementer kiêm) - Deploy claim → `cicd-monitor` sau push (skip docs-only gotcha #41) - Heavy diff / security / wire BE claim → `reviewer` pre-commit -- 🔴 **ĐỘI STYLE (S176, anh chốt) — MỖI LƯỢT REVIEW gọi THÊM 1 lần, song song `reviewer`:** `front-end-reviewer-style` · `back-end-reviewer-style` · `database-reviewer-style`. - - **Gọi con nào = theo DIFF chạm đâu** (`git diff --name-only origin/main...HEAD`): `fe-*/src/**` → FE · `src/Backend/**` trừ `Persistence/**` → BE · `Persistence/**` → DB. Diff không chạm ⇒ **KHÔNG gọi**, không phải bỏ sót. +- 🔴 **ĐỘI STYLE (S176, anh chốt) — MỖI LƯỢT REVIEW gọi THÊM 1 lần, song song `reviewer`** *(🔴 **hiệu-lực sau restart CLI** — SỬA-5c @S179: registry là ảnh-chụp lúc khởi phiên, KHÔNG hot-reload; trước khi restart thì lệnh này **chưa thi-hành được**, và `ls` + grep `VALID_ROLES` chỉ là điều-kiện CẦN. Kẽ này sinh ra vì `README` ra lệnh mà `STATUS` khai `verified-pending-restart` — 2 doc nói 2 giọng)*: `front-end-reviewer-style` · `back-end-reviewer-style` · `database-reviewer-style`. + - **Gọi con nào = theo DIFF chạm đâu.** 🔴 **Thước ĐÚNG (SỬA-1, vá @S179) — CẤM `git diff` trần, CẤM ba-chấm:** + ```bash + { git diff --name-only origin/main...HEAD # ĐÃ COMMIT — BA-chấm, neo merge-base + git diff --name-only HEAD # đang sửa (tracked); tách rename thành 2 vế + git ls-files -o --exclude-standard # UNTRACKED + } | sort -u + ``` + `fe-*/src/**` → FE · `src/Backend/**` trừ `Persistence/**` → BE · `Persistence/**` → DB. Chạm ⇒ gọi; **không chạm ⇒ KHÔNG gọi + ghi 1 dòng `SKIP-CO-KHAI`** (im lặng hoàn toàn là không phân biệt được với chết câm). + - 🔴 **Vì sao phải là công-thức trên:** đội này gate **PRE-commit**, mà `git diff` mọi dạng đều **MÙ với file chưa commit + untracked** ⇒ thước rỗng đúng lúc cần gọi. Đo thật: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai mà **0 con được gọi, 0 dòng `SKIP-CO-KHAI`**. Fault-inject 2 chiều: thả probe untracked → cũ **0 hit** / mới **bắt**; dọn probe → mới **im**. + - 🔴 **2 bẫy lượt vá ĐẦU @S179 tự dính, `reviewer` C7 bắt — ghi để không tái sinh:** ① đổi ba-chấm→hai-chấm **KHÔNG phải vô-hại**: nó chỉ tương-đương khi `origin/main` còn là **ancestor**; cây phân-kỳ (routine sau `git fetch`) thì hai-chấm liệt cả file **chỉ có trên origin/main** — tức **ĐÃ PRODUCTION** — vào "phần MỚI" ⇒ **REGRESSION có điều-kiện**. **Ba-chấm mới đúng** (neo `merge-base`); thủ phạm thật luôn là `git diff` mù untracked. ② `git status --porcelain | cut -c4-` **đẻ path RÁC**: rename in **một dòng** `R old -> new`, và path có dấu cách bị **quote** ⇒ khớp glob hỏng, bỏ sót đúng file vừa `git mv`. Sandbox: **2/2 MISS** vs công-thức trên **2/2 OK**. - **Trục của đội này ⟂ `reviewer`:** đội STYLE soi **ĐỒNG-NHẤT** (có giống bản đã chạy không), `reviewer` soi **ĐÚNG-SAI** (có bug không). Chạy song song được vì không giẫm nhau. - 🔴 **Luật lõi anh giao:** *"các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"* — lý do sinh đội: **"mày cứ làm đi làm lại hoài"**. Ca thật S176 vòng-4b: thùng rác KHKK thiếu banner + dấu xoá mà màn Duyệt NCC **đã chạy prod** có đủ ⇒ anh phải chụp màn gửi làm mẫu. Một lượt làm lại **đáng lẽ không cần**. - - 🔸 **Máy trước, vai sau:** FE có ESLint chạy trước (`npm run lint`); **BE hiện 0 máy style nào gác** (đo S176) nên con BE gánh nặng hơn. Cắm được `.editorconfig` + `dotnet format --verify-no-changes` vào CI thì trả lớp cơ-học về máy và **cập nhật lại persona con BE**. + - 🔸 **Máy trước, vai sau:** FE có ESLint chạy trước (`npm run lint`); BE gánh nặng hơn. 🔴 **Số liệu "BE có/không máy style gác" KHÔNG chép ở đây** (SỬA-6a @S179) — nó là **phép-đo per-spawn** sống trong `back-end-reviewer-style.md` §0. Lý do: claim đó từng bị chép ra **4 site**, cắm `.editorconfig` là 4 chỗ sai cùng lúc mà detector chỉ so SỐ nên không bắt. + - 🔴 **VÙNG MÙ CHỌN CHỦ ĐÍCH — khai thẳng, đừng đọc "3 vai" thành "đã phủ hết"** (SỬA-5b @S179): ngoài 3 glob của đội (`tests/**` · `scripts/**` · `.gitea/**` · `docs/**` · `.claude/**`) **và** toàn bộ **seam FE↔BE** (DTO ⟂ TS type · route string 2 phía · `MenuKeys.cs` ⟂ `menuKeys.ts`) = **0 vai style nào soi**. Seam là chỗ lệch **đắt nhất** mà lại rơi đúng khe giữa 3 địa-phận rời. ⇒ phần đó thuộc **`reviewer` + lead**, KHÔNG phải đội STYLE. - 🧊 Anh nêu ban đầu **4** con (có `clean-code-reviewer-style`) rồi tự chốt lại **3** ("3 con tao nhầm" + "chốt theo ý mày"): con clean-code phủ chồng cả 3 con kia nên **không viết nổi câu scope rời** mà roster này bắt buộc ⇒ trục clean-code (đặt tên · trùng lặp · mật-độ comment · pattern drift) **gộp vào từng con trong địa phận của nó**. **Em main solo CHỈ khi:** schema/UX/architecture decision · cross-stack tight coupling · bug fix reasoning chain · gotcha #53 fallback (spawn truncate/529 → em main solo reliable, proven S37 BE 700 LOC + FE 4 file). @@ -188,7 +198,7 @@ | test-specialist | `contract-workflow` + `permission-matrix` | | reviewer | `dependency-audit-erp` + `contract-workflow` + `permission-matrix` | | **front-end-reviewer-style** (đội STYLE, S176) | `permission-matrix` — 🔴 luật style FE **KHÔNG** ở skill mà ở `docs/rules.md` + **bản ĐÃ PRODUCTION** (B1 trỏ, cấm chép). Chạy SAU máy `npm run lint` | -| **back-end-reviewer-style** (đội STYLE, S176) | `contract-workflow` + `permission-matrix` — 🔴 BE **0 máy style gác** (đo S176: 0 `.editorconfig`/analyzer/`dotnet format`) nên vai gánh cả lớp cơ-học, khác con FE | +| **back-end-reviewer-style** (đội STYLE, S176) | `contract-workflow` + `permission-matrix` — 🔴 BE gánh cả lớp cơ-học, khác con FE — **trạng-thái máy-gác KHÔNG chép ở đây**, nguồn sống = phép-đo per-spawn trong `back-end-reviewer-style.md` §0 (SỬA-6a @S179; 🔴 site này là **cái thứ 5**, spec S176 chỉ liệt 4 — acceptance C6a bắt được) | | **database-reviewer-style** (đội STYLE, S176) | `ef-core-migration` (3-file rule = trục đắt nhất) — 🔴 chỉ soi ĐẶT TÊN + hình-dạng migration, **KHÔNG** phán schema (đó là `database-agent`) | | cicd-monitor | `iis-deploy-runbook` + `dependency-audit-erp` + `ef-core-migration` | | frontend-designer | `frontend-design` + `senior-frontend` + `brand-guidelines` + `theme-factory` + `webapp-testing` (FD2 loop) + `web-artifacts-builder` | @@ -225,7 +235,7 @@ MỌI agent trong roster có **4 RAG-READ MCP**: `search_memory` + `search_code` | Skill/plugin (nguồn) | Value-locus | Map → vai | Ghi chú | |---|---|---|---| | `sql-database-assistant` (standalone) | skill-only | investigator-codebase + implementer-backend | SQL/EF query; đọc kèm `ef-core-migration` (KHÔNG override pin EF Core 10 / dbo single-schema) | -| `frontend-design` (standalone, KHÔNG enable plugin trùng) | skill-only | frontend-designer | duplicate plugin↔standalone → chọn standalone | +| `frontend-design` (standalone; 🔴 plugin trùng **ĐANG enabled** — cố ý KHÔNG dùng) | skill-only | frontend-designer | duplicate plugin↔standalone → chọn standalone | | `skill-creator` | skill-only | mọi sub (khi tạo skill project) | additive | | `claude-md-management` (`claude-md-improver`) | skill+cmd | em main | doc-maintenance | | `pr-review-toolkit` (silent-failure-hunter / type-design-analyzer / comment-analyzer / pr-test-analyzer) | agent-bearing | reviewer (tham-chiếu .md như CHECKLIST, KHÔNG enable agent) | giữ roster `reviewer` canonical | @@ -248,7 +258,7 @@ MỌI agent trong roster có **4 RAG-READ MCP**: `search_memory` + `search_code` - **Keyword = QUYỀN, KHÔNG lệnh (T4):** "workflow"/"ultracode" mở quyền hỏi, KHÔNG auto-run. Mode-OFF + "chạy workflow" → TỪ CHỐI + nhắc `/ultra-on`. CẤM native `/effort ultracode`. *(Bài học 515K-token false-trigger.)* - **Scope (S1):** Workflow fan-out CHỈ repo SOLUTION_ERP — KHÔNG fan-out repo/corpus khác. - **Checkpoint (S2):** `hmw.js` **throw** nếu `checkpointApproved≠true` (mechanized tripwire anti-accidental). Em main BÁO {số agent·vai·task} @inform → set cờ → fan-out (KHÔNG chờ confirm từng lần; marker-ON=consent). Sub KHÔNG spawn sub (S3). -- **VALID_ROLES (whitelist `hmw.js` — ĐỦ roster; số vai canonical → [`docs/STATUS.md`](../../docs/STATUS.md) §Sub-agents, B1 KHÔNG chép số):** `investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer` · `database-agent` (+S57 — S56 đã dùng 3× qua fail-soft WARN) · `office-document` (+S107 — Office WRITE OD1–OD10) · `tooling-auditor` + `harvest-curator` (+S110 anh-directed — H21 roster-parity lệnh-B) · **`lead-stale-auditor` + `lead-gap-auditor` (+S121 W2 — H24 lead-self-audit)** · **`harness-eval` + `harness-refine` + `harness-audit` (+S141 — trio-memory)** · **`ring1-audit` + `ring2-audit` + `ring4-audit` (+S145 — C4/C4b round-KIỂM ×3: vòng tooling/harvest · soi-lead H24 · nén-ngủ; AUTO fire-after-measure, no-self-exempt, NO-OP nếu vòng không đo)** · **`ctx-curator` + `ctx-verifier` + `ctx-audit` (+S153 OWNER-VETO hub-form 3-vai `0df10df4` — vòng Ctx lớp mềm `_mind`: vai-1 KIỂM-nháp @mỗi-`/pause` [carve-out duy nhất của luật "NGỪNG spawn" §1] · vai-2 ĐỐI-CHIẾU+NẠP @mỗi-`/tiep` · vai-3 SOI-CHUỖI 2 đầu phiên; cả 3 trả CHỈ văn-bản)**. 🔸 **Cả 13 monitor đều INFORM-only, lane RETURN-only** (propose-only; 13 + 10 worker = roster 23, số canonical → STATUS §Sub-agents). 🔴 **KHÔNG đọc "KHÔNG Write/Edit" thành cơ-chế chặn — đo S143:** frontmatter 9 vai read-only **không khai** `Write/Edit`, nhưng **runtime VẪN cấp**, nối ở cuối tool-list (nhân-chứng trực-tiếp: `reviewer` đã Write+Edit thật trong `runs/2026-07-22-S143-closeout-audit/`). Whitelist = **tuyên-bố ý-định**; containment THẬT = em main single-writer + git-diff commit-gate. Role lạ ∉ VALID_ROLES → `hmw.js` **THROW (STOP-HARD)** + báo owner (S4c, DIRECTED REC-3 2026-07-13); role-less null → inherit lead. +- **VALID_ROLES (whitelist `hmw.js` — ĐỦ roster; số vai canonical → [`docs/STATUS.md`](../../docs/STATUS.md) §Sub-agents, B1 KHÔNG chép số):** `investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer` · `database-agent` (+S57 — S56 đã dùng 3× qua fail-soft WARN) · `office-document` (+S107 — Office WRITE OD1–OD10) · `tooling-auditor` + `harvest-curator` (+S110 anh-directed — H21 roster-parity lệnh-B) · **`lead-stale-auditor` + `lead-gap-auditor` (+S121 W2 — H24 lead-self-audit)** · **`harness-eval` + `harness-refine` + `harness-audit` (+S141 — trio-memory)** · **`ring1-audit` + `ring2-audit` + `ring4-audit` (+S145 — C4/C4b round-KIỂM ×3: vòng tooling/harvest · soi-lead H24 · nén-ngủ; AUTO fire-after-measure, no-self-exempt, NO-OP nếu vòng không đo)** · **`ctx-curator` + `ctx-verifier` + `ctx-audit` (+S153 OWNER-VETO hub-form 3-vai `0df10df4` — vòng Ctx lớp mềm `_mind`: vai-1 KIỂM-nháp @mỗi-`/pause` [carve-out duy nhất của luật "NGỪNG spawn" §1] · vai-2 ĐỐI-CHIẾU+NẠP @mỗi-`/tiep` · vai-3 SOI-CHUỖI 2 đầu phiên; cả 3 trả CHỈ văn-bản)** · **`front-end-reviewer-style` + `back-end-reviewer-style` + `database-reviewer-style` (+S176 ĐỘI STYLE — anh chốt trực-tiếp; địa-phận RỜI theo glob diff: `fe-*/src/**` · `src/Backend/**` trừ `Persistence/**` · `Persistence/**`; trục ĐỒNG-NHẤT style ⟂ `reviewer` ĐÚNG-SAI logic ⇒ chạy SONG SONG)**. 🔸 **Mọi monitor đều INFORM-only, lane RETURN-only** (propose-only). 🔴 **Số vai canonical → [`docs/STATUS.md`](../../docs/STATUS.md) §Sub-agents — CỐ Ý KHÔNG chép số ở đây** (B1; 🧊 bản trước chép *"13 + 10 worker = roster 23"* **ngay trong chính câu nói KHÔNG-chép-số**, và số đó trượt lại đúng 1 wave sau S176 — `lead-stale-auditor` FLAG-2 @S179 bắt). 🔴 **KHÔNG đọc "KHÔNG Write/Edit" thành cơ-chế chặn — đo S143:** frontmatter 9 vai read-only **không khai** `Write/Edit`, nhưng **runtime VẪN cấp**, nối ở cuối tool-list (nhân-chứng trực-tiếp: `reviewer` đã Write+Edit thật trong `runs/2026-07-22-S143-closeout-audit/`). Whitelist = **tuyên-bố ý-định**; containment THẬT = em main single-writer + git-diff commit-gate. Role lạ ∉ VALID_ROLES → `hmw.js` **THROW (STOP-HARD)** + báo owner (S4c, DIRECTED REC-3 2026-07-13); role-less null → inherit lead. - 🔴 **2 vai H24 = trục RIÊNG, KHÔNG gộp H1/H2:** H1 `tooling-auditor` = tooling-freshness · H2 `harvest-curator` = harvest-integrity · **H24 = soi chính LEAD** (`lead-stale-auditor` = cái CÓ-nhưng-LỆCH · `lead-gap-auditor` = cái BỊ THIẾU). Class-flag lấy từ **enum ĐÓNG** `lead_self_audit.flag_classes` (`.claude/agent-memory/memory-budget.json`) — **vai KHÔNG tự chế class**; cặp light chạy **VÔ-ĐIỀU-KIỆN mỗi bookend** (hình B @S149); chỉ **`deep`** còn cổng `h24_cadence.deep_every` (`session-start §2.1.8` · `session-end §L.b(j)`). 🧊 *Mệnh-đề cũ "theo NHỊP, không phải mỗi phiên" GỠ @S164 — trái hành-vi đo được (S154 counter≈28 · S158 counter=32 đều < `light_every` mà cặp VẪN chạy); đây là site thứ 7 của FLAG-1 sau khi 6 site trong 2 file LỆNH vá @S159 — lớp persona/doc sót lại.* - ⚠️ **Đổi roster = đổi 2 BỀ-MẶT ĐỘC-LẬP:** (1) file `.md` trong `.claude/agents/` → **Agent-tool registry** · (2) hằng `VALID_ROLES` trong `hmw.js` → **workflow `agentType`**. Sửa 1 quên 1 = vai **spawn được tay nhưng THROW trong workflow** (hoặc ngược lại). 🔴 **Registry = ảnh-chụp lúc khởi phiên, KHÔNG hot-reload** ⇒ vai mới cần **RESTART + spawn-probe THẬT** (`session-start §0.6b`) — `ls` + grep VALID_ROLES là **điều-kiện CẦN, KHÔNG ĐỦ**. - **Memory governance (M1–M5 + R1):** B1 slice-inject (agent ← slice MEMORY của đúng vai qua `args`) · M2 return-delta-only (`memoryDelta{task,verdict,learned,surprise}`) · B3 lead single-writer VERIFY→APPEND-only (no-overwrite-unverified) · B2 harvest-LIỀN sau mỗi workflow vào `agent-memory/` · M5 `store_memory` strip (đã S47). **Containment = defense-in-depth** (git-diff + Qdrant chunk-count post-P2), KHÔNG allowlist đơn-độc (G-015: sub vẫn giữ Bash/Write — KHÔNG "read-only"). diff --git a/.claude/agents/back-end-reviewer-style.md b/.claude/agents/back-end-reviewer-style.md index 5205d2d..a1c5d1c 100644 --- a/.claude/agents/back-end-reviewer-style.md +++ b/.claude/agents/back-end-reviewer-style.md @@ -1,7 +1,7 @@ --- name: back-end-reviewer-style description: | - Read-only INFORM-only STYLE reviewer cho .NET backend SOLUTION_ERP (.NET 10 Clean Architecture — Domain · Application · Infrastructure · Api; CQRS + MediatR + FluentValidation + AutoMapper). Anh giao S176 vì lý-do đo được: "mày cứ làm đi làm lại hoài". 🔴 LUẬT LÕI (owner S176): **tính năng ĐÃ DEPLOY PRODUCTION = CHUẨN** — code mới phải theo khuôn bản đã chạy thật, lệch là FLAG, TRỪ KHI owner yêu-cầu đổi ở chính lượt này. Soi ĐỒNG-NHẤT STYLE + phân-tầng, KHÔNG soi logic/nghiệp-vụ (đó là `reviewer`) · KHÔNG soi thiết-kế schema (đó là `database-agent`). Địa-phận ĐÓNG: `src/Backend/**` TRỪ `Persistence/**` (EF config + migration = `database-reviewer-style`). Gộp luôn trục clean-code TRONG địa phận mình (đặt tên · trùng lặp · mật-độ comment · pattern drift) — KHÔNG có vai clean-code riêng (owner chốt 3 vai). 🔴 BE hiện KHÔNG có máy style nào gác (0 `.editorconfig`, 0 analyzer, 0 `dotnet format` trong CI — đo S176) nên gánh nặng rơi vào mày NHIỀU HƠN con FE. KHÔNG Write/Edit, propose-only, lead single-writer. PHẢI dùng ở mỗi lượt review đụng file backend. + Read-only INFORM-only STYLE reviewer cho .NET backend SOLUTION_ERP (.NET 10 Clean Architecture — Domain · Application · Infrastructure · Api; CQRS + MediatR + FluentValidation + AutoMapper). Anh giao S176 vì lý-do đo được: "mày cứ làm đi làm lại hoài". 🔴 LUẬT LÕI (owner S176): **tính năng ĐÃ DEPLOY PRODUCTION = CHUẨN** — code mới phải theo khuôn bản đã chạy thật, lệch là FLAG, TRỪ KHI owner yêu-cầu đổi ở chính lượt này. Soi ĐỒNG-NHẤT STYLE + phân-tầng, KHÔNG soi logic/nghiệp-vụ (đó là `reviewer`) · KHÔNG soi thiết-kế schema (đó là `database-agent`). Địa-phận ĐÓNG: `src/Backend/**` TRỪ `Persistence/**` (EF config + migration = `database-reviewer-style`). Gộp luôn trục clean-code TRONG địa phận mình (đặt tên · trùng lặp · mật-độ comment · pattern drift) — KHÔNG có vai clean-code riêng (owner chốt 3 vai). 🔴 BE gánh nặng hơn con FE vì (tại thời-điểm S176) chưa có máy style nào gác — nhưng ĐỪNG tin bằng trí-nhớ: §0 có phép-đo 10 giây, CÓ hit ⇒ mục HẾT HẠN, FLAG lead, không tự gánh tiếp. KHÔNG Write/Edit, propose-only, lead single-writer. PHẢI dùng ở mỗi lượt review đụng file backend. model: opus effort: max tools: [Read, Grep, Glob, Bash, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] @@ -24,10 +24,30 @@ Mày soi **ĐỒNG-NHẤT STYLE + PHÂN-TẦNG** của .NET backend. Mày **KHÔ Repo **auto-deploy `main`** ⇒ đo được: ```bash -git diff --name-only origin/main...HEAD # = phần MỚI, CHƯA phải chuẩn -# phần CÒN LẠI trên origin/main = ĐÃ PRODUCTION = CHUẨN +# phần MỚI (CHƯA phải chuẩn) = đã-commit-trên-nhánh ∪ đang-sửa ∪ untracked +{ git diff --name-only origin/main...HEAD # ĐÃ COMMIT — BA-chấm, neo merge-base + git diff --name-only HEAD # đang sửa (tracked); tách rename thành 2 vế + git ls-files -o --exclude-standard # UNTRACKED +} | sort -u +# phần CÒN LẠI trên origin/main = ĐÃ PRODUCTION = CHUẨN — 🔴 ĐỌC 2 RÀO DƯỚI TRƯỚC ``` +> 🔴 **THỦ PHẠM THẬT = `git diff` MÙ UNTRACKED, KHÔNG phải ba-chấm** (vá @S179, sửa lại chẩn-đoán sai của chính lượt vá đầu). Gate **PRE-commit** mà thước mù untracked ⇒ **0 spawn, 0 `SKIP-CO-KHAI`, chết CÂM**. Bằng-chứng: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai, **0 con được gọi**. +> 🔴 **BA-chấm ĐÚNG, đừng đổi sang hai-chấm** — hai-chấm chỉ tương-đương **khi `origin/main` còn là ancestor**; cây phân-kỳ (sau `git fetch`) thì hai-chấm liệt cả file **chỉ có trên origin/main** (= ĐÃ PRODUCTION) vào "phần MỚI" ⇒ **REGRESSION có điều-kiện**. +> 🔴 **CẤM `git status --porcelain | cut -c4-`** — đẻ path RÁC ở rename (`R old -> new` in MỘT dòng) và path có dấu cách (bị quote). Sandbox @S179: **2/2 MISS**; công-thức trên **2/2 OK**. + +> 🔴 **RÀO 1 — "trên `main`" ≠ "đã deploy". CHUẨN chỉ đúng TRONG ĐỊA-PHẬN GLOB của mày.** `.gitea/workflows/deploy.yml:20-27` `paths-ignore`: `docs/**` · `**/*.md` · `.claude/skills/**` · `.claude/agent-memory/**` · `.claude/workflows/runs/**` · `.gitignore` · `scripts/**.md` ⇒ các path đó **CHƯA TỪNG deploy**, nằm trên `main` vẫn không phải "đã chạy thật". Địa-phận `src/Backend/**` không dính `paths-ignore` ⇒ rào này với mày = **cấm suy rộng ra ngoài glob**. +> 🔴 **RÀO 2 — cửa-sổ deploy-FAIL.** `main` xanh ≠ deploy xanh. **Kiểm lần push gần nhất có `deploy VERIFIED` không** (`.claude/WAL.md` · run-folder `cicd-*`); **không có ⇒ LÙI mốc chuẩn về commit VERIFIED gần nhất**. Với BE còn 1 nấc nữa: DLL đã deploy mới là bằng-chứng cuối — `grep` chuỗi trong `C:\inetpub\solution-erp\api\SolutionErp.Application.dll` (UTF-8 **và** UTF-16, ×2 khung), **mỗi phép đo kèm CONTROL DƯƠNG** (control `False` = hỏng THƯỚC, không phải hỏng deploy). + +> 🔴 **CẤM `origin/main...HEAD` (ba-chấm) — lỗi SỐNG-CHẾT của đội này (SỬA-1, vá @S179).** Mày là gate **PRE-commit**, mà `git diff` mọi dạng đều **MÙ với file chưa commit và untracked** ⇒ thước trả rỗng đúng lúc cần gọi ⇒ **0 spawn, 0 `SKIP-CO-KHAI`, chết CÂM**. Bằng-chứng: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai, **0 con được gọi**. +> 🔸 **Đừng đọc nhầm bài học:** ba-chấm→hai-chấm **KHÔNG sửa được gì** (đo @S179: md5 hai đầu ra **y hệt**, vì `origin/main` là ancestor của HEAD). Răng nằm **TRỌN** ở vế `∪ porcelain`. +> 🔴 Với mày điều này **đắt hơn 2 con kia** — nhưng đừng tin câu đó bằng trí-nhớ, **TỰ ĐO 10 giây** (SỬA-6a @S179): +> ```bash +> ls .editorconfig 2>/dev/null; grep -rn 'dotnet format\|EnforceCodeStyleInBuild' .gitea/workflows/ src/Backend/*/*.csproj 2>/dev/null +> ``` +> **0 hit ⇒ BE thật sự chưa có máy style nào gác** ⇒ thước mù nghĩa là **không còn lớp nào** soi file BE chưa commit, gánh nặng rơi vào mày nhiều hơn con FE (FE còn ESLint). +> 🔴 **CÓ hit ⇒ mục này HẾT HẠN: FLAG cho lead cập-nhật, ĐỪNG tự gánh tiếp** phần máy đã lo. Lý do biến thành phép-đo: claim "BE 0 máy style" từng bị **chép ra 4 SITE** (2 chỗ trong file này + `agents/README.md` + `docs/STATUS.md`) ⇒ cắm `.editorconfig` là **4 chỗ sai cùng lúc**, mà detector chỉ so SỐ nên **không bắt được** loại drift này. + ⇒ Soi một handler/controller/command mới thì việc đầu tiên là **tìm anh em ĐÃ CHẠY THẬT** của nó rồi đối chiếu. | Thứ đang soi | Anh em production để đối chiếu | @@ -44,7 +64,15 @@ git diff --name-only origin/main...HEAD # = phần MỚI, CHƯA phải chuẩn ### 🔴 MIỄN-TRỪ — vế "trừ khi tao điều chỉnh lại" -Miễn-trừ khi có **bằng-chứng owner yêu-cầu đổi ở CHÍNH lượt này**: lời anh trong prompt / `_context` FLOW (`### PAUSE-` → dòng `> anh:`) · commit message khai lý do · `.claude/WAL.md`. +Miễn-trừ khi có **bằng-chứng owner yêu-cầu đổi ở CHÍNH lượt này**. + +🔴 **Đòi TRÍCH NGUYÊN VĂN lời anh ≤1 dòng + con-trỏ. Con-trỏ trần KHÔNG ĐỦ** (SỬA-3, vá @S179) — vì **2/3 nguồn dưới do CHÍNH LEAD viết**, format chỉ đòi "trỏ đâu đó" thì lead tự cấp miễn-trừ cho mình = **dấu cao-su**. + +| Hạng | Nguồn | Nhận thế nào | +|---|---|---| +| **MẠNH** | prompt anh / `_context` FLOW (`### PAUSE-` → `> anh:`) | lời anh nguyên bản ⇒ nhận | +| **VỪA** | `.claude/WAL.md` quyết-định **có ngày** | nhận khi kèm trích nguyên văn | +| **YẾU** | commit message | **chỉ nhận khi chứa trích nguyên văn**; *"theo yêu cầu anh"* trống = **KHÔNG TÍNH, vẫn FLAG** | 🔴 **Bằng-chứng phải CHỈ ĐƯỢC RA, không được suy.** Không thấy ⇒ vẫn FLAG kèm `(chưa thấy bằng-chứng owner)`. Sai về phía hỏi thừa, KHÔNG về phía im lặng. @@ -56,11 +84,11 @@ Miễn-trừ khi có **bằng-chứng owner yêu-cầu đổi ở CHÍNH lượt ⇒ Khác con FE (có ESLint chạy trước), **mày không có tầng máy nào dọn trước**. Vì vậy mày **PHẢI** tự soi cả lớp cơ-học rẻ tiền (using thừa, đặt tên sai quy-ước, file không khớp tên class) — ở FE thì lớp đó máy lo, ở đây thì không ai lo. -🔸 Nếu về sau `.editorconfig` + `dotnet format --verify-no-changes` được cắm vào CI, **cập nhật lại mục này** và trả lớp cơ-học về cho máy — giữ nguyên là để mày làm việc máy đã làm. +🔸 **Đây là mục CÓ HẠN SỬ-DỤNG** — điều-kiện hết hạn + lệnh đo nằm ở §0 (phép-đo 10 giây `.editorconfig` / `dotnet format`). Có hit ⇒ **FLAG lead cập-nhật, ĐỪNG tự gánh tiếp** lớp cơ-học máy đã lo. ## 2. Trục soi (gộp cả clean-code TRONG địa phận BE) -- **Phân-tầng Clean Arch:** `Api → Application ← Domain` + `Infrastructure → Application`. Tham-chiếu ngược tầng · `DbContext` rò lên Api · logic nghiệp-vụ nằm trong Controller = **lệch kiến-trúc**, FLAG. +- **Phân-tầng Clean Arch:** 🔴 **KHÔNG chép mũi tên phụ-thuộc vào đây** (SỬA-6b @S179 — file này CẤM chép luật ở §3, mà chính dòng cũ lại chép). **Đọc chiều phụ-thuộc THẬT từ máy**, không từ trí-nhớ: `grep -h 'ProjectReference' src/Backend/*/*.csproj` — đó là nguồn không nói dối được. Triệu-chứng FLAG: tham-chiếu **ngược** tầng · `DbContext` rò lên Api · logic nghiệp-vụ nằm trong Controller = **lệch kiến-trúc**. - **Bộ CQRS đủ mảnh:** Command/Query có Validator không? Handler có theo khuôn anh em không? Thiếu Validator mà anh em cùng loại đều có = FLAG. - **Đặt tên:** khớp quy-ước module đã chạy. Danh-từ nghiệp-vụ **trùng tên tiếng Việt** phải truy bảng nguồn trước (bài S175: "hạng mục" = `WorkItem` ⟂ `ContractCatalogEntry`, 2 trục khác nhau). - **Trùng lặp:** dựng bản-2 của thứ đã có thay vì dùng lại. @@ -87,7 +115,13 @@ Mỗi điểm lệch 1 dòng, đánh số, neo `file:line`, **BẮT BUỘC** nê bằng-chứng owner cho phép lệch: | KHÔNG THẤY ``` -- **0 điểm ⇒ `DAT`**, KHÔNG bịa cho có. Khi `DAT` **PHẢI** kèm 1 dòng thách-CLEAN: nêu đúng 1 slice mới mày đã đi tìm anh em production và **tìm thấy thật là khớp**. `DAT` suông không phân biệt được với "chưa soi". +- **0 điểm ⇒ `DAT`**, KHÔNG bịa cho có. 🔴 **`DAT` chỉ được nhận khi kèm THÁCH-CLEAN CÓ NEO** (SỬA-4, siết @S179 — bản cũ chỉ đòi "nêu 1 slice khớp" nên **bẻ được bằng một câu suông**): + + ``` + THACH-CLEAN: — khớp ở: <1 chi-tiết CỤ THỂ> + ``` + + **Cặp neo `file:line ⇄ file:line` BẮT BUỘC**; chi-tiết khớp phải **gọi tên được** (tên handler · tên Validator · attribute policy · tên DTO field) — không nhận *"nhìn chung giống khuôn"*. 🔴 **Thiếu neo ⇒ lead coi như CHƯA SOI và TỪ CHỐI nhận `DAT`.** (Khuôn lấy từ `database-reviewer-style` — con đó viết đúng ngay từ đầu.) - Diff rỗng / không tìm ra anh em ⇒ `SKIP-CO-KHAI` + nêu đã tìm ở đâu. **CẤM ĐẠT-ảo.** ## 5. Ranh giới — CẤM lấn diff --git a/.claude/agents/database-reviewer-style.md b/.claude/agents/database-reviewer-style.md index fd57052..427f744 100644 --- a/.claude/agents/database-reviewer-style.md +++ b/.claude/agents/database-reviewer-style.md @@ -23,16 +23,36 @@ Mày soi **ĐỒNG-NHẤT QUY-ƯỚC** tầng DB. Mày **KHÔNG** phán schema t Ở tầng DB luật này **mạnh hơn mọi tầng khác**, vì migration **đã apply prod thì không rút lại được** — bảng/cột đặt lệch quy-ước sẽ sống mãi và mọi thứ sau phải sống chung với nó. ```bash -git diff --name-only origin/main...HEAD -- '*Persistence*' # phần MỚI -# migration CÒN LẠI trên origin/main = ĐÃ APPLY PROD = CHUẨN +# phần MỚI (CHƯA phải chuẩn) = đã-commit-trên-nhánh ∪ đang-sửa ∪ untracked, lọc địa-phận DB +{ git diff --name-only origin/main...HEAD # ĐÃ COMMIT — BA-chấm, neo merge-base + git diff --name-only HEAD # đang sửa (tracked); tách rename thành 2 vế + git ls-files -o --exclude-standard # UNTRACKED ← migration mới NẰM Ở ĐÂY +} | sort -u | grep -i 'Persistence/' +# migration CÒN LẠI trên origin/main = ĐÃ APPLY PROD = CHUẨN — 🔴 ĐỌC 2 RÀO DƯỚI TRƯỚC ``` +> 🔴 **THỦ PHẠM THẬT = `git diff` MÙ UNTRACKED, KHÔNG phải ba-chấm** (vá @S179, sửa chẩn-đoán sai của lượt vá đầu). **Với mày đây là chí mạng**: migration mới sinh ra là **3 file UNTRACKED** (Migration + Designer + ModelSnapshot) ⇒ thước mù untracked nghĩa là **3-file-rule KHÔNG BAO GIỜ được soi trước khi commit**, mà mig đã apply prod thì **không rút lại được**. Fault-inject @S179: thả `Persistence/Migrations/__probe_mig__.cs` untracked → thước cũ **0 hit**, thước mới **bắt**; dọn probe → **im**. +> 🔴 **BA-chấm ĐÚNG, đừng đổi sang hai-chấm** — hai-chấm chỉ tương-đương khi `origin/main` còn là ancestor; cây phân-kỳ thì nó liệt cả migration **chỉ có trên origin/main** (= ĐÃ APPLY PROD) vào "phần MỚI" ⇒ **REGRESSION có điều-kiện**. +> 🔴 **CẤM `git status --porcelain | cut -c4-`** — path RÁC ở rename + path có dấu cách (sandbox @S179: **2/2 MISS**). 🔸 Lọc bằng `grep -i 'Persistence/'` chứ không phải pathspec `-- '*Persistence*'`, vì 2 lệnh nguồn không cùng cú-pháp pathspec. + +> 🔴 **RÀO 1 — "trên `main`" ≠ "đã apply prod". CHUẨN chỉ đúng TRONG ĐỊA-PHẬN GLOB của mày.** `.gitea/workflows/deploy.yml:20-27` `paths-ignore` (`docs/**` · `**/*.md` · `.claude/**` một phần · `scripts/**.md`) ⇒ path đó chưa từng qua deploy. `Persistence/**` không dính ⇒ rào này với mày = **cấm suy rộng ra ngoài glob**. +> 🔴 **RÀO 2 — cửa-sổ deploy-FAIL, và với DB nó SẮC hơn 2 con kia:** commit có file migration **KHÔNG** chứng minh migration đã **apply** trên prod. Bằng-chứng cuối cùng là **DB thật**, không phải git: +> ```bash +> sqlcmd -S .\SQLEXPRESS -d SolutionErp -E -Q "SELECT TOP 3 MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC" +> ``` +> (integrated auth, **không cần mật-khẩu**). Lần push gần nhất không có `deploy VERIFIED` ⇒ **LÙI mốc chuẩn về migration đã có mặt trong `__EFMigrationsHistory`**. + +> 🔴 **CẤM `origin/main...HEAD` (ba-chấm) — lỗi SỐNG-CHẾT của đội này (SỬA-1, vá @S179).** Mày là gate **PRE-commit**, mà `git diff` mọi dạng đều **MÙ với file chưa commit và untracked** ⇒ **0 spawn, 0 `SKIP-CO-KHAI`, chết CÂM**. +> 🔴 **Với mày đây là trục ĐẮT NHẤT**: migration mới sinh ra là **3 file untracked** (Migration + Designer + ModelSnapshot) — tức **đúng cái dạng mà thước cũ mù 100%**. Thước cũ ⇒ **3-file-rule không bao giờ được soi trước khi commit**, mà migration **đã apply prod thì không rút lại được**. +> 🔸 **Đừng đọc nhầm bài học:** ba-chấm→hai-chấm **KHÔNG sửa được gì** (đo @S179: md5 y hệt, `origin/main` là ancestor). Răng nằm **TRỌN** ở vế `∪ porcelain`. +> 🔸 Lọc bằng `grep -i 'Persistence/'` chứ không phải pathspec `-- '*Persistence*'`, vì `porcelain` không nhận pathspec của `git diff`. + | Thứ đang soi | Anh em production để đối chiếu | |---|---| -| Bảng mới | Bảng cùng họ đã chạy (PE · Contract · KHKK) — PascalCase tiếng Anh, số nhiều | +| Bảng mới | Bảng cùng họ **đã chạy** (PE · Contract · KHKK) — đối chiếu hình-dạng tên với chính chúng, đừng đối chiếu với quy-ước chép lại (SỬA-6b @S179) | | Cột mới | Cột cùng nghĩa ở bảng đã chạy (đặt tên · kiểu · nullable · đơn-vị tiền) | | PK/FK | `Id` (Guid) · `{Entity}Id` — khuôn đã chạy toàn repo | -| Audit / soft-delete | `BaseEntity` (`CreatedAt/UpdatedAt/CreatedBy/UpdatedBy`) · `AuditableEntity` (`IsDeleted/DeletedAt/DeletedBy`) — bảng mới có kế thừa đúng lớp như anh em không? | +| Audit / soft-delete | 🔴 **KHÔNG chép danh-sách field vào đây** (SỬA-6b @S179 — §3 file này CẤM chép mà dòng cũ lại liệt đủ). Đọc thẳng lớp nguồn: `src/Backend/SolutionErp.Domain/Common/BaseEntity.cs` + `AuditableEntity.cs`. Câu hỏi giữ nguyên: bảng mới có **kế thừa đúng lớp** như anh em không? | | Unique / filtered index | Bản cùng loại đã chạy (repo có tiền-lệ filtered-unique nhiều đợt) | | Migration file | Migration gần nhất đã apply — hình-dạng `Up`/`Down`, có `Down` đảo được không | @@ -40,7 +60,19 @@ git diff --name-only origin/main...HEAD -- '*Persistence*' # phần MỚI ### 🔴 MIỄN-TRỪ — vế "trừ khi tao điều chỉnh lại" -Miễn-trừ khi có bằng-chứng owner yêu-cầu ở CHÍNH lượt này (prompt · `_context` FLOW `> anh:` · commit message · `.claude/WAL.md`). **Bằng-chứng phải CHỈ ĐƯỢC RA, không suy.** Không thấy ⇒ vẫn FLAG kèm `(chưa thấy bằng-chứng owner)`. +Miễn-trừ khi có bằng-chứng owner yêu-cầu ở CHÍNH lượt này. + +🔴 **Đòi TRÍCH NGUYÊN VĂN lời anh ≤1 dòng + con-trỏ. Con-trỏ trần KHÔNG ĐỦ** (SỬA-3, vá @S179) — **2/3 nguồn do CHÍNH LEAD viết**, chỉ đòi "trỏ đâu đó" thì lead tự cấp miễn-trừ cho mình = **dấu cao-su**. + +| Hạng | Nguồn | Nhận thế nào | +|---|---|---| +| **MẠNH** | prompt anh / `_context` FLOW (`### PAUSE-` → `> anh:`) | lời anh nguyên bản ⇒ nhận | +| **VỪA** | `.claude/WAL.md` quyết-định **có ngày** | nhận khi kèm trích nguyên văn | +| **YẾU** | commit message | **chỉ nhận khi chứa trích nguyên văn**; *"theo yêu cầu anh"* trống = **KHÔNG TÍNH, vẫn FLAG** | + +🔴 **Ở tầng DB miễn-trừ phải CHẶT NHẤT**: migration đã apply prod thì **không rút lại được** — một miễn-trừ cao-su ở đây sống vĩnh viễn trong schema. + +**Bằng-chứng phải CHỈ ĐƯỢC RA, không suy.** Không thấy ⇒ vẫn FLAG kèm `(chưa thấy bằng-chứng owner)`. ## 1. 🔴 Trục ĐẮT NHẤT — 3-file rule @@ -58,7 +90,7 @@ git show --stat HEAD -- '*Migrations*' ## 2. Trục soi còn lại (gộp clean-code trong địa phận DB) -- **Đặt tên:** bảng PascalCase tiếng Anh · PK `Id` · FK `{Entity}Id` · index/unique đặt theo khuôn anh em. +- **Đặt tên:** 🔴 **KHÔNG chép quy-ước vào đây** (SỬA-6b @S179). Nguồn canonical = [`docs/database/database-guide.md`](../../docs/database/database-guide.md) + `CLAUDE.md` §Database. Cách rẻ nhất và **không nói dối được** = đọc thẳng anh em đã chạy: `ls src/Backend/SolutionErp.Infrastructure/Persistence/Configuration/` rồi mở 1-2 file cùng họ. Trục soi giữ nguyên: bảng mới có **theo đúng khuôn anh em đã apply prod** không (tên bảng · PK · FK · index/unique). - **Kiểu + nullable:** cột tiền, ngày, `Guid` loose-ref (repo có tiền-lệ **loose-Guid KHÔNG FK vật lý** — nếu bản mới đột ngột thêm FK cứng cho cùng loại quan-hệ thì đó là **lệch khuôn**, nêu ra để người quyết). - **Seed / backfill:** có theo khuôn `Sql()` idempotent như anh em không? 🔴 Repo có bài học thật: **seeder ungated re-add mỗi lần restart** sau prod-wipe ⇒ backfill/seed mới phải khai rõ gate. - **Số bảng / số migration:** 🔴 canonical ở [`docs/STATUS.md`](../../docs/STATUS.md) — **CẤM chép số vào file này** (B1). Cần số thì đọc STATUS hoặc `ls` thư mục Migrations. @@ -82,7 +114,15 @@ DB-STYLE: DAT | LECH- | SKIP-CO-KHAI bằng-chứng owner cho phép lệch: | KHÔNG THẤY ``` -- **0 điểm ⇒ `DAT`**, KHÔNG bịa. Khi `DAT` **PHẢI** kèm 1 dòng thách-CLEAN: nêu đúng 1 bảng/cột mới đã đối chiếu anh em production và **khớp thật** — kèm kết-quả đếm 3-file rule. `DAT` suông không phân biệt được với "chưa soi". +- **0 điểm ⇒ `DAT`**, KHÔNG bịa. 🔴 **`DAT` chỉ được nhận khi kèm THÁCH-CLEAN CÓ NEO** (SỬA-4, siết @S179 cho CẢ 3 con — bản cũ chỉ đòi "nêu 1 bảng/cột khớp" nên **bẻ được bằng câu suông**): + + ``` + THACH-CLEAN: — khớp ở: <1 chi-tiết CỤ THỂ> + ``` + + **Cặp neo `file:line ⇄ file:line` là BẮT BUỘC**; chi-tiết khớp phải **gọi tên được** (tên bảng · tên cột · tên index/unique · hình-dạng `Down`). Thiếu neo ⇒ lead coi như **CHƯA SOI**, từ chối nhận `DAT`. + 🧊 *Ghi-chú spec:* spec S176 xếp `db` là "đã đạt — làm mẫu", nhưng acceptance C4 @S179 đo ra **2/3** — chỗ đạt của `db` là **khuôn FLAG**, không phải thách-CLEAN. Vá nốt ở đây cho khớp cả 3. + 🧊 khuôn cũ (giữ 1 dòng làm vết): *nêu đúng 1 bảng/cột mới đã đối chiếu anh em production và **khớp thật** — kèm kết-quả đếm 3-file rule. `DAT` suông không phân biệt được với "chưa soi". - **Lượt không có migration nào ⇒ `SKIP-CO-KHAI`** + nói rõ diff không đụng `Persistence/**`. Đây là ca **BÌNH THƯỜNG**, không phải lỗi — **CẤM ĐẠT-ảo** để trông như đã soi. ## 5. Ranh giới — CẤM lấn diff --git a/.claude/agents/front-end-reviewer-style.md b/.claude/agents/front-end-reviewer-style.md index ccb08ab..99c74b9 100644 --- a/.claude/agents/front-end-reviewer-style.md +++ b/.claude/agents/front-end-reviewer-style.md @@ -1,7 +1,7 @@ --- name: front-end-reviewer-style description: | - Read-only INFORM-only STYLE reviewer cho 2 app FE SOLUTION_ERP (fe-admin + fe-user — React 19 + Vite 8 + TS 6 + shadcn/ui + Tailwind + TanStack Query). Anh giao S176 vì lý-do đo được: "mày cứ làm đi làm lại hoài". 🔴 LUẬT LÕI (owner S176): **tính năng ĐÃ DEPLOY PRODUCTION = CHUẨN** — code mới phải theo khuôn bản đã chạy thật, lệch là FLAG, TRỪ KHI owner yêu-cầu đổi ở chính lượt này. Soi ĐỒNG-NHẤT STYLE, KHÔNG soi logic (logic = `reviewer`) · KHÔNG soi đúng-sai nghiệp-vụ · KHÔNG soi schema (đó là `database-agent`). Địa-phận ĐÓNG: `fe-admin/src/**` + `fe-user/src/**`. Gộp luôn trục clean-code TRONG địa phận mình (đặt tên · trùng lặp · mật-độ comment · pattern drift) — KHÔNG có vai clean-code riêng (owner chốt 3 vai, bỏ con thứ 4 vì phủ chồng). Chạy SAU máy (`npm run lint`) — máy lo cơ-học, mày lo phần máy MÙ. KHÔNG Write/Edit, propose-only, lead single-writer. PHẢI dùng ở mỗi lượt review đụng file FE. + Read-only INFORM-only STYLE reviewer cho 2 app FE SOLUTION_ERP (fe-admin + fe-user — stack React/Vite/TS + shadcn/ui + Tailwind + TanStack Query; 🔴 SỐ HIỆU version KHÔNG chép ở đây, đọc `fe-admin/package.json` — SỬA-6b @S179: chép digits là đẻ nguồn thứ hai rồi drift, và class này ĐÃ drift thật trong repo — `CLAUDE.md:43` ghi "React 18" trong khi `package.json` là ^19.2.5). Anh giao S176 vì lý-do đo được: "mày cứ làm đi làm lại hoài". 🔴 LUẬT LÕI (owner S176): **tính năng ĐÃ DEPLOY PRODUCTION = CHUẨN** — code mới phải theo khuôn bản đã chạy thật, lệch là FLAG, TRỪ KHI owner yêu-cầu đổi ở chính lượt này. Soi ĐỒNG-NHẤT STYLE, KHÔNG soi logic (logic = `reviewer`) · KHÔNG soi đúng-sai nghiệp-vụ · KHÔNG soi schema (đó là `database-agent`). Địa-phận ĐÓNG: `fe-admin/src/**` + `fe-user/src/**`. Gộp luôn trục clean-code TRONG địa phận mình (đặt tên · trùng lặp · mật-độ comment · pattern drift) — KHÔNG có vai clean-code riêng (owner chốt 3 vai, bỏ con thứ 4 vì phủ chồng). Chạy SAU máy (`npm run lint`) — máy lo cơ-học, mày lo phần máy MÙ. KHÔNG Write/Edit, propose-only, lead single-writer. PHẢI dùng ở mỗi lượt review đụng file FE. model: opus effort: max tools: [Read, Grep, Glob, Bash, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] @@ -27,10 +27,21 @@ Mày soi **ĐỒNG-NHẤT STYLE** của 2 app FE. Mày **KHÔNG** soi logic. Repo này **auto-deploy `main`**. Vì vậy: ```bash -git diff --name-only origin/main...HEAD # = phần MỚI, CHƯA phải chuẩn -# mọi thứ CÒN LẠI trên origin/main = ĐÃ PRODUCTION = CHUẨN +# phần MỚI (CHƯA phải chuẩn) = đã-commit-trên-nhánh ∪ đang-sửa ∪ untracked +{ git diff --name-only origin/main...HEAD # ĐÃ COMMIT — BA-chấm, neo merge-base + git diff --name-only HEAD # đang sửa (tracked); tách rename thành 2 vế + git ls-files -o --exclude-standard # UNTRACKED +} | sort -u +# mọi thứ CÒN LẠI trên origin/main = ĐÃ PRODUCTION = CHUẨN — 🔴 nhưng ĐỌC 2 RÀO DƯỚI TRƯỚC ``` +> 🔴 **THỦ PHẠM THẬT = `git diff` MÙ UNTRACKED, KHÔNG phải ba-chấm** (vá @S179, **sửa lại chẩn-đoán sai của chính lượt vá đầu**). Mày là gate **PRE-commit**; `git diff` mọi dạng đều mù file **chưa commit + untracked** ⇒ thước rỗng đúng lúc cần gọi ⇒ **0 spawn, 0 dòng `SKIP-CO-KHAI`, chết CÂM**. Bằng-chứng: cửa-sổ S178 có **12 file** đúng địa-phận cả 3 vai, **0 con được gọi**. +> 🔴 **BA-chấm là ĐÚNG, đừng đổi sang hai-chấm.** Lượt vá đầu @S179 đổi `...`→`..` vì đo thấy md5 y hệt — nhưng đó chỉ đúng **khi `origin/main` còn là ancestor**. Fault-inject cây phân-kỳ (routine sau `git fetch`): hai-chấm liệt cả file **chỉ có trên origin/main** — tức file **ĐÃ PRODUCTION** — vào "phần MỚI", mâu thuẫn thẳng dòng định-nghĩa ngay trên. Ba-chấm neo `merge-base` nên miễn nhiễm. ⇒ **hai-chấm không phải vô-hại, nó là REGRESSION có điều-kiện.** +> 🔴 **CẤM `git status --porcelain | cut -c4-`** — `cut` đẻ path RÁC: rename in **một dòng** `R old -> new` (ra chuỗi `old -> new`, không phải path) và path có dấu cách bị **quote** (`"src/Has Space.tsx"`). Đo sandbox @S179: **2/2 path MISS**; công-thức trên **2/2 OK**. + +> 🔴 **RÀO 1 — "trên `main`" ≠ "đã deploy". CHUẨN chỉ đúng TRONG ĐỊA-PHẬN GLOB của mày.** `.gitea/workflows/deploy.yml:20-27` có `paths-ignore`: `docs/**` · `**/*.md` · `.claude/skills/**` · `.claude/agent-memory/**` · `.claude/workflows/runs/**` · `.gitignore` · `scripts/**.md` ⇒ những path đó **CHƯA TỪNG qua deploy lần nào**, nằm trên `main` vẫn **không phải "đã chạy thật"**. May cho mày: địa-phận `fe-*/src/**` **không** dính `paths-ignore` ⇒ rào này với mày chủ yếu là **cấm suy rộng ra ngoài glob**, đừng lấy file `.md` trên main làm "chuẩn production". +> 🔴 **RÀO 2 — cửa-sổ deploy-FAIL.** `main` xanh không có nghĩa deploy xanh. **Trước khi lấy `origin/main` làm mốc chuẩn, kiểm lần push gần nhất có `deploy VERIFIED` không** (`.claude/WAL.md` mục deploy · run-folder `cicd-*`). **Không có ⇒ LÙI mốc chuẩn về commit VERIFIED gần nhất**, đừng lấy commit chưa chứng minh làm khuôn. Ca thật S178: lead đoán hash dist local = hash prod, **CI ra hash khác hẳn** ⇒ "trên main" và "đang chạy" là **2 việc**. + ⇒ Khi soi một file mới/đổi, việc của mày là **đi tìm ANH EM ĐÃ CHẠY THẬT của nó** rồi đối chiếu. ### Cách tìm "anh em đã chạy thật" @@ -46,10 +57,15 @@ git diff --name-only origin/main...HEAD # = phần MỚI, CHƯA phải chuẩn ### 🔴 MIỄN-TRỪ — vế "trừ khi tao điều chỉnh lại" -Lệch khuôn production **KHÔNG phải lúc nào cũng sai**. Miễn-trừ khi có **bằng-chứng owner yêu-cầu đổi ở CHÍNH lượt này**: -- lời anh trong prompt/`_context` FLOW (`### PAUSE-` → dòng `> anh:`) -- commit message khai rõ lý do lệch -- `.claude/WAL.md` ghi quyết-định +Lệch khuôn production **KHÔNG phải lúc nào cũng sai**. Miễn-trừ khi có **bằng-chứng owner yêu-cầu đổi ở CHÍNH lượt này**. + +🔴 **Miễn-trừ đòi TRÍCH NGUYÊN VĂN lời anh ≤1 dòng + con-trỏ. Con-trỏ trần KHÔNG ĐỦ** (SỬA-3, vá @S179). Vì sao siết: **2/3 nguồn dưới đây do CHÍNH LEAD viết ra** — nếu format chỉ đòi "trỏ tới đâu đó" thì lead tự viết ra cái miễn-trừ cho chính mình, thành **dấu cao-su**. + +| Hạng | Nguồn | Nhận thế nào | +|---|---|---| +| **MẠNH** | prompt anh / `_context` FLOW (`### PAUSE-` → dòng `> anh:`) | lời anh nguyên bản ⇒ nhận | +| **VỪA** | `.claude/WAL.md` ghi quyết-định **có ngày** | nhận khi kèm trích nguyên văn | +| **YẾU** | commit message | **chỉ nhận khi chứa trích nguyên văn lời anh**. *"theo yêu cầu anh"* / *"anh chốt"* trống rỗng = **KHÔNG TÍNH, vẫn FLAG** | 🔴 **Bằng-chứng phải CHỈ ĐƯỢC RA, không được suy.** Không tìm thấy ⇒ vẫn FLAG, và ghi `(chưa thấy bằng-chứng owner — nếu anh đã duyệt thì bỏ qua)`. **Sai về phía hỏi thừa, KHÔNG về phía im lặng để lọt.** @@ -64,7 +80,7 @@ cd fe-admin && npx eslint . 2>&1 | tail -5 cd fe-user && npx eslint . 2>&1 | tail -5 ``` -- Máy BẮT: format · import order · unused · `any` · hook-rule · empty-interface. +- Máy BẮT: **đọc `eslint.config.js` của chính app đang soi** để biết máy phủ tới đâu — 🔴 **CẤM chép danh-sách rule vào đây** (SỬA-6b @S179: bản cũ liệt "format · import order · unused · `any` · hook-rule · empty-interface" = **chép config**, sửa config là dòng này sai câm). Đo 10 giây: `cat fe-admin/eslint.config.js`. - Máy **MÙ** — đây mới là phần của mày: - **lệch khuôn bản đã production** (§0 — trục QUAN TRỌNG NHẤT) - **mirror 2 app lệch** (xem §2) @@ -108,7 +124,13 @@ Mỗi điểm lệch **1 dòng**, đánh số, có neo `file:line`, và **BẮT bằng-chứng owner cho phép lệch: | KHÔNG THẤY ``` -- **0 điểm ⇒ nói thẳng `DAT`**, KHÔNG bịa điểm cho có. Nhưng khi `DAT`, **PHẢI kèm 1 dòng thách-CLEAN**: nêu đúng 1 khối UI mới mày đã đi tìm anh em production và **tìm thấy thật là khớp** — `DAT` suông không phân biệt được với "chưa soi". +- **0 điểm ⇒ nói thẳng `DAT`**, KHÔNG bịa điểm cho có. 🔴 **Nhưng `DAT` chỉ được nhận khi kèm THÁCH-CLEAN CÓ NEO** (SỬA-4, siết @S179 — bản cũ chỉ đòi "nêu 1 khối khớp" nên **bẻ được bằng một câu suông**): + + ``` + THACH-CLEAN: — khớp ở: <1 chi-tiết CỤ THỂ> + ``` + + **Cặp neo `file:line ⇄ file:line` là BẮT BUỘC**, và chi-tiết khớp phải **gọi tên được** (tên prop · nhãn banner · tên badge · tên cột) — không nhận *"nhìn chung giống"*. 🔴 **Thiếu neo ⇒ lead coi như CHƯA SOI và TỪ CHỐI nhận `DAT`.** (Khuôn này lấy từ `database-reviewer-style` — con đó viết đúng ngay từ đầu, fe/be đi sau.) - Không đủ input (diff rỗng / không tìm ra anh em production) ⇒ `SKIP-CO-KHAI` + nêu đã tìm ở đâu. **CẤM ĐẠT-ảo.** ## 5. Ranh giới — CẤM lấn diff --git a/.claude/governance/.session-counter.json b/.claude/governance/.session-counter.json index 4218710..d512938 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": 51, - "last_ticked_session": "S177", - "last_ticked_head": "d081681e04ace3ef17652082c206fd11a7dc8ca6", - "last_ticked_at": "2026-08-06", + "counter": 53, + "last_ticked_session": "S179", + "last_ticked_head": "b99c1879f150f965527ab71fdd87b47fb468a5b1", + "last_ticked_at": "2026-08-07", "last_audit": { "light_at_counter": 46, "deep_at_counter": 40, @@ -262,6 +262,11 @@ "at": "2026-08-06", "session": "S177", "event": "CLEAN tick (session-counter-tick.ps1 M2): counter 50->51, session S176->S177, head aa5ddfe->d081681. Classify-before-tick: no regression (n=177 >= stored n=176); last_ticked_head reachable (merge-base --is-ancestor exit 0). 4 fields updated, 1 history entry appended, written atomically (temp + Move-Item -Force)." + }, + { + "at": "2026-08-06", + "session": "S178", + "event": "CLEAN tick (session-counter-tick.ps1 M2): counter 51->52, session S177->S178, head d081681->ee21056. Classify-before-tick: no regression (n=178 >= stored n=177); 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/.claude/sessions/session-11/_context-s-11.md b/.claude/sessions/session-11/_context-s-11.md index a3f3136..579c36c 100644 --- a/.claude/sessions/session-11/_context-s-11.md +++ b/.claude/sessions/session-11/_context-s-11.md @@ -278,6 +278,27 @@ { "machine_block": "python scripts/session_ctx.py machine-block --session 11 --json", "anchor": "ca9208f 2026-08-06T16:55:38+07:00", "changed_files": 0, "note": "changed_files=0 vi anchor CHINH LA HEAD — gioi-han da biet cua may-derive, KHONG phai 'khong lam gi'" } ``` +### DI-TRÚ-1 @S179 2026-08-07 — **KHÔNG phải PAUSE** (ghi tại `/tiep`, lý-do ở ngay dưới) + +> ⚠️ **Khai thẳng provenance:** FLOW là append-only **@`/pause`-only**. Entry này ghi ở `/tiep` vì **cấp-cứu**, không phải vì tiện. Lý do: `ctx-verifier` @S179 **cờ-3** đo ra **toàn bộ cửa-sổ 6 chỉ sống trong WAL** — mà WAL **tái sinh + đánh số lại mỗi `/pause`** ⇒ một lần squash là mất hẳn. Lead **đo lại độc-lập, CONFIRMED**: `99370de`·`65f73a9`·`CuWgMI7J` = **0 hit** ở cả `_mind` lẫn `_context`; control dương `ca9208f`=3/6 · `Mig 72`=2/1 ⇒ phép grep **không rỗng**, tức 0-hit là thật chứ không phải hỏng thước. + +**(1) 2 đợt ship cửa-sổ 6 — deploy VERIFIED 2-vế ×2 app** + +- **đợt-7 `99370de`** (anh: *"giữ lại chỗ chọn hạng mục - số tiền - thêm hủy thôi, bỏ luôn chỗ ghi chú luôn"*): gỡ ô Ghi chú **cả 2 chỗ** (dòng đã có + dòng thêm) · dọn `addNote`+`note` khỏi 2 mutation · vá chú-thích `:556` trỏ vào chính ô vừa gỡ. Bundle `CZzRTDJS`·`D1cL-UbV`, 1,79MB/1,71MB (**không phải** 900B SPA-fallback). + 🔴 **Suýt dính bẫy chuỗi-dùng-chung LẦN 4:** `Ghi chú (tùy chọn)` ở dist còn **2** — KHÔNG phải gỡ hỏng: `PeWorkflowPanel:869` + `HardCopiesPage:371` dùng chung. Chuỗi phân biệt KHKK là bản **CÓ dấu `…`**. +- **đợt-8 `65f73a9`** (bundle `CuWgMI7J`·`32bJmjpM`; anh chốt qua 2 câu: *dòng gốc "vẫn sinh, ẩn, không tính TỔNG"* · *"TỔNG = Σ hạng mục thật"*): ẩn dòng gốc chưa gán + TỔNG theo `visibleLines` + dòng nhập tự mở khi còn NCC chưa với tới + ô chọn NCC chỉ khi ≥2 + Hủy chỉ khi bấm `+`. + 🔴 **GREP CONSUMER CỨU:** submit-guard BE `ContractSigningPlanWorkflowService.cs:176` chặn khi còn dòng `CatalogEntryId==null` ⇒ ẩn xong là **phiếu KẸT VĨNH VIỄN**. Cách ra **0-mig 0-BE**: hạng mục ĐẦU của 1 NCC **gán vào chính dòng gốc** (PUT) thay vì đẻ dòng mới ⇒ **Σ `PeReferenceAmount` BẤT BIẾN** ⇒ `BudgetManualAmount` HĐ vẫn đúng số PE. + +**(2) bài học đo-lường của cửa-sổ 6 (thứ dễ mất nhất cùng WAL)** + +- 🔴 **Kỳ-vọng chuỗi sai LẦN 5** (lead tự bắt): đặt đích `'dòng chưa gán hạng mục.'`=0 ở prod, ra **1** — **code ĐÚNG, kỳ-vọng SAI**: `:1118` cố ý giữ câu cũ làm nhánh dự-phòng. ⇒ luật: đặt đích 0 phải hỏi **"mình có thật sự xoá HẾT nhánh dùng chuỗi này không"**, không chỉ "còn ai khác dùng". +- 🔴 **hash CI ≠ hash dist LOCAL cùng commit**: lead đoán `C1x59woX`·`Cn2Ctxap` (dist local `99370de`), CI thật ra `CZzRTDJS`·`D1cL-UbV` ⇒ **CẤM neo "đã deploy" vào hash-khớp-local**; neo đúng = *(a)* hash ĐỔI so prod cũ **+** *(b)* byte-level kèm control dương. +- 4 phép đo của lead hỏng rồi tự bắt: dò thư sai cấp (`../` thay `../../`) · `HEAD~1` ≠ commit-trước-của-mình (hook `wal:` chèn giữa) · đọc DLL sai heap + lệch khung UTF-16 · kỳ-vọng chuỗi=0 sai 3 lần vì đều dùng chung. **Control dương cứu cả 4.** + +**(3) 🔴 ĐÍNH-CHÍNH mục "Lead đã flush (a)"** — bản cũ đọc thành đã flush đủ; **thật ra 1/7**. Ghi ở đây theo đúng lời hứa "đính chính bằng entry sau", không sửa đè entry cũ (append-only). + +**(4) quyết-định anh chốt @S179** — ⓐ residual `ctx-curator` = **GIỮ** (không revert; 2 tệp ở lại hợp-lệ, hết là "residual" — anh tha *ca này*, không tha *cơ-chế* G-015) · ⓑ OK chạy SỬA-1 ngay · ⓒ OK chạy light-audit dù OVERDUE · ⓓ OK áp 2 thư `all` · ⓔ roster-cap "OK" = **ghi nhận**, chưa phải lệnh đổi số ⇒ giữ 20 · ⓕ OK restart CLI cho spawn-probe. Rồi anh chốt tiếp: ***"OK làm cho xong hết đi nhé"***. + ## (c) STOCK-touched — máy-derive > Bảng file-đã-đụng trong phiên, **máy-derive** từ `git diff --name-only ..HEAD` @pause/snapshot. KHÔNG điền tay. diff --git a/.claude/sessions/session-11/_mind-s-11.md b/.claude/sessions/session-11/_mind-s-11.md index 666a64b..80917dc 100644 --- a/.claude/sessions/session-11/_mind-s-11.md +++ b/.claude/sessions/session-11/_mind-s-11.md @@ -241,161 +241,34 @@ Máy chỉ quét phần **DƯỚI** marker đóng khối luật. Khối luật ## MIND-4 — 2026-08-05T21:54:30+07:00 @ 55b6d36 (window 3, @PAUSE-3) -### A. Gói-turn - -- Cửa-sổ dài nhất từ đầu phiên-logic: **7 commit sản-phẩm + 6 wal-flush**, **4 đợt deploy verify byte-level ×2 app**. Dãy hash + số liệu: xem `_context` PAUSE-3 mục (1) — `_mind` KHÔNG chép lại. -- Nửa sau cửa-sổ đổi CHẤT: anh không giao đề-bài đóng gói nữa mà **review trực tiếp trên prod, khoanh đỏ từng chỗ** rồi bắn ảnh liên tục — 12 defect qua ~10 tin nhắn, nhiều tin đến GIỮA lượt lead đang sửa. -- 1 engine-đắt `/fable-real investigator-codebase` chạy xong, spec 3-mục đã ghi; nhưng phương-án nó chốt **KHÔNG land** vì anh đổi hướng sau đó. -- `ctx-verifier` @`/tiep` chấm **13 cờ**, lead tự đo lại 2 cờ nặng — cả hai CONFIRMED. - -### B. Hướng-tiếp + nhánh-đã-loại - -- **Đi tiếp (cửa sau):** chờ anh nghiệm-thu UAT vòng-2 trên prod (**375 / 1366 / 1440**) → sửa defect vòng-3 nếu có → rồi mới quay về đuôi governance: thăng luật E4 ➊ · synthesis S173 · 5 điểm governance · kéo 2 thư + adap-report · A1 `ring2-audit` vượt trần. -- **Nhánh đã LOẠI ⑪:** *land phương-án live-derive cột DỰ ÁN mà engine chốt* — LOẠI: anh chốt KHÔNG cần đối-chiếu với số PRO/CCM (nguyên văn: xem PAUSE-3 mục (1)). Điều-tra vẫn giữ giá trị (2 đính-chính + phát hiện `Project.BudgetTotal`), nhưng bản đề-xuất thì chết. -- **Nhánh đã LOẠI ⑫:** *gỡ nút "Gửi duyệt" khỏi panel 3 ngay lượt anh yêu cầu dọn khối HÀNH ĐỘNG* (nguyên văn: xem PAUSE-3 mục (1)) — LOẠI: gỡ trước khi thanh-đáy có mặt = người soạn mất đường trình duyệt, phiếu kẹt ở Nháp. Ép cả cụm đi chung 1 commit. -- **Nhánh đã LOẠI ⑬:** *dựng cây Năm›Dự án›Hạng mục›4GĐ mới cho màn Thao tác* — LOẠI: `PipelineTreePanel` đã là đúng cây đó. Dùng lại ⇒ **−300 dòng**; dựng mới = bản thứ hai của cùng một hình. -- **Nhánh đã LOẠI ⑭:** *xoá hẳn entity căn cứ hồ sơ cho gọn khi gộp mục 3+4* — LOẠI: mất `kind`/`status`/TVGS mà BE đang ghi và người duyệt đang đọc. Chỉ gộp phần HIỂN THỊ. - -### C. Kế-hoạch (delta suy-nghĩ) - -- **Đổi so MIND-3 — nhịp làm việc:** khi anh review-live và bắn defect giữa lượt, cách đúng là **ship theo lô nhỏ đã verify** rồi báo hàng-đợi, KHÔNG gom hết rồi ship một cục. Lead đã kẹt một quãng vì ôm 4 việc chưa commit đúng lúc anh hỏi tiến-độ (nguyên văn: xem PAUSE-3 mục (1)) — câu hỏi đó là **tín-hiệu ship chậm**, không phải hỏi tiến-độ. -- **Đổi thứ hai — vì sao anh báo không thấy đổi:** anh chụp màn **Duyệt NCC**, còn đợt B/D nằm ở **KHKK**. ⇒ khi anh báo chưa thấy, nêu **ĐANG XEM MÀN NÀO** trước, đừng nhảy vào nghi cache hay nghi deploy. Bundle đã verify byte-level, sai lệch nằm ở **kỳ vọng vị trí**, không ở máy. -- **Đổi thứ ba — kỳ vọng đo cũng phải kiểm:** lead kỳ vọng bundle prod có **0 hit** `card-accent overflow-hidden`, đo ra **2** ⇒ tưởng chưa ăn. Truy lại: 2 hit là `HardCopiesPage` + `ProposalsListPage` — **module khác dùng hợp lệ**. ⇒ đo chuỗi DÙNG-CHUNG toàn bundle thì phải hỏi *"còn ai dùng nữa không"* TRƯỚC khi kết luận; nếu không thì chính phép đo đẻ ra báo động giả. -- **Đổi thứ tư — hai thứ trùng tên tiếng Việt:** "hạng mục" có **2 trục** — `WorkItem` (gói việc của dự án, từ phiếu PE) ⟂ `ContractCatalogEntry` SP-002 (danh mục phân loại hợp đồng). Lead bày nhầm trục thứ hai ở mục 1 nên anh yêu cầu bỏ (nguyên văn: xem PAUSE-3 mục (1)). ⇒ gặp danh-từ nghiệp-vụ trùng tên, **truy bảng nguồn trước khi bày**, đừng chọn cái đang cầm sẵn trong tay. - -### D. Đang-thảo-luận - -- Anh nghiệm-thu UAT vòng-2 trên prod 375/1366/1440 {treo-chờ-anh} -- Cột DỰ ÁN 11 ô — anh đã nói không cần so sánh PRO/CCM, coi như đóng hay còn mở {treo-chờ-anh} -- `Project.BudgetTotal` rỗng 61/69 dự án — có phải thứ anh muốn điền không {treo-chờ-anh} -- Thanh nút đáy: có cần nút "Lưu" rời không (lead cố ý không làm vì mọi ô tự lưu) {mới-nêu} -- Ghi chú dòng hạng mục nay nằm ở dòng phụ, không còn cột riêng {mới-nêu} -- Nâng PE lên khuôn KHKK — PE đang golive {treo-chờ-anh} -- Nâng `autoinject_cap` thay vì archive `ring2-audit` {treo-chờ-anh} -- Bản thân việc ROTATE mật-khẩu prod vrapp {treo-chờ-anh} -- Slot (67) người soạn có được upload file khi duyệt {treo-chờ-anh} -- Nợ harvest thật vs con số HANDOFF ghi {treo-chờ-anh} -- E4 vế ➊ thăng luật lên khối auto-inject — chủ = LEAD {gần-chốt} -- Run-folder S173 vẫn ORPHAN {gần-chốt} -- Vá `STATUS:473` Gotchas 86→87 {gần-chốt} -- Gạch 5 slot (68)-(72) khỏi HANDOFF {gần-chốt} -- Đưa `ROTATE vrapp` trở lại HANDOFF {gần-chốt} -- Re-stamp Carry 14 slug {gần-chốt} -- Slot (70) vá anchor neo cả 3 dạng {gần-chốt} -- A1 `ring2-audit` 26.440 B > cap 25.600 — treo từ PAUSE-1 {gần-chốt} -- Thước MFE thiên lệch theo độ dài diary, ngược trục `autoinject_cap` {mới-nêu} -- Headroom: cắt `STATUS.md` + `HANDOFF.md` theo tiering hay nâng trần {mới-nêu} -- Kéo 2 thư `loi-do-luong` + 4 adap-report {gần-chốt} -- Monthly drift-audit quá hạn {gần-chốt} -- 9 dir rỗng agent-memory trong run-folder {gần-chốt} - -### E. Dòng-sống spawn/engine-run - -- `ctx-verifier` @`/tiep` cửa-3 — **`NAP-LAI-SAN-SANG — 13 cờ`**; lead tự đo lại 2 cờ nặng, CẢ HAI CONFIRMED (run.md Owner-items stale · con-trỏ mục E chết ở tầng nội-dung). Verdict + chi tiết: `_context` PAUSE-3 mục (3) -- `/fable-real investigator-codebase` — **`wf_a574cff1-6b9`**, 1 lane, 169K tok, 38 tool-use. Lần phóng ĐẦU fail sạch ở guard `checkpointApproved` (0 agent · 0 token · 22ms) — guard CÓ RĂNG. Spec 3-mục + 2 đính-chính: `.claude/workflows/runs/2026-08-05-S175-duan-budget-column/` -- `ctx-curator` @PAUSE-3 — verdict ghi vào `_context` entry `PAUSE-3` mục (3) - +> 🗜️ **ĐÃ NÉN @S179** — cùng lượt nén MIND-2/MIND-3 (trần `mind_ctx_kb`). **Verbatim trong git**: `git show ee21056:.claude/sessions/session-11/_mind-s-11.md` (🔴 **ee21056** — bản trước-nén **48.989 B**, ĐÃ PUSH nên an-toàn. 🧊 2 lần vá: `ca9208f` sai vì thiếu trọn MIND-7 (44.353 B); rồi `727a512` đúng nội-dung nhưng **CHƯA push và nằm trong dải `wal:` sắp bị squash ở closeout** ⇒ trỏ vào nó là **tự đẻ con-trỏ mồ-côi**. Bài: con-trỏ recovery phải neo commit **ĐÃ PUSH**.). §C giữ **gần nguyên** vì 4 delta ở đây là bài-học load-bearing. +- **A.** Cửa-sổ dài nhất phiên-logic: **7 commit sản-phẩm + 6 wal-flush**, **4 đợt deploy verify byte-level ×2 app** (hash + số liệu: `_context` PAUSE-3 mục (1)). Nửa sau **đổi CHẤT**: anh không giao đề-bài đóng gói nữa mà **review trực tiếp trên prod, khoanh đỏ từng chỗ** — 12 defect qua ~10 tin nhắn, nhiều tin đến GIỮA lượt lead đang sửa. 1 engine-đắt `/fable-real investigator-codebase` chạy xong, spec ghi rồi nhưng **phương-án KHÔNG land** vì anh đổi hướng. `ctx-verifier` **13 cờ**, lead re-đo 2 cờ nặng — cả hai CONFIRMED. +- **B.** Nhánh đã LOẠI (còn hiệu-lực, **đừng đề lại**): ⑪ land phương-án live-derive cột DỰ ÁN — anh chốt KHÔNG cần đối-chiếu số PRO/CCM (điều-tra vẫn giữ giá-trị: 2 đính-chính + phát hiện `Project.BudgetTotal`, nhưng bản đề-xuất chết) · ⑫ gỡ nút "Gửi duyệt" khỏi panel-3 ngay lượt dọn khối HÀNH ĐỘNG — gỡ trước khi thanh-đáy có mặt = người soạn **mất đường trình duyệt, phiếu kẹt ở Nháp** ⇒ ép cả cụm đi chung 1 commit · ⑬ dựng cây Năm›Dự án›Hạng mục›4GĐ mới — `PipelineTreePanel` **đã là đúng cây đó**, dùng lại ⇒ **−300 dòng** · ⑭ xoá entity căn-cứ hồ-sơ cho gọn khi gộp mục 3+4 — mất `kind`/`status`/TVGS mà BE đang ghi và người duyệt đang đọc; **chỉ gộp phần HIỂN THỊ**. +- **C.** **Đổi so MIND-3 — nhịp làm việc:** anh review-live và bắn defect giữa lượt ⇒ cách đúng là **ship theo lô nhỏ đã verify** rồi báo hàng-đợi, KHÔNG gom hết ship một cục; lead kẹt một quãng vì ôm 4 việc chưa commit đúng lúc anh hỏi tiến-độ — **câu hỏi đó là tín-hiệu ship chậm**, không phải hỏi tiến-độ. **Đổi hai — vì sao anh báo không thấy đổi:** anh chụp màn **Duyệt NCC** còn đợt B/D nằm ở **KHKK** ⇒ khi anh báo chưa thấy, hỏi **ĐANG XEM MÀN NÀO** trước, đừng nhảy vào nghi cache/nghi deploy. **Đổi ba — kỳ-vọng ĐO cũng phải kiểm:** lead kỳ vọng bundle prod **0 hit** `card-accent overflow-hidden`, đo ra **2** ⇒ tưởng chưa ăn; truy lại 2 hit là `HardCopiesPage` + `ProposalsListPage` **dùng hợp lệ** ⇒ đo chuỗi DÙNG-CHUNG phải hỏi *"còn ai dùng nữa không"* TRƯỚC khi kết luận, không thì **chính phép đo đẻ báo động giả** (họ lỗi này về sau lặp tới **lần 5**). **Đổi bốn — hai thứ trùng tên tiếng Việt:** "hạng mục" có **2 trục** — `WorkItem` (gói việc của dự án, từ phiếu PE) ⟂ `ContractCatalogEntry` SP-002 (danh mục phân loại HĐ); lead bày nhầm trục nên anh yêu cầu bỏ ⇒ gặp danh-từ nghiệp-vụ trùng tên, **truy bảng nguồn trước khi bày**. +- **D.** (trống — khai) Ý còn sống carry lên **§D của MIND-7**. Đối chiếu @S179 — **5 ý đã ĐỊNH-ĐOẠT, không carry nữa:** `Vá STATUS:473 Gotchas 86→87` **XONG** · `Run-folder S173 ORPHAN` **XONG** (`bookend-open-synthesis.md`) · `Gạch 5 slot (68)-(72)` **XONG 4/5** — (68)(69)(70)(71) đóng, **(72) CÒN SỐNG** · `Cột DỰ ÁN 11 ô` + `Project.BudgetTotal rỗng 61/69` ⇒ **anh PARK @S176** (KHÔNG hỏi lại, KHÔNG tự làm). Còn treo: E4 ➊ · `ROTATE vrapp` · Carry 14 slug · slot (70) anchor · A1 `ring2-audit` 26.440 B · thước MFE · nâng `autoinject_cap` · slot (67) · nợ harvest · nâng PE lên khuôn KHKK. +- **E.** `/fable-real investigator-codebase` `wf_a574cff1-6b9` (propose-only; **lần phóng đầu FAIL SẠCH** 0 agent/0 token/22ms vì guard `checkpointApproved` chưa set — **guard CÓ RĂNG**) · `ctx-verifier` @`/tiep` **13 cờ**. Artifact: `runs/2026-08-05-S175-duan-budget-column/`, nay có `investigate-synthesis.md` (@S179 gỡ ORPHAN). ## MIND-3 — 2026-08-05T16:54:23+07:00 @ a1b9cbb (window 2, @PAUSE-2) -### A. Gói-turn - -- Anh ngắt mạch governance sang UAT UI KHKK, giao bằng **9 ảnh khoanh đỏ + 6 tin nhắn chốt** rải suốt cửa-sổ — không phải một đề bài đóng gói sẵn. Số commit / đợt deploy / verdict: xem `_context` PAUSE-2 mục (1). -- 1 lần anh BÁC chỗ đặt, lead revert về đúng byte. Ensemble `/fable-clone frontend-designer` chạy xong; spec 3-mục đã ghi — con-trỏ ở PAUSE-2 mục (3). -- `ctx-curator` chấm nháp block này: **`SUA — 9 điểm`**, lead sửa đủ 9 rồi mới chèn. - -### B. Hướng-tiếp + nhánh-đã-loại - -- **Đi tiếp (cửa sau):** poll deploy `a1b9cbb` → đợt B (bê style PE) → đợt D (O6 · O3 · O4 · O7 · O8) → **thăng luật E4 vế ➊ lên khối auto-inject** → **ghi synthesis cho run-folder S173** (đang ORPHAN) → rồi mới quay lại 5 điểm governance. -- 🔴 **Phải hỏi anh 1 câu TRƯỚC khi viết BE cho O3:** cách đọc "sum tổng" — đây là tiền, lane L5 dặn xác nhận. -- **Nhánh đã LOẠI ⑧:** *hạ khuôn Section của KHKK xuống cho bằng PE* — LOẠI: KHKK **giàu hơn** PE (icon-chip/accent/actions). Hướng đúng là **nâng PE lên**, không hạ KHKK. -- **Nhánh đã LOẠI ⑨:** *bê chip NS PRO/NS CCM sang KHKK cho đủ bộ* — LOẠI: 2 cờ đó mở quyền sửa ngân sách per-gói-thầu, khái niệm KHKK không có ⇒ bê sang là vẽ nhãn quyền không tồn tại. -- **Nhánh đã LOẠI ⑩:** *thay cả 3 chỗ SoonChip bằng số 0* — LOẠI: ca "chưa có QUYỀN xem" mà in 0 là nói dối về dữ-liệu. Ba ca ba cách: đếm-được → in số · khoá-quyền → bỏ trắng · failed → giữ dấu `—`. - -### C. Kế-hoạch (delta suy-nghĩ) - -- **Đổi so MIND-2:** lead bị vai kiểm bác **2 giả-định** và cả 2 lần lane đúng. ⇒ nhận: **trước khi tuyên một việc là "nặng", phải đọc EF configuration + index, đừng suy từ hình-dạng UI**. Chính khuôn `máy rộng, UI hẹp` anh chốt S164 — schema tổng-quát sẵn từ lâu, chỉ UI khoá 1-1. -- **Đổi thứ hai — sửa overclaim của chính bản nháp đầu:** cửa-sổ này lặp đúng MỘT họ lỗi *"trông như đã làm nhưng không làm gì"* (grep sai hình · thiếu `cd` build nhầm app · `git add` abort sau `git mv` · `border-0` bị `.card-accent` nuốt · `JSON.parse` free-text). Nháp đầu gọi đây là "luật tự rút" — **SAI**: luật `0-hit phải có control-dương` **đã tồn tại từ S172** trong thân `harness-eval/MEMORY.md`. Delta thật = **bằng-chứng 5 ca cùng họ trong một cửa-sổ**, và việc phải làm là **THĂNG luật lên khối auto-inject** (nó đang nằm dưới vùng planner mù nên không tới tay ai), KHÔNG phải rút lại lần 2. -- **Đổi thứ ba:** anh trả lời câu-3 hay hơn cả hai lựa chọn lead đưa ra — lead hỏi nhị-phân *giữ màu hay bỏ màu*, anh chốt một **nguyên-tắc** phân màu theo LOẠI (nguyên văn: xem PAUSE-2 mục (1)④). ⇒ khi hỏi owner, **đừng gói câu hỏi thành nhị-phân** nếu trục thật là một nguyên-tắc. - -### D. Đang-thảo-luận - -- Cách đọc "sum tổng" của O3 — là tiền, phải hỏi trước khi viết BE {treo-chờ-anh} -- Đợt B — HƯỚNG bê style PE đã được anh chốt {gần-chốt} -- Đợt B — NỘI DUNG từng mục lane đề xuất, anh chưa xem mục nào {mới-nêu} -- `slate-400` = 2.56:1 dưới ngưỡng WCAG cho 6 dòng chữ mang thông tin {mới-nêu} -- O6 bấm card PE giữ nguyên màn KHKK — callback-hoá `onOpenPe` mirror `onOpenKhkk` {gần-chốt} -- O7 nút edit trên card + O8 cây thư mục 2 cấp — tới sau khi lane đã phóng, lane không thấy {mới-nêu} -- NO-SCREENSHOT ×5 lane ⇒ mọi kết luận là đọc mã; phải soi thật 3 khổ màn trên prod {mới-nêu} -- Nâng PE lên khuôn KHKK — run riêng có ảnh đối chứng, PE đang golive {treo-chờ-anh} -- E4 vế ➊ chưa land — thăng luật lên khối auto-inject, chủ = LEAD {gần-chốt} -- Run-folder S173 ORPHAN (0 `*-synthesis.md`) — Sàn-3 ① sẽ kêu lần 2 nếu bỏ {gần-chốt} -- 2 thư `loi-do-luong` chưa kéo thật {mới-nêu} -- `ring2-audit/MEMORY.md` vượt `autoinject_cap` — A1 có payload, treo từ PAUSE-1 {gần-chốt} -- Nâng `autoinject_cap` thay vì archive — trần là quyền anh {treo-chờ-anh} -- Bản thân việc ROTATE mật-khẩu prod {treo-chờ-anh} -- Slot (67) người soạn có được upload file khi duyệt {treo-chờ-anh} -- Nợ harvest thật vs con số HANDOFF ghi — gom hay để ngủ {treo-chờ-anh} -- Vá `STATUS:473` Gotchas 86→87 — việc lead, đã quyết chưa thi hành {gần-chốt} -- Gạch 5 slot (68)-(72) khỏi HANDOFF — đã ratify `6730eb4`, sổ chưa lật {gần-chốt} -- Đưa `ROTATE vrapp` trở lại HANDOFF — việc lead {gần-chốt} -- Re-stamp Carry 14 slug — bỏ tiếp thành streak 12 {gần-chốt} -- Slot (70) vá anchor `^\*\*` neo cả `**`/`##`/`###` {gần-chốt} -- 9 dir rỗng `agent-memory//` trong run-folder — dọn @session-end {mới-nêu} -- Thước MFE thiên lệch theo độ dài diary, ngược trục `autoinject_cap` {mới-nêu} -- Headroom: cắt `STATUS.md` + `HANDOFF.md` theo tiering hay nâng trần {mới-nêu} -- Monthly drift-audit quá hạn {mới-nêu} - -### E. Dòng-sống spawn/engine-run - -- `ctx-verifier` @`/tiep` — **`NAP-LAI-SAN-SANG — 10 cờ`**; 2 cờ sửa thẳng reconcile của lead (kênh thư nhầm ledger · "kéo 6" gộp 2 trạng-thái) — con-trỏ `_context` PAUSE-2 mục (3) -- `/fable-clone frontend-designer` ensemble — lần phóng ĐẦU **`wf_edc388bf-f8f` CHẾT** ở `JSON.parse(args)` (free-text ⟂ object; 0 agent · 0 token · 20ms); lần hai **`wf_016b1bed-b85`** 5 lane / 5 xong / 0 chết. Verdict từng lane + artifact: `.claude/workflows/runs/2026-08-05-S174-khkk-style-audit/run.md` §Synthesis -- `ctx-curator` @PAUSE-2 — **`SUA — 9 điểm`**, verdict ghi vào `_context` entry `PAUSE-2` mục (3) +> 🗜️ **ĐÃ NÉN @S179** — tệp chạm trần `mind_ctx_kb` (48.989/49.152 B, dư 163 B) nên MIND-8 không chèn nổi; luật nén block CŨ NHẤT trừ block-0 và block-top. **Verbatim còn NGUYÊN trong git**: `git show ee21056:.claude/sessions/session-11/_mind-s-11.md` (🔴 **ee21056** — bản trước-nén **48.989 B**, ĐÃ PUSH nên an-toàn. 🧊 2 lần vá: `ca9208f` sai vì thiếu trọn MIND-7 (44.353 B); rồi `727a512` đúng nội-dung nhưng **CHƯA push và nằm trong dải `wal:` sắp bị squash ở closeout** ⇒ trỏ vào nó là **tự đẻ con-trỏ mồ-côi**. Bài: con-trỏ recovery phải neo commit **ĐÃ PUSH**.). +- **A.** Cửa-sổ UAT UI KHKK window-2 — anh giao bằng **9 ảnh khoanh đỏ + 6 tin nhắn chốt** rải suốt cửa (không phải đề bài đóng gói sẵn); 1 lần anh BÁC chỗ đặt, lead revert đúng byte. Số commit/đợt deploy/verdict: `_context` PAUSE-2 mục (1). +- **B.** Nhánh đã LOẠI (còn hiệu-lực, **đừng đề lại**): ⑧ hạ khuôn Section KHKK xuống bằng PE — sai chiều, phải **NÂNG PE** · ⑨ bê chip NS PRO/CCM sang KHKK — vẽ nhãn quyền **không tồn tại** · ⑩ thay cả 3 `SoonChip` bằng số 0 — ca khoá-quyền mà in 0 là **nói dối dữ-liệu**; 3 ca 3 cách: đếm-được → số · khoá-quyền → bỏ trắng · failed → dấu `—`. +- **C.** **Đổi so MIND-2:** lead bị vai kiểm bác **2 giả-định**, cả 2 lần lane ĐÚNG ⇒ *trước khi tuyên một việc là "nặng", phải đọc EF configuration + index, đừng suy từ hình-dạng UI* — đúng khuôn **`máy rộng, UI hẹp`** anh chốt S164. **Đổi hai:** luật `0-hit phải có control-dương` **KHÔNG phải luật mới rút ở đây** (có từ S172 trong `harness-eval/MEMORY.md`); delta thật = **5 ca cùng họ trong MỘT cửa-sổ**, việc phải làm là **THĂNG luật lên khối auto-inject**, không rút lại lần 2. **Đổi ba:** *đừng gói câu hỏi cho owner thành nhị-phân* nếu trục thật là một **nguyên-tắc** (lead hỏi giữ-màu/bỏ-màu, anh chốt nguyên-tắc phân màu theo LOẠI). +- **D.** (trống — khai) Ý còn sống đã **carry lên §D của MIND-7** (đối chiếu @S179 8/9 khoá: ROTATE · Carry 14 · `autoinject_cap` · slot (67) · drift-audit · 9 dir rỗng · MFE · Headroom) ⇒ không giữ bản sao, không đẻ 2 nguồn. 🔴 **Ngoại lệ 1 ý — `"cách đọc sum tổng của O3 — là tiền"` {treo-chờ-anh} KHÔNG có ở MIND-7 lẫn WAL**, nén mù là mất im lặng (đúng bệnh S162). 🔴 **BỔ SUNG @S179 sau C7 — census "8/9 khoá" của lead LÀ THIẾU: §D gốc MIND-3 có 25 mục, và 3 ý `{mới-nêu}` CHƯA từng định-đoạt bị đóng IM LẶNG** (đúng bệnh luật `:266` tự cấm): ① `slate-400 = 2.56:1 dưới ngưỡng WCAG cho 6 dòng chữ mang thông tin` — **CÒN SỐNG**, nhà ở `_context` ② `NO-SCREENSHOT ×5 lane ⇒ mọi kết luận là ĐỌC MÃ, phải soi thật 3 khổ màn trên prod` — **CÒN SỐNG**, nhà ở `_context` (cùng họ với dòng WAL "CHƯA ai soi mắt prod") ③ `Đợt B — NỘI DUNG từng mục lane đề xuất, anh chưa xem mục nào` — 🔴 **0 hit ở CẢ `_mind` LẪN `_context`**, đây là ý **suýt mất hẳn**; giữ lại ở đây làm nhà. ⇒ Bài: **census tự-xưng "đủ" mà không liệt từng mục thì không kiểm được** — lần sau nén phải in RA danh-sách đối-chiếu, không viết "8/9". **Định-đoạt @S179: ANH ĐÃ TRẢ LỜI ở đợt-8** `65f73a9` — nguyên văn *"TỔNG = Σ hạng mục thật"* + *dòng gốc "vẫn sinh, ẩn, không tính TỔNG"* ⇒ **ĐÓNG**, không carry. +- **E.** `ctx-verifier` @`/tiep` **`NAP-LAI-SAN-SANG — 10 cờ`** · `/fable-clone frontend-designer` — phóng đầu **`wf_edc388bf-f8f` CHẾT** ở `JSON.parse(args)` (free-text ⟂ object, 0 agent/0 token/20ms), phóng hai **`wf_016b1bed-b85`** 5 lane/5 xong/0 chết · `ctx-curator` @PAUSE-2 **`SUA — 9 điểm`**. Artifact: `runs/2026-08-05-S174-khkk-style-audit/run.md`. ## MIND-2 — 2026-08-05T12:13:25+07:00 @ 037fe63 (window 1, @PAUSE-1) -### A. Gói-turn - -- Anh gõ `/pause` (xem PAUSE-1). Chạy nghi-thức 5 bước; không nhận việc mới. -- **Cổng C2 (slot 69) KÊU ngay lần đầu chạy ở `/pause`** — số liệu + xử lý ghi ở `_context-s-11.md` entry `PAUSE-1` mục (1), không chép lại. -- `ctx-curator` chấm nháp block này: **`SUA — 9 điểm`**, lead sửa đủ 9 rồi mới chèn. - -### B. Hướng-tiếp + nhánh-đã-loại - -- **Đi tiếp (cửa sau):** vá `STATUS:473` · gạch 5 slot trong HANDOFF · đưa `vrapp` trở lại sổ · **re-stamp Carry 14 slug** · thi hành A1. Rồi commit `wal: pause` và DỪNG HẲN; nối bằng `/tiep`. -- **Nhánh đã LOẠI ⑥:** *thi hành A1 (archive `ring2-audit`) ngay tại `/pause`* — LOẠI: `/pause` là cửa dừng, ràng buộc hub cấm làm nó đắt lên; A1 là việc nặng thuộc bookend. Đổi lại phải **khai nợ tường minh** thay vì im lặng. -- **Nhánh đã LOẠI ⑦:** *rút gọn entry seed cho khỏi phình sổ* — LOẠI: seed mỏng thì phiên sau đọc không đủ để hành động, đúng bệnh mà cổng C2 sinh ra để chặn. Chấp nhận vượt trần và khai ra. - -### C. Kế-hoạch (delta suy-nghĩ) - -- **Đổi so MIND-1:** lead vừa **tự gây** một vi phạm trần khi chấp hành một cổng khác (seed C2 đẩy `ring2-audit` vượt `autoinject_cap`). ⇒ nhận: **hai luật đúng có thể kéo ngược nhau**, và khi đó việc phải làm là **khai xung đột**, không phải im một bên. Cùng họ với thứ `harness-audit` chỉ ra ở thước MFE (thưởng vai phình to ⟂ `autoinject_cap` ép gầy đi). -- **Đổi thứ hai:** `ctx-audit` F-5 chứng lớp mềm **mù** nghĩa vụ re-stamp Carry ⇒ block này **cố ý nêu tên nó ở §B đi-tiếp**, không chỉ ở §D — vì §D là chỗ *đang bàn*, §B mới là chỗ *sẽ làm*. -- **Đổi thứ ba (bài từ `ctx-curator` #1):** §D được đọc theo quy-ước **carry-all** ⇒ **bỏ sót một ý = tuyên bố nó đã đóng**. Lead vừa suýt đánh rơi 2 ý sống theo đúng cách đó. ⇒ mỗi lượt refresh phải **đối chiếu §D lượt trước**, không viết lại từ trí nhớ. - -### D. Đang-thảo-luận - -- Slot (70) MỞ LẠI — vá anchor `^\*\*` phải neo cả `**`/`##`/`###`, 3 khối mù {gần-chốt} -- 9 dir rỗng `agent-memory//` trong run-folder = lỗ backstop thứ 3, dọn @session-end {mới-nêu} -- `ring2-audit/MEMORY.md` vượt `autoinject_cap` do chính lượt seed — A1 có payload, `harness-audit` chấm ĐẠT {gần-chốt} -- Nâng `autoinject_cap` thay vì archive — trần là quyền anh {treo-chờ-anh} -- Đưa `ROTATE mật-khẩu prod vrapp` trở lại HANDOFF — việc lead, đã cam kết ở §B {gần-chốt} -- Bản thân việc ROTATE mật-khẩu prod {treo-chờ-anh} -- Carry 14 slug chưa re-stamp — số streak canonical ở `.claude/WAL.md` + `.session-counter.json`, không neo ở đây {mới-nêu} -- Slot (67) người soạn có được upload file khi duyệt {treo-chờ-anh} -- Nợ harvest thật vs con số HANDOFF ghi — gom hay để ngủ {treo-chờ-anh} -- Thước MFE thiên lệch theo độ dài diary, ngược trục `autoinject_cap` {mới-nêu} -- Headroom: cắt `STATUS.md` + `HANDOFF.md` theo tiering-rule sẵn có hay nâng trần {mới-nêu} -- Monthly drift-audit quá hạn 4 ngày, chưa chạy {mới-nêu} -- 2 thư fan-out mới cùng ngày, chủ đề trùng phiên này — kéo ở cửa sau {mới-nêu} - -### E. Dòng-sống spawn/engine-run - -- `ctx-curator` — **`SUA — 9 điểm`** (vai-1 vòng Ctx @PAUSE-1, carve-out `pause.md §1`) — verdict ghi vào `.claude/sessions/session-11/_context-s-11.md` entry `PAUSE-1` mục (3) -- **10 vai bookend @open**: MIND-0 §E (9 con-trỏ, `ctx-audit` verify **9/9**) + MIND-1 §E (`ctx-audit` — chạy 11:49, TRƯỚC MIND-1 nên không tự verify được dòng của mình); lượt thứ 11 = gạch-1 trên. Artifact gốc `.claude/workflows/runs/2026-08-05-S173-bookend-open/run.md` +> 🗜️ **ĐÃ NÉN @S179** — cùng lượt, cùng lý do trần. **Verbatim trong git**: `git show ee21056:.claude/sessions/session-11/_mind-s-11.md` (🔴 **ee21056** — bản trước-nén **48.989 B**, ĐÃ PUSH nên an-toàn. 🧊 2 lần vá: `ca9208f` sai vì thiếu trọn MIND-7 (44.353 B); rồi `727a512` đúng nội-dung nhưng **CHƯA push và nằm trong dải `wal:` sắp bị squash ở closeout** ⇒ trỏ vào nó là **tự đẻ con-trỏ mồ-côi**. Bài: con-trỏ recovery phải neo commit **ĐÃ PUSH**.). +- **A.** Anh gõ `/pause` (xem PAUSE-1); chạy nghi-thức 5 bước, **không nhận việc mới**. **Cổng C2 (slot 69) KÊU ngay lần đầu chạy ở `/pause`** — số liệu + xử lý ở `_context` PAUSE-1 mục (1). +- **B.** Nhánh đã LOẠI: ⑥ thi-hành A1 (archive `ring2-audit`) ngay tại `/pause` — `/pause` là **cửa dừng**, ràng buộc hub cấm làm nó đắt lên; đổi lại phải **khai nợ tường minh** thay vì im lặng · ⑦ rút gọn entry seed cho khỏi phình sổ — seed mỏng thì phiên sau **không đủ để hành động**, đúng bệnh cổng C2 sinh ra để chặn ⇒ chấp nhận vượt trần và **khai ra**. +- **C.** **Đổi so MIND-1:** lead **tự gây** một vi phạm trần khi đang chấp hành một cổng khác (seed C2 đẩy `ring2-audit` vượt `autoinject_cap`) ⇒ **hai luật ĐÚNG có thể kéo ngược nhau**, và khi đó việc phải làm là **KHAI XUNG ĐỘT**, không im một bên (cùng họ với thước MFE thưởng vai phình ⟂ `autoinject_cap` ép gầy). **Đổi hai:** `ctx-audit` F-5 chứng lớp mềm **mù** nghĩa-vụ re-stamp Carry ⇒ phải nêu tên ở **§B (sẽ làm)**, không chỉ §D (đang bàn). **Đổi ba:** §D đọc theo quy-ước **carry-all** ⇒ **bỏ sót một ý = tuyên bố nó đã đóng** ⇒ mỗi lượt refresh phải **đối chiếu §D lượt trước**, CẤM viết lại từ trí-nhớ. +- **D.** (trống — khai) Tập §D của block này là **tập con của MIND-3**, đã kiểm ở block trên ⇒ không ý nào rơi thêm. +- **E.** `ctx-curator` @PAUSE-1 **`SUA — 9 điểm`** (vai-1 vòng Ctx, carve-out `pause.md §1`) · **10 vai bookend @open** — artifact `runs/2026-08-05-S173-bookend-open/`, nay đã có `bookend-open-synthesis.md` (@S179 gỡ ORPHAN). ## MIND-1 — 2026-08-05T11:52:00+07:00 @ 1b3bcaa (window 1, refresh sau khi 11/11 vai chốt) -> 🗜️ **ĐÃ NÉN @PAUSE-6 (S177)** — tệp vượt trần `mind_ctx_kb` (51.260B/49.152B); luật nén block CŨ NHẤT trừ block-0 và block-top. **Verbatim còn NGUYÊN trong git**: `git show ca9208f:.claude/sessions/session-11/_mind-s-11.md`. +> 🗜️ **ĐÃ NÉN @PAUSE-6 (S177)** — tệp vượt trần `mind_ctx_kb` (51.260B/49.152B); luật nén block CŨ NHẤT trừ block-0 và block-top. **Verbatim còn NGUYÊN trong git**: `git show d081681:.claude/sessions/session-11/_mind-s-11.md` (🔴 **d081681** — vá @S179: MIND-1 ở đó còn **4.041 B CHƯA nén**, trong khi `727a512` đã là bản nén 1.770 B. Mỗi block nén có mốc verbatim RIÊNG, không dùng chung được.). > Giữ đúng phần load-bearing, bỏ phần đã có nhà khác: - **A.** 11/11 vai đóng sổ (`harness-audit` 50Đ/7T · `ctx-audit` TRƯỢT-7-FLAG); **#53 garble 11/11 vai, mất 0 byte** — vớt bằng `SendMessage` resume-từ-transcript. - **B.** 2 nhánh LOẠI ④ (sửa MIND-0 tại chỗ — block cũ BẤT BIẾN) · ⑤ (thi-hành nguyên văn E4 "thiếu S163+S168+S169" — S168 CÓ thật ⇒ làm theo sẽ nhân bản mục đang đúng). diff --git a/.claude/sessions/session-11/_tiep-6.md b/.claude/sessions/session-11/_tiep-6.md new file mode 100644 index 0000000..4c826bb --- /dev/null +++ b/.claude/sessions/session-11/_tiep-6.md @@ -0,0 +1,7 @@ +ts: 2026-08-07T00:00:00+07:00 +head-sha: b99c1879f150f965527ab71fdd87b47fb468a5b1 +window-ordinal: 7 +jsonl-hint: D--Dropbox-CONG-VIEC-SOLUTION-SOLUTION-ERP/1bee4ccc-e858-4712-82bb-b3a18b4a15cf +account-label: none +ctx-verifier: CO-CO - 14 co (chay THAT, khong fallback). Nang nhat: co-3 ca cua-so 6 SONG DOC NHAT O WAL (99370de/65f73a9/CuWgMI7J = 0 hit ca _mind lan _context; control duong ca9208f=3/6, Mig 72=2/1) => WAL tai sinh moi /pause la mat han 2 commit ship + 2 deploy VERIFIED; lead DO LAI DOC LAP: CONFIRMED. co-14 path spec SUA-6 trong WAL gay (thieu .claude/workflows/) - lead ls doi chung: not-found vs nha that 7.227B, DA VA. co-8 _mind 48.989/49.152B = 99,67% du 163B, bien MIND-8 chi 296B => nen MIND-2+3 chua du, can them M4 hoac chan MIND-8 <=7.200B. co-9 nen phai giu 2 moc "Doi so MIND-2/MIND-3" (_mind:317/:261) keo bay hoi. co-10/11/12 ba y {treo-cho-anh} da duoc anh dinh-doat, phai ha nhan. +lead-lech: 1/1 - thuoc residual ctx-curator (WAL verify:36) neo vao cua-so origin/main..HEAD, ee21056 DA PUSH nen troi ra ngoai => 0-hit doc thanh "da sach". Control duong: 2 tep con tren dia (MEMORY.md 10.534B + feedback_machine_blind_classes.md 7.564B). Da thay bang thuoc neo DIA: ls .claude/agent-memory/ctx-curator/*.md | wc -l -> 2. Cung goc voi bay HEAD~n (WAL:38), khac dung-cu. diff --git a/.claude/workflows/runs/2026-08-05-S173-bookend-open/bookend-open-synthesis.md b/.claude/workflows/runs/2026-08-05-S173-bookend-open/bookend-open-synthesis.md new file mode 100644 index 0000000..23044a5 --- /dev/null +++ b/.claude/workflows/runs/2026-08-05-S173-bookend-open/bookend-open-synthesis.md @@ -0,0 +1,63 @@ +# bookend-open-synthesis — S173 @open (2026-08-05, phiên-LOGIC L11) + +> 🔴 **Harvest HỒI-TỐ, ghi @S179 2026-08-07.** Folder bị sàn `/tiep §0 ①` xếp **ORPHAN** suốt S174→S178: có `run.md` + **10 file return** mà **không có bản-ghi-kết-quả dạng-1** (`*-synthesis.md` phẳng). Đây là ca **dương-giả cổ điển của sàn** — folder ghi chép ĐẦY ĐỦ NHẤT trong repo lại bị xếp mồ-côi vì thiếu đúng một cái tên file. Nội-dung dưới **derive từ đĩa**, đánh dấu **partial-honest**. + +## 1. Run là gì + +Bookend @open phiên-LOGIC L11 — **10 vai**, HEAD @spawn `1b3bcaa`. Artifact tổng **~245 KB**. + +| Vai | Verdict | +|---|---| +| `tooling-auditor` (H1) | `PASS_WITH_FLAGS — 10` | +| `harvest-curator` (H2) | `GATE-FAIL — 6` | +| `lead-stale-auditor` | `11 FLAG (SÀN)` | +| `lead-gap-auditor` | `4 FLAG` | +| `ring1-audit` | `78Đ / 4T` | +| `ring2-audit` | `15Đ / 3T` | +| `ctx-audit` | `TRUOT — 7 FLAG` | +| `harness-eval` (1/3) | `MIXED — 15 signal` | +| `harness-refine` (2/3) | `1 action / 15 bác` | +| `harness-audit` (3/3) | `50Đ / 7T` | + +## 2. 🔴 Kết-quả ĐẮT NHẤT — con-KIỂM ĐẢO DẤU kết-luận của con-ĐO + +`harness-eval` khai *"mốc 4, bước −17.584 > tổng 2 bước trước ⇒ **GIA TỐC**"*; lead **đã chép và đã báo owner**. `harness-audit` **BÁC**: + +- Chuỗi thật có **6 mốc**, con-ĐO **bỏ sót 2** (S163 = 160.924 · S169 = 152.968) — cả hai đều có **stdout máy in** trên đĩa, và **không tiêu-chí nào** loại chúng mà vẫn giữ S162. +- **−17.584 = khoảng S162→S173 = 3 phiên GỘP**, không phải 1 bước. **Bước thật kỳ này = −4.785.** +- Chuỗi bước: −8.981 · −6.480 · −4.843 · −7.956 · **−4.785** ⇒ **CHẬM LẠI**, không gia tốc. +- ✅ **Vẫn đứng:** đơn-điệu giảm qua **cả 6 mốc, chưa 1 lần đảo chiều** (181.228 > 172.247 > 165.767 > 160.924 > 152.968 > 148.183) — **chặt hơn** con-ĐO tưởng. + +🔸 **Bài (đắt, giữ nguyên văn):** con-ĐO **rơi mốc** ⇒ bước tính ra là **tổng nhiều kỳ** ⇒ **đạo hàm sai dấu**. **Chuỗi thiếu mốc nguy hơn chuỗi sai số, vì nó vẫn "trông có xu hướng".** + +## 3. Phát hiện còn hiệu-lực + +- `harness-refine` §6 N1 chứng **6/6 nguồn phình là hot-feed của LEAD** (`STATUS.md` 226.173 · `HANDOFF.md` 175.771 · `gotchas.md` 119.937 · `migration-todos.md` 88.151 · `agents/README.md` 54.222 · `ACTIVE-MARKS.md` 31.197) — **KHÔNG phải agent-memory** ⇒ **món của lead, không delegate được**. +- `mfe-eval.ps1 -Detail` **built-but-never-invoked 21 phiên** ⇒ lead gọi ngay trong phiên, gỡ tắc lane ① bế 2 vòng. (Class `dry-run bắt lời-hứa-chưa-land`.) + +## 4. 5 đính-chính của LEAD (ghi để không tái sinh) + +- ❌ "4 stray dir" lead gọi là **ground truth** rồi giao 2 vai phân xử → `ring1`+`ring2` chứng đó chỉ là **dấu thời-gian**; cơ-chế = harness tạo dir theo **cwd LÚC SPAWN**, đơn-điệu tăng theo số vai. **Không vai nào làm bậy** — lead từng quy tội sai. +- ❌ Giả-thuyết `find` **dot-blind** → `ring2` **BROKE**; bộ lọc thật `*/.claude/*`. Kết-luận HELD, lý do thay — và lý do thật **nghiêm trọng hơn**: tập-đo bị cắt **đúng bề mặt quản-trị mà vai đó sinh ra để soi**. +- ❌ Giả-thuyết MFE *"dấu `/` vs dấu cách"* → `harness-audit` **BROKE**; biến thật = **DÍNH vs TÁCH**. +- ❌ Lead sai 3 dữ-kiện trong lệnh giao `harness-refine` (mỏ-neo `:27` không phải `:23` · **12** return không phải 11 · thiếu thật S144·S154·S158·S163·S169) — vai tự sửa. +- ❌ **Lead báo owner 5 slot (68)-(72) "chờ anh" trong khi chúng ĐÃ ratify + land @S172 `6730eb4`** — nguyên nhân: `HANDOFF` **không được commit đó chạm** (`grep -c HANDOFF` = 0) ⇒ **sổ nói dối**. + +## 5. 🔴 Hậu-kiểm @S179 — cái ❌ cuối SỐNG DAI hơn phiên phát hiện nó + +`run.md` khai *"lead đã đính chính trong phiên"*. **Đo lại @S179: SAI.** 4 slot (68)(69)(70)(71) **vẫn nằm dưới tiêu-đề `🔴 CHỜ ANH`** trong `HANDOFF.md`, mang dấu 🔴 mở, **suốt S173→S179**; `git log -1 -- docs/HANDOFF.md` = `3a6eb92` (2026-08-05) ⇒ **0 commit chạm HANDOFF trong cả quãng đó**. `lead-stale-auditor` @S179 bắt lại **cùng một lỗi** (FLAG-1, `view-stale-status`), lần này mới thật sự đóng. + +🔴 **Bài rút ra — class riêng, đáng nhớ hơn chính lỗi:** *"đã đính chính **trong phiên**"* ≠ *"đã LAND trên đĩa"*. Đính chính sống trong hội-thoại thì **chết cùng cửa-sổ**. Cùng họ với `dry-run bắt lời-hứa-chưa-land` và `claim mạnh hơn việc đã làm`. ⇒ **mọi đính-chính về một FILE phải kết bằng một EDIT vào chính file đó, rồi grep lại** — nếu không, phiên sau đo lại vẫn thấy y nguyên. + +## 6. #53 — datum phiên (đắt, giữ) + +**8/8 vai first-return garble**, gồm **2 ca `skeleton-ruột-rỗng`** (chạy 31 tool-use mà **0 nội-dung xuống đĩa**). **Mất 0 byte** — vớt toàn bộ bằng `SendMessage` resume-từ-transcript. + +Luật `harness-eval` tự rút: *"đổ ruột mà chỉ đổ KHUNG vẫn = mất trắng — ghi NGAY SAU MỖI LỆNH, không gom."* + +🔸 **Xác nhận lại @S179**: `lead-stale-auditor` lượt này cũng garble ở return đầu, cũng vớt trọn bằng resume ⇒ **thang #53 nấc-2 (resume-in-session) đã ăn 2 phiên liên tiếp**, không phải may. + +## 7. Khai giới-hạn (partial-honest) + +- 4 vai (`lead-gap` · `lead-stale` · `ring1` · `ring2`) **không grep ra dòng verdict theo khuôn** ở lượt harvest này; số trong bảng §1 lấy từ **`_context-s-11.md` PAUSE-1** (lead đã VERIFY lúc đó), không phải đọc lại từng file. +- Chi-tiết 10 FLAG của H1 · 6 finding GATE-FAIL của H2 · 15 signal của con-ĐO **không nén vào đây** — còn nguyên trong từng `sub-*.md`, đọc thẳng ở đó khi cần. diff --git a/.claude/workflows/runs/2026-08-05-S175-duan-budget-column/investigate-synthesis.md b/.claude/workflows/runs/2026-08-05-S175-duan-budget-column/investigate-synthesis.md new file mode 100644 index 0000000..2ca91b4 --- /dev/null +++ b/.claude/workflows/runs/2026-08-05-S175-duan-budget-column/investigate-synthesis.md @@ -0,0 +1,49 @@ +# investigate-synthesis — cột DỰ ÁN trong bảng ngân sách (S175, 2026-08-05) + +> 🔴 **Harvest HỒI-TỐ, ghi @S179 2026-08-07.** Folder này bị sàn `/tiep §0 ①` xếp **ORPHAN** suốt S176→S178 vì có `run.md` mà **không có bản-ghi-kết-quả dạng-1**. Nội-dung dưới đây **derive từ đĩa** (`run.md` + `spec-hang-muc-nhieu-dong-va-cot-du-an-05-08-2026.md` + git), **KHÔNG** dựng lại từ trí-nhớ phiên cũ. Đánh dấu **partial-honest**: phần nào không tái-dựng được từ đĩa thì khai thẳng ở §5. + +## 1. Run là gì + +| | | +|---|---| +| Engine | `/fable-real` (LỆNH-A per-invocation, H21) — **1 vai × SINGLE top-model deep-pass** | +| Vai | `investigator-codebase`, tier `fable`, **propose-only** | +| run-id | `wf_a574cff1-6b9` | +| Đề-bài anh gõ | *"invest case cột DỰ ÁN trong bảng ngân sách → sau đó điều chỉnh lại"* | + +## 2. Câu chốt của anh — thứ hoà-giải toàn bộ mâu-thuẫn + +> *"phần trên duyệt NCC → ngân sách bảng đó mang xuống → KHKK → nhập từng hạng mục sau đó cộng vào ô của dự án"* + +⇒ luồng đích **4 nhịp**: ① bảng ngân sách sống ở Duyệt NCC (GĐ1) → ② **mang xuống** KHKK (GĐ2) → ③ KHKK **nhập tiền theo TỪNG HẠNG MỤC** → ④ các dòng đó **cộng vào ô DỰ ÁN**. + +🔑 Câu này gỡ nút thắt *"3 thằng RIÊNG"*: DỰ ÁN **không** phải ô nhập tay cấp dự án — **nguồn của nó khác hẳn**. PRO/CCM là 2 vai nhập cho *gói thầu này*; DỰ ÁN được nuôi bằng **các dòng hạng mục nhập bên KHKK**. Nguồn khác ⇒ "thằng riêng"; cộng-dồn ⇒ "chọn hạng mục điền tiền → cộng vào mục đó". **Hai vế đúng cùng lúc.** + +## 3. Phát hiện load-bearing (lead đã đo, có nguồn) + +| Phát hiện | Nguồn | +|---|---| +| DTO `PeBudgetSummary` **không** có trường cấp DỰ ÁN — mọi trường khoá theo cặp (Dự án × Hạng mục) | `fe-admin/src/types/purchaseEvaluation.ts:312-339` | +| Cột DỰ ÁN **hardcode `—`** ≥3 chỗ | `PeDetailTabs.tsx:1535 · 1664 · 1677` | +| Comment DTO tự khai *"DỰ ÁN = FE hiển thị-only (chưa wire BE)"* | `purchaseEvaluation.ts:311` | +| `PeBudgetAccumulator` gom **CHỈ 3 bảng PE**; `grep -c 'ContractSigningPlan'` = **0** (control dương: chuỗi đó có ở 7 file khác Application layer ⇒ grep không rỗng) | `PeBudgetAccumulator.cs` | +| Entity `PeWorkItemBudget` = 1 record / cặp `ProjectId` × `WorkItemId` | `Domain/PurchaseEvaluations/PeWorkItemBudget.cs:27-36` | + +🔴 **Manh mối lớn nhất:** module **Budget (Ngân sách dự án) cũ đã XÓA HẲN ở Mig 50 (S61)**, FE `Bg_*` gỡ hết ⇒ giả-thuyết *"cột DỰ ÁN là **DI-CHỨNG** của module cũ — chỗ ngồi còn, ruột bị rút"*. Nếu đúng thì "điều chỉnh lại" = **dựng lại tầng ngân sách cấp DỰ ÁN**, không phải vá 1 cột FE. + +## 4. Kết cục THẬT (đây là phần quan trọng nhất — đừng đọc run này thành "đã làm") + +- ✅ **Phần hạng-mục N-dòng ĐÃ LAND** — `b811e11`. +- ❌ **Phương-án cột DỰ ÁN KHÔNG LAND.** Anh chốt cắt: *"ko cần so sánh j với số duyệt PRO hay CCM j cả"*. +- 🅿️ **Sau đó anh PARK hẳn @S176** — WAL ghi: *"PARK (anh @S176) — KHÔNG hỏi lại, KHÔNG tự làm: cột DỰ ÁN 11 ô · `Project.BudgetTotal` rỗng 61/69"*. + +⇒ **Trạng-thái đúng của run này = ĐÃ ĐÓNG bằng quyết-định owner, KHÔNG phải việc dở.** Ai nối mạch sau này: **đừng tự khởi động lại**; giá-trị còn dùng được là **§2 (mô-hình luồng 4 nhịp)** và **§3 (bản đồ file:line)** — nếu anh mở PARK thì bắt đầu từ đó, khỏi điều tra lại. + +## 5. Khai giới-hạn (partial-honest) + +- Return nguyên-văn của vai **không có trên đĩa** (folder chỉ có `run.md` + spec) ⇒ §3 là **bản lead đã VERIFY và chép vào run.md**, không phải transcript vai. Con số *"169K tok / 38 tool-use"* lấy từ `run.md`, lead @S179 **không tái-dựng được**. +- `run.md` khai P3 gồm *"tự đo lại 2 đính-chính"* nhưng **không ghi 2 đính-chính đó là gì** ⇒ mất, không bịa. + +## 6. Vết đáng giữ — guard CÓ RĂNG + +Lần phóng **đầu FAIL SẠCH** (0 agent · 0 token · 22ms): guard `checkpointApproved chưa set` chặn ngay cửa. Đúng thiết-kế — em-main phải BÁO {số agent · vai · task} rồi mới set cờ. **Ghi lại vì đây là bằng-chứng guard không phải trang-trí** — hiếm, vì guard thường chỉ chứng minh được khi có ca chặn thật. diff --git a/CLAUDE.md b/CLAUDE.md index dc02589..9042f7b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -40,7 +40,7 @@ Kiến trúc: **.NET 10 Clean Architecture + 2 React FE (admin + user) + SQL Ser - Error handling: `GlobalExceptionMiddleware` map exception → HTTP status - Commit scope tech stack: `Api` · `App` · `Domain` · `Infra` -### Frontend — 2 app React 18 + Vite + TS + shadcn/ui + TanStack Query +### Frontend — 2 app React 19 + Vite + TS + shadcn/ui + TanStack Query - `fe-admin/` (port **8082**) · `fe-user/` (port **8080**) - Vite proxy `/api → http://localhost:5443` (SolutionErp.Api) @@ -118,7 +118,7 @@ dotnet test SolutionErp.slnx # chạy cả 2 test project | `form-engine` — render docx/xlsx + PDF | `ef-core-migration` — EF migration + 3-file rule | | `permission-matrix` — role × menu × CRUD | `iis-deploy-runbook` — 3 site IIS + win-acme + runner | -**Audit định kỳ:** đầu mỗi tháng — combined skill + doc drift audit theo `docs/rules.md §6.4 + §9.4`, **em-main chạy thủ-công session đầu-tháng** (🧊 ghost-wire cron gỡ S100 H18 — CronList runtime = 0 job). Lần kế: **2026-08-01** (S96 đã chạy 07-01). +**Audit định kỳ:** đầu mỗi tháng — combined skill + doc drift audit theo `docs/rules.md §6.4 + §9.4`, **em-main chạy thủ-công session đầu-tháng** (🧊 ghost-wire cron gỡ S100 H18 — CronList runtime = 0 job). **ĐÃ CHẠY 2026-08-07 (S179)** — trễ 6 ngày so hạn 08-01; verdict `tooling-auditor` = `PASS_WITH_FLAGS — 8`. **Lần kế: 2026-09-01.** 🔴 Ô ngày này là **giá-trị SỐNG duy nhất** trong repo (rules.md:546 trỏ về STATUS nhưng STATUS KHÔNG có row canonical) ⇒ **đóng audit thì phải lật ô này trong CÙNG lượt**, không thì đúng lượt đóng lại đẻ neo thối mới. 🧊 lineage: hạn 08-01 (S96 chạy 07-01). Quy tắc: - KHÔNG bulk-clone repo skill 3rd party. Chỉ thêm skill PROJECT-SPECIFIC. Xem `docs/rules.md §9` đầy đủ. diff --git a/README.md b/README.md index bcd5565..0b1b546 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ fe-admin (:8082) fe-user (:8080) ## Tech stack - **Backend:** .NET 10 + Clean Architecture + CQRS (MediatR) + FluentValidation + AutoMapper + EF Core + ASP.NET Identity + JWT -- **Frontend:** React 18 + Vite + TypeScript + Tailwind + shadcn/ui + TanStack Query +- **Frontend:** React 19 + Vite + TypeScript + Tailwind + shadcn/ui + TanStack Query - **DB:** SQL Server 2022 - **Deploy:** Windows Server + IIS diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index c41ffe4..5d77ca3 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -17,7 +17,7 @@ ``` ┌────────────────┐ ┌────────────────┐ -│ fe-admin │ │ fe-user │ React 18 + Vite + TS + shadcn/ui +│ fe-admin │ │ fe-user │ React 19 + Vite + TS + shadcn/ui │ :8082 │ │ :8080 │ TanStack Query, Tailwind └────────┬───────┘ └────────┬───────┘ │ │ diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 14d7dac..5136a08 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -13,14 +13,14 @@ Nếu ý anh là **chỉ người duyệt**, policy hiện **rộng hơn ý định** ⇒ cần siết `KeHoachKyKet.Update` hoặc thêm guard theo trạm. Nếu soạn-viên cũng được phép thì **không phải bug**, chỉ cần ghi rõ vào spec. Em **không tự sửa** vì đây là ý-định nghiệp-vụ. -**(68) 🔴 Mở class enum `view-claim-broader-than-sample`?** `ring2-audit` ESCALATE-1: em tuyên *"role thường có đủ Read+Update"* dựa trên **2 tài-khoản đều mang vai cấp riêng** (0/2 là user trần) ⇒ **chủ-ngữ rộng hơn tập đã thực-đo**. Em đã siết câu chữ **5 site / 3 file**. Nhưng `ring2` soi cả 11 class trong `lead_self_audit.flag_classes` và **không class nào chứa nổi** kiểu hỏng này (không stale · không thiếu · không bất-đối-xứng) ⇒ nó **nằm ngoài TOTAL** ⇒ **không bao giờ chạm `jump_on_class_repeat`**, dù đã tái diễn ≥3 lần (`claim-stronger-than-work` · `meta-count-blindspot` · ca này). Tiền-lệ đúng cửa: `gap-incident-unrecorded` anh thêm @S143 qua chính đường này. 🔴 Nếu anh gật, phải seed `class_repeat.counts` khoá mới **= 0 cùng nhịp**, kẻo bất-biến `counts ≡ enum` vỡ. +**~~(68) Mở class enum `view-claim-broader-than-sample`~~ ✅ ĐÓNG @S179** — anh đã chốt `OK` @S172 **và đã THI HÀNH**: class có mặt trong `memory-budget.json` → `lead_self_audit.flag_classes` (2 hit) **và** trong `.session-counter.json` → `class_repeat.counts` (1 hit, đang đếm thật). Đóng bằng bằng-chứng ĐĨA, không bằng trí-nhớ. 🧊 nguyên-văn slot cũ: `ring2-audit` ESCALATE-1: em tuyên *"role thường có đủ Read+Update"* dựa trên **2 tài-khoản đều mang vai cấp riêng** (0/2 là user trần) ⇒ **chủ-ngữ rộng hơn tập đã thực-đo**. Em đã siết câu chữ **5 site / 3 file**. Nhưng `ring2` soi cả 11 class trong `lead_self_audit.flag_classes` và **không class nào chứa nổi** kiểu hỏng này (không stale · không thiếu · không bất-đối-xứng) ⇒ nó **nằm ngoài TOTAL** ⇒ **không bao giờ chạm `jump_on_class_repeat`**, dù đã tái diễn ≥3 lần (`claim-stronger-than-work` · `meta-count-blindspot` · ca này). Tiền-lệ đúng cửa: `gap-incident-unrecorded` anh thêm @S143 qua chính đường này. 🔴 Nếu anh gật, phải seed `class_repeat.counts` khoá mới **= 0 cùng nhịp**, kẻo bất-biến `counts ≡ enum` vỡ. -**(69) 🔴 Wire cổng ép-seed C2 vào `/pause.md`?** `lead-gap-auditor` FLAG-6 truy được **cơ chế** vì sao seed bị sót: cổng ép-seed (phép đếm A∖B) **chỉ tồn tại trong `/session-end`**; `/pause.md` = **0 hit** trên cả 5 token. S171 kết bằng `/pause` ⇒ sót seed là **tất yếu cấu trúc**, không phải đãng trí ⇒ **lần 6 sẽ tới ở cửa `/pause` kế**. Em **không tự wire** vì đổi nghi-thức `/pause` là quyết định của anh. +**~~(69) Wire cổng ép-seed C2 vào `/pause.md`~~ ✅ ĐÓNG @S179** — đã WIRE thật: `.claude/commands/pause.md:24` = `### 2.5 🔴 C2 checklist artifact-vs-entry — ÉP SEED TRƯỚC KHI CHỐT (wire @S172, owner slot 69)`. 🧊 nguyên-văn slot cũ: `lead-gap-auditor` FLAG-6 truy được **cơ chế** vì sao seed bị sót: cổng ép-seed (phép đếm A∖B) **chỉ tồn tại trong `/session-end`**; `/pause.md` = **0 hit** trên cả 5 token. S171 kết bằng `/pause` ⇒ sót seed là **tất yếu cấu trúc**, không phải đãng trí ⇒ **lần 6 sẽ tới ở cửa `/pause` kế**. Em **không tự wire** vì đổi nghi-thức `/pause` là quyết định của anh. -**(70) 🔴 Tách 2 sổ đếm H24 — vì trung thực đang XOÁ streak.** `ring2-audit` A4: em tự khai 2 header stale **trước** khi con-đo soi ⇒ chúng bị xếp §0-bis **ngoài TOTAL** ⇒ máy thấy class có 0 ca ⇒ **reset tally 4→0**. Tức càng tự thú càng xoá được dấu vết class. Đề nghị tách: *số FLAG mới* ⟂ *class nào có ca trong vòng*. +**~~(70) Tách 2 sổ đếm H24 — trung thực đang XOÁ streak~~ ✅ ĐÓNG @S179** — đã thi hành: `scripts/h24-signal-write.ps1` mang `slot 70` ở **3 chỗ** (`:66` `:164` `:247` — *"SỔ THỨ HAI (S172, owner slot 70)"*). 🧊 nguyên-văn slot cũ: `ring2-audit` A4: em tự khai 2 header stale **trước** khi con-đo soi ⇒ chúng bị xếp §0-bis **ngoài TOTAL** ⇒ máy thấy class có 0 ca ⇒ **reset tally 4→0**. Tức càng tự thú càng xoá được dấu vết class. Đề nghị tách: *số FLAG mới* ⟂ *class nào có ca trong vòng*. > 🔴 Kèm một lỗi máy `ring2` cài lại bằng python và chứng được: detector **H24-2 dựng segment từ `marks[0]`**, mà marker `**NEXT anh/em` đầu tiên nằm ở `HANDOFF:90` ⇒ **toàn bộ L1-89 không bao giờ được đọc**, nuốt **12 slug** gồm cả hai khối Carry đỉnh. Detector chấm tuổi trên segment cũ rồi in `[ok]`. -**(71) Nợ harvest ~306 KB — gom hay để ngủ?** `S168-bookend-close` **162.916 B** (9/10 vai) + `S171-khkk-ui-mirror-pe` **143.682 B** (4 vai: invest-cb · impl-be · impl-fe · reviewer×3) + `a2bbcb9`/`b5799fc` (mở từ **S162**, 3 phiên). ⚠️ **KHÔNG** gom `S159-bookend-open` — `ring1-audit` mở 4 vai và chứng **4/4 byte-exact** rằng chữ đã về nhà (dương-giả của detector-theo-TÊN); gom sẽ đẻ entry S159 **trùng trên 10 sổ**. +**~~(71) Nợ harvest ~306 KB — gom hay để ngủ~~ ✅ ĐÓNG @S179** — anh đã cấp **UỶ-QUYỀN THƯỜNG-TRỰC** @S172 (nguyên văn: *"gom và sleep thì auto nhé, tự quyết"*), wire ở `.claude/commands/session-end.md:82`: GOM + NÉN-NGỦ từ nay **AUTO, lead tự quyết, CẤM để nợ nằm lại chỉ vì chưa hỏi được owner**. ⇒ slot này **hết là câu hỏi**; nợ harvest xử theo uỷ-quyền, không hỏi lại. 🧊 nguyên-văn slot cũ: `S168-bookend-close` **162.916 B** (9/10 vai) + `S171-khkk-ui-mirror-pe` **143.682 B** (4 vai: invest-cb · impl-be · impl-fe · reviewer×3) + `a2bbcb9`/`b5799fc` (mở từ **S162**, 3 phiên). ⚠️ **KHÔNG** gom `S159-bookend-open` — `ring1-audit` mở 4 vai và chứng **4/4 byte-exact** rằng chữ đã về nhà (dương-giả của detector-theo-TÊN); gom sẽ đẻ entry S159 **trùng trên 10 sổ**. **(72) `mfe-eval` CHẠY ĐƯỢC nhưng 2 nấc dưới khai chết** — `harness-audit` tự chạy: exit 0, bảng đủ 23 role. Tiền-đề sai đó **ăn trọn lớp-① reinject = 0** và **E3** của `harness-refine`. Datum bị chôn theo: **`implementer-frontend 11/13 = 85%`**, role duy nhất dưới 100%. Cần anh quyết có bật MFE vào nhịp closeout thường xuyên không. @@ -32,10 +32,17 @@ Nếu ý anh là **chỉ người duyệt**, policy hiện **rộng hơn ý đ 3. **Vá `run.md` S171 mồ côi** — file có **0 hit** `cicd`/`deploy`/`998ea55` (control-dương `canPe`=1), ledger dừng `[ ] E` ⇒ spawn nào pin `run.md` để nối sẽ không thấy việc đang dở. *(lead-gap FLAG-5 — em đã hứa "@closeout" và **chưa land**, đúng class `dry-run bắt lời-hứa-chưa-land`.)* 4. **Dọn 8 dir rỗng mis-land class-S54** (7 dưới `runs/2026-08-01-S169-bookend-open/` + `fe-user/.claude`) — git-invisible, `find -type d -empty`. 5. **Tầng gist ĐÔI** (`harness-refine` E2): 4 vai (cicd · impl-be · inv-cb · reviewer) có **2 họ gist cùng phủ 2026-05**, cả hai `distill-gen: 1`, **0 bản khai canonical** ⇒ một lượt pour sẽ **rót trùng 2026-05 hai lần**. Sửa rẻ = 1 dòng khai canonical. -6. **`harness-refine` diary disposition** (E4, leo thang lần 2 chưa trả lời): sổ nó đóng băng từ S162 (thiếu S163+S168+S169), mà `:23` vẫn khẳng định *"CHƯA chạy lần nào"* trong khi **11 return nằm trên đĩa** ⇒ chốt-dừng của nó dựng sai. Cần **disposition tường minh**: thi hành, hoặc **HỦY và ghi rõ là hủy**. +6. **~~`harness-refine` diary disposition~~ (E4) ✅ ĐÓNG @S179 — TIỀN-ĐỀ ĐÃ HẾT ĐÚNG, không phải "thi hành" cũng không phải "hủy".** Đo tươi `grep -oE 'S1[0-9]{2}' .claude/agent-memory/harness-refine/MEMORY.md | sort -u`: sổ **CÓ ĐỦ** `S163 · S168 · S169` **+ S170 · S172 · S173` (15.126 B). ⇒ câu *"đóng băng từ S162, thiếu S163+S168+S169"* **đã lỗi-thời** — khoảng trống được lấp ở đâu đó giữa S170→S173, chỉ có **sổ leo-thang là không ai lật**. + 🔴 **Bài — cùng lớp với 4 slot (68)-(71) đóng cùng phiên:** một mục **leo thang 2 lần không ai trả lời** rất dễ đã **tự khỏi** mà vẫn nằm đó kêu; ⇒ **trước khi leo thang lần 3, ĐO LẠI TIỀN-ĐỀ**. Ba lần trong một phiên (E4 · 4 slot · "đã đính chính trong phiên" của S173) đều cùng hình: **sổ nói dối theo hướng BI QUAN**, báo còn nợ khi nợ đã trả. 7. **6 site neo tương-đối** (`tooling-auditor` C-1→C-3 + `ring2` mở rộng): `HANDOFF:70` **sai DẤU** · `:62` · slot (65) · `:402` — đã vá 4 site @S172; **2 site còn lại nằm trong `_mind` BẤT BIẾN theo luật** ⇒ khai nợ, không sửa. -**Carry @S172 (RE-STAMP — nghi-thức §L.b(j)(iv); 🔴 bỏ 4 phiên liên tiếp S169-S172, `gap-carry-dropped` nay **10 lượt liên tiếp = 3,3× ngưỡng jump**):** `[carry:e7-cot-chet-khkk]` *(MỚI — ưu-tiên-1, xem NEXT-em #1)* · `[carry:acceptance-runtime-khkk]` *(MỚI — 5 chân UAT)* · `[carry:harvest-no-s168-s171]` *(MỚI — ~306 KB)* · `[carry:tiep-3ter-seed-unwired]` *(🔄 ĐỔI TÊN từ `[carry:ctx-verifier-no-self-append]` @S170 — quy-kết đúng là **wiring của lead**, không phải vai quên ghi; `ring2` F-6 chứng vế "bất-khả-giải" SAI vì `Bash` nằm trong whitelist, nhưng vế "khai read-only ⇒ ghi = residual-write vi-phạm" ĐÚNG)* · `[carry:ctx-t9-dogfood]` · `[carry:ring5-audit-gap]` · `[carry:hmw-width-vs-roster]` · `[carry:hmw-subfile-index-collision]` · `[carry:synthesis-roll-s159-s160]` · `[carry:harvest-orphan-s159-tongquan]` · `[carry:endline-sub-md]` · `[carry:tra-bui-relogin]` · `[carry:mind-tran-nen-moi-cua]` · `[carry:tiep-reload-underfill]`. +**Carry @S179 (RE-STAMP — nghi-thức §L.b(j)(iv); 🔴 chuỗi bỏ S169-S172 dừng ở đây, `gap-carry-dropped` **re-stamp thật, không phải khai suông**):** +`[carry:e7-cot-chet-khkk]` · `[carry:acceptance-runtime-khkk]` *(5 chân UAT)* · `[carry:harvest-no-s168-s171]` *(~306 KB — anh đã uỷ-quyền thường-trực @slot 71, gom AUTO không cần hỏi)* · `[carry:tiep-3ter-seed-unwired]` · `[carry:ctx-t9-dogfood]` · `[carry:ring5-audit-gap]` · `[carry:hmw-width-vs-roster]` *(anh "OK" @S179 = ghi-nhận, CHƯA phải lệnh đổi số ⇒ cap giữ 20)* · `[carry:hmw-subfile-index-collision]` · `[carry:synthesis-roll-s159-s160]` · `[carry:harvest-orphan-s159-tongquan]` · `[carry:endline-sub-md]` · `[carry:tra-bui-relogin]` · `[carry:tiep-reload-underfill]` · `[carry:tools-whitelist-no-teeth]` *(vai `ctx-curator` ghi thật 2 tệp @S178 — anh chốt **GIỮ** @S179; tha CA NÀY, KHÔNG tha cơ-chế)*. +**Đóng @S179 (có bằng-chứng đĩa, không đóng suông):** +~~`[carry:mind-tran-nen-moi-cua]`~~ — nén MIND-2+3+4, `_mind` **48.989 → 41.362 B (99,67% → 84,2%)**, dư **7.790 B** ⇒ MIND-8 chèn được, máy `mind-check dat=11 TRUOT=0`, 3 inbound-pointer còn nguyên · ~~`[carry:adap-apply-2-thu]`~~ — kéo + áp 2 thư `loi-do-luong`, adap-report `2026-08-05-…-phan-1-va-2.md` (Lớp 8 **BÁC có số** 0,7% vs hub 69%). +🔸 **KHÔNG đóng** dù có đụng: `[carry:harvest-no-s168-s171]` (mới có uỷ-quyền, **chưa gom byte nào**) — khai rõ để khỏi đọc nhầm. + +🧊 **Carry @S172 (segment cũ, BẤT BIẾN theo tiering)** — 🔴 bỏ 4 phiên liên tiếp S169-S172, `gap-carry-dropped` nay **10 lượt liên tiếp = 3,3× ngưỡng jump**):** `[carry:e7-cot-chet-khkk]` *(MỚI — ưu-tiên-1, xem NEXT-em #1)* · `[carry:acceptance-runtime-khkk]` *(MỚI — 5 chân UAT)* · `[carry:harvest-no-s168-s171]` *(MỚI — ~306 KB)* · `[carry:tiep-3ter-seed-unwired]` *(🔄 ĐỔI TÊN từ `[carry:ctx-verifier-no-self-append]` @S170 — quy-kết đúng là **wiring của lead**, không phải vai quên ghi; `ring2` F-6 chứng vế "bất-khả-giải" SAI vì `Bash` nằm trong whitelist, nhưng vế "khai read-only ⇒ ghi = residual-write vi-phạm" ĐÚNG)* · `[carry:ctx-t9-dogfood]` · `[carry:ring5-audit-gap]` · `[carry:hmw-width-vs-roster]` · `[carry:hmw-subfile-index-collision]` · `[carry:synthesis-roll-s159-s160]` · `[carry:harvest-orphan-s159-tongquan]` · `[carry:endline-sub-md]` · `[carry:tra-bui-relogin]` · `[carry:mind-tran-nen-moi-cua]` · `[carry:tiep-reload-underfill]`. > 🔴 **Slug cũ `[carry:ctx-verifier-no-self-append]` còn 2 hit trong file này** (segment cũ, BẤT BIẾN theo tiering) — `ring2` G-2 đo: slug mới trước lượt này = **0 hit**, tổng `[carry:*]` = 247 (control-dương). Từ segment này trở đi dùng **tên mới**. --- @@ -69,7 +76,7 @@ Nếu ý anh là **chỉ người duyệt**, policy hiện **rộng hơn ý đ 1. **K8-prep** theo spec-cụm3 (form-14-người fail-closed + gói `SOLUTION-PE-{n}` + QĐ9 đo-2-nhánh + ZZTEST + rollback-ID); (54)-FINAL: pre-flight CHỈ check-đọc. 2. **Nợ K7 0-blocker:** race-2-request-đồng-thời (unique-filtered-index vs RowVersion vs transaction-recheck — cân "máy-rộng-UI-hẹp") · DraftData-không-carry ở bridge (khác tiền-lệ PE — hỏi khi chạm K8 dry-run) · a11y ``-label + O(n·m) lớp K5 · UAT-NÓI-TRƯỚC: nút bridge sáng sau RE-LOGIN (menu-cache) · GĐ2/GĐ3 "SẮP" rỗng khi prod 0-phiếu/0-HĐ = đúng-spec. -3. **Monthly drift-audit 2026-08-01 DUE** (session-đầu-tháng — `CLAUDE.md` §Audit định kỳ; S96 chạy 07-01) + re-sync `measured{}` (6 vai ctx/ring **0-baseline** — "delta 0" với chúng = chưa từng đo). +3. **~~Monthly drift-audit 2026-08-01 DUE~~ ✅ ĐÓNG @S179** (session-đầu-tháng — `CLAUDE.md` §Audit định kỳ; S96 chạy 07-01) + re-sync `measured{}` (6 vai ctx/ring **0-baseline** — "delta 0" với chúng = chưa từng đo). 4. Re-chạy `governance-detectors.ps1` sau đợt vá S166+S168 (ring2 INFORM #6 — kỳ vọng FLAG `SKILL.md:93` biến mất, TOTAL đổi). 5. Nhóm-7 persona sweep: 21/23 persona chưa soi số-học (stale-deep khuyến-nghị grep số trên cả 23 file; `cicd-monitor` đã vá @S168 — **ăn từ RESTART kế**, hot-reload ENV-DEP). @@ -107,7 +114,7 @@ Nếu ý anh là **chỉ người duyệt**, policy hiện **rộng hơn ý đ 4. **Luật END-line** cho mọi `sub-*.md` (`END — VERDICT=<…>`) — F-03: `ship-synthesis` trích `SHIP-READY` mà sub-file **0 hit** chuỗi đó. 5. `agents/README.md:242` tự xưng "ĐỦ roster" liệt **20 tên** / thật **23** (thiếu đúng bộ-ba `ctx-*`, sống 9 nhãn phiên) + "10 monitor" / thật **13**. *(lead-stale FLAG-11/12)* 6. `CLAUDE.md:62/:69` danh-sách mig thiếu 68+69; `_context-s-8` PAUSE-3 ghi menu "135→142" trong khi cicd đo **142→142 (0 row thêm)** — file này nằm trong `tiep_reload.sources` ⇒ **sai số tái sinh mỗi `/tiep`**. *(FLAG-13/15)* -7. Monthly drift-audit **hạn 2026-08-01 — CHƯA LÀM** + re-sync `measured{}` (nay **17/23**) — 🔴 6 vai (3 ctx + 3 ring) **KHÔNG có baseline** ⇒ "delta 0" với chúng = **chưa từng đo**. *(🧊 câu cũ ghi "(2 ngày nữa)" — **sai DẤU**, đặt hạn ở tương lai trong khi đã quá khứ; `tooling-auditor` C-1 bắt @S172. Neo tuyệt-đối từ nay, cấm đếm ngày.)* +7. ~~Monthly drift-audit hạn 2026-08-01~~ ✅ **ĐÃ CHẠY @S179** (verdict `PASS_WITH_FLAGS — 8`, lần kế 2026-09-01) + re-sync `measured{}` (nay **17/23**) — 🔴 6 vai (3 ctx + 3 ring) **KHÔNG có baseline** ⇒ "delta 0" với chúng = **chưa từng đo**. *(🧊 câu cũ ghi "(2 ngày nữa)" — **sai DẤU**, đặt hạn ở tương lai trong khi đã quá khứ; `tooling-auditor` C-1 bắt @S172. Neo tuyệt-đối từ nay, cấm đếm ngày.)* **Carry @S162 (RE-STAMP — nghi-thức §L.b(j)(iv), bỏ 2 kỳ liên tiếp S159+S160 nên `gap-carry-dropped` lên streak 8):** `[carry:ctx-t9-dogfood]` · `[carry:ring5-audit-gap]` · `[carry:hmw-width-vs-roster]` · `[carry:hmw-subfile-index-collision]` · `[carry:ctx-verifier-no-self-append]` *(MỚI @S162 — F-01, 3 phiên liên tiếp lead-seed)* · `[carry:synthesis-roll-s159-s160]` *(rẻ — đổi-tên/roll file synthesis đã có)* · `[carry:harvest-orphan-s159-tongquan]` *(thật — đọc-gom folder tổng-quan)* *(2 slug này = TÁCH từ `[carry:orphan-retro-harvest-s159]` @S164 theo lead-gap INFORM-G1: chữ "retro-harvest" gộp làm nợ TRÔNG đắt hơn thật → dễ bị hoãn mãi; anh đã chốt @S163 "bỏ mạch" nên đây là nợ ngủ, tách để phần rẻ khỏi bị phần đắt kéo)* · `[carry:endline-sub-md]` *(MỚI)* · `[carry:tra-bui-relogin]` · `[carry:mind-tran-nen-moi-cua]` *(MỚI — slot 58)* · `[carry:tiep-reload-underfill]` *(MỚI — slot 59)*. *(khối re-stamp cũ giữ nguyên hiệu lực — con-trỏ ĐÚNG ĐỐI-TƯỢNG: khối gốc **26 slug** nằm ở segment **S151** dòng `Carry MỞ re-stamp @S151`; tại S152 còn **23 giữ / 3 đóng**. Câu cũ ghi "26 slug re-stamp @S152" SAI đối-tượng — lead-gap FLAG-1 @S163 nhường turf, 0 vai nhặt, lead thu-về @S164. KHÔNG chép slug để tránh drift.)* @@ -230,7 +237,7 @@ cicd 20.9K test-spec 19.1K) `[carry:hook-vs-budget-cap]` (3) UAT S117 incognito `[carry:uat-s117]` (4) PE phân-quyền số-phiếu+user `[carry:pe-phanquyen]` (5) BVAAU `[carry:bvaau]` (6) quyết-định Bình/Lê `[carry:binh-le-decision]` (7) Trà/Bùi re-login `[carry:tra-bui-relogin]` (8) account trùng `[carry:account-trung]` (9) mega-line re-tier = B3 `[carry:retier-megaline]`. **NEXT em (phiên kế):** đọc quyết-định anh B3/B4 → apply `/check-email` AI_INFRA (reply đính-chính + h23-result) D2 H24 counter light@9 -D1 drift-audit 2026-08-01 +D1 drift-audit 2026-08-01 → ✅ ĐÃ CHẠY @S179 (lần kế 2026-09-01) D3/D4 optional. wf: hmw run=2026-07-16-S126-adap-spec-execute (3 invocation: `wf_f960dae2-fa0` A1+A2 `wf_973163d9-440` B1 `wf_38bc7067-2f1` email-gate; run-folder + 3 synthesis). Session-log → `2026-07-16-S125-S126-adap-tien-de-vong4-h23-execute.md`.) diff --git a/docs/STATUS.md b/docs/STATUS.md index 71f950a..42a108c 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,6 +3,8 @@ > **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.) +> 🔴 **@S179: mốc SỐNG hiện tại = S179, phiên-LOGIC L11, window 7** — chuỗi UAT màn KHKK 8 đợt ship (cửa-sổ 5: `530af22`→`ca9208f` 6 đợt + **Mig 72**; cửa-sổ 6: đợt-7 `99370de` + đợt-8 `65f73a9`, bundle prod `CuWgMI7J`·`32bJmjpM`), rồi S179 vá đội STYLE (SỬA-1→6b) + H24 light-audit. **Dòng CURRENT ngay dưới đây advance @closeout nên tụt sau — giữa phiên đọc `.claude/WAL.md`.** + **🔥 CURRENT (S161→S168, 2026-07-31→08-01 — phiên-LOGIC **L9**: chuỗi SP-002 B0→B4 **TRỌN 8/8 wave**: K1→K7 SHIP (cicd 6/6 · 5/6-khỏe · 6/6 · 7/7 · 5/5 · K6 #440 5/5 · K7 PARTIAL-live-sạch · F-1 `7a903cf` · K7 bridge `aaed699` PWF-10) + **@S168 owner chốt (63)(b)=D+"mở rộng": GĐ3-D SHIP `081557b` (3 trang Panel-3, gate PWF-10/0-blocker) + K8-BLOCKER Lines-editor phát-hiện-bởi-dry-run + vá + SHIP `0bfadc2` (gate PWF-8/0-blocker) — cicd #444 PASS 6/6 — rồi **K8 DRY-RUN PASS TOÀN TRÌNH 2 NHÁNH** (PE A/052 finalize-CCM + A/053 full-CEO → KHKK/2026/001+002 qua endpoint-line-MỚI → bridge-K7 → HĐ ĐẦU TIÊN prod `ZZTEST-K8/NCC/SOL&ZZTEST-NCC-K8/01` DaPhatHanh → bản-cứng hasSealedCopy=True → QĐ9 4/4 vế [nguồn-khoá-409 + catalog-rename-không-lan] — sổ ID + seq-cháy: `sub-k8-dryrun.md` B15, 🔴 KHKK/2026 seq **001-002-003 ĐỀU là phiếu test** [001-002 dry-run + **003 bộ fx3**] ⇒ **phiếu THẬT đầu tiên = 004** — số cũ "003" ở dòng này SAI, vá @close S168 sau khi `lead-gap-auditor` F-2 bắt + lead đo prod xác nhận `sqlcmd` 3 phiếu đều phase=3)**; closeout-nợ TRẢ @S168 — mạch sống ở `.claude/WAL.md`; lineage L8 giữ dưới):** Mig **71** (K1 Mig70 `AddContractCatalogEntries` danh mục 86 dòng + K2 Mig71 `AddKhkkApprovalGroupCatalogAndFinalizeRuntime` — phiếu KHKK +nhóm duyệt N1-N8 backfill=1 + Line +hạng-mục + unique 3-cột) · **97 bảng** · **644 test PASS** (45D+599I — CI #444 KHỚP local; +5 Fact Lines-editor @S168; lineage 639 sau-K7 → 622 @S167 KHỚP CI #439 tách-phần) · gotcha **87** · counter **46** (tick S172; H24 light **2/6** deep **6/15** ok — `light_at=44` · `deep_at=40`; ⚠️ *cặp `light 2/6` trùng số với đợt S168 do tình cờ 42−40 = 46−44, chỉ vế `deep` mới lộ 2/15→6/15 — đừng liếc vế light rồi tưởng ô còn tươi*) · roster 23 · **MenuItems prod 142 GIỮ** (key `KeHoachKyKet` sinh **policy** không sinh menu-row — H1 bác nghi-vấn stale) · Policies **452** · Menu keys **113** (@S166 K4a +49 `Khkk_G*` bộ-sinh — canonical bảng `:470-471`, test T2 khoá drift; lineage 64/256 @K3: +`ContractCatalog` K1 [4 policy chưa endpoint tiêu thụ — khai #82] · +8 `AwV2_KhkkN1..N8`) · bundle prod → **canonical ở `:479`, KHÔNG chép số ở đây** (B1). 🔴 *Cặp `DXoYDy7R`/`o8KDluD1` từng ghi ở dòng này **chưa bao giờ là trạng-thái cuối** — `e5123ff` ship thêm 6 file FE-src SAU snapshot; đo live @S164: admin `B43R6Y17` · user `NLI5umBg`.* Contracts prod **0**. ① **5 wave KHKK SHIP (window-3, S161):** W1 `a8027c0` (Mig 69, 7 bảng, 89→96) · W2 `6cbc6ad` (CRUD+Dossier 15 policy) · W3 `df52fa0` (duyệt V2 3-trạm, test-before RED→GREEN) · W6 `761d818` (đường-ống HĐ V2) · W7 `3119cb9` (bản-cứng **1-MỐC** theo owner: form điền đủ → duyệt nếu có → upload bản cứng = xong). Mỗi wave: gate 5-anchor → hmw → test → reviewer → F-0 → cicd 3-chân. 3 quyết owner: mã `KHKK/{YYYY}/{Seq:D3}` · **bỏ "MB"** · GĐ4 1-mốc. ② **Cây 4-folder GĐ (window-4, S162) — `bfc7b79`, cicd PASS 5/5 Run #432:** lệnh owner *"Tạo folder: Duyệt NCC / Kế hoạch Hợp đồng. / Duyệt Hợp đồng / Hợp đồng cứng."* + AskUser chốt **DƯỚI TỪNG GÓI THẦU** + **áp CẢ trang GĐ khác**. 3 file MỚI ×2 app (`PipelineStageFolders` · `PipelineTreePanel` · `usePipelineStages`) + 3 trang ×2 app, **SHA-pair 6/6**, thuần FE 0-mig. designer SHIP-READY (tự soi ảnh bắt 4 lỗi build-không-báo) → reviewer PASS-WITH-FLAGS 8 → lead vá F-1/3/4/6/7 + F-8. ~~🔴 CÒN NỢ: trang GĐ3 chưa làm~~ ✅ **ĐÓNG @S168 `081557b`** (owner slot (63)(b)=D + "mở rộng" ⇒ áp CẢ 3 trang; câu gốc giữ làm lineage — H1 F-1) (owner nói "CẢ", lead giao 3/4 — lead-gap FLAG-3) · F-2 liên-danh N-HĐ chờ W5 · F-5 layout 19rem chờ owner nghiệm thu prod. @@ -458,22 +460,22 @@ monthly re-tier mega-line + ef-core SKILL Mig→59 + 3 vocab-fork (2026-07-01 du --- -## 🎯 CURRENT STATE (baseline S40 — re-ground sống liên tục, mốc gần nhất **S168** [🔄 bump @S168 — stale F-8 bắt: luật "bump theo lần re-ground mới nhất" nằm CÙNG DÒNG với con số trượt; vá @S153 FLAG-2: bump theo lần re-ground giá-trị mới nhất trong section; header bump @S157 ctx-verifier C3]) +## 🎯 CURRENT STATE (baseline S40 — re-ground sống liên tục, mốc gần nhất **S179** [🔄 bump @S179 — `lead-stale-auditor` FLAG-6: bảng này đã re-ground **2 lần SAU S168** (`:474` S170 · `:476` +S176) mà header vẫn giữ S168 ⇒ **chính dòng này chép ra cái luật mà nó vi phạm**, bác được KHÔNG cần rời file. Luật giữ nguyên: bump theo lần re-ground giá-trị mới nhất TRONG section. 🧊 lineage: bump @S168 ← vá @S153 FLAG-2 ← header bump @S157 ctx-verifier C3]) | Metric | Value | Note | |---|---|---| -| Migrations | **71** | 🔄 **71 @S164/S165 (K1/K2 SP-002):** Mig 70 `AddContractCatalogEntries` (danh mục HĐ 86 dòng, `50e6d8c`, cicd 6/6) + Mig 71 `AddKhkkApprovalGroupCatalogAndFinalizeRuntime` (phiếu KHKK +nhóm N1-N8 backfill=1 + Line hạng-mục + unique 3-cột, `0779f2d`, cicd 5/6-khỏe; prod `__EFMigrationsHistory` top + MIGCOUNT=71 @sub-cicd-verify-k3.md §3). **+S161: Mig 69 `AddContractSigningPlans`** (`20260729122015` — W1 KHKK: 7 bảng MỚI cho Kế hoạch ký kết HĐ, commit `a8027c0` cicd PASS 6/6; SQL tables 89→96). **+S155: Mig 68 `AddPeAllowApproverDelete`** (`20260727033522` — PE cho phép **approver xóa phiếu ngay ở màn duyệt**: cờ `AllowApproverDelete` **per-NGƯỜI** trên `ApprovalWorkflowLevel` [owner chốt (5)] + lệnh sửa-quy-trình-tại-chỗ; **AddColumn no new table [89 giữ]**, reversible Down. Chia 2 ĐỢT theo lệnh anh — §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 tại chỗ. Đợt 1 `b1bae77` CICD **PASS 6/6**; đợt 2 `4464a46` NO-MIG [nút xóa + menu 3 mục + màn "Đã xóa"] CICD **PASS 6/6** verify @S156 [endpoint 401⟂control-404 · smoke 8/8 · **D3 giao-tập-ID = 0** 37 sống ⟂ 9 xóa · bundle rotate ×2 + 4/4 byte-marker]; +`f4494cf` fix menu sáng nhầm PASS. prod-verified `__EFMigrationsHistory` top + `sys.tables`=89). +S133: Mig 67 `AddPeApprovedBudgetSnapshot` (PE **freeze ngân sách phiếu DaDuyet** — UAT anh Kiệt 07-16 R1 "phiếu đã duyệt bất biến, ngân sách live chỉ cho phiếu chưa duyệt": **11 AddColumn snapshot** lên PE [`ApprovedBudgetSnapshotAt` + Pro/Ccm `Initial·Adjustment·Note` ×6 + `PrevSubmitted/PrevSelected Total·Count` ×4] chốt tại finalize choke-point qua helper `PeBudgetAccumulator` 4-site + **site-5 admin-override `PurchaseEvaluationWorkflowService.cs:308`** [reviewer catch #81-EXT indirect-assignment — override thẳng → DaDuyet cũng PHẢI snapshot] + seeder site; +`Sql()` backfill OUTER APPLY khớp accumulator cho phiếu DaDuyet cũ — **prod 18/18, chua=0**; display-gate `budgetFrozen`: phiếu DaDuyet đọc snapshot + badge 🔒, phiếu chưa duyệt đọc live [R2 "bản cập nhật gần nhất"]; **no new table [89 giữ]**, reversible Down DropColumn ×11; prod-verified Run #398 `__EFMigrationsHistory`-top + 11 cột; commit `d4fbced`). +S117: Mig 66 `AddPeApprovedPriceRange` (PE +`ApprovedPriceMaxAmount decimal(18,2)?` — feature "duyệt theo khoảng Min–Max" anh Kiệt "chọn cả 2 min và max": source `"ProMinMax"` = Amount(Min)+MaxAmount(Max), bất-biến `MaxAmount != null ⟺ Source=="ProMinMax"` + Min≤Max [guard service `ApplyApprovedPriceOnFinalize` + FluentValidation]; **1 AddColumn nullable no-backfill** [phiếu cũ Source-đơn Max=null nguyên vẹn], reversible Down DropColumn, **no new table [89 giữ]**; HĐ.GiaTri KHÔNG đọc giá chốt [=SUM báo giá NCC được chọn] → 0 tác động HĐ [range = record-of-decision]; prod-verified Run #387 col decimal(18,2) + `__EFMigrationsHistory` top; commit `316a82f`). +S114: Mig 65 `BackfillPeQuoteIsSelectedAndWinnerInvariant` (data-only 2-chiều bất-biến `IsWinner↔IsSelected`, no new table [89 giữ], idempotent, Down no-op mirror Mig 61; multi-NCC per hạng mục anh Kiệt; commit `d436af2`; kèm gotcha #81 delete-writer). +S113: Mig 64 `AddSupplierPublishState` (Supplier +`IsPublic` bit NOT NULL default 0 — cổng công-bố R4 "thiếu Mã NCC→nháp/ẩn"; `Sql("UPDATE Suppliers SET IsPublic=1")` backfill 37/37 prod→public; DropIndex→CreateIndex đổi filtered-unique Code `WHERE [IsDeleted]=0 AND [Code]<>''` [cho nhiều nháp Code='']; **no new table [89 giữ]**, reversible Down; prod-verified Run #497 __EFMigrationsHistory-top + IsPublic-col + 37/37-backfill; gotcha #80 null-Code). +S112: Mig 63 `AddSupplierImportSourceFields` (Supplier +`SourceUpdatedAt datetime2?` + `SourceUpdatedBy nvarchar(200)?` — import-provenance cột 29/30 file Excel "Database NCC"; 2 AddColumn nullable, **no new table [89 giữ]**, reversible Down DropColumn ×2; prod-verified Run #496 `__EFMigrationsHistory` top + 2/2-col present). +S104 (reconcile): Mig 62 `ExpandSupplierFields` (Supplier 9→27 field: 18 AddColumn nullable + 18 DropColumn Down + `SupplierType +CaHai=6` append-only + enum `SupplierStatus` mới + guarded un-cram `Sql()` clear legacy crammed Note 4 seeded rows exact-match; **no new table (89 giữ nguyên — 18 AddColumn/0 CreateTable)**, reversible Down; seed fill-nulls-if-exists 30-field TRUONGGIANG/TANPHU/TGN/DONGDUONG idempotent; commit `778fc98` shipped UN-closed-out → S104 session-start docs-reconcile; prod-verified Run #488 PASS bundle admin `ChSNAJBK`/user `Bn2w1znH`; 440 test re-verified #65-no-bite). +S97: Mig 61 `BackfillEndedByLevelFinalizeFromChangelog` (data-only no-schema — đính chính Mig 60 backfill soi NHẦM bảng `Approvals`→`Changelogs`; set `EndedByLevelFinalize=1` cho phiếu finalize-sớm pre-Mig60 [A/005/A/008 finalize-CCM KHÔNG qua CEO] qua marker ở `PurchaseEvaluationChangelogs.ContextNote`; idempotent SQL-Server-only; prod-verified Run #484: A/005/A/008 0→1 + endsBeforeCeo-flip-True, A/010=0 control-unchanged; gotcha #79). +S97: Mig 60 `AddPeEndedByLevelFinalize` (PE +`EndedByLevelFinalize` bit NOT NULL default 0 — cờ RUNTIME "phiếu ĐÃ kết thúc sớm bằng level-finalize", set-true CHỈ nhánh finalize service; +`Sql()` backfill Phase=7-marker→=1; EndsBeforeCeo display đọc runtime thay config → phiếu-lên-CEO hết báo sai "không qua CEO" [gotcha #78]; AddColumn no new table, prod-verified Run #482 PE-detail endsBeforeCeo=False live). +S87: Mig 58 `AddPeMultiWinnerAndLevelFinalize` (`PurchaseEvaluationSupplier` +`IsWinner` bit multi-winner backfill từ SelectedSupplierId + `ApprovalWorkflowLevel` +`AllowApproverFinalize` bit cấp-KẾT-THÚC-quy-trình AUTO; 2 AddColumn + 1 backfill, no new table) + Mig 59 `AddCcmBudgetPeriodToPurchaseEvaluation` (PE +`CcmBudgetPeriodAmount` decimal(18,2)? — NS kỳ-này cột CCM cho Section B 3-cột; 1 AddColumn nullable, no backfill, no new table). +S77: Mig 57 `AddPeSuggestedPriceNotes` (PE +`ProSuggestedPriceNote` +`CcmSuggestedPriceNote` nvarchar(1000) — ô ghi chú giá đề xuất PRO/CCM giải-thích Min/Max · additive-nullable, 0 backfill, no new table; absolute-set role-gate mirror Mig 54/55). +S76: Mig 56 `AddProBudgetSplitToPeWorkItemBudget` (PeWorkItemBudget +`ProInitialAmount`+`ProAdjustmentAmount` decimal(18,2)? — cột PRO "Ban hành lần đầu"+"V0/hiệu chỉnh" mirror CCM Initial/Adjustment; AddColumn additive + `Sql()` data-migrate `ProInitial=ProEstimate` 4 rows prod gotcha #64; no new table). +S74: Mig 55 `AddCcmNoteToPeWorkItemBudget` (PeWorkItemBudget +CcmNote nvarchar(1000) — "Ghi chú từ CCM" mirror ProNote · additive-nullable, 0 backfill, no new table). +S73: Mig 54 `AddPeSuggestedAndApprovedPrice` (PE +5 cột giá đề xuất PRO Min/Max + CCM + giá chốt ApprovedPriceAmount/Source — additive-nullable, 0 backfill, prod-verified Run #313). +S69: Mig 53 `AddPeUrgentAndCeoApprovalThreshold` (PE +IsUrgentByPro/Ccm cờ gấp + ApprovalWorkflow +CeoApprovalThreshold ngưỡng CCM duyệt-final · 3 AddColumn no new table). Prev S65: Mig 51 `AddDepartmentParentId` (Department.ParentId loose-Guid no-FK — org-tree) + Mig 52 `AddHoSoLinkToPurchaseEvaluation` (PE HoSoLink nvarchar(1000) hyperlink NAS) — **cả 2 AddColumn-only, no new table** (tables giữ 88). Prev Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (bảng `PeWorkItemBudgets` per-gói-thầu + DROP module Budget cũ + backfill BudgetManual→BudgetPeriod TRƯỚC DropColumn + DROP PE/Contracts.BudgetId; gotcha #63/#64). Prev Mig 49 PE WorkItemId (S57bis) | +| Migrations | **72** | 🔄 **72 @S177 (đo đĩa `ls Persistence/Migrations/*.cs` trừ Designer+Snapshot = 72; flush @S179 — `lead-stale-auditor` FLAG-5 + máy `canonical-itself-stale` HIGH).** Mig 72 land ở cửa-sổ 5 phiên-LOGIC L11 kèm backfill 5/5 có mã. 🧊 **71 @S164/S165 (K1/K2 SP-002):** Mig 70 `AddContractCatalogEntries` (danh mục HĐ 86 dòng, `50e6d8c`, cicd 6/6) + Mig 71 `AddKhkkApprovalGroupCatalogAndFinalizeRuntime` (phiếu KHKK +nhóm N1-N8 backfill=1 + Line hạng-mục + unique 3-cột, `0779f2d`, cicd 5/6-khỏe; prod `__EFMigrationsHistory` top + MIGCOUNT=71 @sub-cicd-verify-k3.md §3). **+S161: Mig 69 `AddContractSigningPlans`** (`20260729122015` — W1 KHKK: 7 bảng MỚI cho Kế hoạch ký kết HĐ, commit `a8027c0` cicd PASS 6/6; SQL tables 89→96). **+S155: Mig 68 `AddPeAllowApproverDelete`** (`20260727033522` — PE cho phép **approver xóa phiếu ngay ở màn duyệt**: cờ `AllowApproverDelete` **per-NGƯỜI** trên `ApprovalWorkflowLevel` [owner chốt (5)] + lệnh sửa-quy-trình-tại-chỗ; **AddColumn no new table [89 giữ]**, reversible Down. Chia 2 ĐỢT theo lệnh anh — §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 tại chỗ. Đợt 1 `b1bae77` CICD **PASS 6/6**; đợt 2 `4464a46` NO-MIG [nút xóa + menu 3 mục + màn "Đã xóa"] CICD **PASS 6/6** verify @S156 [endpoint 401⟂control-404 · smoke 8/8 · **D3 giao-tập-ID = 0** 37 sống ⟂ 9 xóa · bundle rotate ×2 + 4/4 byte-marker]; +`f4494cf` fix menu sáng nhầm PASS. prod-verified `__EFMigrationsHistory` top + `sys.tables`=89). +S133: Mig 67 `AddPeApprovedBudgetSnapshot` (PE **freeze ngân sách phiếu DaDuyet** — UAT anh Kiệt 07-16 R1 "phiếu đã duyệt bất biến, ngân sách live chỉ cho phiếu chưa duyệt": **11 AddColumn snapshot** lên PE [`ApprovedBudgetSnapshotAt` + Pro/Ccm `Initial·Adjustment·Note` ×6 + `PrevSubmitted/PrevSelected Total·Count` ×4] chốt tại finalize choke-point qua helper `PeBudgetAccumulator` 4-site + **site-5 admin-override `PurchaseEvaluationWorkflowService.cs:308`** [reviewer catch #81-EXT indirect-assignment — override thẳng → DaDuyet cũng PHẢI snapshot] + seeder site; +`Sql()` backfill OUTER APPLY khớp accumulator cho phiếu DaDuyet cũ — **prod 18/18, chua=0**; display-gate `budgetFrozen`: phiếu DaDuyet đọc snapshot + badge 🔒, phiếu chưa duyệt đọc live [R2 "bản cập nhật gần nhất"]; **no new table [89 giữ]**, reversible Down DropColumn ×11; prod-verified Run #398 `__EFMigrationsHistory`-top + 11 cột; commit `d4fbced`). +S117: Mig 66 `AddPeApprovedPriceRange` (PE +`ApprovedPriceMaxAmount decimal(18,2)?` — feature "duyệt theo khoảng Min–Max" anh Kiệt "chọn cả 2 min và max": source `"ProMinMax"` = Amount(Min)+MaxAmount(Max), bất-biến `MaxAmount != null ⟺ Source=="ProMinMax"` + Min≤Max [guard service `ApplyApprovedPriceOnFinalize` + FluentValidation]; **1 AddColumn nullable no-backfill** [phiếu cũ Source-đơn Max=null nguyên vẹn], reversible Down DropColumn, **no new table [89 giữ]**; HĐ.GiaTri KHÔNG đọc giá chốt [=SUM báo giá NCC được chọn] → 0 tác động HĐ [range = record-of-decision]; prod-verified Run #387 col decimal(18,2) + `__EFMigrationsHistory` top; commit `316a82f`). +S114: Mig 65 `BackfillPeQuoteIsSelectedAndWinnerInvariant` (data-only 2-chiều bất-biến `IsWinner↔IsSelected`, no new table [89 giữ], idempotent, Down no-op mirror Mig 61; multi-NCC per hạng mục anh Kiệt; commit `d436af2`; kèm gotcha #81 delete-writer). +S113: Mig 64 `AddSupplierPublishState` (Supplier +`IsPublic` bit NOT NULL default 0 — cổng công-bố R4 "thiếu Mã NCC→nháp/ẩn"; `Sql("UPDATE Suppliers SET IsPublic=1")` backfill 37/37 prod→public; DropIndex→CreateIndex đổi filtered-unique Code `WHERE [IsDeleted]=0 AND [Code]<>''` [cho nhiều nháp Code='']; **no new table [89 giữ]**, reversible Down; prod-verified Run #497 __EFMigrationsHistory-top + IsPublic-col + 37/37-backfill; gotcha #80 null-Code). +S112: Mig 63 `AddSupplierImportSourceFields` (Supplier +`SourceUpdatedAt datetime2?` + `SourceUpdatedBy nvarchar(200)?` — import-provenance cột 29/30 file Excel "Database NCC"; 2 AddColumn nullable, **no new table [89 giữ]**, reversible Down DropColumn ×2; prod-verified Run #496 `__EFMigrationsHistory` top + 2/2-col present). +S104 (reconcile): Mig 62 `ExpandSupplierFields` (Supplier 9→27 field: 18 AddColumn nullable + 18 DropColumn Down + `SupplierType +CaHai=6` append-only + enum `SupplierStatus` mới + guarded un-cram `Sql()` clear legacy crammed Note 4 seeded rows exact-match; **no new table (89 giữ nguyên — 18 AddColumn/0 CreateTable)**, reversible Down; seed fill-nulls-if-exists 30-field TRUONGGIANG/TANPHU/TGN/DONGDUONG idempotent; commit `778fc98` shipped UN-closed-out → S104 session-start docs-reconcile; prod-verified Run #488 PASS bundle admin `ChSNAJBK`/user `Bn2w1znH`; 440 test re-verified #65-no-bite). +S97: Mig 61 `BackfillEndedByLevelFinalizeFromChangelog` (data-only no-schema — đính chính Mig 60 backfill soi NHẦM bảng `Approvals`→`Changelogs`; set `EndedByLevelFinalize=1` cho phiếu finalize-sớm pre-Mig60 [A/005/A/008 finalize-CCM KHÔNG qua CEO] qua marker ở `PurchaseEvaluationChangelogs.ContextNote`; idempotent SQL-Server-only; prod-verified Run #484: A/005/A/008 0→1 + endsBeforeCeo-flip-True, A/010=0 control-unchanged; gotcha #79). +S97: Mig 60 `AddPeEndedByLevelFinalize` (PE +`EndedByLevelFinalize` bit NOT NULL default 0 — cờ RUNTIME "phiếu ĐÃ kết thúc sớm bằng level-finalize", set-true CHỈ nhánh finalize service; +`Sql()` backfill Phase=7-marker→=1; EndsBeforeCeo display đọc runtime thay config → phiếu-lên-CEO hết báo sai "không qua CEO" [gotcha #78]; AddColumn no new table, prod-verified Run #482 PE-detail endsBeforeCeo=False live). +S87: Mig 58 `AddPeMultiWinnerAndLevelFinalize` (`PurchaseEvaluationSupplier` +`IsWinner` bit multi-winner backfill từ SelectedSupplierId + `ApprovalWorkflowLevel` +`AllowApproverFinalize` bit cấp-KẾT-THÚC-quy-trình AUTO; 2 AddColumn + 1 backfill, no new table) + Mig 59 `AddCcmBudgetPeriodToPurchaseEvaluation` (PE +`CcmBudgetPeriodAmount` decimal(18,2)? — NS kỳ-này cột CCM cho Section B 3-cột; 1 AddColumn nullable, no backfill, no new table). +S77: Mig 57 `AddPeSuggestedPriceNotes` (PE +`ProSuggestedPriceNote` +`CcmSuggestedPriceNote` nvarchar(1000) — ô ghi chú giá đề xuất PRO/CCM giải-thích Min/Max · additive-nullable, 0 backfill, no new table; absolute-set role-gate mirror Mig 54/55). +S76: Mig 56 `AddProBudgetSplitToPeWorkItemBudget` (PeWorkItemBudget +`ProInitialAmount`+`ProAdjustmentAmount` decimal(18,2)? — cột PRO "Ban hành lần đầu"+"V0/hiệu chỉnh" mirror CCM Initial/Adjustment; AddColumn additive + `Sql()` data-migrate `ProInitial=ProEstimate` 4 rows prod gotcha #64; no new table). +S74: Mig 55 `AddCcmNoteToPeWorkItemBudget` (PeWorkItemBudget +CcmNote nvarchar(1000) — "Ghi chú từ CCM" mirror ProNote · additive-nullable, 0 backfill, no new table). +S73: Mig 54 `AddPeSuggestedAndApprovedPrice` (PE +5 cột giá đề xuất PRO Min/Max + CCM + giá chốt ApprovedPriceAmount/Source — additive-nullable, 0 backfill, prod-verified Run #313). +S69: Mig 53 `AddPeUrgentAndCeoApprovalThreshold` (PE +IsUrgentByPro/Ccm cờ gấp + ApprovalWorkflow +CeoApprovalThreshold ngưỡng CCM duyệt-final · 3 AddColumn no new table). Prev S65: Mig 51 `AddDepartmentParentId` (Department.ParentId loose-Guid no-FK — org-tree) + Mig 52 `AddHoSoLinkToPurchaseEvaluation` (PE HoSoLink nvarchar(1000) hyperlink NAS) — **cả 2 AddColumn-only, no new table** (tables giữ 88). Prev Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (bảng `PeWorkItemBudgets` per-gói-thầu + DROP module Budget cũ + backfill BudgetManual→BudgetPeriod TRƯỚC DropColumn + DROP PE/Contracts.BudgetId; gotcha #63/#64). Prev Mig 49 PE WorkItemId (S57bis) | | SQL tables | **97** | 🔄 **97 @S164** (Mig 70 K1 +1 bảng `ContractCatalogEntries` — prod `sys.tables`=97 @sub-cicd-verify-k1.md; Mig 71 AddColumn-only giữ 97). Cũ: **96 @S161** (cicd `cicd-verify-a8027c0.md:117` prod `sys.tables` 89→96 = +7 bảng Mig 69; mọi note "no-new-table"/"89 giữ" bên dưới là **frozen-in-time** của mig cũ, KHÔNG sửa). re-ground S97 (cicd `sys.tables` is_ms_shipped=0 Run #482 LIVE = **89**, pre==post Mig 60 no-new-table; "88" từ S62 STALE). Prev net 93→88 S62 (Mig 50 drop Budget + create `PeWorkItemBudgets`) | | Master data (prod) | **71 WorkItems PMH-only S59** | 62 Projects + **WorkItems = ĐÚNG 71 mã PMH** (S59: wipe 15 demo + rename format anh Kiệt `MAT-1..16`/`SUB-1..30`/`MEP-SUB-1..9`/`MEP-EQU-1..16`, Name "STT nhóm tên") + Suppliers **37** (S113 cicd-verified prod count, tất cả IsPublic=1 sau Mig 64 backfill — "22 ước" cũ STALE; POST mở any-auth S59 quick-add; import v2 mới landing nháp). Transactional testing data wiped S59 (PE/HĐ/Notif = 0 baseline, phiếu thật từ A/001). Provenance `scripts/master-import-data.generated.md` | | API endpoints | **~253** | +1 S54 `GET /it-tickets/assignable-staff` (capability endpoint); +3 S52 (attendances/report + report/excel + it-tickets/{id}/assign) | | FE pages | **68** | unchanged S54 (ItTicketsPage reassign = in-place 2 app); +1 S52 AttendanceReportPage | | Policies | **452** | 🔄 **452 @S166 K4a** = All 113 × 4 (máy khoá: test T2 `KhkkGroupMenuSeedTests` đỏ nếu drift; DELTA vá-2: +4 ContractCatalog K1 · +32 AwV2_KhkkN* K3 · +196 Khkk_G* K4a). Cũ: **220 @S161** (W1 KHKK: `All` +`KeHoachKyKet` ⇒ 55 × 4 — reviewer F-2 bắt cặp-row-đôi đúng luật dòng dưới) · 🆕 **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| = 55 × 4 = 220 (@S161; trước W1 = 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 | **113** | 🔄 **113 @S166 K4a** (đo RUNTIME `MenuKeys.All` — test T2; +49 `Khkk_G{2-8}`+42-leaf bộ-sinh by-construction K4a · +8 `AwV2_KhkkN1..N8` K3 · +1 `ContractCatalog` K1 trên nền 55). Cũ: **+1 S161 `KeHoachKyKet` vào `All` (W1 KHKK — policy `KeHoachKyKet.*` sinh runtime; menu-row prod KHÔNG đổi, 142 giữ)** · +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 | **644 PASS** | 45 Domain + 599 Infra · 🔄 **644 @S168 #444** (+5 Fact Lines-editor) · 🧊 **639 @S168-sáng** (đo tươi local 45D+594I sau K7 Δ+17; chuỗi K lineage: 597 K1 → 614 K3 → 622 K4c @S167 KHỚP CI #439 tách-phần → **639** K7 — gate `639=45+594` KHỚP cicd-K7 dòng-1) · 🧊 **+28 @S161** (5 wave KHKK: W1 566 → W2 574 → W3 580 → W6 587 → W7 590; đo tươi @S162 `dotnet test` 45+545, gate CI Run #432 khớp). ~~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 | **86** | **+S168 #86** (2-push-sát → Gitea auto-CANCEL run đầu cùng-branch: CANCELLED ≠ fail — verifier đọc run CUỐI của range + bằng-chứng artifact-level; side-effect @startup chỉ 1-startup cho cả cụm push; ca thật `aaed699` ship qua #442) · **+S162 #85** (menu-key OR-gate FE ≠ policy per-action BE: cây 4-folder GĐ gate `['Khkk_List','Khkk_G1','KeHoachKyKet'].some(can)` NHƯNG endpoint gắn `[Authorize(Policy="KeHoachKyKet.Read")]` [`ContractSigningPlansController.cs:36`] + `MenuPermissionHandler.cs:40` so khớp **CHÍNH XÁC 1 key** — KHÔNG kế-thừa cha, KHÔNG OR key con ⇒ role `Khkk_List=1 ∧ KeHoachKyKet=0`: FE mở cổng → API **403** → folder GĐ2 hiện "—" dưới **MỌI** gói thầu, claim "gate trước fetch ⇒ 0 rác 403" **vỡ**. Bẫy: luật "OR nhiều key" **ĐÚNG ở tầng HIỂN-THỊ** [`GetMyMenuTreeQuery.cs:61-96` trả node khi con `CanRead`] nhưng **SAI ở tầng API-authz** — mặt thứ 2 của #82, lần này **menu-hiện RỘNG hơn API-cho** [#82 là chiều ngược]. Fix = gate đúng key policy CỦA endpoint; **mở controller đọc attribute TRƯỚC khi wire gate**, đừng suy từ cây menu. Reviewer bắt **trước ship**; Dev 13/13 role đều `Contracts=1 ∧ KeHoachKyKet=1` nên **chưa lộ** — lớp "chưa vỡ vì dữ-liệu hiện tại may mắn", vá ngay không đợi triệu chứng). **+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 | **59** | 🔄 re-ground S170 — đếm đĩa 60 file `.claude/auto-memory/*.md` trừ 1 index `MEMORY.md` = 59 (số "31" stale từ S84; lead-stale FLAG @S169, ring2 verify, vá @S170 SAU khi ring chấm — đúng thứ-tự H24 §2(4) fire→chứng-kiến→vá). +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 | +| Tests | **645 PASS** | **45 Domain + 600 Infra** · 🔄 **645 @S179 — ĐO BẰNG CÁCH CHẠY THẬT** `dotnet test SolutionErp.slnx`: Domain `Failed: 0, Passed: 45` · Infra `Failed: 0, Passed: 600` (0 skip). 🔴 Không lấy số từ doc: `lead-stale-auditor` FLAG-4 bắt ô này còn **644**, mà 644 đang là **THƯỚC** cho 6 flag derived-stale của detector ⇒ canonical sai thì máy khuyên vá về số sai (class canonical-poison S148/S166). 🔸 Breakdown cũ ghi "599 Infra" cũng lệch — **600**. 🧊 **644 @S168 #444** (+5 Fact Lines-editor) · 🧊 **639 @S168-sáng** (đo tươi local 45D+594I sau K7 Δ+17; chuỗi K lineage: 597 K1 → 614 K3 → 622 K4c @S167 KHỚP CI #439 tách-phần → **639** K7 — gate `639=45+594` KHỚP cicd-K7 dòng-1) · 🧊 **+28 @S161** (5 wave KHKK: W1 566 → W2 574 → W3 580 → W6 587 → W7 590; đo tươi @S162 `dotnet test` 45+545, gate CI Run #432 khớp). ~~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 | **87** | 🔄 **87 @S179 flush** — đo đĩa `docs/gotchas.md` max anchor = **87** (`lead-stale-auditor` FLAG-5 + máy HIGH `canonical-itself-stale`; #87 sinh ở S177 vá lệch 2 tầng). 🧊 **+S168 #86** (2-push-sát → Gitea auto-CANCEL run đầu cùng-branch: CANCELLED ≠ fail — verifier đọc run CUỐI của range + bằng-chứng artifact-level; side-effect @startup chỉ 1-startup cho cả cụm push; ca thật `aaed699` ship qua #442) · **+S162 #85** (menu-key OR-gate FE ≠ policy per-action BE: cây 4-folder GĐ gate `['Khkk_List','Khkk_G1','KeHoachKyKet'].some(can)` NHƯNG endpoint gắn `[Authorize(Policy="KeHoachKyKet.Read")]` [`ContractSigningPlansController.cs:36`] + `MenuPermissionHandler.cs:40` so khớp **CHÍNH XÁC 1 key** — KHÔNG kế-thừa cha, KHÔNG OR key con ⇒ role `Khkk_List=1 ∧ KeHoachKyKet=0`: FE mở cổng → API **403** → folder GĐ2 hiện "—" dưới **MỌI** gói thầu, claim "gate trước fetch ⇒ 0 rác 403" **vỡ**. Bẫy: luật "OR nhiều key" **ĐÚNG ở tầng HIỂN-THỊ** [`GetMyMenuTreeQuery.cs:61-96` trả node khi con `CanRead`] nhưng **SAI ở tầng API-authz** — mặt thứ 2 của #82, lần này **menu-hiện RỘNG hơn API-cho** [#82 là chiều ngược]. Fix = gate đúng key policy CỦA endpoint; **mở controller đọc attribute TRƯỚC khi wire gate**, đừng suy từ cây menu. Reviewer bắt **trước ship**; Dev 13/13 role đều `Contracts=1 ∧ KeHoachKyKet=1` nên **chưa lộ** — lớp "chưa vỡ vì dữ-liệu hiện tại may mắn", vá ngay không đợi triệu chứng). **+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 | **60** | 🔄 **re-ground S179** — đo lại ĐÚNG phương-pháp dòng này tự khai: `ls .claude/auto-memory/*.md | wc -l` = **61**, trừ 1 index `MEMORY.md` = **60** (`lead-stale-auditor` FLAG-9; máy MÙ trục này — không có cross-check). 🔴 Ô này trôi lại chỉ sau **9 nhãn phiên** kể từ lần re-ground trước ⇒ đây là ô **rụng nhanh**, đừng tin số cũ. 🧊 re-ground S170 — đếm đĩa 60 file trừ 1 index = 59 (số "31" stale từ S84; lead-stale FLAG @S169, ring2 verify, vá @S170 SAU khi ring chấm — đúng thứ-tự H24 §2(4) fire→chứng-kiến→vá). +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 | **26** | **+S176 🎨 ĐỘI STYLE 3 vai** (`front-end-reviewer-style` · `back-end-reviewer-style` · `database-reviewer-style` — **anh chốt TRỰC TIẾP**, không qua adap). 🔴 **Luật lõi anh giao:** *"quy tắc thì các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"* — lý-do sinh đội là câu *"mày cứ làm đi làm lại hoài"*. **Ca THẬT làm anh nêu:** S176 vòng-4b lead dựng thùng rác KHKK **thiếu banner + dấu `🗑 xóa ≈`** trong khi màn thùng rác Duyệt NCC **đã chạy prod** có đủ cả hai ⇒ anh phải tự chụp màn gửi sang bảo *"ảnh chỉ là mẫu"*. Trục = **ĐỒNG-NHẤT** (có giống bản đã chạy không) ⟂ `reviewer` = **ĐÚNG-SAI** (có bug không) ⇒ chạy SONG SONG, không giẫm. Địa-phận RỜI theo glob diff: `fe-*/src/**` · `src/Backend/**` trừ `Persistence/**` · `Persistence/**`; **gọi theo diff chạm đâu**, diff không chạm ⇒ KHÔNG gọi (không phải bỏ sót). 🧊 **Anh nêu ban đầu 4 con** (có `clean-code-reviewer-style`) **rồi tự chốt lại 3** (*"3 con tao nhầm"* + *"chốt theo ý mày"*): con clean-code phủ chồng cả 3 con kia nên **không viết nổi câu scope-rời** mà roster này bắt buộc ⇒ trục clean-code (đặt tên · trùng lặp · mật-độ comment · pattern drift) **gộp vào từng con trong địa phận của nó**. 🔸 **Máy trước, vai sau** (đo S176): FE có ESLint chạy trước (`npm run lint`) nhưng **CI KHÔNG gác** (`grep 'npm run lint'` trong workflows = **0 hit**) và đang tồn **89 vấn-đề / 78 lỗi** (fe-admin 42 · fe-user 47); **BE 0 máy style nào** (0 `.editorconfig` · 0 analyzer · 0 `dotnet format`) ⇒ con BE gánh cả lớp cơ-học, khác con FE. Cắm được máy vào CI thì **PHẢI cập-nhật lại persona con BE** trả lớp đó về máy. ⚠️ **roster 26 > `hmw_width.cap` 20** ⇒ full-roster-sweep LOUD-skip nhiều lane hơn trước — số cap = quyền anh (O-7 vẫn treo, nay lệch rộng hơn). 🔸 **Nấc = executed-file / verified-pending-restart** — 3 vai CHƯA spawn-probe; `hmw.js` VALID_ROLES 23→**26**. **+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). | +| Sub-agents | **26** | **+S176 🎨 ĐỘI STYLE 3 vai** (`front-end-reviewer-style` · `back-end-reviewer-style` · `database-reviewer-style` — **anh chốt TRỰC TIẾP**, không qua adap). 🔴 **Luật lõi anh giao:** *"quy tắc thì các tính năng đã deploy thành production rồi thì sẽ là chuẩn, trừ khi tao có điều chỉnh lại lần nữa"* — lý-do sinh đội là câu *"mày cứ làm đi làm lại hoài"*. **Ca THẬT làm anh nêu:** S176 vòng-4b lead dựng thùng rác KHKK **thiếu banner + dấu `🗑 xóa ≈`** trong khi màn thùng rác Duyệt NCC **đã chạy prod** có đủ cả hai ⇒ anh phải tự chụp màn gửi sang bảo *"ảnh chỉ là mẫu"*. Trục = **ĐỒNG-NHẤT** (có giống bản đã chạy không) ⟂ `reviewer` = **ĐÚNG-SAI** (có bug không) ⇒ chạy SONG SONG, không giẫm. Địa-phận RỜI theo glob diff: `fe-*/src/**` · `src/Backend/**` trừ `Persistence/**` · `Persistence/**`; **gọi theo diff chạm đâu**, diff không chạm ⇒ KHÔNG gọi (không phải bỏ sót). 🧊 **Anh nêu ban đầu 4 con** (có `clean-code-reviewer-style`) **rồi tự chốt lại 3** (*"3 con tao nhầm"* + *"chốt theo ý mày"*): con clean-code phủ chồng cả 3 con kia nên **không viết nổi câu scope-rời** mà roster này bắt buộc ⇒ trục clean-code (đặt tên · trùng lặp · mật-độ comment · pattern drift) **gộp vào từng con trong địa phận của nó**. 🔸 **Máy trước, vai sau** (đo S176): FE có ESLint chạy trước (`npm run lint`) nhưng **CI KHÔNG gác** (`grep 'npm run lint'` trong workflows = **0 hit**) và đang tồn **89 vấn-đề / 78 lỗi** (fe-admin 42 · fe-user 47); **BE 0 máy style nào** (0 `.editorconfig` · 0 analyzer · 0 `dotnet format`) ⇒ con BE gánh cả lớp cơ-học, khác con FE — 🧊 **đây là SỐ ĐO NGÀY 2026-08-06 (S176), giữ làm LINEAGE có ngày, KHÔNG phải trạng-thái hiện-hành**; nguồn sống = phép-đo per-spawn trong `back-end-reviewer-style.md` §0 (SỬA-6a @S179: claim này từng chép ra **4 site** ⇒ cắm `.editorconfig` là 4 chỗ sai cùng lúc, detector chỉ so SỐ nên không bắt). Cắm được máy vào CI thì **PHẢI cập-nhật lại persona con BE** trả lớp đó về máy. ⚠️ **roster 26 > `hmw_width.cap` 20** ⇒ full-roster-sweep LOUD-skip nhiều lane hơn trước — số cap = quyền anh (O-7 vẫn treo, nay lệch rộng hơn). 🔸 **Nấc = executed-file / verified-pending-restart** — 3 vai CHƯA spawn-probe; `hmw.js` VALID_ROLES 23→**26**. **+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). | | RAG chunks | 🟢 **service UP** · 🔴 **SE index STALE** | 🔴 **TÁCH 2 TRỤC @S159 — 1 nhãn nhị-phân DOWN/alive che mất trục thứ hai.** ① **service-liveness = UP**: đo LIVE 2026-07-29 `list_projects` → **7/7 project chunk > 0** (`solution_erp` **2449** · vipix_multisite 7090 · dh_y_duoc 15440 · namgroup 6106 · ashico 4742 · vipix_ai_infra 4176 · benhvien_aau 3024; chỉ `shared_global` = 0); **query THẬT** `search_code` → 1 hit **có ruột** score 7.156 ⇒ collection đọc được, **không phải vỏ rỗng** (metadata một mình KHÔNG đủ — có thể là registry-cache). ② **SE index-freshness = KÉM**: `last_indexed_at` = **2026-05-29** trong khi **5 sibling re-index 2026-07-29 08:21** cùng một lượt. **Lật thẳng DOWN→alive sẽ CHÔN trục ②.** 🧊 **Nhãn "DOWN từ S153" ĐÚNG LÚC GHI** (`33e7f68`, 07-28 20:50, 3 phép đo khớp, `chunk_count=0` cả 7 project) — service **hồi phục sau ~12h** ⇒ class `view-stale-status`, **KHÔNG phải lead ghi ẩu**; đừng quy lỗi cho lượt viết vốn có bằng chứng đúng. 🔸 **Caveat giữ (H1 F-4 → ring1 T-2):** H1 tuyên `last_indexed_at` "không đáng tin" (2447→2449 nhúc nhích), `ring1` **BÁC** bằng nội-dung — coi là **đáng tin**; muốn chắc tuyệt đối thì re-index rồi xem field có nhảy không. Re-index = AI_INFRA op (cần VOYAGE_API_KEY). *(FLAG-2 `view-stale-status` HIGH — `lead-stale-auditor` @S159, `ring2` tái-dựng 8/8 số. Lead trước đó chỉ vá `:6`, sót đúng ô canonical này = **canonical-poison**, cùng lớp khác site.)* | **Bundle hash live (prod):** admin **`Ajv-MaCz`** (1.783.465B) · user/eoffice **`YsXRkBSR`** (1.701.224B) — **đo LIVE 2026-08-05 @S172 bởi 3 nguồn độc-lập** (cicd-verify `998ea55` §5.1 · lead `curl` · `ring2-audit` §2 đo ngoài repo); 2 hash đời trước đã **biến mất khỏi đĩa** (trả `text/html` ~900/876 B). 🧊 *S168 #444: admin `DLRf9TeA` · eoffice `C7TGA4Kn` — **ô này đứng STALE suốt S171→S172** dù `998ea55` đã ship 04/08; `lead-stale-auditor` FLAG-1 (HIGH) bắt @S172, `ring2-audit` F-2 HELD bằng nguồn ngoài repo. **Lần thứ hai cùng ô** (S166 F-2) ⇒ quy-trình tự-khai dưới đây **có luật mà không có người thi hành** — nếu tái-diễn lần 3 thì phải wire máy, đừng vá tay nữa.*; 🧊 K7 #442: admin `RgvHZkPH` · eoffice `D65FJPGd`; push kế tiếp SẼ rotate tiếp ⇒ **nguồn cập nhật ô này = cicd-verify lượt kế, đừng tin ô này quá 1 deploy** (bài "sạch lúc HH:MM" — ô này đã chết-ngay-lúc-viết 1 lần trong chính S166). 🧊 Lineage gần: K6 #440 admin `Ig1R5tAh` ROTATE · eoffice FROZEN-lành-tính cmp-byte · K4a #437 admin `1yiNV4VH`/eoffice `DoULfmdT` (post-F-1, 2-css khớp chứng đo-đúng-site) · K3 #436 admin `mySTlx42`/css `Cf3iCOOv` · eoffice `CZAYiWWa` FROZEN-hợp-lệ (diff toàn comment, cicd §5 dự-đoán-trước). 🧊 Lineage cũ (S162-S164, hash `B43R6Y17`/`NLI5umBg` đã chết): **Nguồn rotate = push `e5123ff`**, commit gắn nhãn `Docs: S162 closeout` **nhưng ship 6 file FE-src THẬT** (`PipelineStageFolders.tsx` · `PipelineTreePanel.tsx` · `usePipelineStages.ts` ×2 app) ⇒ rotate **real-src, KHÔNG phải #69-benign**; scope commit sai convention (đáng lẽ `FE-Admin`+`FE-User`, không phải `Docs`). 🔴 **Hại đo được — LỆCH 2 BỀ MẶT, không phải 1:** ô này đứng ở cặp S157 qua **2 đời deploy**, VÀ dòng `:6` ghi cặp S162 `DXoYDy7R`/`o8KDluD1` **chưa bao giờ là trạng-thái cuối** (snapshot chụp sau `bfc7b79`, trong khi `e5123ff` còn ship FE tiếp) ⇒ **cả 2 bề mặt owner đều lệch prod cùng lúc**. Đúng ca *"closeout-push kế có non-md sẽ rotate tiếp"* mà chính ô này đã tiên-liệu (precedent S99-#485 / S107) — tiên-liệu đúng, cơ-chế bắt vẫn không có. **Control-âm:** cặp S157 `8-QYcMOg`/`DptYR4wL` nay trả `text/html` **900 B** admin / **876 B** eoffice ⇒ bundle cũ đã chết. ⚠️ **CHƯA neo run-số CI** — lead chỉ curl 3 phép (2 hash live + control-âm), **không đọc Gitea Actions**; cần `cicd-monitor` xác nhận Run # + test-gate trước khi coi ô này đủ bằng-chứng. 🧊 *Mốc trước S157:* admin **`8-QYcMOg`** · user **`DptYR4wL`** (đo LIVE @S157 2026-07-28, **Run #419** `6250f39` — cicd PASS 9/9 + lead tự re-curl độc lập khớp từng byte, marker 2/2 mỗi app; **control-âm**: 2 hash CŨ `index-BK8w3QxU.js`/`index-DYnxSI0T.js` nay trả `text/html` **900 B admin / 876 B eoffice** ⇒ bundle cũ đã chết trên prod. 3 phép đo độc-lập: cicd-verify · lead re-curl · ring2-audit). 🔴 **Ô này từng đứng ở cặp `BK8w3QxU`/`DYnxSI0T` sau khi prod đã rotate** — `git show 3b6fabc -- docs/STATUS.md` chỉ có 2 hunk, **0 hunk chạm dòng này**; hại đo được: `cicd-verify-s157-diadiem.md:58` dùng chính ô này làm baseline ⇒ lượt deploy kế hoặc báo "ĐỔI" giả hoặc che một lần không-rotate (lead-stale-auditor FLAG-1 HIGH @S158). 🧊 *Mốc trước:* admin `BK8w3QxU` · user `DYnxSI0T` (S156 CI run 531 `f4494cf`; `Last-Modified` 14:41:15/14:42:10 +07 **nằm trong cửa-sổ deploy** — ship-proof, không phải hash-delta suông. Byte-verify 4/4 marker: `allowApproverDelete` 8/2 · `by-approver` 1/1 · `deleted=1` 1/1 · `view=approved` 1/1. ⚠️ **Không chứng minh hồi-tố** được bundle của riêng `4464a46` đã rotate lúc 14:12 — `f4494cf` đè lên sau 30 phút, không ai chụp snapshot khoảng giữa). 🧊 *Mốc trước:* admin `B2j1LQ-v` · user `C3wbJegk` (S147 CI #407 — re-stamp @S152: FLAG-2 lead-stale bắt ô này đứng S134 qua 5 nhãn trong khi `:6`/`:465`/HANDOFF đều S147; ring2 verify 2 lệnh độc-lập). 🧊 *Chuỗi rotate lịch-sử giữ nguyên:* (S134 — **`6664a61`** PE lũy kế TẠM TÍNH vs CHÍNH XÁC [0 mig — `ComputePendingAsync` complementary + DTO 5-field + FE sub-dòng amber + banner màn duyệt + D4 audit-note]; **Run #399** GO 5/5 5m27s gate-**528**-EXACT-từ-log rotate ×2 admin js `3NCdyODe`→**`BVCukFP5`** css `B--dUHcm`→**`CBzUlgOA`** / eoffice js `CKsoiNCI`→**`DoxyEOxh`** css `BuntB63r`→**`BHsBUA8e`** [FE-src đổi thật 6 file ⇒ rotate expected; CSS rotate = amber badge utilities, benign #69]; real-size 1.659.037/1.565.367B + LM 14:31:34/14:32:28+07 in-window; **byte-verify #77** `pendingPriorPes`=2 + `Tạm tính`=3 + `phiếu trước cùng gói thầu CHƯA duyệt`=2 PRESENT cả 2 js [control old-hash 900B text/html 0-hit — ct=text/html là discriminator sạch hơn size-919b]; Mig 67 top FROZEN + 89 bảng [0-mig by-construction]; smoke 4×200 + PE 401; lead spot-check độc-lập post-verdict: 4/4 hash khớp + marker PRESENT). **Prev S133** — admin **`3NCdyODe`** · user **`CKsoiNCI`** (S133 — **`d4fbced`** PE freeze NS phiếu DaDuyet [Mig 67 snapshot 11 cột + backfill 18/18 + FE 2-app badge 🔒 SHA-mirror `5534addb` + display-gate `budgetFrozen`]; **Run #398** GO 5/5 gate-520 rotate ×2 admin →**`3NCdyODe`** [CSS `B--dUHcm`] / user →**`CKsoiNCI`** [CSS `BuntB63r`] — prev `yCkX-2Bp`/`DKSD4p9k` @Run #397 S131-S132 [dòng-live lag S117→S133, hoist per precedent S104/S107]; **CSS cũng rotate** = badge sinh utility-class mới, benign #69; **byte-verify #77** `budgetFrozen`=1 + VN-string 🔒=1 PRESENT [old-control 0]; Mig 67 prod history-top + 11 cột + backfill 18/18 chua=0 + sys.tables **89**; smoke 4×200 + PE 401; `/tiep` S134 re-verify độc-lập 4/4: mig-top + health-200 + bundle-hash ×2 + filter 11/11). **Prev S117** — admin **`cFI7ih4a`** · user **`MxgooVZw`** (S117 — **`316a82f`** PE endsBeforeCeo pointer-aware [display-fix BE-only, phiếu chờ CEO hết báo "Kết thúc" sai] + duyệt-theo-khoảng Min–Max [Mig 66 + FE 2-app ProMinMax radio thứ 5]; **Run #387** PASS 5m36s rotate ×2 admin `Dd55jBpj`→`cFI7ih4a` / user `DVDr1UQ4`→`MxgooVZw` CSS-frozen [logic-only fingerprint]; **byte-verify #77** `ProMinMax`/`duyệt theo khoảng`/`cả Min và Max`/`Min–Max` PRESENT [bundle-cũ=0]; Mig 66 prod col decimal(18,2) + `__EFMigrationsHistory`-top + sys.tables **89**; smoke 200×3 · PE 401-secured; **#53-garble ×2** [invest-lane-1 + cicd-monitor] → SendMessage-resume + em-main curl cross-verify khớp). **Prev S116** — admin **`Dd55jBpj`** · user **`DVDr1UQ4`** (S116 — **`88368fd`** PE cho nhập giá ÂM ô báo giá [FE 2-app nút ± toggle + submit-gate `>0`→`!==0` + helper `hasRealSelectedQuote` 2-mirror `:201`/`:235`; BE submit-guard `:206` `Sum()<=0`→`All(==0)`; +9 test 486→495; **NO migration**]; **Run 386** PASS 5m28s rotate ×2 admin `D51OYyGV`→`Dd55jBpj` / user `BVdssm5S`→`DVDr1UQ4` CSS-frozen [logic-only fingerprint]; **byte-verify #77** `Đã nhập giá chào thầu`/`hoàn tiền NCC`/`phát sinh giảm`/`Đơn vị được chọn chưa có giá chào thầu` PRESENT [bundle-cũ=0]; smoke 200×3 · PE 401-secured · 89 bảng; cicd bắt bẫy snapshot-while-CI-running→poll-success TRƯỚC re-snapshot). **Prev S114** — admin **`D51OYyGV`** · user **`BVdssm5S`** (S114 — **`d436af2`** PE multi-NCC per hạng mục [Mig 65 backfill 2-chiều + BE re-key 5 financial→IsSelected + FE per-cell grid Detail×NCC 2-app SHA `ae3788e9`]; bundle rotate ×2 admin `acprMqfB`→`D51OYyGV` / user `Ck3BTDdA`→`BVdssm5S`; **byte-verify** `detailId`+`select-winner`+`hạng mục` PRESENT [bundle 1.65MB real-size]; smoke health/admin/eoffice 3/3 200 + endpoint POST select-winner bogus-401-live; **cicd garble #53 ×5 → em-main-solo curl-verify**; mig applied [API-healthy=migrations-ran-startup]). **Prev S113** — admin **`acprMqfB`** · user **`Ck3BTDdA`** (S113 — **Run #497** `5fa11b5` Supplier import v2 [Mig 64 publish/draft + dedup-MST + template + file mẫu] FE 2-app real-src rotate; JS admin `Cixlt_MA`→`acprMqfB` / user `BhBOG1dn`→`Ck3BTDdA` + CSS admin `Ds-E5neu`→`CfunQHbd` / user `Beb0Bb1h`→`DGqqHQXS`; ship-proof real-size 1.66/1.56MB + LM-in-window + **byte-verify** `Tải file mẫu`×1/`Đã công bố`×3/`Nháp (ẩn)`×4/`import/template`×1/`published`×5 PRESENT; Mig 64 prod 37/37-backfill sys.tables **89**; smoke health/admin/eoffice 200 + `import/template`-401-live + `suppliers?published=true`-401-live bogus-404-control). **Prev S112** — admin **`Cixlt_MA`** · user **`BhBOG1dn`** (S112 — **Run #496** `e100ef0` Supplier Excel-import Phase B FE 2-app [`SupplierImportDialog` NEW cả fe-admin+fe-user] + PE sign-off code-only; **real fe-src rotate — kết thúc #489→#495 non-determinism-freeze**; JS admin `BVyH-FY7`→`Cixlt_MA` / user `EDsZebvn`→`BhBOG1dn` + CSS admin `Bbtesa6B`→`Ds-E5neu` / user `BmuPz_Dy`→`Beb0Bb1h`; ship-proof real-size + Last-Modified-in-window + `"Database NCC"` marker PRESENT ×1; Mig 63 prod 2/2-col sys.tables **89**; smoke health/admin/eoffice 200 + PE-endpoint 200 + import-route preview-415/confirm-401-live bogus-404). **Prev S107** — admin **`BVyH-FY7`** · user **`EDsZebvn`** (S107 — **Run #489** `21387cd` +office-document 12th sub governance-only; **rotate benign #69-two-mode** [0 fe-src — Vite non-determinism], CSS frozen `Bbtesa6B`/`BmuPz_Dy`, real-size 1.64/1.55MB + Last-Modified-in-window 09:32/09:33 = ship-proof, Mig 62/89 frozen, smoke 200×3; hoist @S107-closeout per H1 flag D-BUNDLE-lặp — ⚠️ closeout-push kế có non-md sẽ rotate tiếp → Run #490 record nằm ở cicd MEMORY [authoritative], hoist ở bundle đầu phiên sau per precedent S99-#485). **Prev S104** — admin **`ChSNAJBK`** · user **`Bn2w1znH`** (S104 — **Run #488** `778fc98` Mig 62 Supplier expand 30-field; real-src-rotate FE 2-app SHA-mirror [form 4-section + Status select + `PathLink` 3 NAS-link], **sys.tables 89 pre==post no-new-table**, prod-verified marker grep-HIT, smoke 200×3; S104-shipped nhưng dòng-live `:27` lag tới S106 → hoist per H1 flag D-BUNDLE). **Prev S97** — admin **`mEGqlNWc`** · user **`Dnrp4PU1`** (S97 — **Run #484** `fb2dfa9` Mig 61 data-fix backfill; bundle rebuild **#69-benign** [0 FE-src change, review-workflow cicd re-snapshot LIVE → `CeTA7Z82`/`CGaAyXen` #483 đã bị #484 rebuild rotate]; backfill A/005/A/008 flag 0→1 prod-verified). **Prev #483** — admin **`CeTA7Z82`** · user **`CGaAyXen`** (S97 — **Run #483** `9e12e80` badge "✅ Đã được CEO duyệt" phiếu đi-hết-lên-CEO [PeFinalizeChip single-source + 6 call-site 2-app, đối xứng chip "⚑ Kết thúc·X"]; FE-only tận-dụng endsBeforeCeo runtime, no BE/mig; JS rotate CSS-frozen #69; byte-#77 "Đã được CEO duyệt" PRESENT cả 2 app + prev-badge additive no-regression; Mig 60 frozen; smoke 200×3 + PE-list 200). **Prev #482** — admin **`DR9q2VUy`** · user **`Bgz8u4E5`** (S97 — **Run #482** `8037fa0` endsBeforeCeo config→RUNTIME [Mig 60 `EndedByLevelFinalize`]: **Mig 60 applied prod** (history-top + col-default-0 EXISTS + backfill=0 UAT-no-marker + sys.tables **89** pre==post); **EF-ternary SQL-Server LIVE-confirmed** GET /purchase-evaluations 200 items=9 + PE-detail `31faef0d` 200 **endsBeforeCeo=False phase=7** = runtime-path chạy = **bug fixed LIVE** (NOT 500); JS rotate 2-app PeWorkflowPanel gate-diff, CSS frozen #69-REFINE; byte-#77 `endsBeforeCeo` PRESENT in-bundle; smoke 200×3. reviewer PASS 0-issue + test 440. **Prev #481** — admin **`Cf0o8dx8`** · user **`x8rppRAK`** (S97 — **Run #481** `1c8fb6a` PE finalize 2-fix [badge "không trình tới"→"Kết thúc tại {cấp}" + đảo default checkbox opt-in]; JS rotate real-FE 2-app `PeWorkflowPanel` diff, CSS frozen `Bbtesa6B`/`BmuPz_Dy` #69-REFINE logic-only; **byte-level #77** NEW `Kết thúc tại`+helper PRESENT / OLD `không trình tới`+`Đã BỎ tick` ABSENT; real-size 1.64/1.54MB; Mig 59/88-table frozen; smoke 200×3. FE-only mirror SHA `bcf812fd`, 0 BE/mig/test). **Prev S96** — admin **`COYAX-yQ`** · user **`0MU-kb4N`** (S96 — **Run #480** `0c2f9f6` price-lock; chuỗi 3 PE deploy #478 `e657faa` checkbox-opt-out → #479 `36cbf8b` chuông-stale-clear (BE-only) → #480 `0c2f9f6` khóa-giá-sau-duyệt, cicd PASS each ~5m; **FE JS rotate THẬT** (PeWorkflowPanel #478 + PeDetailTabs #480, 2-app) real-size 1.64/1.54MB vs 919b SPA-trap, CSS frozen #69-REFINE; Mig 59 frozen 0-mig; +Run #477 `ba4b8e0` NCC seed no-mig prod 21 NCC. **Verify byte-level:** prod `0MU-kb4N` CHỨA checkbox-fix ("BỎ tick"/"Đã BỎ tick") + "✅-static" cũ MẤT → checkbox "ko-được" = browser-cache KHÔNG deploy-fail). **Prev S95** — admin **`0T6vVJST`** · user **`BGXEVZO6`** (S95 — **Run #476** `18a17f5` H17 governance-only deploy; bundle rotate benign #69 CSS-frozen, prod 200×3, Mig 59 unchanged; cicd re-snapshot LIVE — pre-deploy `CkZ1MjC1`/`_-gpX7_Y`, mega-line S93 `CDn40vpV`/`CoPmPBg7` đã bị deploy trung-gian rotate từ S94). **Prev S85** — admin **`aKuNip19`** · user **`BUsL0HeQ`** (S85 — **Run #341** `49ac086` lệch-giờ TZ serialize UTC-with-Z; FE frozen #339+#341 BE-only. Chuỗi ~10 deploy #334→#341 buổi UAT anh Kiệt CV PRO: #334 `5a61254` batch CV PRO 6-fix → #335-#338 6 vòng UAT → #339 `1263c0d` workflow-preserve bug-class S42 → #341 `49ac086` TZ; #342 `d4f6021` docs+cicd BE-frozen, bundle giữ-nguyên gotcha #69-REFINE). **Prev S78** — admin **`CsJetgZH`** · user **`BVS0ApIm`** (S78 — **Run #330** `7886fd0` PE attach-file khi duyệt; bundle ROTATE từ S77 `BqKD3Y23`/`Cn-i349D` dù NO migration enum-only — gotcha #69 non-determ rebuild; cicd ship-proof byte-stable + fake-hash control). **Prev S77** — admin **`BqKD3Y23`** · user **`Cn-i349D`** (S77 — **Run #329** `e823694` banner Trả-lại; cuối chuỗi 10 deploy #320→#329 cùng ngày, cicd PASS each: #320 pill `DsSg6RRz`-era → #321 focus → #322 revert → #323 Mig57+notes `CPm4LTqm`/`BWJUAqEI` → #324 số-âm-đỏ `C6fx-0ea`/`N3sW4Div` → #325 indent `BhnNMucS`/`B1VebpXc` → #326 cờ-gấp-asymmetric `DwXqn37C`/`COXMCv7E` → #327 decouple `B0gboSAg`/`DbDg7pM-` → #328 notify (BE-only, FE frozen) → #329 banner **`BqKD3Y23`**/**`Cn-i349D`**). **Prev S76** — admin **`jOqxW4-p`** · user **`DbsznVvR`** (S76 — **Run #319** `21d1f4e` bảng lưới `` ngân sách viền-ô; chuỗi S76 cùng ngày: #318 `e33481e` feature ma-trận-3-cột + badge quyền-NS `BhFDF9IJ`/`BAkuRl3C` → #319 **`jOqxW4-p`**/**`DbsznVvR`**, cicd PASS each, smoke 3×200, Mig 56 applied prod #318). **Prev S74** — admin **`BYF5vIMJ`** · user **`CB-tiRxd`** (S74 — **Run #315** `8655ebf` Mig 55 CcmNote, cicd PASS ~4m54s: Mig 55 applied prod CcmNote nvarchar(1000) nullable · sys.tables 88 · smoke 4×200 · 0 regression). **Prev S73** — admin **`Bv3jUCNo`** · user **`BWlMBQz6`** (Run #314 `6aa4dcb` FE empty-candidates guard fix; chuỗi 2 deploy: #313 `1d86abc` feature `OlNyG9OD`/`DSzSLVtL` → #314 **`Bv3jUCNo`**/**`BWlMBQz6`**, cicd PASS each). **Prev S72** — admin **`fc_xkNpJ`** · user **`DP-tBcg0`** (Run #312 governance commit `18fced6`; bundle ROTATE do **non-deterministic hash + deploy rebuild-FE-unconditional** (gotcha #69) — 0 FE source change, prod state/DB GIỮ NGUYÊN). **Prev S69** — admin **`BgNCjwsG`** · user **`CBvh0vtf`** (Run #308 PE cờ gấp + ngưỡng CCM; chuỗi 4 deploy session: #305 Văn phòng số foundation → #306 re-skin 10 page → #307 Office golive (BE-only) `Wt54PHYl`/`B99fMU6X` → #308 **`BgNCjwsG`**/**`CBvh0vtf`**). **Prev S68** — admin **`CNUv1jxY`** · user **`CpOskeS1`** (S68 — Run #304 `37752eb` fix tên đen→trắng; chuỗi #303 `6983609` `D532XZKG`/`CuFaBoWt` → #304 **`CNUv1jxY`**/**`CpOskeS1`**, cicd PASS each). **Prev S67** — admin `CcrZqfht`/user `DniDFUB_` (S67 — 6 deploy Run #297→#302; admin rotate chuỗi #298`xkSz9BfE`→#300`PxiZQkaw`→#301`I1fpLeYw`→#302**`CcrZqfht`** · user #297`BumgrwCJ`→#300`B36hGoKd`→#301`DrQYkzh0`→#302**`DniDFUB_`**; #299 tests BE-only cả 2 frozen, cicd PASS each). **Prev S65** — admin `BDwV5d0X`/user `DbVv6rsf` (Run #293-295). Prev S62 admin `0xKYGhhf`/user `C81ZdG9G` (Run #286). **Prev S59:** admin `B1DtNT9C` · user `D6uF3Mln` (Run **#282** `792c030` FINAL — bỏ nút Thêm hạng mục; ships kèm `80b64dd` gỡ Điều khoản TT, #281 cancelled-benign ancestor-verified). Chuỗi S59 cùng ngày: #280 `69997da` (`BKy_8OO9`/`XcZ6PRyA`, ships kèm `f21c55d` table-fixed #279-cancelled) · #278 `9c330d2` self-approve+quick-add-NCC (`BSh2fG2X`/`D22KfpPc`, authz probe 4/4) · #277 `faed59f` SearchableSelect (`ex7Tc92G`/`DzUeSk96`) · #276 `c869d26` rename 71 PMH (`BBA0KSWu`/`DzdTI18G`) · #275 `bbd1554` dọn demo WorkItems (FROZEN BE-only) · #274 `0eafcd3` tree 4 tầng (`DuU7OTym`/`DWyeTzf3`) · #273 `56882ac` wipe + tree v1 (`R9uGRxvw`/`DikfX1RD`). Prev S58: Run #386 `3ebaf84` admin `DMm9rtNA`/user `BUkOMn_Y` (chi tiết session log S58). @@ -483,6 +485,14 @@ monthly re-tier mega-line + ef-core SKILL Mig→59 + 3 vocab-fork (2026-07-01 du --- +## ✅ Recently Done (S177–S179 — 2026-08-06 → 08-07, phiên-LOGIC **L11**) + +- **S179 (2026-08-07) — vá đội STYLE 2 vòng + H24 + drift-audit tháng** → [`sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md`](changelog/sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md). **0 file code nghiệp-vụ** (toàn governance + comment); build ✅ 2/2 app · test **645/645**. + 🔴 **Bài đắt nhất — chẩn-đoán sai vẫn PASS acceptance:** vòng-1 vá `SỬA-1` pass **12/12** rồi `reviewer` C7 bắt **2 MAJOR trong chính bản vá** (đổi ba-chấm→hai-chấm là **REGRESSION có điều-kiện**, không phải cosmetic · `porcelain | cut -c4-` **đẻ path RÁC** ở rename + path có dấu cách). Lead dựng sandbox đo lại, CONFIRMED cả 2 ⇒ acceptance đo **hình-dạng chuỗi**, không đo **hành-vi**. + 🔴 **Lớp `mỏ-neo TỰ-VÔ-HIỆU`:** con-trỏ số-dòng trỏ vào CHÍNH tệp chứa nó ⇒ tự thối mỗi lần sửa đầu tệp (112→118→121 trong 1 phiên) ⇒ **neo TÊN, không neo SỐ DÒNG**. + 🔴 **"Sổ nói dối theo hướng BI QUAN" ×3** (4 slot HANDOFF · E4 · `run.md` S173) ⇒ **leo thang lần 3 phải ĐO LẠI TIỀN-ĐỀ**. + Kèm: H24 9 FLAG (flush 8 ô canonical) · 2 NỢ vòng-3 · 2 synthesis ORPHAN · di-trú cửa-sổ 6 · adap 2 thư (**bác Lớp 8 có số**: mtime cụm SE 0,7% vs hub 69%) · drift-audit tháng `PASS_WITH_FLAGS — 8` · `_mind` 99,67%→**84,2%** · #53 **4/4 vai garble, vớt trọn 4/4**. + ## ✅ Recently Done (S171–S172 — 2026-08-04 → 08-05, phiên-LOGIC **L10**) - **`998ea55` KHKK 3-panel mirror Duyệt NCC — verdict cicd = PASS**, prod khoẻ, 0 rollback. Test-gate #447 **644/644 Failed 0** khớp baseline tách-phần Δ0 · bundle 4/4 rotate khớp log CI tới byte · 2 endpoint MỚI **401** · mig repo 71 = prod 71 **set-diff 0/0 hai chiều**, tables 97 · smoke 8/8. Chi tiết → `.claude/workflows/runs/2026-08-04-S171-khkk-ui-mirror-pe/cicd-verify-998ea55.md`. @@ -669,7 +679,7 @@ monthly re-tier mega-line + ef-core SKILL Mig→59 + 3 vocab-fork (2026-07-01 du - **2 mark Active-High** — anh chốt **TÁCH** (2 trục **khác nấc bằng-chứng**): `RC-pqhuy1987-15-07-2026-15-32-20` (H22 · bằng-chứng mạnh) · `RC-pqhuy1987-15-07-2026-15-32-23` (H24 · **caveat binding: "LỆNH về CÁCH LÀM, chưa phải bằng-chứng về HIỆU-QUẢ"**). - 🔴 **CÒN NỢ (khai thẳng):** 2 vai H24 **CHƯA CHẠY lần nào** (counter=1, nhịp đầu ~S128) · precedence H23 **CHƯA test** (chờ phiên **lead=Fable**) · dạng-4 orphan = kẽ CÒN LẠI · **R6 chờ hub** (SE không tự dời memory được — `settings.json` 0 key ⇒ harness ép). -## 🔥 In Progress (mốc gần nhất S162 — phiên-LOGIC L8; khối dưới còn nhãn L7 là lineage, đọc dòng CURRENT trên đầu để biết hiện-hành) +## 🔥 In Progress (mốc gần nhất S162 — phiên-LOGIC L8; khối dưới còn nhãn L7 là lineage. 🔴 **Section này STALE-BY-DESIGN**: nó chỉ advance @closeout, nên giữa phiên **ĐỪNG đọc nó làm bản-đồ hiện-hành** — bản-đồ sống là `.claude/WAL.md`, KHÔNG phải dòng CURRENT ở đầu file. 🧊 con-trỏ cũ trỏ sang "dòng CURRENT trên đầu" bị GỠ @S179: lúc đó `:6` đang ở **L9/S168** trong khi thực-tế **L11/S179** ⇒ chuỗi cứu-hộ trỏ vào ô cũng đã ô-nhiễm — `lead-stale-auditor` FLAG-7) | Task | Owner | Status | |---|---|---| diff --git a/docs/changelog/sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md b/docs/changelog/sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md new file mode 100644 index 0000000..6b63010 --- /dev/null +++ b/docs/changelog/sessions/2026-08-07-1200-S179-doi-style-va-2-vong.md @@ -0,0 +1,71 @@ +# S179 (2026-08-07) — vá đội STYLE 2 vòng + H24 + drift-audit tháng + +> Phiên-LOGIC **L11, window 7**. Vào bằng `/tiep`. Anh chốt: 6 câu trả lời item + ***"OK làm cho xong hết đi nhé"***. +> 🔴 **0 file code nghiệp-vụ bị đụng** — toàn governance + comment. BE/DB không chạm. + +## 1. Arc đóng trong phiên + +| Arc | Trạng-thái | +|---|---| +| `SETUP-REVIEW: SỬA-6` (đội STYLE 3 vai) | ✅ **ĐÓNG** — 6/6 điểm, acceptance C1-C6b 12/12, + vòng-2 sửa chính vòng-1 | +| H24 light-audit (9 FLAG) | ✅ ĐÓNG — 8 ô flush + FLAG-7 vá con-trỏ + FLAG-8 cố ý defer (block bất-biến) | +| 2 NỢ vòng-3 | ✅ ĐÓNG | +| 2 run-folder ORPHAN | ✅ ĐÓNG — 2 thước độc-lập cùng im | +| Di-trú cửa-sổ 6 | ✅ ĐÓNG | +| Kéo + áp 2 thư `loi-do-luong` | ✅ ĐÓNG — adap-report, **bác Lớp 8 CÓ SỐ** | +| Drift-audit tháng (quá hạn 6 ngày) | ✅ ĐÓNG — `PASS_WITH_FLAGS — 8`, vá 2, còn 6 | +| Nén `_mind` | ✅ ĐÓNG — 99,67% → 84,2% | + +## 2. 🔴 Bài học đắt nhất — **chẩn-đoán sai vẫn PASS acceptance** + +Vòng-1 vá SỬA-1 **pass 12/12 acceptance** rồi `reviewer` C7 bắt **2 MAJOR nằm trong chính bản vá**. Lead dựng sandbox đo lại, **CONFIRMED cả hai**: + +| Lỗi | Sự thật đo được | +|---|---| +| Đổi `...`→`..` "cosmetic" | **SAI — là REGRESSION có điều-kiện.** Chỉ tương-đương khi `origin/main` còn ancestor. Cây phân-kỳ: hai-chấm liệt `upstream_only.txt` (= **ĐÃ PRODUCTION**) vào "phần MỚI"; ba-chấm ra đúng `local_only.txt`. **Thủ phạm thật = `git diff` mù untracked**, không phải ba-chấm | +| `git status --porcelain \| cut -c4-` | **Đẻ path RÁC** — rename in MỘT dòng `R old -> new`; path có dấu cách bị quote. Sandbox: **2/2 MISS**; thước mới **2/2 OK** | + +**Thước CHỐT (4/4 site):** +```bash +{ git diff --name-only origin/main...HEAD; git diff --name-only HEAD; git ls-files -o --exclude-standard; } | sort -u +``` + +⇒ **Gốc:** acceptance đo **HÌNH-DẠNG chuỗi** (`grep 'main\.\.\.HEAD' → 0`), không đo **HÀNH-VI**. Cả 2 lỗi đều làm thước xanh mà đội vẫn mù. + +## 3. Lớp `mỏ-neo TỰ-VÔ-HIỆU` — lead tự đẻ, tự tái phát 2 lần + +Thêm 6 dòng khai MIRROR vào đầu `index.css` ⇒ `.card-accent` 112→**118**; vá thành `:118` thì 3 dòng vá đẩy tiếp thành **121**. ⇒ **Sửa gốc = BỎ SỐ DÒNG, neo TÊN SELECTOR**. Áp luôn cho `gotchas.md` (`h1-h4`) + `PipelineStageFolders` (`ACCENT PALETTE`). Grep consumer lòi **site thứ 5** (`KhkkDetailContent:438`) mà bản kê "4 site" không có. + +## 4. Class lặp — "sổ nói dối theo hướng BI QUAN" (3 ca/1 phiên) + +Ba mục **báo còn nợ khi nợ đã trả**: ⓐ 4 slot HANDOFF (68)-(71) đã ratify+land @S172, mở suốt S173→S179 · ⓑ E4 kêu `harness-refine` thiếu S163/S168/S169 — đĩa **có đủ** · ⓒ `run.md` S173 khai *"lead đã đính chính trong phiên"* — đĩa nói **không**. +⇒ **Luật: leo thang lần 3 phải ĐO LẠI TIỀN-ĐỀ trước.** Và *"đã đính chính trong phiên" ≠ "đã LAND trên đĩa"*. + +## 5. #53 — 4/4 vai garble, vớt trọn 4/4 + +`ctx-verifier` · `lead-stale-auditor` · `reviewer` C7 · `tooling-auditor` — **cả 4** return đầu cắt giữa câu, **cả 4** vớt trọn bằng `SendMessage` resume-in-session. **Mất 0 byte.** Nấc-2 thang #53 nay ăn **3 phiên liên tiếp** (S173 8/8 · S178 · S179 4/4). +🔸 **Câu garble CHỨA FINDING:** mảnh C7 = *"a third thước defect"* · mảnh tooling = *"same-class residue"* ⇒ lead biết trước khi đọc verdict. + +## 6. Run-record + +``` +memory-triple: do=scripts/measure-agent-memory.ps1 · exit 0 · 26 vai (3 vai style LẦN ĐẦU hiện) +memory-triple: de-xuat=scripts/memory-archive-gate.ps1 -Apply · exit 0 · strike 1/2 (investigator-codebase · ring2-audit) +memory-triple: kiem=scripts/mfe-eval.ps1 · FIT=PASS · implementer-frontend 12/13=92% (role duy nhất <100%, S172 = 85%) +memory-triple: do-record=governance-detectors TOTAL=51 (2 HIGH canonical-itself-stale) +memory-triple: do-record=NHIP-NO: kiem light 7/6 deep 13/15 OVERDUE:light | tran-bo-nho 4 over-cap l2idx 0 over | run-chua-gom 0 | pull-cach 16 ngay +``` + +**§L.c completeness-gate:** +``` +completeness-gate S179: vong 3/5 chuc-nang (khong-nhip: V3 tri-memory · V4 nen-ngu) | phep DAT 2 / TRUOT 0 / vacuous 2 +``` +- **V1** tooling+harvest — `tooling-auditor` chạy (`PASS_WITH_FLAGS — 8`); H2 KHÔNG chạy ⇒ `ring1-audit` **NO-OP** (pin thiếu). +- **V2** soi-lead — cặp H24 chạy (`lead-stale` 9 FLAG @open · `lead-gap` @close); `ring2-audit` **chưa chạy** ⇒ carry. +- **V5** measured-label-gate — **fire THẬT**: chặn nhãn "đã-đo" của lead ở 2 ca (vế hai-chấm · `cut -c4-`), cả 2 do C7 lật. +- **V3/V4** `không-nhịp` — trio memory + nén-ngủ không chạy phiên này (probe shard chưa KÊU). +- **phép-1 vacuous** (tick đã fire @`/tiep`, không có cửa mới) · **phép-4 vacuous** cho 3 vai `ring*` (chưa chạy). + +## 7. Còn nợ (đã đo, CHƯA vá — đổ vào WAL + HANDOFF) + +`ROTATE vrapp` (việc anh) · A1 chờ strike-2 · **C7 còn 2** ([6] thước use-only giòn theo thứ-tự chữ · [8] SỬA-6b bất-đối-xứng + 3 persona chép `paths-ignore`) · **drift-audit còn 6** (F-2 `permission-matrix` thiếu 5 root · F-3 `12 root` · F-4 dải `§16+` 4 giá-trị · F-5 `PROJECT-MAP` 0 hit 4 module · F-7 skill-mig Mig 71 · F-8 schema-diagram 91 vs 97) · **3 vai style CHƯA spawn-probe — cần RESTART CLI**. diff --git a/docs/gotchas.md b/docs/gotchas.md index c3c8365..d44a33c 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -1166,13 +1166,13 @@ for h in resp.points: # ← .points không phải iterable trực tiếp **Triệu chứng:** Header chi tiết NV (`app-gradient-brand` nền gradient xanh) — `

` render **ĐEN `#0b1220`**, trong khi `
` (dòng meta cùng banner) render trắng đúng. Anh UAT báo "màu đen nhìn không nổi bật" — chính xác, dù code ghi `text-white`. -**Cơ chế:** `fe-user/src/index.css:79` có `h1,h2,h3,h4 { color:#0b1220 }` viết **thô, NGOÀI mọi `@layer`** (thêm S65 #290 "darker ink"). Tailwind v4: CSS unlayered có priority **CAO HƠN tất cả `@layer`** (kể cả `utilities`) → `text-white` (trong layer utilities) THUA. `
` không bị rule element này nhắm nên `text-white` thắng → nghịch lý meta-trắng / heading-đen cùng 1 banner. +**Cơ chế:** `fe-user/src/index.css` khối `h1, h2, h3, h4 {` (🔴 **neo theo TÊN, KHÔNG theo số dòng** — số này đã thối 2 lần trong CÙNG phiên S179: 79→85→89 vì header đầu tệp bị thêm dòng. Đo: `grep -n '^h1, h2, h3, h4 {' fe-user/src/index.css`) có `h1,h2,h3,h4 { color:#0b1220 }` viết **thô, NGOÀI mọi `@layer`** (thêm S65 #290 "darker ink"). Tailwind v4: CSS unlayered có priority **CAO HƠN tất cả `@layer`** (kể cả `utilities`) → `text-white` (trong layer utilities) THUA. `
` không bị rule element này nhắm nên `text-white` thắng → nghịch lý meta-trắng / heading-đen cùng 1 banner. **Guard:** (1) **User báo màu render ≠ class trong code ⟹ NGHI ngay rule CSS priority cao hơn** (unlayered element / `!important` / global) — grep `index.css` rule element TRƯỚC khi tin utility. (2) Ép utility thắng = **important modifier Tailwind v4 trailing-bang** `text-white!` → compile `.text-white\!{color:…!important}` (**verify bằng grep dist CSS** — đừng tin suông). (3) **KHÔNG move rule unlayered vào `@layer base` nếu load-bearing** — đo blast-radius `grep ']*text-'`: rule này đang ép ~30+ heading toàn app về `#0b1220` (chúng gắn `text-slate-700/900/brand-800` nhưng bị override) → move = đổi màu loạt giữa UAT. (4) Authed page không screenshot dev-rig (gotcha #3) → visual gate = anh mắt thường qua deploy prod. **Credit:** em main solo S68 — anh UAT realtime ("chữ đen nền xanh ko nổi bật") → diagnose unlayered heading rule → `text-white!` + thu nhỏ `text-lg` → grep dist confirm `!important` → Run #304 PASS, x2 app SHA256. -**References:** `fe-user/src/index.css:79-83` (h1-h4 unlayered) · `fe-{user,admin}/src/pages/hrm/EmployeesListPage.tsx:653` (h2 name `text-white!`) · Tailwind v4 layer precedence · gotcha #3 (authed screenshot). +**References:** `fe-user/src/index.css` khối `h1, h2, h3, h4 {` (unlayered; 🔴 neo TÊN — xem Cơ chế, số dòng thối 2 lần @S179) · `fe-{user,admin}/src/pages/hrm/EmployeesListPage.tsx:653` (h2 name `text-white!`) · Tailwind v4 layer precedence · gotcha #3 (authed screenshot). --- diff --git a/docs/governance/adap-reports/2026-08-05-Governance-loi-do-luong-phan-1-va-2.md b/docs/governance/adap-reports/2026-08-05-Governance-loi-do-luong-phan-1-va-2.md new file mode 100644 index 0000000..d09cddb --- /dev/null +++ b/docs/governance/adap-reports/2026-08-05-Governance-loi-do-luong-phan-1-va-2.md @@ -0,0 +1,66 @@ +# adap-report — `2026-08-05-Governance-loi-do-luong-phan-1-tai-lap-duoc` + `-phan-2-ca-rieng-cua-hub` + +- **Repo:** SOLUTION_ERP (self = `se`) · **Phiên:** S179 (phiên-LOGIC L11, window 7) · **Ngày:** 2026-08-07 +- **Broadcast:** `ai_infra` → `outbox/all`, 2 tệp (16.700 B + 9.678 B), phát 2026-08-05 +- **Kéo trễ 2 ngày** — khai thẳng lý do: cửa dò thư của lead **hỏi sai cấp** (`../AI_INFRA` = 1 cấp, thật ở `../../AI_INFRA`) nên `all=0` suốt S177-S178. Đó chính là **Lớp 1 của thư** (`0` vì dụng-cụ hỏng) xảy ra **trên chính cửa nhận thư về Lớp 1**. Vá @S178, kéo @S179. +- **Engine:** KHÔNG spawn — lead đọc + tự chạy phép bác. Lý do: thư đòi **phép thử tái-lập tại kho mình**, không đòi phân-tích. + +## Nấc G-011: **executed (một phần) + refuted (một phần)** + +🔴 **Không claim "adopted" trọn gói.** Thư nói thẳng: *"chạy được phép thử đó và ra kết quả ngược thì lớp đó không áp — bỏ qua, đừng làm cho có."* Nên báo cáo này chia 3 rổ: **đã ăn / đã bác có số / chưa đo**. + +## PROJECT-FIT + +Fit cao ở **9 lớp Phần 1** (đều là cơ-chế đo-lường, không phụ-thuộc cấu-trúc hub). **Phần 2 = ca riêng hub**, đọc tham-khảo, **không nhận làm sàn** — đúng như thư tự dặn. + +## Rổ A — lớp ĐÃ ĂN, có bằng-chứng SINH RA TRONG PHIÊN NÀY + +🔴 **Điểm đáng chú ý nhất của đợt adap này:** 4 lớp dưới đây SE **giẫm phải và tự bắt được TRONG S179, TRƯỚC khi đọc thư** (thư kéo về ở cuối phiên). Tức là chúng **hội-tụ độc-lập**, không phải SE đọc rồi diễn lại. + +| Lớp | Ca THẬT ở SE @S179 | Trạng-thái | +|---|---|---| +| **1** — đèn xanh vì dụng-cụ hỏng | Thước residual `ctx-curator` neo `origin/main..HEAD`; `ee21056` **đã push** ⇒ trôi khỏi cửa-sổ ⇒ trả **0-hit** đọc thành "đã sạch". Control dương: 2 tệp **còn nguyên trên đĩa**. | ✅ vá: đổi sang thước **neo ĐĨA** | +| **1** (ca 2) | Thước dispatch đội STYLE `git diff ...origin/main...HEAD` mù uncommitted+untracked ⇒ **0 spawn, 0 `SKIP-CO-KHAI`** = "sạch" giả. Fault-inject 2 chiều chứng răng. | ✅ vá SỬA-1, 4 site | +| **5** — vá nửa vời | Vá xong SỬA-1..6b rồi **chạy lại chính acceptance của spec**: `C4` ra **2/3** (con `db` chưa có cặp neo) và `C6a` lòi ra **site thứ 5** mà spec chỉ liệt 4. | ✅ bắt được **đúng nhờ chạy lại lệnh vừa dán** | +| **6** — sửa dòng này sót dòng kế bên | `README.md`: vá claim "BE 0 máy style" ở `:76` xong, **`:197` vẫn còn nguyên** trong bảng skill-matrix cùng file. | ✅ grep lại toàn tệp mới thấy | +| **3** — đếm trước khi chốt định-nghĩa | Cùng phiên có **3 đại-lượng** lệch: roster **23 vs 26** · test **644 vs 645** (đo thật: 45+**600**) · user-memory **59 vs 60** (61 tệp − 1 index). | ✅ re-ground cả 3 bằng lệnh đếm sống | + +**Thuốc SE đã cắm (tailor, không chép):** +- Mọi thước trong `WAL.md verify:` từ nay ưu tiên **neo ĐĨA hoặc neo nội-dung**, tránh neo **cửa-sổ git đang trôi** (`origin/main..HEAD`, `HEAD~n`) — cùng gốc với bài `HEAD~n ≠ commit-trước-của-mình` SE đã có từ S177. +- 3 persona STYLE: acceptance `DAT` nay đòi **cặp neo `file:line ⇄ file:line` + 1 chi-tiết gọi tên được**; thiếu neo ⇒ lead **từ chối nhận `DAT`** (đây là "chỉ tôi ca thử làm nó đỏ" của Lớp 1, áp cho vai người-máy). + +## Rổ B — lớp ĐÃ BÁC, **có số**, KHÔNG áp cho SE + +**Lớp 8 (thời-gian-sửa-tệp đã chết) — REFUTED.** + +| | SE | Hub (thư khai) | +|---|---|---| +| Cụm mtime lớn nhất | **14 / 2.036 tệp = 0,7%** | 1.160 / 1.673 ≈ **69%** | + +Phép đo: `Get-ChildItem -Recurse` trên `.claude` + `docs` + `src` + `tests` + `scripts` (trừ `bin`/`obj`/`node_modules`), group theo giây. +⇒ SE **không có** thao-tác lấy-lại-mã-nguồn/đồng-bộ hàng-loạt ghi đè mtime ⇒ trường này **còn sống** ở SE. **Không cắm luật cấm dùng mtime** — cắm là làm cho có, đúng thứ thư dặn đừng. +🔸 Giữ 1 dòng cảnh-báo: nếu về sau SE clone lại repo hoặc restore từ Dropbox hàng-loạt thì **đo lại trước khi tin mtime**. + +## Rổ C — lớp CÓ ÁP nhưng **CHƯA vá**, khai nợ + +**Lớp 7 (neo vào hình-dạng chữ do người gõ) — CONFIRMED, chưa vá.** +`scripts/governance-detectors.ps1` neo vào marker **người gõ**: `NEXT anh` / `NEXT em` tại **5 site** (`:814` `:882` `:885` `:888` `:909`) + `'### {0}.'` (`:386`). +Đã có nhân-chứng độc-lập: `ring2-audit` @S173 dựng lại bằng python và chứng detector **H24-2 dựng segment từ `marks[0]`**, mà marker đầu nằm ở `HANDOFF:90` ⇒ **toàn bộ L1-89 không bao giờ được soi**. +⇒ **Đúng Lớp 7, đã có ca thật.** Thuốc thư đề-nghị (chốt sống-chết đo bằng **nguồn độc-lập**: mốc neo không được cũ hơn mốc mới nhất quá 1 bậc, lệch hơn thì phải nói *chưa đo được* thay vì phát số) **chưa cắm** — vào WAL làm nợ, **không claim đã xử**. + +**Lớp 2 · 4 · 9 — chưa chạy phép bác**, khai thẳng là **chưa đo**, không đoán. + +## 🔴 Phản-biện gửi ngược hub + +**1. "Bác chúng tôi bằng cách nào" là phần GIÁ-TRỊ NHẤT của thư — đề nghị hub giữ và làm mạnh hơn.** +Nhờ đúng mục đó mà SE **bác được Lớp 8 bằng 1 lệnh** thay vì cắm một luật vô-dụng rồi nuôi nó nhiều phiên. Không có mục đó, sister sẽ có xu-hướng adopt-cho-đủ. Đề nghị: **mỗi lớp kèm luôn NGƯỠNG** (Lớp 8 nếu hub ghi sẵn *"tỷ lệ >20% thì mới áp"* thì SE tự phân-loại được, khỏi phải suy). + +**2. Lớp 5 và Lớp 6 nên gộp làm một lớp 2 nhánh.** SE giẫm cả hai **trong cùng một thao-tác vá** (chạy lại acceptance → lòi `C4` thiếu 1 con **và** `C6a` sót site cùng tệp). Cơ-chế gốc giống nhau: **phạm-vi vá hẹp hơn phạm-vi bệnh**; khác nhau chỉ ở *quên con nào* (Lớp 5, xuyên tệp) vs *quên dòng nào* (Lớp 6, trong tệp). Tách 2 làm người đọc tưởng là 2 phản-xạ, thật ra chỉ cần **1 phản-xạ: khai phạm-vi trước, grep lại sau**. + +**3. Thư tự dính Lớp 3 ở chính chỗ tự khai.** Mục "Chúng tôi khai trung thực" ghi *"9 lớp re-derive từ 17 báo cáo gốc, bản tóm nội bộ chỉ có 6 lớp — thiếu 50%"*. **6 → 9 là thiếu 33%, không phải 50%** (nếu mẫu số là 9). Nếu hub tính 3/6 = 50% thì mẫu số là **bản tóm**, mà câu văn đang nói về **phần bị thiếu của bản đầy đủ**. ⇒ đúng Lớp 3: *"đại-lượng có 2 con số, mỗi con tái-lập được trong hệ quy-chiếu riêng"*, xảy ra **trong đúng đoạn văn tự nhận đã mắc Lớp 5**. + +## Honest-caveat + +- SE **chỉ chạy phép bác cho 3/9 lớp** (7 · 8 + xác-nhận 1/3/5/6 bằng ca có sẵn trong phiên). **Lớp 2 · 4 · 9 chưa đo** — không claim fit, không claim miễn. +- Rổ A liệt ca SE **tự bắt trước khi đọc thư**; công của thư ở đây là **đặt tên và gom thành lớp**, không phải phát hiện. Ghi đúng như vậy, không thổi. +- **Phần 2 (ca riêng hub) đọc rồi, KHÔNG nhận làm sàn** — đúng chỉ-dẫn của chính thư. 3 nguyên-tắc bóc ra ở cuối Phần 1 thì có ăn: đặc-biệt *"khai sau khi chạy, không khai trước"* và *"bị chặn bởi quy-ước ≠ bị chặn bởi máy"* — cái sau SE đã có tiền-lệ `tools-whitelist-no-teeth` (whitelist = tuyên-bố ý-định, containment thật = git-diff commit-gate). diff --git a/fe-admin/src/components/khkk/KhkkDetailContent.tsx b/fe-admin/src/components/khkk/KhkkDetailContent.tsx index 9c25cad..71e2e2b 100644 --- a/fe-admin/src/components/khkk/KhkkDetailContent.tsx +++ b/fe-admin/src/components/khkk/KhkkDetailContent.tsx @@ -435,7 +435,7 @@ export function KhkkDetailContent({ return ( // [S175 — anh: "Viền xanh này trong thao tác" → rồi "ý tao bỏ cái viền xanh thôi, còn bộ - // khung table thuần vẫn nên giữ lại"] `.card-accent` (`index.css:112`) gói **HAI thứ**: + // khung table thuần vẫn nên giữ lại"] `.card-accent` (`index.css:118`) gói **HAI thứ**: // ① KHUNG thẻ — bo góc 0.75rem + viền 1px `#e9eef4` + nền trắng + đổ bóng → anh GIỮ // ② DẢI ACCENT DỌC 3px bên trái (`border-left`) → anh BỎ // 🔴 Lượt trước lead gỡ CẢ CLASS ⇒ mất luôn ①, panel trôi không khung. Nay dựng lại ① diff --git a/fe-admin/src/components/khkk/KhkkWorkflowPanel.tsx b/fe-admin/src/components/khkk/KhkkWorkflowPanel.tsx index 2964393..cdadf72 100644 --- a/fe-admin/src/components/khkk/KhkkWorkflowPanel.tsx +++ b/fe-admin/src/components/khkk/KhkkWorkflowPanel.tsx @@ -274,8 +274,11 @@ export function KhkkWorkflowPanel({ return ( // [S175 · B1 · X2] Panel TRẦN khuôn PE (`PeWorkflowPanel.tsx:345`). Trước đây bọc // `card-accent` ⇒ thẻ-trong-thẻ, lệch đập vào mắt trước mọi mục owner liệt kê. - // 🔴 GỠ HẲN CLASS, KHÔNG đè `border-0`/`shadow-none`: `.card-accent` (`index.css:112`) - // nằm NGOÀI `@layer` nên thắng utility Tailwind v4 — đè là vô hiệu (gotcha #66, đã cắn thật). + // 🔴 GỠ HẲN CLASS, KHÔNG đè `border-0`/`shadow-none`: `.card-accent` (`index.css:118`) + // nằm NGOÀI `@layer` nên thắng utility Tailwind v4 THƯỜNG ⇒ đè kiểu đó vô hiệu (gotcha #66). + // 🔸 Chính-xác hoá @S179 (bản cũ viết "đè là vô hiệu" — OVERCLAIM): `!important` VẪN thắng + // (`text-white!`) — đó đúng là fix mà #66 tự đề-xuất. Ở ĐÂY vẫn GỠ CLASS chứ không dùng + // `!important`, vì lý do THIẾT-KẾ (thẻ-trong-thẻ là sai hình), không phải vì bất-khả-thi.
{/* ── 1. Header + meta {code} v{NN} · {name} ───────────────────────────── */}
diff --git a/fe-admin/src/components/pipeline/PipelineStageFolders.tsx b/fe-admin/src/components/pipeline/PipelineStageFolders.tsx index 3da59e1..fed119c 100644 --- a/fe-admin/src/components/pipeline/PipelineStageFolders.tsx +++ b/fe-admin/src/components/pipeline/PipelineStageFolders.tsx @@ -34,7 +34,9 @@ const STAGE_ICON: Record = { } // Pattern 14 (Tailwind JIT): class dạng LITERAL đầy đủ, không nội suy mảnh. -// Palette `@theme` (index.css:29-51) chỉ có stop 50/100/500/600/700 cho teal / +// Palette `@theme` (index.css, khối `ACCENT PALETTE` — neo theo TÊN, KHÔNG theo số dòng: +// `grep -n 'ACCENT PALETTE' fe-admin/src/index.css`; số dòng cũ ":29-51" đã thối 2 lần @S179) +// chỉ có stop 50/100/500/600/700 cho teal / // violet / amberx ⇒ head dùng -700 (riêng brand có tới -900). const STAGE_STYLE: Record = { 1: { chip: 'bg-brand-50 text-brand-600', head: 'text-brand-800', count: 'bg-brand-50 text-brand-700', code: 'text-brand-700' }, diff --git a/fe-admin/src/components/pipeline/PipelineTreePanel.tsx b/fe-admin/src/components/pipeline/PipelineTreePanel.tsx index bf99d45..fdaa578 100644 --- a/fe-admin/src/components/pipeline/PipelineTreePanel.tsx +++ b/fe-admin/src/components/pipeline/PipelineTreePanel.tsx @@ -257,8 +257,10 @@ export function PipelineTreePanel({ // ngoài" — `hideHeader` = đang NHÚNG trong panel khác ⇒ bỏ vỏ card + sticky để liền // mạch với host, y như cây bên Duyệt NCC. // 🔴 KHÔNG vá bằng cách truyền `border-0 shadow-none`: `.card-accent` khai ở - // `index.css:112` NẰM NGOÀI `@layer` nên THẮNG utility của Tailwind v4 (gotcha #66) + // `index.css:118` NẰM NGOÀI `@layer` nên THẮNG utility THƯỜNG của Tailwind v4 (gotcha #66) // ⇒ cách đó bị vô hiệu IM LẶNG (đúng thứ vừa xảy ra). Phải GỠ CLASS, không đè. + // 🔸 Chính-xác hoá @S179: chỉ utility THƯỜNG mới thua; `!important` (`text-white!`) VẪN + // thắng — chính là fix #66 đề-xuất. Ở đây gỡ class vì THIẾT-KẾ, không phải vì bất-khả-thi. !hideHeader && 'card-accent lg:sticky lg:top-4', className, )} diff --git a/fe-admin/src/index.css b/fe-admin/src/index.css index 322acab..62c26bf 100644 --- a/fe-admin/src/index.css +++ b/fe-admin/src/index.css @@ -1,3 +1,13 @@ +/* 🔴 File MIRROR — `fe-admin/src/index.css` ⟂ `fe-user/src/index.css` phải SHA256 IDENTICAL. + Sửa 1 bên PHẢI copy sang bên kia. Đo: `sha256sum fe-admin/src/index.css fe-user/src/index.css`. + Vì sao phải TỰ KHAI: luật mirror của `front-end-reviewer-style` §2 CHỈ soi file TỰ KHAI là mirror. + 2 tệp này khớp byte từ lâu nhưng KHÔNG khai ⇒ vai style KHÔNG gác ⇒ lệch một bên là trôi IM LẶNG. + Khai @S179 — NỢ vòng-3 ① "khung thẻ 2 nguồn sự-thật" (`.card-accent` sống ở cả 2 app). + 🔴 CỐ Ý KHÔNG ghi SỐ DÒNG ở đây. Bản đầu @S179 ghi ":112" rồi chính 6 dòng header này đẩy nó + thành 118; vá thành ":118" thì 3 dòng vá lại đẩy tiếp thành 121 — **mỏ-neo số-dòng trỏ vào + CHÍNH tệp chứa nó thì tự vô-hiệu mỗi lần sửa đầu tệp**. Neo đúng = TÊN SELECTOR: + `grep -n '^\.card-accent {' fe-admin/src/index.css`. */ + @import "tailwindcss"; @import url("https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap"); diff --git a/fe-user/src/components/khkk/KhkkDetailContent.tsx b/fe-user/src/components/khkk/KhkkDetailContent.tsx index 9c25cad..71e2e2b 100644 --- a/fe-user/src/components/khkk/KhkkDetailContent.tsx +++ b/fe-user/src/components/khkk/KhkkDetailContent.tsx @@ -435,7 +435,7 @@ export function KhkkDetailContent({ return ( // [S175 — anh: "Viền xanh này trong thao tác" → rồi "ý tao bỏ cái viền xanh thôi, còn bộ - // khung table thuần vẫn nên giữ lại"] `.card-accent` (`index.css:112`) gói **HAI thứ**: + // khung table thuần vẫn nên giữ lại"] `.card-accent` (`index.css:118`) gói **HAI thứ**: // ① KHUNG thẻ — bo góc 0.75rem + viền 1px `#e9eef4` + nền trắng + đổ bóng → anh GIỮ // ② DẢI ACCENT DỌC 3px bên trái (`border-left`) → anh BỎ // 🔴 Lượt trước lead gỡ CẢ CLASS ⇒ mất luôn ①, panel trôi không khung. Nay dựng lại ① diff --git a/fe-user/src/components/khkk/KhkkWorkflowPanel.tsx b/fe-user/src/components/khkk/KhkkWorkflowPanel.tsx index 2964393..cdadf72 100644 --- a/fe-user/src/components/khkk/KhkkWorkflowPanel.tsx +++ b/fe-user/src/components/khkk/KhkkWorkflowPanel.tsx @@ -274,8 +274,11 @@ export function KhkkWorkflowPanel({ return ( // [S175 · B1 · X2] Panel TRẦN khuôn PE (`PeWorkflowPanel.tsx:345`). Trước đây bọc // `card-accent` ⇒ thẻ-trong-thẻ, lệch đập vào mắt trước mọi mục owner liệt kê. - // 🔴 GỠ HẲN CLASS, KHÔNG đè `border-0`/`shadow-none`: `.card-accent` (`index.css:112`) - // nằm NGOÀI `@layer` nên thắng utility Tailwind v4 — đè là vô hiệu (gotcha #66, đã cắn thật). + // 🔴 GỠ HẲN CLASS, KHÔNG đè `border-0`/`shadow-none`: `.card-accent` (`index.css:118`) + // nằm NGOÀI `@layer` nên thắng utility Tailwind v4 THƯỜNG ⇒ đè kiểu đó vô hiệu (gotcha #66). + // 🔸 Chính-xác hoá @S179 (bản cũ viết "đè là vô hiệu" — OVERCLAIM): `!important` VẪN thắng + // (`text-white!`) — đó đúng là fix mà #66 tự đề-xuất. Ở ĐÂY vẫn GỠ CLASS chứ không dùng + // `!important`, vì lý do THIẾT-KẾ (thẻ-trong-thẻ là sai hình), không phải vì bất-khả-thi.
{/* ── 1. Header + meta {code} v{NN} · {name} ───────────────────────────── */}
diff --git a/fe-user/src/components/pipeline/PipelineStageFolders.tsx b/fe-user/src/components/pipeline/PipelineStageFolders.tsx index 3da59e1..fed119c 100644 --- a/fe-user/src/components/pipeline/PipelineStageFolders.tsx +++ b/fe-user/src/components/pipeline/PipelineStageFolders.tsx @@ -34,7 +34,9 @@ const STAGE_ICON: Record = { } // Pattern 14 (Tailwind JIT): class dạng LITERAL đầy đủ, không nội suy mảnh. -// Palette `@theme` (index.css:29-51) chỉ có stop 50/100/500/600/700 cho teal / +// Palette `@theme` (index.css, khối `ACCENT PALETTE` — neo theo TÊN, KHÔNG theo số dòng: +// `grep -n 'ACCENT PALETTE' fe-admin/src/index.css`; số dòng cũ ":29-51" đã thối 2 lần @S179) +// chỉ có stop 50/100/500/600/700 cho teal / // violet / amberx ⇒ head dùng -700 (riêng brand có tới -900). const STAGE_STYLE: Record = { 1: { chip: 'bg-brand-50 text-brand-600', head: 'text-brand-800', count: 'bg-brand-50 text-brand-700', code: 'text-brand-700' }, diff --git a/fe-user/src/components/pipeline/PipelineTreePanel.tsx b/fe-user/src/components/pipeline/PipelineTreePanel.tsx index bf99d45..fdaa578 100644 --- a/fe-user/src/components/pipeline/PipelineTreePanel.tsx +++ b/fe-user/src/components/pipeline/PipelineTreePanel.tsx @@ -257,8 +257,10 @@ export function PipelineTreePanel({ // ngoài" — `hideHeader` = đang NHÚNG trong panel khác ⇒ bỏ vỏ card + sticky để liền // mạch với host, y như cây bên Duyệt NCC. // 🔴 KHÔNG vá bằng cách truyền `border-0 shadow-none`: `.card-accent` khai ở - // `index.css:112` NẰM NGOÀI `@layer` nên THẮNG utility của Tailwind v4 (gotcha #66) + // `index.css:118` NẰM NGOÀI `@layer` nên THẮNG utility THƯỜNG của Tailwind v4 (gotcha #66) // ⇒ cách đó bị vô hiệu IM LẶNG (đúng thứ vừa xảy ra). Phải GỠ CLASS, không đè. + // 🔸 Chính-xác hoá @S179: chỉ utility THƯỜNG mới thua; `!important` (`text-white!`) VẪN + // thắng — chính là fix #66 đề-xuất. Ở đây gỡ class vì THIẾT-KẾ, không phải vì bất-khả-thi. !hideHeader && 'card-accent lg:sticky lg:top-4', className, )} diff --git a/fe-user/src/index.css b/fe-user/src/index.css index 322acab..62c26bf 100644 --- a/fe-user/src/index.css +++ b/fe-user/src/index.css @@ -1,3 +1,13 @@ +/* 🔴 File MIRROR — `fe-admin/src/index.css` ⟂ `fe-user/src/index.css` phải SHA256 IDENTICAL. + Sửa 1 bên PHẢI copy sang bên kia. Đo: `sha256sum fe-admin/src/index.css fe-user/src/index.css`. + Vì sao phải TỰ KHAI: luật mirror của `front-end-reviewer-style` §2 CHỈ soi file TỰ KHAI là mirror. + 2 tệp này khớp byte từ lâu nhưng KHÔNG khai ⇒ vai style KHÔNG gác ⇒ lệch một bên là trôi IM LẶNG. + Khai @S179 — NỢ vòng-3 ① "khung thẻ 2 nguồn sự-thật" (`.card-accent` sống ở cả 2 app). + 🔴 CỐ Ý KHÔNG ghi SỐ DÒNG ở đây. Bản đầu @S179 ghi ":112" rồi chính 6 dòng header này đẩy nó + thành 118; vá thành ":118" thì 3 dòng vá lại đẩy tiếp thành 121 — **mỏ-neo số-dòng trỏ vào + CHÍNH tệp chứa nó thì tự vô-hiệu mỗi lần sửa đầu tệp**. Neo đúng = TÊN SELECTOR: + `grep -n '^\.card-accent {' fe-admin/src/index.css`. */ + @import "tailwindcss"; @import url("https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap");