wal: flush 20260729T1425

This commit is contained in:
pqhuy1987
2026-07-29 14:25:17 +07:00
parent 0ac6e361f8
commit ceeebf3c3b
4 changed files with 236 additions and 19 deletions

View File

@ -1,26 +1,23 @@
# WAL — auto-generated, không sửa tay
updated: 2026-07-29 | session: S159 (phiên-LOGIC L8, window 1) | branch: main
goal: arc-2 MỞ LẠI ĐỢT-4 (anh khoanh đỏ khối dưới hero): BỎ 5 KPI + 2 list "gần đây" → danh sách phiếu CHI TIẾT (tab 4-GĐ mang count + bảng full-width + cột Hành-trình 4-chấm per-row + phân trang thật) — designer đang chạy nền; pipeline sau đó: build → reviewer (>50 LOC) → commit → cicd. Đợt 1-3 ĐÃ ĐÓNG restart-proof (giữ nguyên khối chain dưới).
goal: arc-2 UI toàn-trình — đợt 1-4 SHIPPED (4 commit, cicd 3×PASS + 1 FAIL-bắt-revoker); đợt-5 CODE XONG chờ reviewer → commit → push → cicd → /pause (LỆNH ANH: "xong thì /pause")
chain:
- [x] bookend @open 5 vòng + (49)-(53) — run `2026-07-29-S159-bookend-open`
- [x] arc-2 ĐÓNG — run `2026-07-29-S159-tong-quan-pipeline-menu`:
Đ1 `b5799fc` Tổng quan pipeline (PASS 9/9) · Đ2 `1a47a61` tab strip + menu 4-GĐ + 01-07 (8/8 sạch, mục-9 lộ REVOKER)
· Đ3 `2a72695` gỡ nhánh S92 + skeleton GĐ2/GĐ4 + ComingSoonPage ×2 + 3 test spec-change (PASS 9/9, **restart-proof 494/494 + control âm 3 chân kiềng**)
- [x] sự cố revoker xử trọn: regrant=447 tức thì + code-fix + REGRESSION-GUARD test + verify-by-restart-THẬT (khuôn S91)
- [x] dọn dư-lượng ×3 lần trong phiên (stray 0 · empty 0 · agent-memory 23 nguyên)
- [ ] CLOSEOUT còn nợ (làm ở /session-end hoặc lượt kế):
· HANDOFF: chép verbatim ❹-risk (owner chấp nhận mở HĐ khi authz trần) + sự cố revoker + bộ tên 4-GĐ chốt cuối (Kế hoạch ký kết HĐ — supersede nhãn ❶) + baseline bundle mới
· STATUS CURRENT: bổ sung arc-2 (3 commit + revoker + skeleton) + row bundle baseline `CC1pGE1F`/`DWDbm5As`/`DeAg7MWm`/`BQIZ-rUe`
· gotchas.md: +#84 candidate "owner-supersede-owner: revoker ungated thi hành quyết cũ lật data-change tay — audit seeder CẢ HAI CHIỀU (re-add ⟂ revoke) trước mọi grant/hide SQL; nghiệm thu = restart THẬT + control âm"
· spec KHKK: ghi chú Wave-1 phải TÁI DÙNG/thay root `KeHoachKyKet` + skeleton keys Khkk_*
· session-log S159 + seed diary cicd-monitor đã tự ghi (nó khai), verify lúc closeout
· mind: chèn MIND-2 @close (mục E bổ sung 5 lượt arc-2: designer/reviewer/cicd×3-lượt + 2 resume)
- [x] Đ1 `b5799fc` Tổng quan pipeline — PASS 9/9 · Đ2 `1a47a61` tab strip + menu 4GĐ + 01-07 — 8/8 + mục-9 lộ REVOKER · Đ3 `2a72695` gỡ nhánh S92 + skeleton — PASS 9/9 restart-proof · Đ4 `a2bbcb9` list chi tiết + 7 FLAG + "Bảng cứng" — PASS 9/9 (durability ×2 restart)
- [x] Đ5 CODE XONG (build fe-user ✓521ms · test 45+517=562 ✓ · grep mồ-côi 0):
· BE: `ListDeletedContractsQuery` (ContractFeatures, chỗ-thứ-2 IgnoreQueryFilters + Where(IsDeleted) + IDOR mirror :297-302) + GET `/contracts/deleted` policy Contracts.Read + D3 note PE cập nhật
· Seeder: Ct ×7 nhóm +3 leaf (WfView/Approved/Deleted) + "Đang duyệt" backfill + Khkk 6 leaf + Dashboard→"Tổng quan quy trình" + reviewKeys +23
· FE fe-user: matrix +type=3 (HĐ chung 1 bộ V2) + route alias `/contracts/workflow-matrix` + Ct regex +3 action + staticMap Khkk ×2 + MyContractsPage (phase/deleted + banner + ẩn Tạo) + MenuLeaf depth-0 UPPERCASE + UserDashboardPage BỎ HERO + title "Tổng quan quy trình"
· fe-admin: leaf mới drop-silent CỐ Ý (tiền lệ WfView-PE)
- [!] reviewer đợt-5 ĐANG CHẠY (`sub-reviewer-diff-dot5.md`) — 6 trục, nặng nhất: endpoint vs khuôn PE + detail HĐ-đã-xóa 404? (trục 4)
- [ ] SAU verdict: xử FLAG → commit `[CLAUDE] Contract+FE-User: dot-5 ...` → push → message cicd verify (chạy NỀN, kết quả đọc phiên sau) → /pause
next: /session-end (đóng L8 window 1) — hoặc anh giao tiếp việc mới thì closeout dồn cuối phiên
next: (phiên sau /tiep) đọc verdict cicd đợt-5 (`cicd-verify-<sha>.md`) + closeout sổ bền (HANDOFF: ❹-risk verbatim + revoker + 4 đợt + tên-4-GĐ chốt cuối "Kế hoạch ký kết HĐ"(GĐ2)/"Duyệt hợp đồng"/"Hợp đồng cứng" + "Tổng quan quy trình"; STATUS CURRENT arc-2; gotchas +#84 revoker-2-chiều; spec KHKK note W1 tái dùng root/skeleton Khkk_*; session-log; MIND-2 @close)
verify:
- prod state chốt: 38-key 13/13 · Khkk 5 · Hdc 7 · root 12 · 3 root ẩn · Pe% 197/185 · nhãn 01-07 ×2 nhóm (Ct_+Hdc_ =14, đúng thiết kế)
- ⚠️ seeder grant = skip-existing KHÔNG nâng row false — prod rơi false thì re-grant TAY
- 🔴 lỗi lead phiên này để RCA closeout: grant SQL không audit revoker (bài S91 áp thiếu 1 chiều) — guard đã dựng bằng test
- prod hiện hành: menu 4-GĐ + 01-07 "- Bảng cứng" + 38-key 13/13 (bền ×2 restart) · bundle user `CLfAftby`/`B6bUSFBt` admin `CC1pGE1F`/`DWDbm5As`
- Đ5 CHƯA push — mọi thứ Đ5 mới ở local (kể cả seeder; menu leaf mới CHƯA có trên prod — deploy Đ5 seeder tự insert)
- 🔴 3 bài máy phiên này: cut-code = LINE-SCAN so CẢ DÒNG (bracket-count vỡ vì destructure/string; substring ' })' khớp sớm) · python heredoc bash vỡ → Write file script + PowerShell · script chết trước save = file NGUYÊN (đọc "cut X" in ra ≠ đã ghi đĩa)
- 🔴 diagnostics IDE stale ×3 lần hôm nay — chỉ tin build sạch chạy SAU (#68); grep 0-hit đối chứng

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-3 ⇒ file **ĐÃ 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 `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 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]`
- **07-29 verify `b5799fc` ĐỢT-1 (FE-User: Tổng quan tất cả luồng duyệt) [S159 L8]:** PASS 9/9 — Run **#422** success 5m59s, gate **562** (45+517), 0 mig, user js `DptYR4wL``0GO8mgrG`. 🔑 **marker PHÂN-BIỆT-PHIÊN-BẢN** (mạnh hơn marker-hiện-diện): designer gốc ghi `Pipeline 4 giai đoạn`, bản sau review-fix ghi `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 comment-strip**: `grep -c` source ra 2 mà bundle=1 — occurrence dư ở COMMENT đầu file (minifier strip) ⇒ so bundle với occurrence-CODE. ⚠️ **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 của lượt này SAI**: đo 11:46 tức TRƯỚC pool-restart ~11:49 ⇒ không chứng minh được durability; phần 38-key sau đó mất thật (đợt-2 bắt) → đóng ở đợt-3. Evidence: `runs/2026-07-29-S159-…/cicd-verify-b5799fc.md`. Tag `[run-422, marker-phan-biet-phien-ban, comment-strip-trap, query-shape-not-drift]`
- _(**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`)_
- _(**S157 #419 `a52a91e` PE cảnh-báo amber ô Địa-điểm (FE 2-app) GO 9/9** — gate 562 [45+517, khớp canonical STATUS cả tách-phần]; NO-Mig; 🔑 byte-marker **count=2/app = khớp SỐ FILE trong diff** ["đúng-BỘI-SỐ" > "tìm thấy ≥1"]; js-rotate ×2 css-FROZEN ×2; control âm 2 tầng [fake-hash + **hash CŨ** đều `ct=text/html` ⇒ bundle cũ biến mất = chứng ghi-đè]; self-correct on-disk "6 file"→13 commit/26 file · verbatim → `archive/2026-07.md` @S159-curate)_
- _(**#416 S155 `b1bae77` Workflow duyệt-TẠI-CHỖ +Mig 68 APPLIED-PROD 6/6** [gate 551; FLAG 'mig rớt khỏi commit' loại-trừ 3 lớp — mạnh nhất `GET /approval-workflows-v2` trả cột ×54 **materialize qua EF từ DB thật**] · **#407 S135 `4510cea` mã-dự-án normalize 5/5** [gate 532] · **#399 S134 `6664a61` PE lũy-kế 0-mig 5/5** [gate 528; 🔑 `ct=text/html` discriminator SẠCH HƠN size-919B vì shell-size drift] · **#398 S133 `d4fbced` +Mig 67 budget-freeze 5/5** [gate 520; backfill 18/18; python text=True crash cp1252 → dùng bytes] · verbatim → `archive/2026-07.md` via `_INDEX`)_
@ -35,7 +37,7 @@ cicd-lane đôi khi trả nhầm slice transcript (memory-curation) thay verdict
- **#25 IIS WebSocket** `notification-hub/negotiate` 401/404 prod. Fix: WebSocket module enable `web.config` site api (skill `iis-deploy-runbook`).
- **#48 SQLite tie-break** `OrderByDescending(CreatedAt).First()` pick wrong khi 2+ `.Add()` cùng frozen-clock. Fix: discriminator filter BEFORE OrderBy.
- **Bundle hash unchanged = ship FAIL** push+action success nhưng prod không đổi. Verify via INDEX.HTML ref (`curl -s https://admin.solutions.com.vn/ | grep -oE '/assets/index-[A-Za-z0-9_-]+\.(js|css)'`), NOT by GETting a hash-named asset directly. verify MUST sau status=success (Run #242 false-positive: check khi "running" stale hash).
- **🔴 #69 TWO-MODE (S72 #312 + S83 #333) FE hash vừa thể ROTATE vừa thể FROZEN.** deploy.yml copy `dist\*` UNCONDITIONALLY mọi run (path-filter gate cả workflow, không per-step) 0-FE-change vẫn rotate được (mode-A); ngược lại src y hệt Vite ra byte-identical hash FROZEN (mode-B). **Cả hai lành tính ⟹ hash-delta KHÔNG phải ship-proof.** Ship-proof THẬT = `Last-Modified` in deploy-window + real-size + byte-marker. Muốn biết FE đổi thật diff `fe-*/src` trong range.
- **🔴 #69 TWO-MODE (S72 #312 + S83 #333) FE hash vừa thể ROTATE vừa thể FROZEN.** deploy.yml copy `dist\*` UNCONDITIONALLY mọi run (path-filter gate cả workflow, không per-step) 0-FE-change vẫn rotate được (mode-A); ngược lại src y hệt Vite ra byte-identical hash FROZEN (mode-B). **Cả hai lành tính ⟹ hash-delta KHÔNG phải ship-proof.** Ship-proof THẬT = `Last-Modified` in deploy-window + real-size + byte-marker. Muốn biết FE đổi thật diff `fe-*/src` trong range. 🔑 **Phân biệt FROZEN-lành-tính vs bundle-cũ-kẹt: xem `Last-Modified`** frozen + LM **trong** cửa-sổ deploy = re-ship byte-identical (OK); frozen + LM **cũ** = deploy không chạm file (cờ đỏ). S159 #425 admin frozen, LM in-window lành tính.
- **⚠ SPA-fallback 200 trap (S72):** server rewrite `/*``index.html` GET `/assets/index-<BỊA>.js` vẫn **200**. Discriminator sạch = **`Content-Type`** (`text/html` ~876-919B = trap · `application/javascript` ~1,6MB = thật); size drift per-build nên đừng neo số byte. **Hash CŨ rơi về text/html = bundle cũ biến mất khỏi đĩa = chứng ghi-đè (control âm tầng-2).**
- **🔴 Durability: đo SAU recycle + 3 CHÂN KIỀNG** pool restart CUỐI deploy-window query DB lúc `running` = trạng thái (S159 đợt-2 tao sai đúng chỗ này). Khuôn đúng: (i) **chứng minh restart thật** (`w3wp` StartTime in-window + dòng ĐẦU log `Applying migrations...` hợp lệ deploy xoá `logs/`), (ii) đo chỉ-số đích SAU mốc đó, (iii) **control ÂM chứng minh checker còn sống** (thiếu (iii) thì 'fix' kiểu xoá checker cũng xanh). Ca gốc: `RevokeTemporarilyHiddenModulesAsync` ungated lật 447/494 row grant SQL tay (#423) đợt-3 #424 gỡ nhánh S92 + guard test 2 vế 494/494 sống sót. Data-change ngoài CI luôn phải re-verify SAU status=success.
- **Migration drift prod vs repo** compare `ls .../Persistence/Migrations/*.cs` vs `sqlcmd __EFMigrationsHistory`. Fix: check `Program.cs`/DbInitializer `app.MigrateDatabase()` + app pool recycle. Mig-applied proof = `__EFMigrationsHistory` top==repo-HEAD; stuck-old pool didn't recycle FAIL even if status=success+bundle-rotated.

View File

@ -0,0 +1,190 @@
# cicd-verify `a2bbcb9` — S159 ĐỢT-4 "danh sách toàn trình: 7 FLAG reviewer fix + nhãn 'Bảng cứng'"
> Ghi-TỪNG-MỤC-trong-lúc-làm (chống #53). File = SẢN PHẨM CHÍNH; return chỉ tóm tắt.
> Đợt-1 `b5799fc` PASS 9/9 · đợt-2 `1a47a61` PARTIAL 8/9 · đợt-3 `2a72695` PASS 9/9 — 3 file cũ KHÔNG chạm.
> Bắt đầu: 2026-07-29 ~13:52+07 · cicd-monitor (READ-only)
---
## M1 — Push + phạm vi · ✅ PASS
```
git log -1 → a2bbcb91c37de3d79a61809fd903d918e7d9f105
[CLAUDE] FE-User: dot-4 danh sach toan trinh - 7 FLAG reviewer fix
+ nhan 'Bang cung' (owner ve) · 2026-07-29 13:51:07 +0700
git log origin/main..HEAD → EMPTY (đã push)
```
Range `2a72695..a2bbcb9` = 9 file; **2 file CODE** (7 file còn lại `.claude/**`, ignored):
| File code | +/ | ghi chú |
|---|---|---|
| `fe-user/src/pages/UserDashboardPage.tsx` | **+1043 / 337** | redesign list toàn trình + 7 FLAG fix |
| `src/Backend/…/Persistence/DbInitializer.cs` | **+9 / 1** | **label-only** |
⚠️ Tự-đính-chính nhẹ so với brief: brief ghi "1050+/338", số thật `--numstat` = **1043/337**.
Không đổi bản chất (FE-user 1 file + BE label-only).
**`fe-admin` KHÔNG có file nào trong diff** ⇒ admin bundle có thể rotate HOẶC frozen — cả hai
đều lành tính (#69 TWO-MODE). Sẽ **ĐO rồi mới nói**, không phán trước.
**DbInitializer đúng là label-only** (đọc diff):
```csharp
- tree.Add(("Hdc_" + code, label, MenuKeys.HopDongCung, hdcOrder++, "FileText"));
+ tree.Add(("Hdc_" + code, label + " - Bảng cứng", MenuKeys.HopDongCung, hdcOrder++, "FileText"));
+ ["Hdc_ThauPhu"] = "01. HĐ Thầu phụ - Bảng cứng", ×7 (labelBackfill)
```
Không đụng revoker / reviewKeys / grant ⇒ **không có rủi ro mới cho durability**, nhưng vẫn sẽ đo lại (M6).
## M2 — Migration VẮNG là ĐÚNG · ✅ PASS
```
git diff --name-only 2a72695..a2bbcb9 -- '*Migrations*' → 0
```
Mig giữ **68** / 89 bảng.
## 📌 BASELINE TRƯỚC RESTART (đo 13:52+07, run #425 đang `running`, pool CHƯA recycle)
| Phép đo | TRƯỚC restart |
|---|---|
| 38-key set | **min=13 max=13 keys=38** |
| Skeleton `Khkk_`+`Hdc_` permission rows | **156** |
| `Hdc_*` MenuItems có hậu tố (`Label LIKE '%-%'`) | **7** (prod đã SQL cùng ngày) |
Bundle trước deploy: admin js `CC1pGE1F` css `DWDbm5As` · user js `DeAg7MWm` css `BQIZ-rUe`
— khớp CHÍNH XÁC baseline hậu-đợt-3 ⇒ baseline hợp lệ.
## 🔎 M3-pre — Marker kỳ vọng, đếm trên SOURCE (chốt trước khi soi bundle)
`UserDashboardPage.tsx` (63.124 B):
| Chuỗi | source | vai trò | dự đoán bundle |
|---|---|---|---|
| `chưa có thông tin ở giai đoạn này` | 1 | dương | 1 |
| `đã sinh hợp đồng` | 1 | dương | 1 |
| `Không tìm thấy` | 3 | dương | ≥1 |
| `HĐ ĐANG SOẠN` | **0** | ÂM (KPI cũ bỏ) | 0 |
| `Tổng giá trị nháp` | **0** | ÂM (KPI cũ bỏ) | 0 |
| `chưa tới` | **2** ⚠️ | ÂM (DOT_TEXT cũ đã thay) | **0** |
⚠️ **BẪY ĐÃ GỠ TRƯỚC (nếu không soi sẽ báo FAIL oan):** `chưa tới` grep ra **2** trên source,
nhưng cả 2 đều nằm trong **COMMENT** giải thích lý do FLAG-2:
```
L343: // [FLAG-2 reviewer đợt-4] 'chưa tới' là lời KHẲNG ĐỊNH sai với chấm PHÍA TRƯỚC
L344: // giai đoạn hiện tại (HĐ ở GĐ3 thì GĐ1/GĐ2 là quá khứ, không phải "chưa tới").
L345: none: 'chưa có thông tin ở giai đoạn này', ← chuỗi THAY THẾ (code thật)
```
⇒ occurrence-**CODE** = **0**; minifier strip comment ⇒ bundle phải = **0**.
(Đúng mẫu comment-strip đã học ở đợt-1 — so bundle với occurrence-CODE, không với grep-source thô.)
## M4 — Poll terminal · ✅ PASS
- **id=538 · run_number=425 · head_sha `a2bbcb91`** · created 13:51:15 → **`status=success` 13:56:55**
- **Duration 5m40s** (đợt-1 5m59s · đợt-2 5m44s · đợt-3 5m56s) — ổn định, dưới ngưỡng.
### M4b — Test gate · ✅ 562 EXACT
```
Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, 159 ms - SolutionErp.Domain.Tests.dll
Passed! - Failed: 0, Passed: 517, Skipped: 0, Total: 517, 1m27s - SolutionErp.Infrastructure.Tests.dll
```
`Failed!` ×0 ⇒ **562**. Giữ nguyên — đúng kỳ vọng (FE + label BE, không đụng test).
Regression-guard đợt-3 (`StillHiddenKeys` / `ReopenedKeys`) nằm trong 517 này và **vẫn xanh**.
## M5 — Bundle · ✅ PASS (đo 13:57:23, sau status=success)
| App | asset | TRƯỚC | SAU | KQ |
|---|---|---|---|---|
| **user** | js | `DeAg7MWm` | **`CLfAftby`** | ✅ **ROTATE** (điều kiện bắt buộc) |
| **user** | css | `BQIZ-rUe` | **`B6bUSFBt`** | ✅ ROTATE |
| admin | js | `CC1pGE1F` | `CC1pGE1F` | **FROZEN** — lành tính, xem dưới |
| admin | css | `DWDbm5As` | `DWDbm5As` | **FROZEN** — lành tính |
🔑 **Admin FROZEN = #69 mode-B, KHÔNG phải deploy hỏng — và tao chứng minh được, không đoán:**
```
ADMIN index-CC1pGE1F.js ct=application/javascript size=1.678.733 LM=13:55:31+07
```
`Last-Modified` **13:55:31 nằm TRONG cửa sổ deploy** (13:51:15→13:56:55) ⇒ file **ĐÃ được ghi lại**
trong lần deploy này (deploy copy `dist\*` vô điều kiện), chỉ là Vite dựng ra **byte y hệt**
`fe-admin` 0-file-thay-đổi ⇒ content-hash không đổi. Size trùng khít đợt-3 (1.678.733).
⇒ Đây là "re-ship nội dung giống hệt", **không phải** "bundle cũ kẹt lại". Brief dặn "ghi nhận,
không phán sai" — kết luận: **lành tính, nhất quán với diff**.
```
USER index-CLfAftby.js ct=application/javascript size=1.601.698 LM=13:56:28+07 (in-window)
```
Control âm 2 tầng: hash CŨ `DeAg7MWm` **và** hash bịa đều trả 200 nhưng `ct=text/html` 876 B
⇒ bundle đợt-3 đã biến mất khỏi đĩa = chứng ghi-đè thật.
## M3 — Byte-marker bundle USER · ✅ PASS (3 dương / 3 âm)
| Chuỗi | bundle | kỳ vọng | KQ |
|---|---|---|---|
| `chưa có thông tin ở giai đoạn này` | **1** | dương | ✅ |
| `đã sinh hợp đồng` | **1** | dương | ✅ |
| `Không tìm thấy` | **10** | dương | ✅ |
| `chưa tới` | **0** | **ÂM** | ✅ |
| `HĐ ĐANG SOẠN` | **0** | **ÂM** | ✅ |
| `Tổng giá trị nháp` | **0** | **ÂM** | ✅ |
🔑 **Dự đoán comment-strip ĐÚNG:** source có `chưa tới` ×2 (đều trong comment L343-344), bundle ra
**0** — xác nhận lại quy tắc "so bundle với occurrence-CODE, không với grep-source thô".
Nếu đọc grep-source thô sẽ báo FAIL oan cho một control vốn ĐÚNG.
⚠️ `Không tìm thấy` bundle=10 > source=3: chuỗi phổ thông, xuất hiện ở module khác nữa
(empty-state dùng chung). Là marker DƯƠNG nên "≥1" đủ kết luận; không dùng nó làm phép đếm-chính-xác.
## M6 — RESTART-DURABILITY lần 2 · ✅ PASS (chứng bền qua ≥2 restart)
**Bước 0 — chứng minh có restart THẬT (giữ khuôn đợt-3):**
| Bằng chứng | Giá trị |
|---|---|
| Dòng ĐẦU log `solution-erp-20260729.log` | **`13:56:39.193 +07:00 [INF] Applying migrations...`** |
| `w3wp` StartTime (mới nhất trong cửa sổ) | **13:56:33** |
Deploy xoá `logs/` ⇒ log mở lại lúc 13:56:39 = **boot mới**, DbInitializer (seeder + revoker) đã chạy.
Mọi số dưới đo SAU mốc này.
| Phép đo | TRƯỚC restart (13:52) | **SAU restart (13:57)** | KQ |
|---|---|---|---|
| **38-key set** | 13/13/38 | **min=13 max=13 keys=38 · totcr=494/494** | ✅ **GIỮ** |
| Skeleton `Khkk_`+`Hdc_` perms | 156 | **156** | ✅ |
| `Hdc_*` nhãn có hậu tố `%-%` | 7 | **7** | ✅ |
| Root menu | — | **12** | ✅ |
| 3 root ẩn `Hrm`/`Off`/`Personal` `IsVisible` | — | **0 / 0 / 0** | ✅ |
| **Control ÂM** `Hrm%`/`Off%`/`Personal` non-Admin canread | 0 | **0** | ✅ revoker CÒN SỐNG |
| Control `Pe%` | — | **197 / 185** | ✅ |
🎯 **Đây là restart thứ 2 liên tiếp sau khi gỡ nhánh S92** (#424 rồi #425). Grant 38-key giữ
**494/494** cả hai lần ⇒ không phải "may một lần". Control âm vẫn 0 ⇒ fix không phải do
vô hiệu hoá cả revoker (chống Goodhart, giữ đủ 3 chân kiềng của đợt-3).
## M7 — Smoke · ✅ PASS 4/4
```
/health/live 200 Healthy · /health/ready 200 Healthy · admin 200 · eoffice 200
```
---
## VERDICT: **PASS — 9/9**
| # | Mục | KQ |
|---|---|---|
| 1 | Push + range 2 file code (1043/337 + 9/1 label-only) | ✅ |
| 2 | Migration VẮNG là ĐÚNG | ✅ |
| 3 | Run #425 success 5m40s | ✅ |
| 4 | Test gate **562** (45+517, 0 fail) | ✅ |
| 5 | Bundle **user rotate** `DeAg7MWm``CLfAftby` (+css) | ✅ |
| 6 | Admin FROZEN — chứng minh lành tính bằng **LM in-window + size trùng** (#69 mode-B) | ✅ |
| 7 | 3 marker DƯƠNG trong bundle user | ✅ |
| 8 | 3 control ÂM VẮNG (`chưa tới` / `HĐ ĐANG SOẠN` / `Tổng giá trị nháp`) + hash-cũ `text/html` | ✅ |
| 9 | **Durability lần 2: 38-key 494/494 · skeleton 156 · Hdc nhãn 7 · root 12 · control âm 0 · Pe 197/185** | ✅ |
**Không có cờ đỏ. Không khuyến nghị rollback.**
Baseline mới: **user js `CLfAftby` / css `B6bUSFBt`** · admin **giữ** js `CC1pGE1F` / css `DWDbm5As`
(frozen hợp lệ) · gate 562 · Mig 68 / 89 bảng · menu root 12 · 38-key 13/13 · skeleton 156.
### Ghi cho arc S159 (4 đợt)
đợt-1 PASS 9/9 → đợt-2 PARTIAL 8/9 (bắt regression revoker ăn 447/494 row) → đợt-3 PASS 9/9
(đóng regression, chứng bằng 3 chân kiềng) → **đợt-4 PASS 9/9 (tái xác nhận durability qua restart thứ 2)**.
<!-- END cicd-verify-a2bbcb9 · VERDICT=PASS 9/9 -->

View File

@ -0,0 +1,28 @@
# sub-reviewer — soi đối kháng diff đợt-5 (S159 L8)
**Vật soi:** `git diff` working-tree vs HEAD (`bbc39be`), 9 file trong scope (BE 4 + FE 5).
**Chế độ:** tĩnh (không live-verify, theo lệnh lead).
**Ghi từng FLAG NGAY khi chốt (chống #53).**
---
## Bản đồ file trong scope (đo từ `git diff --stat`)
| File | +/- |
|---|---|
| `src/Backend/SolutionErp.Api/Controllers/ContractsController.cs` | +12 |
| `src/Backend/SolutionErp.Application/Contracts/ContractFeatures.cs` | +55 |
| `src/Backend/SolutionErp.Application/PurchaseEvaluations/PeSoftDeleteFeatures.cs` | +1/-1 (comment) |
| `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` | +33/-3 |
| `fe-user/src/App.tsx` | +2 |
| `fe-user/src/components/Layout.tsx` | +15/-3 |
| `fe-user/src/pages/UserDashboardPage.tsx` | +18/-339 |
| `fe-user/src/pages/contracts/MyContractsPage.tsx` | +32/-7 |
| `fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx` | +4/-1 |
Ngoài scope lead khai (KHÔNG soi, chỉ ghi nhận có mặt trong working-tree): `.claude/agent-memory/cicd-monitor/MEMORY.md`, `.claude/commands/session-{start,end}.md`, `.claude/governance/.session-counter.json`, `docs/HANDOFF.md`, `docs/STATUS.md`, `scripts/governance-detectors.ps1`, `scripts/session_ctx.py`.
---
## FLAG (ghi dần)