wal: pause

This commit is contained in:
pqhuy1987
2026-07-29 14:53:58 +07:00
parent ea962b1e59
commit febe6b1696
19 changed files with 645 additions and 43 deletions

View File

@ -1,10 +1,12 @@
# CI/CD Monitor Agent — Persistent Memory
- **07-29 verify `a2bbcb9` ĐỢT-4 (danh sách toàn trình: 7 FLAG reviewer fix + nhãn 'Bảng cứng') [S159, 2 file code: FE-user 1043/337 + DbInitializer label-only 9/1, 0 mig]:** ✅ **PASS 9/9** — Run **#425** (id=538) success **5m40s**; gate **562**. User bundle rotate `DeAg7MWm``CLfAftby` (+css `BQIZ-rUe``B6bUSFBt`). 🔑 **ADMIN bundle FROZEN mà vẫn chứng minh được là LÀNH TÍNH (#69 mode-B) — khuôn dùng lại:** `fe-admin` 0 file trong diff ⇒ hash không đổi; nhưng `Last-Modified` của admin js = **13:55:31 NẰM TRONG cửa-sổ deploy** (13:51:15→13:56:55) + size trùng khít đợt-3file **ĐÃ ghi lại**, chỉ là Vite ra byte y hệt. ⟹ 'frozen' + LM-in-window = **re-ship giống hệt**, KHÁC hoàn toàn 'bundle cũ kẹt lại' (cái sau LM sẽ cũ). Đừng phán hash-frozen là fail. 🔑 **Comment-strip DỰ ĐOÁN TRƯỚC rồi mới đo (tiến bộ so đợt-1 là phát hiện SAU):** control âm `chưa tới` grep source ra **2** — soi ra cả 2 nằm trong COMMENT L343-344 giải thích chính FLAG-2 ⇒ **dự đoán bundle=0**, đo xong đúng **0**. Nếu đọc grep-source thô là FAIL oan một control vốn đúng. ⚠️ Ngược lại `Không tìm thấy` bundle=**10** > source=3 (chuỗi phổ thông, có ở module khác) ⇒ marker DƯƠNG chỉ dùng '≥1', **đừng lấy nó làm phép đếm-chính-xác**; chọn chuỗi ĐẶC-THÙ mới đếm-khớp được. **Durability lần 2 (khuôn 3 chân kiềng đợt-3, chạy lại rẻ):** restart thật (log mở lại **13:56:39 `Applying migrations...`** + w3wp 13:56:33) → 38-key **min=13 max=13 keys=38 totcr=494/494 GIỮ** · skeleton 156 · `Hdc_` nhãn `%-%`=7 · root 12 · 3 root vis=0 · **control âm Hrm/Off/Personal non-Admin=0 (revoker còn sống)** · `Pe%` 197/185. ⟹ **2 restart liên tiếp (#424, #425) đều giữ ⇒ fix bền, không phải may.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-a2bbcb9.md`. Tag `[run-425, pass-9-9, admin-frozen-LM-in-window-proof, comment-strip-du-doan-truoc, marker-pho-thong-khong-dem-chinh-xac, durability-restart-2, gate-562]`
- **07-29 verify `ea962b1` ĐỢT-5 (menu 6-leaf y-chang-Duyệt-NCC + `GET /contracts/deleted` + bỏ hero) [S159, 10 file 173+/371, 0 mig]:** ✅ **PASS 9/9** — Run **#426** (id=539) success **5m38s**; gate **562**. JS rotate cả 2 app (admin `CC1pGE1F``D0sXA0fe` · user `CLfAftby``Y6dW_5CM` +css `B6bUSFBt``6YIAufJR`); admin-css FROZEN nhưng **LM 14:44:29 in-window** ⇒ lành tính (#69 mode-B, khuôn đợt-4 dùng lại được ngay). 🔑 **CỨU FALSE-FAIL — luật MỚI về control ÂM:** brief bảo `Toàn trình 4 giai đoạn` phải VẮNG; tao grep repo-wide TRƯỚC khi đo → chuỗi vẫn sống hợp lệ ở `PePipelineStrip.tsx:24` **`aria-label`** (cả 2 app, có từ đợt-2)**dự đoán bundle=1 chứ không 0**, đo đúng 1. Áp máy móc là FAIL OAN. Thay bằng `Quy trình mua sắm` (eyebrow hero) — `grep -rc` 2 app = **0 hit mọi file** ⇒ ĐỘC QUYỀN ⇒ bundle=0 = chứng hero đã gỡ (kèm `UserDashboardPage` 63.124→50.142 B). **LUẬT: trước khi nhận 1 chuỗi làm control ÂM phải grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ mình muốn chứng vắng; chuỗi dùng-chung chỉ làm marker DƯƠNG.** 🔑 **SEEDER-INSERT delta khớp TOÁN (khuôn mạnh, tái dùng):** đo baseline TRƯỚC deploy rồi so SAU restart — `Ct_%_WfView` 0→**7** · `_Approved` 0→**7** · `_Deleted` 0→**7** · `Khkk_%` 5→**7** · nhãn `Ct_%_Pending`=`Đang%` 0→**7** · Dashboard `%quy tr%` 0→**1** · **MenuItems 119→142 = +23 = 7+7+7+2 khớp từng đồng** · root 12 · DUPKEYS 0 · **21 key mới đủ 13/13 canread** (nhánh reviewKeys skip-existing ăn vì key HOÀN TOÀN MỚI — khác đợt-2/3 nơi row `false` sẵn có không được nâng). **Endpoint mới:** `GET /api/contracts/deleted`**401** + **control route bịa → 404** ⇒ 401 CÓ NGHĨA, không phải catch-all (đừng chỉ đo 401 trần). ⚠️ brief ghi `/contracts/deleted` thiếu prefix — route thật có `[Route("api/contracts")]`. **Durability lần 3:** 38-key **494/494** · control âm Hrm/Off/Personal=0 · `Pe%` 197/185 · `Hdc_` nhãn 7 · 3 root ẩn. ⚠️ **Bẫy phạm-vi mới: `Ct_*` nay đẻ thêm 21 key ⇒ `LEFT(MenuKey,3)='Ct_'` cho ra 59 key, KHÔNG so được với đợt trước — phải NOT LIKE 3 hậu tố mới để giữ đúng tập 38 gốc.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-ea962b1.md`. Tag `[run-426, pass-9-9, control-am-phai-DOC-QUYEN, seeder-delta-khop-toan, 401-voi-control-404, durability-restart-3, query-scope-re-anchor, gate-562]`
- _(**#425 S159 đợt-4 `a2bbcb9` 7-FLAG fix + nhãn 'Bảng cứng' — PASS 9/9**: gate 562, user js `DeAg7MWm``CLfAftby`. 🔑 **admin FROZEN vẫn chứng được lành tính**: LM 13:55:31 **in-window** + size trùng ⇒ re-ship byte-identical (#69 mode-B). 🔑 **comment-strip DỰ ĐOÁN TRƯỚC rồi mới đo**: `chưa tới` source=2 (cả 2 trong comment) → dự đoán bundle=0 → đúng 0. ⚠️ `Không tìm thấy` bundle 10 > source 3 ⇒ marker phổ-thông chỉ dùng '≥1'. **Durability lần 2**: 38-key 494/494 giữ + control âm 0)_
- **07-29 verify `2a72695` ĐỢT-3 (gỡ nhánh S92 khỏi revoker + skeleton menu GĐ2/GĐ4 + ComingSoonPage×2) [S159, 9 file code, 0 mig]:** ✅ **PASS 9/9 — ĐÓNG regression tao bắt ở đợt-2.** Run **#424** (id=537) success **5m56s**; gate **562** giữ nguyên (3 test SỬA theo spec-change, không thêm ⇒ tổng không đổi). Bundle rotate **4/4** (admin `D6Pz7nfV``CC1pGE1F`/`B1ErASuI``DWDbm5As` · user `Bpb8WEuY``DeAg7MWm`/`7oAYFlzM``BQIZ-rUe`); marker `Phân hệ đang được triển khai`=1 cả 2 bundle + `Quay lại`=4; hash CŨ→`text/html` = chứng ghi-đè. Menu-tree: Khkk=5 · Hdc=7 · root=12 · DUPKEYS=0 · 3 root vis=0. 🔑 **PHÉP DURABILITY LÀM ĐÚNG (sửa lỗi đo-sớm đợt-2) — khuôn 3 CHÂN KIỀNG, tái dùng cho mọi ca 'fix có bền không':** (i) **CHỨNG MINH có restart THẬT trước khi đo**`w3wp` PID StartTime 12:39:56 trong cửa-sổ deploy + **dòng ĐẦU log = 12:40:03 `Applying migrations...`** (dùng được vì deploy xoá `logs/` ⇒ log mở lại = boot mới) + DLL mtime; (ii) đo CÁI CẦN: 38-key **min=13 max=13 keys=38, tổng 494/494** SAU restart (đợt-2 chính phép này ra 47/494); (iii) **control ÂM chống Goodhart**: `Hrm/Off/Personal` non-Admin vẫn **=0** ⇒ revoker CÒN SỐNG, nên (ii) xanh KHÔNG phải do vô hiệu hoá cả hàm. **Thiếu (iii) thì 'fix' bằng cách xoá luôn checker cũng xanh y hệt.** Bổ sung: `Revoked` **0 dòng** trong log = ĐÚNG (hàm chỉ log khi `rows.Count>0`; nay 0 row cần lật, so 447 ở đợt-2) — **vắng-mặt phải giải-trình bằng cơ-chế, đừng đọc thành thiếu dữ liệu**. Guard mới có RĂNG 2 vế: `StillHiddenKeys` phải false + `ReopenedKeys` phải TRUE ⇒ re-add nhánh S92 là CI đỏ. ⚠️ Bẫy số: nhãn `01.-07.` đếm ra **14** (kỳ vọng 7) — tách prefix ra `Ct_`=7 + `Hdc_`=7 + other=0, đúng thiết kế 'GĐ4 tái dùng nhãn đã đánh số', KHÔNG phải nhân đôi. ⚠️ seeder grant là **skip-existing** ⇒ không tự nâng row `false` sẵn có trên prod; prod phải re-grant SQL + revoker thôi lật. Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-2a72695.md`. Tag `[run-424, pass-9-9, durability-3-chan-kieng, restart-proof-w3wp-log-head, control-am-chong-goodhart, gate-562]`
- **07-29 verify `1a47a61` ĐỢT-2 (tab strip 4 trên phiếu PE + menu 4-GĐ + đánh số 01-07 nhóm HĐ) [S159, 8 file code 190+/18, FE×2 + seeder-only BE]:** **PARTIAL 8/9** — Run **#423** (id=536) success **5m44s**; gate **562 EXACT** (45+517). 0 migration (BE chỉ `MenuKeys.cs` const + `DbInitializer.cs` seeder). Bundle rotate **4/4** (admin js `BHodkPNV``D6Pz7nfV` css `DiNJjaoo``B1ErASuI` — admin-css rotate ĐÚNG vì fe-admin có sửa, khác đợt-1 frozen; user js `0GO8mgrG``Bpb8WEuY` css `BARVqkP-``7oAYFlzM`). Mirror `PePipelineStrip.tsx` 2 app **md5 IDENTICAL** `ef7b7824…`. 🔑 **Quy luật đếm marker (nối tiếp bài comment-strip): bundle-count = SỐ MODULE chứa chuỗi** (bundler pool hằng-số trong 1 module ⇒ nhiều occurrence cùng file gộp còn 1). USER=2 module→2 · ADMIN=1 module→1, đúng **6/6** (3 marker × 2 app) = 'đúng-BỘI-SỐ'. 2 control ÂM (`Đề xuất ký kết hợp đồng`, `Ký cứng & phát hành`) =0 cả 2 bundle + grep repo-wide 0-hit. Menu-data 5/5: **root=12 (0 double-insert) · DUPKEYS=0** · 2 root mới `KeHoachKyKet` ord26 / `HopDongCung` ord32 vis=1 (13 rows/13 canread mỗi key) · 3 root vẫn vis=0 · rename prefix `Duy…` ×2 · `Pe%` 197/185. 🔴 **FAIL #9 — BẮT ĐƯỢC REGRESSION NGOÀI CHECKLIST:** Serilog `Revoked 9 permission rows … Hợp đồng/Danh mục khỏi non-Admin` ⇒ đo lại grant-38-key của đợt-1: **47/494 canread, 0 key còn 13** (Admin=38 · Procurement=9 · 11 role còn lại=0, mất 447). Gốc = `DbInitializer.cs:2203-2236` **`RevokeTemporarilyHiddenModulesAsync` UNGATED chạy MỖI startup**, tập revoke TRÙNG KHỚP grant-set ⇒ **grant SQL tay không bao giờ bền, phải sửa CODE**. ⚠️⚠️ **BÀI HỌC LỚN NHẤT — bẫy ĐO-TRƯỚC-RECYCLE: pool restart nằm ở CUỐI deploy-window, nên đo DB lúc run còn `running` = đo trạng thái CŨ, KHÔNG chứng minh được 'sống sót recycle'. Mọi mục durability PHẢI đo SAU `status=success`.** (đợt-1 tao đo 11:46 vs restart 11:49 → kết luận sai). ⚠️ deploy `Remove-Item …pi\*` **xoá luôn `logs/`** ⇒ Serilog chỉ còn từ lần deploy cuối, không truy ngược được restart trước. ⚠️ prod Identity table = **`Roles`** không `AspNetRoles` (#472 tái xác nhận). Đợt-2 tự nó ship ĐÚNG — KHÔNG rollback. Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-1a47a61.md`. Tag `[run-423, partial-8-9, do-truoc-recycle-trap, revoker-ungated-durability, marker-count-per-module, gate-562]`
- _(**#423 S159 đợt-2 `1a47a61` tab-strip 4GĐ + menu 4-GĐ — PARTIAL 8/9**: 8 mục ship đúng, **FAIL mục-9 = phát hiện lớn nhất arc**: `RevokeTemporarilyHiddenModulesAsync` UNGATED lật 447/494 row grant SQL tay (còn 47: Admin 38 + Procurement 9). ⚠️ **bẫy ĐO-TRƯỚC-RECYCLE** (đo lúc `running` = trạng thái CŨ) — đã nâng thành luật ở mục 'Recurring bug patterns'. 🔑 marker-count = SỐ MODULE chứa chuỗi. verbatim → `archive/2026-07.md`)_
- _(**07-29 `b5799fc` ĐỢT-1 (Tổng quan tất cả luồng duyệt) PASS 9/9** — Run #422 5m59s, gate 562, 0 mig, user js `DptYR4wL``0GO8mgrG`. 🔑 **marker PHÂN-BIỆT-PHIÊN-BẢN**: designer gốc `Pipeline 4 giai đoạn` vs bản-sau-review `Toàn trình 4 giai đoạn` ⇒ bundle có `Toàn trình`=1 & `Pipeline`=0 ⟹ chứng prod chạy bản ĐÃ-FIX. Dùng khi review sửa CHỮ: chọn cặp chuỗi cũ/mới làm phép phân-biệt. ⚠️ **bẫy hình-dạng-truy-vấn**: control `Pe` ra 182/182 vs kỳ vọng 197/185 vì tao dùng `LEFT(MenuKey,3)='Pe_'` còn gốc là `LIKE 'Pe%'` (+`Permissions`/`Personal`/`PeWorkflows`=+15/+3) ⇒ **LỆCH-số phải truy PHẠM-VI-QUERY trước khi hô drift**. 🔴 M7 lượt này SAI (đo 11:46 TRƯỚC restart ~11:49) → regression lộ ở đợt-2, đóng ở đợt-3/4. Evidence `cicd-verify-b5799fc.md`)_

View File

@ -55,3 +55,8 @@
## Run #419 `a52a91e` (2026-07-28) — moved from L1 @S159 curate, byte-exact
- **07-28 verify `a52a91e` (PE: cảnh báo amber ô Địa điểm khi dự án thiếu Location) [S157, FE-ONLY 2-app, CLEAN-return]:** VERDICT **PASS 9/9** — Run **#419** (id=532) success **5m40s** (09:40:18→09:45:58+07); gate **562 EXACT từ log** (45 Domain + **517** Infra, 0 fail/skip) — khớp canonical `docs/STATUS.md:452` **cả TỔNG lẫn TÁCH 45/517** (khớp thành-phần > khớp tổng). NO-Mig đúng kỳ vọng: `git diff f4494cf..a52a91e -- 'src/Backend/*' '*Migrations*' | wc -l` = **0** ⇒ Mig vẫn 68, 89-table, KHÔNG query DB (không có gì để đối chiếu). 🔑 **Phép quyết định = byte-marker #77, KHÔNG tin status CI:** tải thẳng JS prod, `bytes.count(marker.encode())` 4 chuỗi VN độc lập → **2/2 app, count=2 mỗi app = KHỚP SỐ FILE/app trong diff** (`PeHeaderForm`+`PeWorkspaceCreateView`) — "đúng-BỘI-SỐ" mạnh hơn "tìm thấy ≥1", bắt được cả ca ship nửa-vời. Bundle js rotate CẢ 2 (admin `BK8w3QxU`→**`8-QYcMOg`** · eoffice `DYnxSI0T`→**`DptYR4wL`**; css `DiNJjaoo`/`BRCvEHvC` FROZEN ×2 = #69-REFINE lành tính — utility `text-amber-700`/`text-[11px]` đã có sẵn) real-size 1.675.282/1.575.513B, LM 09:44:33/09:45:30+07 in-window. 🆕 **Control âm 2 TẦNG (tái dụng):** (i) fake-hash→200 nhưng `ct=text/html` 900/876B marker=0; (ii) **hash CŨ cũng rơi về text/html ⇒ bundle cũ BIẾN MẤT khỏi đĩa** = chứng GHI-ĐÈ thật (mạnh hơn hash-delta đơn thuần). Smoke: health live+ready 200 · login 200 tok-468 · `/api/projects` 200 (đúng nguồn `location` feature đọc) · PE/menus/suppliers 200. ⚠️ **Self-correct on-disk:** viết "range=6 file" SAI (đó là số của 2 commit) — range thật **13 commit/26 file** (11 `wal:` xen giữa); đính chính ngay, BE=0 không đổi. Tag `[run-419, pass-9-9, fe-only, marker-2of2-count-exact, old-hash-gone-control, js-rotate-css-frozen, gate-562]`
## Run #423 `1a47a61` (2026-07-29, S159 đợt-2) — moved from L1 @S159 curate, byte-exact
- **07-29 verify `1a47a61` ĐỢT-2 (tab strip 4 GĐ trên phiếu PE + menu 4-GĐ + đánh số 01-07 nhóm HĐ) [S159, 8 file code 190+/18, FE×2 + seeder-only BE]:** **PARTIAL 8/9** — Run **#423** (id=536) success **5m44s**; gate **562 EXACT** (45+517). 0 migration (BE chỉ `MenuKeys.cs` const + `DbInitializer.cs` seeder). Bundle rotate **4/4** (admin js `BHodkPNV``D6Pz7nfV` css `DiNJjaoo``B1ErASuI` — admin-css rotate ĐÚNG vì fe-admin có sửa, khác đợt-1 frozen; user js `0GO8mgrG``Bpb8WEuY` css `BARVqkP-``7oAYFlzM`). Mirror `PePipelineStrip.tsx` 2 app **md5 IDENTICAL** `ef7b7824…`. 🔑 **Quy luật đếm marker (nối tiếp bài comment-strip): bundle-count = SỐ MODULE chứa chuỗi** (bundler pool hằng-số trong 1 module ⇒ nhiều occurrence cùng file gộp còn 1). USER=2 module→2 · ADMIN=1 module→1, đúng **6/6** (3 marker × 2 app) = 'đúng-BỘI-SỐ'. 2 control ÂM (`Đề xuất ký kết hợp đồng`, `Ký cứng & phát hành`) =0 cả 2 bundle + grep repo-wide 0-hit. Menu-data 5/5: **root=12 (0 double-insert) · DUPKEYS=0** · 2 root mới `KeHoachKyKet` ord26 / `HopDongCung` ord32 vis=1 (13 rows/13 canread mỗi key) · 3 root vẫn vis=0 · rename prefix `Duy…` ×2 · `Pe%` 197/185. 🔴 **FAIL #9 — BẮT ĐƯỢC REGRESSION NGOÀI CHECKLIST:** Serilog `Revoked 9 permission rows … Hợp đồng/Danh mục khỏi non-Admin` ⇒ đo lại grant-38-key của đợt-1: **47/494 canread, 0 key còn 13** (Admin=38 · Procurement=9 · 11 role còn lại=0, mất 447). Gốc = `DbInitializer.cs:2203-2236` **`RevokeTemporarilyHiddenModulesAsync` UNGATED chạy MỖI startup**, tập revoke TRÙNG KHỚP grant-set ⇒ **grant SQL tay không bao giờ bền, phải sửa CODE**. ⚠️⚠️ **BÀI HỌC LỚN NHẤT — bẫy ĐO-TRƯỚC-RECYCLE: pool restart nằm ở CUỐI deploy-window, nên đo DB lúc run còn `running` = đo trạng thái CŨ, KHÔNG chứng minh được 'sống sót recycle'. Mọi mục durability PHẢI đo SAU `status=success`.** (đợt-1 tao đo 11:46 vs restart 11:49 → kết luận sai). ⚠️ deploy `Remove-Item …pi\*` **xoá luôn `logs/`** ⇒ Serilog chỉ còn từ lần deploy cuối, không truy ngược được restart trước. ⚠️ prod Identity table = **`Roles`** không `AspNetRoles` (#472 tái xác nhận). Đợt-2 tự nó ship ĐÚNG — KHÔNG rollback. Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-1a47a61.md`. Tag `[run-423, partial-8-9, do-truoc-recycle-trap, revoker-ungated-durability, marker-count-per-module, gate-562]`

View File

@ -140,4 +140,5 @@
- 2026-07-17 · S134 #399 `6664a61` PE lũy-kế tạm-tính (0-mig) GO — js+css rotate… · PASS · `2026-07.md` · substring:"S134 (07-17) verify 6664a61"
- 2026-07-23 · S155 #407 `4510cea` App chuan-hoa ma du-an normalize + PE attach-gate FE both-apps… · PASS 5/5 · `2026-07.md` · substring:"Run #407 `4510cea` (2026-07-23)"
- 2026-07-27 · S155 #416 `b1bae77` Workflow duyet-TAI-CHO + co F6 AllowApproverDelete… · PASS · `2026-07.md` · substring:"Run #416 `b1bae77` (2026-07-27)"
- 2026-07-28 · S157 #419 `a52a91e` PE canh-bao amber o Dia-diem khi du-an thieu Location… · PASS 9/9 · `2026-07.md` · substring:"Run #419 `a52a91e` (2026-07-28)"
- 2026-07-28 · S157 #419 `a52a91e` PE canh-bao amber o Dia-diem khi du-an thieu Location… · PASS 9/9 · `2026-07.md` · substring:"Run #419 `a52a91e` (2026-07-28)"
- 2026-07-29 · S159 #423 `1a47a61` dot-2 tab strip 4GD + menu 4-GD — PARTIAL 8/9, bat regression revoker an 447/494 row · `2026-07.md` · substring:"Run #423 `1a47a61` (2026-07-29"

View File

@ -1,5 +1,7 @@
# Reviewer Agent — Persistent Memory
- **S159 (07-29) đợt-5 menu 6-leaf HĐ + endpoint `/contracts/deleted` (PWF 10 FLAG 0H/4M/6L):** 🔴 **con-số TRONG CHÚ THÍCH cũng là khẳng-định đo-được** — diff SỬA comment D3 thành "NAY CÓ 2 chỗ `IgnoreQueryFilters`", `grep -rn` ra **3 file/17 site** (ApprovalWorkflowV2AdminFeatures 15 site); tôi suýt duyệt bằng mắt ⇒ **luật: comment mang số ⇒ chạy phép đếm, và số viết dưới dạng LUẬT ("chỗ duy nhất ⇒ CẤM…") sai thì lan sang người sửa sau**. · class **`mirror-nửa-vời khai thừa phạm-vi`**: comment nói "Hộp thư + Tổng quan viết HOA" nhưng "Hộp thư" render bằng `StaticLeaf` KHÁC component ⇒ đọc comment ≠ đọc call-site. · **cookie-cutter phải soi CẢ phần PE đã CHẶN**: bản HĐ copy list-deleted nhưng bỏ `disabled={deletedView}` ⇒ click row → detail 404 → panel **trắng** (page thiếu nhánh `isError`) + mobile navigate ra trang 404. · mirror 2-app: fe-admin ẩn `Ct_*` (⇒ 21 leaf mới KHÔNG cần route) nhưng `Khkk_*` KHÔNG ẩn ⇒ thiếu 2 staticMap = drop silent #50**kiểm hide-filter TRƯỚC khi kêu thiếu mirror**. · `tsc -p tsconfig.app.json` EXIT=0 + `noUnusedLocals` = chứng cắt-hero-không-mồ-côi MẠNH HƠN grep (nhắc lại: fe-user KHÔNG bật `strict`). · `Contracts``MenuKeys.All` ⇒ policy `Contracts.Read` có thật; `MenuPermissionHandler` khớp ĐÚNG-KHOÁ, KHÔNG kế thừa root (#82). [→ `runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot5.md`]
- **S159 (07-29) dashboard "toàn trình" đợt-4 FE-only (fe-user 984+/337, PWF 7 FLAG 0H/2M/5L):** 🔴 **`tsc` XANH đo ÍT hơn vẻ ngoài** — `fe-user/tsconfig*.json` KHÔNG có `strict`/`strictNullChecks` (chỉ `noUnusedLocals`) ⇒ **tra cờ tsconfig TRƯỚC khi trích tsc làm bằng chứng**; ngược lại `noUnusedLocals`+pass = bằng chứng MẠNH HƠN grep cho claim "đã gỡ khối X" (compiler chặn nếu sót import). · class **`nhãn khẳng định chiều-ngược`**: dot-map `none='chưa tới'` — không-suy-diễn "đã xong" là đúng, nhưng "chưa tới" CŨNG là khẳng định ⇒ sai cho GĐ ĐỨNG TRƯỚC + sai khi `contractId != null` **có sẵn trong payload**. · pager tính `data.page±1` (keepPreviousData ⇒ stale) thay vì state ⇒ double-click = no-op. · **verify đích điều hướng phải đọc CẢ breakpoint trang đích** (panel `hidden lg:block` ⇒ ngõ cụt mobile; trang đích tự có nhánh `matchMedia` mà caller mới không copy). · regression đo HEAD⟂work bằng `grep -c` từng token: count 5→2 mà KHÔNG mất nhãn (inline-prop → `STAGES[i].title`) ⇒ **đếm lệch phải truy CẤU TRÚC trước khi kêu hồi quy**. · tự tính lại 4 tỉ-số contrast + tra `@theme` mọi `var(--color-*)` (0 dòng `--color-*: initial` ⇒ nấc mặc định còn) — 3/3 số designer ĐÚNG. · lời khai sub-file "766→1.130 dòng" SAI (đĩa 1.413 = 766337+984). [→ `runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot4.md` 28,5KB]
- **[→ archive/2026-07.md @S159-curate] S155-đợt2 (07-27) PE delete-approver DIFF-review #2 (12 FLAG 2H/4M/6L · ĐỪNG-DEPLOY):** class **`hợp-đồng-đứt-giữa-2-bờ`** (FE type khai cờ, BE DTO không có ⇒ nút chết mà tsc+build+561-test đều xanh) · policy-gate đo DB 11/13 vai `CanDelete=0` · mã ĐỔI giữa lượt soi ⇒ re-đo đĩa TRƯỚC verdict · đổi-chiều-assert ≠ nới-assert.
- **[→ archive/2026-07.md @S155-curate] S155 ×2 (07-27) PE delete-approver — DIFF-review đợt 1 tiền-deploy (14 FLAG 4H/6M/3L/1I, DEPLOY-CÓ-RỦI-RO) + SPEC-review (PWF 4H/8M/5L):** 🔴 class MỚI **`HIGH nằm ở git chứ không ở mã`** — 2/3 file migration UNTRACKED mà snapshot ĐÃ tracked ⇒ `commit -a` nạp model-có-cột nhưng bỏ migration ⇒ `Invalid column name` cả 7 module, build+test vẫn xanh ⇒ **gate deploy phải chấm `git status ^??` cho `Migrations/`** · `ExecuteDelete` ngoài transaction TRƯỚC `SaveChanges` = mất dữ liệu không hoàn tác · purge xoá CỨNG chữ ký phiếu XOÁ MỀM ⇒ **test đang KHOÁ chiều ngược, vá xong test đỏ ≠ hồi quy, CẤM nới assert** · ~600 dòng BE = mã chết (`grep api.put`=0) · **xanh-giả bắt bằng phép 2-thế-giới** (còn-gate ⟂ bỏ-gate cùng cho 0 ⇒ 0 thông tin) · CLEAN chứng bằng **liệt kê vét cạn** write-site + sweep gián-tiếp (#81-EXT) · 2 lỗi TỰ BẮT: trích line-number **từ diff** (diff không mang số dòng file) · `grep -v Snapshot` ăn nhầm tên migration · **file bị sửa TRONG LÚC soi ⇒ neo bằng NỘI DUNG DÒNG + ghi bản-đồ-trôi**.