wal: flush 20260729T1207

This commit is contained in:
pqhuy1987
2026-07-29 12:07:47 +07:00
parent 1a47a61c21
commit b5a7dd8a92
6 changed files with 232 additions and 18 deletions

View File

@ -1,11 +1,9 @@
# CI/CD Monitor Agent — Persistent Memory
- **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]`
- **07-29 verify `b5799fc` (FE-User: Tổng quan tất cả luồng duyệt — pipeline 4 GĐ) [S159 L8, FE-USER-ONLY 1 file-code, ghi-đĩa-suốt-lượt]:** **PASS 9/9** — Run **#422** (id=535) success **5m59s** (11:43:34→11:49:33+07); gate **562 EXACT** (45 D + **517** I, `Failed!`×0 toàn log). NO-Mig đúng kỳ vọng (diff `src/Backend/*`+`*Migrations*`=0 ⇒ KHÔNG query DB; Mig 68/89-table). Range **8 commit/37 file** (7 `wal:`) — chỉ `fe-user/src/pages/UserDashboardPage.tsx` thoát 7-glob ⇒ CI fire đúng. 🔑 **KỸ THUẬT MỚI — marker PHÂN-BIỆT-PHIÊN-BẢN (mạnh hơn marker-hiện-diện):** bả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 prod có **`Toàn trình`=1 & `Pipeline`=0** ⟹ chứng prod chạy bản ĐÃ-FIX, không chỉ 'có nội dung mới'. 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ư nằm ở COMMENT đầu file (minifier strip) ⇒ so bundle với **occurrence-CODE**, đừng so grep-source thô. ⚠️ **Bẫy hình-dạng-truy-vấn (suýt hô cờ đỏ):** control `Pe` ra 182/182 vs kỳ vọng 197/185 — do tao dùng `LEFT(MenuKey,3)='Pe_'` còn gốc là `LIKE 'Pe%'` (+`Permissions`1/1+`Personal`13/1+`PeWorkflows`1/1=+15/+3). **LỆCH-số ⇒ truy PHẠM-VI-QUERY trước khi kết luận drift.** Bundle: user js `DptYR4wL`→**`0GO8mgrG`** css `BRCvEHvC``BARVqkP-` (1.584.514B, LM 11:49:05 in-window); admin js `8-QYcMOg``BHodkPNV` css `DiNJjaoo` FROZEN (#69 mode-A + REFINE). Control 2 tầng: fake-hash & **hash CŨ** đều `ct=text/html` 876B ⇒ bundle cũ biến mất = chứng ghi-đè. Smoke health live+ready 200 + 2 FE 200. **M7 menu-data (data-change NGOÀI CI, verify sống sót recycle): 3 root IsVisible=0 · 38-key grant min=max=13 · `Pe%` 197/185.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-b5799fc.md`. Tag `[run-422, pass-9-9, marker-phan-biet-phien-ban, comment-strip-trap, query-shape-not-drift, gate-562]`
- _(**S155 #416 `b1bae77` Workflow duyệt-TẠI-CHỖ + cờ F6 `AllowApproverDelete` GO 6/6** — gate 551 [45+506, khớp local 2-nguồn]; **Mig 68 `AddPeAllowApproverDelete` APPLIED-PROD** [history-top + INFORMATION_SCHEMA cùng có, 89-table]; 🔑 reviewer-FLAG F8 "mig rớt khỏi commit" loại-trừ 3 lớp — mạnh nhất = `GET /approval-workflows-v2` trả `allowApproverDelete` ×54 **materialize qua EF từ DB thật** (thiếu cột thì query đã ném) · verbatim → `archive/2026-07.md` @S157-curate)_
- _(**S135 #407 `4510cea` mã-dự-án normalize + PE attach-gate GO 5/5** gate 532 [45+487, +4 delta-proof]; NO-Mig `git diff -- *Migrations*` EMPTY + history-top unchanged; js-rotate/css-frozen ×2 · verbatim → `archive/2026-07.md` @S155-curate)_
- _(**S134 #399 `6664a61` PE lũy-kế tạm-tính (0-mig) GO 5/5** — gate 528 [45+483, +8 PePendingAccumulation]; js+css rotate ×2 admin `BVCukFP5`/`CBzUlgOA` eoffice `DoxyEOxh`/`BHsBUA8e`; byte-verify #77 urllib-BYTES; 🔑 **ct=text/html discriminator SẠCH HƠN size-919B** [shell size drift per-build]; `body.count(marker.encode())` bulletproof cp1252 · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**S133 #398 `d4fbced` PE budget-freeze + Mig 67 `AddPeApprovedBudgetSnapshot` APPLIED-PROD GO 5/5** — gate 520 [45+475]; 11-col ApprovedBudget\* + backfill 18/18 DaDuyet + 89-table; js+CSS rotate ×2 [badge utility-class → CSS content-hash đổi, benign #69]; python text=True crash cp1252 → text=False bytes+json.loads · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**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`)_
> **Persistent diary cross-session.** Auto-injected first ~200 lines at spawn (L1 HOT).
> Update BEFORE every stop. Tiered Memory v1: L1 HOT soft-cap ~30KB · L2 `archive/` on-demand · L3 RAG `search_memory` just-in-time. Keep entry ≤ 1.5K chars (gotcha #53).
@ -21,7 +19,7 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve
## ⚠️ cicd-lane return-garble tracker (#53)
cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay verdict (×5/6 qua S114; cumulative ×18 all-agents [[feedback_agent_return_garble_recover]], root-cause = curate-at-return). Recover: em-main-solo curl-verify. **S115 (#385)+S116 (#386) cicd-lane CLEAN-return no-garble ×2; S117 (#387) garble→SendMessage-resume (em-main curl cross-verify khớp, verdict disk-true) — return-mechanics garbled NHƯNG verdict-substance OK.** **S118 (#388+#389) cicd-lane garble ×2 → em-main-solo curl+sqlcmd recover (#388 durability tra.bui=20 seed-race "9 upgraded" · #389 Reports.Read→Admin-only+401), both verdict-substance disk-verified OK; curate-at-return root-cause persists (harvest-curator S118-end bắt nhãn "CLEAN-return" tự-dán sai → habitual pattern).**
cicd-lane đôi khi trả nhầm slice transcript (memory-curation) thay verdict **tao TÁI PHẠM dai nhất trong roster** (×5/6 qua S114; S117/S118 ×3 nữa; cumulative all-agents ×66-cận-dưới [[feedback_agent_return_garble_recover]]). Từng **tự dán nhãn 'CLEAN-return' SAI** (harvest-curator bắt S118) **KHÔNG tự phong return sạch** mình không quan sát được return của chính mình. 🔒 **Đối-sách đã chứng minh (S158, xác nhận lần 5): ghi-đĩa TRONG LÚC LÀM.** Prompt đúng KHÔNG chặn được garble; artifact mới chặn vai có-ép-ghi-đĩa mất **0 B**, vai không-ép mất TOÀN BỘ. Mỗi lượt: file evidence trong run-folder SẢN PHẨM CHÍNH, ghi từng mục ngay khi bằng chứng, kết bằng dòng `END … VERDICT=`; return chỉ tóm tắt. Recover khi garble: em-main re-curl + sqlcmd 2-nguồn-khớp, hoặc đọc thẳng file evidence.
---
@ -33,9 +31,8 @@ cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay
- **#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 (S72 #312) FE bundle hash NON-DETERMINISTIC per rebuild.** `deploy.yml` `Remove-Item fe-*\* -Exclude web.config`+`Copy-Item dist\*` runs UNCONDITIONALLY every run (path-filter gates whole-workflow, NOT per-step). "BE/governance frozen" can be FALSE; rotation possible every deploy. **To detect REAL FE change, diff `fe-*/src` in commit/range, NOT hash-delta.**
- **⚠ SPA-fallback 200 trap (S72):** server rewrites `/*``/index.html` so GET `/assets/index-<ANYTHING>.js` returns **200** even for fake hash (control `ZZdoesnotexist0.js`200, size~919b text/html). Old-hash-still-200 MEANINGLESS. RELIABLE signal = parse index.html `<script src>`, GET that exact path + check `size_download` LARGE (real ~1.6MB vs fake ~919b) + `Last-Modified` in deploy window + 2nd-fetch byte-stable (no mid-deploy transient).
- **🟢 #69-REFINE (S83 #333) hash can stay IDENTICAL across deploy when fe-*/src 0-change.** #69 "rotates EVERY deploy" NOT absolute: identical Vite source byte-identical output same content-hash. **MOST RELIABLE ship-proof = `Last-Modified` on real bundle IN deploy-window + real-size, NOT hash-delta** (hash-delta false-NEG when src unchanged, false-POS risk per #69). 0-FE-change hash EITHER same (#333/#485-487/#495/#385-S115) OR rotated (#312/#489) both benign; ship-proof = fresh LM-in-window + real-size + marker.
- **🔴 #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.
- **⚠ 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).**
- **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.
---
@ -45,7 +42,7 @@ cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay
- **Stage 0 RAG infra:** `Get-Service Qdrant` Running + `http://localhost:6333/healthz`. Collection `proj_solution_erp`.
- **Stage 1 Push+filter:** `git log -1 --format='%H %s'` + `git log origin/main..HEAD` empty + diff vs paths-ignore (docs-only SKIPPED-DOCS return).
- **Stage 2 Gitea poll** (max 10 iter × 60s): API `.../actions/tasks?limit=5` (NOT `/runs` 404). Match `head_sha` (NOT run_number cancelled runs shift numbering). `updated_at` stale ~2min (gotcha #46) cross-check VPS mtime. Foreground-sleep BLOCKED Windows Monitor-style busy-wait-curl-spin ~30s/iter.
- **Stage 3 Test gate:** baseline **509 PASS** (45 Domain + 464 Infra; S118 #389 `c808b9a` 505+4 `AuthorizePolicyRegressionTests` ReportsController Reports.Read gate; Infra 460464, Domain frozen 45; prior 505 [#388 `c2135ba` ProcurementMasterAccessSeed], 501, 495, 486, 458, 440, 421). CI runs both proj BEFORE build/deploy status=success test gate passed (`tasks` terminal=`status:success`, `conclusion` NOT populated trust success NOT log-numeric). Local grep undercounts (Theory/InlineData). Phase 9 UAT skip OK.
- **Stage 3 Test gate:** baseline **562 PASS** (45 Domain + 517 Infra; run #422 `b5799fc` 07-29; climb 562/551/532/528/520/509/505/501/495/486/458/440/421). CI chạy cả 2 proj TRƯỚC build/deploy `status:success` = gate passed (`tasks` KHÔNG populate `conclusion` tin `status`). Local grep undercount (Theory/InlineData). Phase 9 UAT skip OK.
- **Stage 4 Post-deploy** (if SUCCESS): auth login bearer (admin + nv.test gotcha #44; token=`accessToken` route `/api/auth/login`) 3-5 endpoint smoke 2XX (incl new NEW-endpoint bodyless-POST returns **411 IIS Length-Required pre-auth NOT 404**; re-probe WITH body 401 confirms wired) FE bundle hash 2 app (per #69 = real-size-vs-fake not hash-delta) SignalR negotiate (gotcha #25) EF mig prod==repo.
- **Stage 4.6 (S29 CRITICAL):** sqlcmd seed sample verify post-deploy (NOT chỉ schema). Seed=runtime-row-insert (no history/tables advance) verify via DB-query (e.g. Permissions count), NOT bundle-frozen-alone.
- Discovery: ASP.NET 10 record enum needs numeric input unless `JsonStringEnumConverter` (SOL has NO converter FE sends numeric). sqlcmd ssh Windows-auth `\\\\SQLEXPRESS` 4-backslash. INFRASTRUCTURE seed MUST run (NOT inside `if(!demoSeedDisabled)`); DEMO seed gated gotcha #51.
@ -63,9 +60,9 @@ cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay
- **Gitea:** `git.baocaogiaoduc.vn/vietreport-admin/solution-erp` · workflow `.gitea/workflows/deploy.yml` · paths-ignore 7-entry (D10 S111 #495): `['docs/**','**/*.md','.claude/skills/**','.claude/agent-memory/**','.claude/workflows/runs/**','.gitignore','scripts/**.md']`. Anon API works (public repo) when GITEA_TOKEN absent.
- **Prod:** api/admin/eoffice `.solutions.com.vn` · SSH `ssh vietreport-vps` (Administrator, id_ed25519) · IIS phys paths: API `C:\inetpub\solution-erp\api` · admin `\fe-admin` · user `\fe-user`. DB `.\SQLEXPRESS`/`SolutionErp`/`vrapp` SQL-auth. **Conn key = `ConnectionStrings.Default` (NOT `DefaultConnection`)**. DB pw = `buKL3TGBkD0wDDbYVw65QeX9` (User Id=`vrapp`; Password field has NO `vrapp/` prefix S89 login-failed when prefix included; read verbatim from prod `appsettings.Production.json` ConnectionStrings.Default when `$env:PROD_DB_PASSWORD` empty). skill-doc path `C:\inetpub\apps\SolutionErp\Api` STALE.
- **SSHPS quoting (S42):** nested bashsshpowershell mangles `$var`/`\"` use `iconv UTF-16LE | base64` `powershell -EncodedCommand $B64`; OR write ps1-file + `powershell -File $(cygpath -w)`. sqlcmd over SSH direct `-W -h -1` pw-inline. sys-catalog string-concat `COLLATE DATABASE_DEFAULT` (collation conflict).
- **Tests baseline:** **562 PASS** (45 Domain + 517 Infra · 0 fail/skip; run #419 `a52a91e` 07-28, khớp canonical `docs/STATUS.md:452` cả tách-phần; prior climb 551/532/528/520/509/505/501/495/486/458/440/421). Phase 9 UAT skip OK. 🔑 **Concrete count via web-UI log `https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/{run_number}/jobs/0/logs` (~18KB, NO `/api/v1/` prefix — api/v1 runs+tasks logs BOTH 404) → per-project `Passed! - Failed: 0, Passed: N, Skipped: 0`. Delta-proof new-tests = compare prev-run count (dotnet summary hides names). status=success alone ⟹ gate-passed (tests pre-deploy).**
- **Tests baseline:** **562 PASS** (45 Domain + 517 Infra · 0 fail/skip; run #422 `b5799fc` 07-29; khớp canonical `docs/STATUS.md`). 🔑 **Số cụ thể lấy ở web-UI log `https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/{run_number}/jobs/0/logs` (~18KB, KHÔNG có `/api/v1/` — api/v1 runs+tasks logs đều 404)** mỗi project 1 dòng `Passed! - Failed: 0, Passed: N, Skipped: 0`; đối chiếu TÁCH-PHẦN (45/517) chứ đừng chỉ khớp tổng. Delta test mới = so run trước.
- **Mig latest repo: Mig 68 `AddPeAllowApproverDelete`** (`20260727033522`, S155 `b1bae77` AddColumn `AllowApproverDelete` bit NOT NULL def-0 trên **`ApprovalWorkflowLevels`**, no-new-table; VERIFIED-APPLIED-PROD history-top + col-present + sys.tables **89**). Prev Mig 67 `AddPeApprovedBudgetSnapshot` / 66 `AddPeApprovedPriceRange` / 65 backfill-invariant / 62 `ExpandSupplierFields` (full table docs/CLAUDE.md). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (68 `.cs` excl Designer/Snapshot). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC`. **`sys.tables`(is_ms_shipped=0)=89** AddColumn/data-only/enum-additive don't change count; no-new-table commit 89 correct, don't FAIL. **NO-Mig proof = history NOT-advance + empty `git diff <base>..<head> -- '*Migrations*'`.**
- **Bundle hash live:** ship-baseline = run #416 (07-27) admin js `CiUBEEJr`/css `DX5ew0wg` · eoffice js `DFh7GK0t`/css `BHsBUA8e` (real-size 1,670,035/1,570,257b; LM 12:41:28/12:42:22+07). PER #69 TWO-MODE = SNAPSHOT-per-run NOT stable-baseline (rotate on real-src, freeze byte-id on 0-src) ALWAYS re-snapshot LIVE post-success; **ship-proof = LM-in-window + real-size (vs 900b `ct=text/html` SPA-trap) + marker-grep, NOT hash-delta**. js-rotate/css-frozen = FE-logic-no-style fingerprint (S134-refine: `ct=text/html` cleaner discriminator than 919b, shell size drifts per-build). idrun_number (head_sha-keyed).
- **Bundle hash live:** ship-baseline = run #422 (07-29) admin js `BHodkPNV`/css `DiNJjaoo` · eoffice js `0GO8mgrG`/css `BARVqkP-` (user real-size 1.584.514B, LM 11:49:05+07). Đây **SNAPSHOT-per-run, KHÔNG phải mốc ổn định** (#69 TWO-MODE) LUÔN re-snapshot LIVE sau status=success; ship-proof = LM-in-window + real-size + marker, KHÔNG phải hash-delta. id run_number (key theo head_sha).
- **Bearer:** admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM, gotcha #44 check).
- **API Serilog log (S118 correction):** real sink = `C:\inetpub\solution-erp\api\logs\solution-erp-YYYYMMDD.log` (lowercase `logs`, rolling daily). skill-runbook path `…\Logs\log-YYYYMMDD.txt` STALE empty grep. MinimumLevel Default=Information (DbInitializer `LogInformation` seed/revoke lines DO persist) Microsoft/System overridden Warning (no "Now listening" INFO). **Startup seed-race audit pattern (durability deploys):** grep this log for revoke-line THEN seeder-line same-second "N added + M upgraded" proves seeder actively flipped rows revoke knocked down (0-upgraded = seeder no-op = FAIL flag).
@ -75,7 +72,7 @@ Node CI `20.x` (`feedback_node_cicd`) · MediatR `12.4.1` (gotcha #1, flag `Vers
---
## 🎯 Per-NV admin opt-in wire — 10-point checklist (cumulative S22→S23)
Cross-ref `feedback_per_nv_permission_scope`. Per-NV/per-Level refactor MUST verify: 1 Domain field · 2 EF `HasDefaultValue(false)` · 3 Mig 3-file · 4 Service read · 5 Domain+App DTO mirror · 6 Designer FE checkbox · 7 AwLevelDto+ToDto · 8 CreateAwLevelInput+Update mutation · 9 **Lookup discrimination** (`FirstOrDefault` ADD `ApproverUserId==actorId` + admin fallback) · 10 **Controller body record count == Command record count**. Bug latency 2-3 days prod silent khi miss 9-10. Scan `grep -n "FirstOrDefault.*Order.*==" *.cs` after OR-of-N refactor.
Cross-ref `feedback_per_nv_permission_scope`. Refactor per-NV/per-Level phải verify 10 điểm: Domain field · EF `HasDefaultValue(false)` · Mig 3-file · Service read · Domain+App DTO mirror · Designer FE checkbox · AwLevelDto+ToDto · Create/Update input · **(9) Lookup discrimination** (`FirstOrDefault` thêm `ApproverUserId==actorId` + admin fallback) · **(10) Controller body record count == Command record count**. Miss 9-10 bug prod im-lặng 2-3 ngày. Sau refactor OR-of-N: `grep -n "FirstOrDefault.*Order.*==" *.cs`.
## 📊 Run stats baseline
BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code / 0s docs-only**. >5min → escalate. Recent runs all ~4m40-5m.
@ -84,10 +81,7 @@ BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code /
## 📅 Recent runs (compressed — verbatim → archive via `_INDEX.md`)
- _(**S128 #395 `289ba96` + S129 #396 `295c70c` + S132 #397 `72f68d1` GOVERNANCE/SCRIPTS/TOOLING GO** gate **509** [45+464, 0 fail/skip]; smoke 4×200; bundle benign #69 [S128 FULL-ROTATE from S117 → `yCkX-2Bp`/`DKSD4p9k`; S129+S132 FROZEN byte-id 0-fe-src] ship-proof = LM-in-window + real-size ≠919b NOT hash-delta; NO-BE/NO-Mig [Mig 66/89-table]; 🔑 **AS-6 #41: soi TỪNG file vs 7-glob** `.ps1` thoát `scripts/**.md` glob + `.claude/rag.json` / `.session-counter.json` thoát ⟹ non-.md governance VẪN trigger CI; `conclusion:None` dù success trust `status` [tái-xác-nhận S126/S128/S129/S132] · verbatim → `archive/2026-07.md`)_
- _(**S118 #389 `c808b9a` SECURITY-AUTHZ** ReportsController→Reports.Read GO 5m34s [gate 509=45+464 (+4 authz-reflection vs 505); DB `Reports.Read`→Admin-ONLY sqlcmd (Procurement CanRead=0 → non-admin 403 by-construction); no-token 401 class-`[Authorize]` intact; NO-FE/NO-Mig; cicd-lane GARBLED #53 → em-main curl+sqlcmd recovered, verdict disk-TRUE] · **+S117 #387 `316a82f`** PE duyệt-khoảng MinMax + Mig 66 `AddPeApprovedPriceRange` APPLIED-PROD [gate 501; js-rotate×2 css-frozen; byte-verify #77 4-str PRESENT; Mig66 `COL_LENGTH=9`+sys.tables 89; 🔑 pre-deploy snapshot BEFORE poll-success] · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**S111-S116 #383-#386/#495/#496** PE multi-NCC per-hạng-mục (Mig 65 backfill) + nhập-giá-ÂM + submit-guard + Supplier-import Phase-B/v2 (Mig63 `AddSupplierImportSourceFields`/Mig64 `AddSupplierPublishState` APPLIED-PROD, IsPublic 37/37) + H22-WAL-adopt (deploy.yml self-change +2 paths-ignore) + GOVERNANCE GO [gate 458→495; js-rotate/css-frozen; 🔑 AS-6 baseline-shift memory-push HẾT trigger; 411-refine bodyless-POST→411 → re-probe-with-body 401/415≠404; #69-REFINE 0-src FROZEN-proof; byte-verify #77 str-PRESENT] · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**S98-S110 + S126 #485-#494/#394** GOVERNANCE/MEMORY/TOOLING-push FROZEN-streak sau ROTATE #489 (#69 TWO-MODE; ship-proof = LM-in-window + real-size, hash-delta phụ); gate 440→509; Mig 62 + 89-table frozen · 🔑 #494 LM-newer-than-verified-window = missed-run detector; bare `/health`=404 UNMAPPED (đừng FAIL — thật `/health/live`+`/ready`) · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**S98-S132 #383-#397/#485-#496 — GOVERNANCE/FE/SECURITY streak, all GO** (gate leo 440→509): 🔑 bài-học còn dùng — **AS-6 #41 soi TỪNG file vs 7-glob** (`.ps1`/`.json` thoát `scripts/**.md` ⇒ governance non-.md VẪN trigger CI; memory-push thì HẾT trigger từ #495) · `conclusion:None` dù success tin `status` · **411-refine**: endpoint MỚI bodyless-POST trả **411** (IIS Length-Required, pre-auth) KHÔNG phải 404 → re-probe CÓ body, 401/415 ⇒ đã wire · bare `/health`=404 UNMAPPED, thật là `/health/live`+`/ready` (đừng FAIL nhầm) · **LM mới hơn cửa-sổ đã verify = detector 'có run mình bỏ sót'** · Mig 63/64/65/66 + Mig 67 đều APPLIED-PROD, 89-table giữ · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**PASS-pattern library S69b→S104 #307-#494** all GO — 🔑 reusable verify-recipes: **SCHEMA-ADD+DATA-UN-CRAM** [#488 Supplier 9→27 Mig62: AddColumn×18-exact + 89-invariant + un-cram 4-NCC + DTO-live] · **DATA-FIX-BACKFILL** [#484 Mig61: Mig-top==HEAD + target-rows-flip-EXACT + control-untouched + derived-API-FLIP-live] · **DATA-SEED-PASS** [#477: pre/post-DB-row-delta + DLL-mtime + w3wp-recycle]; #482 Mig60 EF-ternary-SQL 200≠500; #472 PROD Identity NON-prefix `Roles`; #470 no-resurrect DB-count-diff; Mig54-62 applied-prod; #348 411→401 · verbatim → git + `2026-06/07.md`)_
- **Older (S83 #325 ← S29 #232) → git `d2f52ba` + `archive/2026-06.md`** (incl #291 06-16 FAIL [gotcha #65]); pre-S38 → `archive/2026-05-*`.

View File

@ -50,3 +50,8 @@
## Run #416 `b1bae77` (2026-07-27) — moved from L1 @S157 curate, byte-exact
- **07-27 verify b1bae77 (Workflow: quy-trình duyệt TẠI CHỖ + cờ F6 `AllowApproverDelete` đợt-1) [S155, MIG-BEARING deploy, CLEAN-return]:** VERDICT **PASS 6/6** — Run **#416** (id=529) success **5m31s** (12:37:18→12:42:49+07); gate **551 EXACT từ log** (45 Domain + **506** Infra, 0 fail/skip) — **+19 vs run #407 (532)**, **KHỚP CHÍNH XÁC số lead đo local (551)** = cross-check 2-nguồn. **Mig 68 `20260727033522_AddPeAllowApproverDelete` VERIFIED-APPLIED-PROD** (AddColumn `AllowApproverDelete` bit NOT NULL default `(CONVERT([bit],(0)))` trên `ApprovalWorkflowLevels`; history-TOP + `INFORMATION_SCHEMA.COLUMNS` **cả 2 cùng có ⟹ không lệch**; sys.tables **89** giữ nguyên đúng AddColumn-no-new-table). 🔑 **Reviewer FLAG F8 (mig-file rớt khỏi commit ⟹ `Invalid column name` hạ 7 module V2) LOẠI TRỪ bằng 3 lớp:** (i) pre-deploy baseline 12:38 history-top còn `AddPeApprovedBudgetSnapshot` ⟹ mig áp TRONG cửa-sổ này không phải sẵn có; (ii) smoke 8/8 HTTP 200 `Invalid column name`=0 (PE·HĐ·Đề-xuất·Nghỉ-phép·Tăng-ca·Công-tác·Đặt-xe + AwV2); (iii) **phép mạnh nhất = `GET /api/approval-workflows-v2` trả `allowApproverDelete` ×54 materialize qua EF từ DB thật** — DB thiếu cột thì chính query này đã ném. Endpoint mới `PUT /api/approval-workflows-v2/{id}` no-token → **401** + **control route bịa → 404** (discriminator sạch, 401 có nghĩa). Bundle **JS rotate CẢ 2** (admin `hHISK1Ig`→**`CiUBEEJr`** css `CBzUlgOA`→**`DX5ew0wg`** rotate; eoffice `CJeXZso2`→**`DFh7GK0t`** css `BHsBUA8e` **FROZEN** = #69-REFINE lành tính, 2 file fe-user là logic/type no-new-utility) real-size 1.670.035/1.570.257B, LM 12:41:28/12:42:22+07 **in-window**; byte-verify #77 marker `allowApproverDelete` admin ×7 / eoffice ×1 ⟹ đúng mã F6 đã ship. SPA-trap control `ct=text/html` 900/876B. health live+ready 200. Tag `[run-416, pass-6-6, mig-bearing, F8-averted-3-layer, col-materialize-x54, js-rotate-both, gate-551-khớp-local]`
## 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]`

View File

@ -139,4 +139,5 @@
- 2026-07-17 · S133 #398 `d4fbced` PE budget-freeze + Mig67 AddPeApprovedBudgetS… · PASS · `2026-07.md` · substring:"S133 (07-17) verify d4fbced"
- 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-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)"

View File

@ -0,0 +1,189 @@
# cicd-verify `b5799fc` — S159 L8 "Tổng quan tất cả luồng duyệt"
> 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.
> Bắt đầu: 2026-07-29 ~11:44+07 · agent cicd-monitor (READ-only)
---
## M1 — Push + path-filter · ✅ PASS
```
git log -1 → b5799fc5d373feaf94604cc4b4d9207cfb277826
[CLAUDE] FE-User: Tong quan tat ca luong duyet - pipeline 4 giai doan
2026-07-29 11:43:25 +0700
git log origin/main..HEAD → EMPTY (đã push thật)
```
**Range `bbc39be..b5799fc` = 8 commit** (b5799fc + 7 `wal:` flush xen giữa), **37 file**.
⚠️ Tự-đính-chính vs spec: spec nói "1 file" — đúng ở nghĩa **1 file CODE**, nhưng range thật 37 file
(36 file còn lại đều `.claude/**` governance/memory/run-trace + `*.md`).
**Soi TỪNG file vs 7-glob `paths-ignore` (AS-6, gotcha #41):**
- `.claude/agent-memory/**` (12 file) → ignored
- `.claude/workflows/runs/**` (21 file, gồm 2 `.txt`) → ignored
- `.claude/WAL.md` + `.claude/sessions/session-8/*.md` (3 file) → khớp `**/*.md` → ignored
- **`fe-user/src/pages/UserDashboardPage.tsx` → KHÔNG khớp glob nào ⇒ CI PHẢI fire.**
`git diff --stat` file code: **`fe-user/src/pages/UserDashboardPage.tsx` | 743 +++/---**
## M3 — Migration VẮNG là ĐÚNG · ✅ PASS (kỳ vọng, không phải cờ đỏ)
```
git diff --name-only bbc39be..b5799fc -- 'src/Backend/*' '*Migrations*' → 0 dòng
```
⇒ 0 BE, 0 migration. **KHÔNG query `__EFMigrationsHistory`** (không có gì để đối chiếu).
Mig prod vẫn kỳ vọng 68 `AddPeAllowApproverDelete` / 89 `sys.tables` — không đụng.
## Pre-deploy bundle snapshot (chốt TRƯỚC khi deploy land — bài học S117)
Đo lúc **2026-07-29 11:44:56+07** (run #422 đang `running`, chưa tới step deploy):
| App | js | css | HTTP |
|---|---|---|---|
| admin | `index-8-QYcMOg.js` | `index-DiNJjaoo.css` | 200 |
| user | `index-DptYR4wL.js` | `index-BRCvEHvC.css` | 200 |
**Khớp CHÍNH XÁC baseline S158** (admin `8-QYcMOg` · user `DptYR4wL`) ⇒ baseline hợp-lệ, deploy chưa land.
## M5-pre — Marker có trong SOURCE local (chốt kỳ vọng trước khi soi bundle prod)
`fe-user/src/pages/UserDashboardPage.tsx` (31.768 B), đếm BYTES utf-8:
| Chuỗi | count source | vai trò |
|---|---|---|
| `Tổng quan tất cả luồng duyệt` | **2** | header trang |
| `Toàn trình 4 giai đoạn` | **1** | h2 — CHỈ có ở bản SAU review-fix |
| `Đề xuất ký kết hợp đồng` | **2** | nhãn GĐ2 |
| `Pipeline 4 giai đoạn` | **0** | ✅ bản designer gốc đã bị thay |
| `sẵn sàng nối tiếp` | **0** | ✅ control ÂM — FLAG-3 đã gỡ |
⇒ Local ĐÚNG là bản-đã-fix. Bundle prod phải phản chiếu y hệt (dương 3 / âm 0).
## M7 — Menu-data prod áp TRƯỚC push (data-change, KHÔNG qua CI) · ✅ PASS 3/3
Đo **2026-07-29 ~11:46+07** (sau khi run #422 đã start, tức đã qua ít nhất 1 nhịp) — `sqlcmd -S .\SQLEXPRESS -E -d SolutionErp`:
**(a) 3 root ẩn — kỳ vọng 0×3:**
```
Hrm:0 · Off:0 · Personal:0 ✅ NGUYÊN (backup pre-apply ghi 1/1/1 → apply hạ về 0)
```
**(b) grant-set 38 key — kỳ vọng min=max=13:**
```
GRANT min=13 max=13 keys=38 minrows=13 ✅ khớp verify-post-apply
```
(grant-set = 9 key Master-subtree + `Contracts` + 28 `Ct_*`; khớp toán 9×11=99 UPDATE · 28×13+12=376 INSERT)
**(c) control ÂM `Pe_*` — kỳ vọng 197/185:**
```
WHERE MenuKey LIKE 'Pe%' → rows=197 canread=185 ✅ EXACT
```
🔎 **Tự-bắt lỗi hình-dạng-truy-vấn (đừng đọc nhầm thành cờ đỏ):** lần đo đầu tao dùng
`LEFT(MenuKey,3)='Pe_'` → ra **182/182**, LỆCH so với 197/185. Không vội FAIL — enumerate ra
nguyên nhân là **phạm-vi truy vấn**, không phải dữ liệu đổi:
- 14 key `Pe_*` × 13 = **182 rows / 182 canread**
- `LIKE 'Pe%'` gom thêm `Permissions` (1/1) + `Personal` (13/1) + `PeWorkflows` (1/1) = **+15 rows / +3 canread**
- 182+15 = **197** · 182+3 = **185** ⇒ khớp từng đồng, control âm NGUYÊN VẸN.
⇒ App pool recycle (nếu có) **không hề đụng** menu-data. M7 PASS.
## M2 — Poll terminal · ⏳ đang chờ
Run tìm được qua `actions/tasks?limit=5` khớp `head_sha`:
- **id=535 · run_number=422 · head_sha `b5799fc5` · created 2026-07-29T11:43:34+07 · status=`running`**
- (kề trên: #421 id=534 `4169e14` success — S158; #420 `33e7f68` cancelled ⇒ run_number lệch, phải key theo head_sha)
- poll 11:46:26 · 11:47:37 · 11:48:09 · 11:48:42 · 11:49:13 → `running`
- **11:49:45 → `status=success`** (upd 11:49:33). `conclusion=null` là BÌNH THƯỜNG với endpoint `tasks`
(tái xác nhận từ S126/S128/S132) ⇒ tin `status`, không tin `conclusion`.
- **Duration: 11:43:34 → 11:49:33 = 5m59s** (nhỉnh hơn dải gần đây 4m405m40, vẫn dưới ngưỡng escalate 10m)
### M2b — Test gate trong log · ✅ 562 EXACT
`…/actions/runs/422/jobs/0/logs` (17.910 B):
```
Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, Duration: 149 ms - SolutionErp.Domain.Tests.dll
Passed! - Failed: 0, Passed: 517, Skipped: 0, Total: 517, Duration: 1m37s - SolutionErp.Infrastructure.Tests.dll
```
`Failed!` xuất hiện **0 lần** trong toàn log.
**45 + 517 = 562**, khớp baseline S158 **cả TỔNG lẫn TÁCH-PHẦN** (khớp thành-phần > khớp tổng).
Delta = 0 — đúng kỳ vọng cho commit FE-only không kèm test mới.
## M4 — Bundle rotate · ✅ PASS (đo, không giả định)
Đo **11:49:58+07**, ~25s sau khi run terminal:
| App | asset | TRƯỚC | SAU | KQ |
|---|---|---|---|---|
| **user** | js | `DptYR4wL` | **`0GO8mgrG`** | ✅ **ROTATE** (điều kiện PASS bắt buộc) |
| user | css | `BRCvEHvC` | **`BARVqkP-`** | ROTATE (utility-class mới: lưới pipeline/amber) |
| admin | js | `8-QYcMOg` | **`BHodkPNV`** | ROTATE — #69 mode-A, lành tính (CI build cả 2 app dù 0 admin-src) |
| admin | css | `DiNJjaoo` | `DiNJjaoo` | FROZEN byte-identical — #69-REFINE, 0 admin-src ⇒ CSS y hệt |
Cặp admin (js rotate + css frozen) = dấu-vân-tay "không có thay đổi nguồn admin", nhất quán với diff.
## M5 — Byte-marker trong bundle USER prod · ✅ PASS 3 dương + 2 âm
Tải THẲNG `https://eoffice.solutions.com.vn/assets/index-0GO8mgrG.js`, đếm trên **BYTES** (`b.count(s.encode('utf-8'))`, tránh bẫy decode cp1252):
```
200 · ct=application/javascript · size=1.584.514 B · LM=Wed, 29 Jul 2026 04:49:05 GMT (= 11:49:05+07)
```
LM **nằm trong cửa-sổ deploy** (run kết thúc 11:49:33) + real-size 1,58 MB ⇒ artifact thật, mới ghi.
| Chuỗi | bundle | code-occurrence trong source | KQ |
|---|---|---|---|
| `Tổng quan tất cả luồng duyệt` | **1** | 1 (L398 `title=`) | ✅ EXACT |
| `Toàn trình 4 giai đoạn` | **1** | 1 (L414 `<h2>`) | ✅ EXACT |
| `Đề xuất ký kết hợp đồng` | **1** | 1 (L476 `StageCard index={2}`) | ✅ EXACT |
| `Pipeline 4 giai đoạn` | **0** | 0 | ✅ bản designer CŨ VẮNG |
| `sẵn sàng nối tiếp` | **0** | 0 | ✅ **control ÂM VẮNG** (FLAG-3 đã gỡ) |
🔎 **Giải-trình lệch 2-vs-1 (đo được, không phẩy tay):** `grep -c` trên source ra **2** cho marker 1 và 3,
nhưng bundle chỉ **1**. Truy ra: occurrence dư nằm ở **COMMENT đầu file** (L1 `// "Tổng quan…"`,
L5 `// GĐ2 Đề xuất ký kết hợp đồng …`) — minifier strip comment. Literal JSX THẬT đúng **1 lần/marker**.
⇒ Bundle **khớp CHÍNH XÁC số occurrence-code**, mạnh hơn "tìm thấy ≥1".
🔒 **Kết luận then-chốt:** thấy `Toàn trình 4 giai đoạn` + KHÔNG thấy `Pipeline 4 giai đoạn`
⇒ prod đang chạy **bản SAU review-fix**, KHÔNG phải bản designer gốc. Đây là phép quyết định của lượt này.
### Control ÂM 2 TẦNG (SPA-fallback trap + chứng ghi-đè)
| Probe | HTTP | Content-Type | size | Đọc thế nào |
|---|---|---|---|---|
| `index-0GO8mgrG.js` (thật) | 200 | `application/javascript` | 1.584.514 | artifact thật |
| `index-ZZdoesnotexist0.js` (bịa) | **200** | **`text/html`** | **876** | SPA rewrite → 200 VÔ NGHĨA; `ct` là bộ phân-biệt sạch |
| `index-DptYR4wL.js` (**hash CŨ**) | **200** | **`text/html`** | **876** | 🔑 **bundle cũ ĐÃ BIẾN MẤT khỏi đĩa** ⇒ chứng GHI-ĐÈ thật, mạnh hơn hash-delta đơn thuần |
## M6 — Smoke · ✅ PASS 4/4
```
GET https://api.solutions.com.vn/health/live → 200 "Healthy"
GET https://api.solutions.com.vn/health/ready → 200 "Healthy"
GET https://admin.solutions.com.vn/ → 200 <!doctype html> lang="vi"
GET https://eoffice.solutions.com.vn/ → 200 <!doctype html> lang="vi"
```
(BE 0-change nên health = kiểm tra app pool sống sau recycle, không phải kiểm feature.)
---
## VERDICT: **PASS 9/9**
| # | Mục | KQ |
|---|---|---|
| 1 | Push + path-filter (CI fire đúng, không skip #41) | ✅ |
| 2 | Run #422 terminal `success` 5m59s | ✅ |
| 3 | Test gate **562** = 45 D + 517 I, 0 fail/skip | ✅ |
| 4 | Migration VẮNG là ĐÚNG (0 file BE/Mig) | ✅ |
| 5 | Bundle **user** rotate `DptYR4wL``0GO8mgrG` | ✅ |
| 6 | 3 marker DƯƠNG, count-exact vs code | ✅ |
| 7 | 2 marker ÂM vắng (`sẵn sàng nối tiếp` + `Pipeline 4 giai đoạn`) | ✅ |
| 8 | Smoke API health ×2 + FE origin ×2 | ✅ |
| 9 | Menu-data prod nguyên (0×3 · 38 key 13/13 · Pe 197/185) | ✅ |
**Không có cờ đỏ. Không khuyến nghị rollback.**
Ghi-chú cho lượt sau: baseline ship mới = **user js `0GO8mgrG` / css `BARVqkP-` · admin js `BHodkPNV` / css `DiNJjaoo`**;
gate giữ **562**; Mig vẫn **68** / 89 bảng (không đụng).
<!-- END cicd-verify-b5799fc · VERDICT=PASS 9/9 -->

View File

@ -28,3 +28,13 @@ Key IsVisible
Hrm 1
Off 1
Personal 1
## label-backup TRUOC danh so (2026-07-29T11:50:52+07:00)
Key Order Label
--- ----- -----
Ct_ThauPhu 31 HD Th?u ph?
Ct_GiaoKhoan 35 HD Giao kho<68>n
Ct_NhaCungCap 39 HD Nh<4E> cung c?p
Ct_DichVu 43 HD D?ch v?
Ct_MuaBan 47 HD Mua b<>n
Ct_NguyenTacNcc 51 HD Nguy<75>n t?c NCC
Ct_NguyenTacDv 55 HD Nguy<75>n t?c D?ch v?

View File

@ -37,6 +37,21 @@
· FLAG-6 [L] 2 nút Thử-lại trùng → **PARK** (reviewer tự đính chính giữa chừng; cosmetic, chấp nhận)
· FLAG-7 [L] nhãn GĐ4 → **NO_CHANGE** (đúng spec owner ❷/❹ — GĐ4 cố ý ngoài hệ thống)
- [x] **T4b — build độc lập SAU mọi edit** ✅ PASS 454ms (`tsc -b && vite build`) · 6/6 `group` land · diagnostics IDE giữa chừng = snapshot dở (#68), bác bằng compiler thật
- [x] **T4c — commit đợt-1 `b5799fc` push → cicd `PASS 9/9`** (bundle user `DptYR4wL``0GO8mgrG`, 3 marker dương + 2 control âm, smoke 4/4; return garble #53 lần 10 — đĩa `cicd-verify-b5799fc.md` 9.930B trọn)
## ĐỢT-2 (3 lệnh mid-turn của anh, 11:24-11:5x)
**Owner verbatim:***"sửa giao diện nhanh"* ② ảnh tab strip 4 giai đoạn trên phiếu + *"cho hiển thị các tab phía trên như này nhé"**"Phần menu cũng hiển thị đúng như vậy luôn. (Trình ký Hợp đồng đổi thành Duyệt hợp đồng, ký cứng -> Hợp đồng cứng)"* · UAT anh Kiệt (chat FDC): *"cho đánh số thứ tự phía trước giúp anh — 01 . HĐ thầu phụ"*.
🔴 **Bộ tên 4-GĐ CHỐT MỚI NHẤT (supersede nhãn ❶ sáng nay):** Duyệt NCC · **Kế hoạch ký kết HĐ** · **Duyệt hợp đồng** · **Hợp đồng cứng** — tin-mới-nhất-thắng; nhãn "Đề xuất ký kết hợp đồng" (❶) chỉ sống 1 buổi, spec sẽ ghi cả 2 đời.
- [x] **Đ2-a — đánh số 01.-07. nhóm HĐ** ✅ prod LIVE tức thì (`renamed=7`, prepend-only **0 ký tự VN qua wire** — né E-010) + seeder `typeLabels` + labelBackfill 7 entry
- [x] **Đ2-b — menu 4-GĐ prod** ✅ SQL qua **file UTF-16 + scp** (3 nhãn VN mới an toàn): `ren_pe=1 ren_ct=1 perm=26` (=13×2, khớp toán) · root order: Duyệt NCC(25) → Kế hoạch ký kết HĐ(26) → Duyệt hợp đồng(31) → Hợp đồng cứng(32) · bẫy shell VPS = PowerShell 5.1 không nhận `&&`
- [x] **Đ2-c — `PePipelineStrip` mirror ×2 app** ✅ byte-identical (`ef7b78…`) + chèn `PeDetailTabs` ×2 giữ **md5 parity** (`5be2ca…`, edit qua python assert count==1) — GĐ1 active, GĐ2/GĐ4 badge "Sắp", stage không-active KHÔNG click (không giả link)
- [x] **Đ2-d — staticMap +2 route** (`KeHoachKyKet`/`HopDongCung``/dashboard`; thiếu là sidebar **drop SILENT** — gotcha #50) + đồng bộ 3 nhãn + 3 aria-group dashboard
- [x] **Đ2-e — build FE ×2 PASS + test 562 PASS** (seeder đụng ⇒ chạy đủ) → **commit `1a47a61` push** (8 file, 190+/18)
- [!] **Đ2-f — cicd verify `1a47a61`** đang chạy (kèm check seeder-re-run không double-insert: 12 root, 7 nhãn `01.` nguyên)
🔸 fe-admin sidebar: 2 root placeholder sẽ **drop silent** (không thêm staticMap admin — cố ý, admin không cần placeholder; ghi để khỏi đọc thành bug)
- [x] **T2 — Prod menu data****LIVE + VERIFY TRỌN** (`prod-backup-pre-apply.txt` → apply `hide=3 upd=99 ins=376``prod-verify-post-apply.txt`):
· Inspect lộ thực-trạng ≠ giả định: Master subtree có matrix 13-row/key (canread 2/13) nhưng **`Ct_*` 28 key = 0 ROW** (chưa từng seed), `Contracts` root 1 row ⇒ INSERT 376 + UPDATE 99, số khớp toán từng đồng (9×11=99 · 28×13+12=376)
· Verify: **38/38 key min=max=13 canread** · 3 root `IsVisible=0` · control âm **Pe_* 197/185 NGUYÊN** (❹ "để như cũ") · `Hrm_Config*` canread=7 nguyên (vùng đang-làm loại khỏi grant, đúng ý ❸)