From ceeebf3c3bf6548f1aa4da8dad311f8293595c57 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Wed, 29 Jul 2026 14:25:17 +0700 Subject: [PATCH] wal: flush 20260729T1425 --- .claude/WAL.md | 31 ++- .claude/agent-memory/cicd-monitor/MEMORY.md | 6 +- .../cicd-verify-a2bbcb9.md | 190 ++++++++++++++++++ .../sub-reviewer-diff-dot5.md | 28 +++ 4 files changed, 236 insertions(+), 19 deletions(-) create mode 100644 .claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-a2bbcb9.md create mode 100644 .claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot5.md diff --git a/.claude/WAL.md b/.claude/WAL.md index ba168b4..34b5de6 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -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-.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 diff --git a/.claude/agent-memory/cicd-monitor/MEMORY.md b/.claude/agent-memory/cicd-monitor/MEMORY.md index f8c85ad..09267b1 100644 --- a/.claude/agent-memory/cicd-monitor/MEMORY.md +++ b/.claude/agent-memory/cicd-monitor/MEMORY.md @@ -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 có thể ROTATE vừa có 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 có đổi thật → diff `fe-*/src` trong range. + - **🔴 #69 TWO-MODE (S72 #312 + S83 #333) — FE hash vừa có thể ROTATE vừa có 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 có đổ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-.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 CŨ (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ệ vì 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. diff --git a/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-a2bbcb9.md b/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-a2bbcb9.md new file mode 100644 index 0000000..cdc72a9 --- /dev/null +++ b/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-a2bbcb9.md @@ -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** vì +`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)**. + + + diff --git a/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot5.md b/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot5.md new file mode 100644 index 0000000..36179aa --- /dev/null +++ b/.claude/workflows/runs/2026-07-29-S159-tong-quan-pipeline-menu/sub-reviewer-diff-dot5.md @@ -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) +