From 1e3434b32cc16e92f8b543d4b6acdd2950f0d1b0 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Wed, 29 Jul 2026 22:46:27 +0700 Subject: [PATCH] wal: flush 20260729T2246 --- .claude/WAL.md | 5 +- .../cicd-verify-df52fa0.md | 173 ++++++++++++++++++ .../w3-synthesis.md | 19 ++ .../2026-07-29-S161-khkk-w6-duongong/run.md | 24 +++ 4 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 .claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/cicd-verify-df52fa0.md create mode 100644 .claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md create mode 100644 .claude/workflows/runs/2026-07-29-S161-khkk-w6-duongong/run.md diff --git a/.claude/WAL.md b/.claude/WAL.md index 40389ff..009c287 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -27,7 +27,10 @@ chain: - [x] W3 đợt-3 `wf_c9d5f8d4-cbe` XONG (#53, sub-md 15KB trọn §0-§7): 6/6 GREEN + **suite 580/0 lead-tươi** · choke-point **1-site-proof-cấu-trúc** (hợp-đồng 0 targetPhase ⇒ admin xuyên choke-point) · sửa-test đúng 1 seed `2→1` (FAULT-INJECT sót, 0 assert đổi) · save-điểm = 1 SaveChanges cuối (service là điểm vào, khác nguồn :537) · **Q1-Q6 lead DUYỆT cả 6**; tồn UAT: mark-read chuông cũ (mirror PE S96) - [x] reviewer W3 **PASS 7/7 trục 0-chặn** (4 trục vai [fidelity 0-lỗi · choke-point khai-đúng · Q4 panel ĐÃ-gate · hợp-đồng KHỚP 5/5 — trục W2-đứt-6 nay sạch] + 3 trục lead [test-integrity soi-RUỘT ĐẠT kèm caveat "phép git-diff lane khai không tồn tại với file untracked — lời-khai≠phép-đo phía NGƯỜI-KHAI-TỐT" · notify exclusion :41 · boundary 0-diff]) - [x] commit W3 `df52fa0` (11 file +2.370/−6) PUSHED -- [!] wf: cicd-monitor verify `df52fa0` ĐANG CHẠY (CI 580 · 0-mig · marker độc-quyền tự chọn · **smoke transitions THẬT: action-nonsense→409 + GUID-ma→404** · CỜ giữ) → PASS ⇒ **W3 ĐÓNG** → còn W6 → W5 → W7 (+setup WF tay type-3/type-10 trước W5) +- [x] **W3 ĐÓNG — cicd VERDICT=PASS 5/5** (§1 CI 580 + §3 marker [né PASS-GIẢ "Đến lượt bạn duyệt"] = cicd · §2 0-mig/96/142 + §4 smoke transitions THẬT 409-đúng-lời + 404-ProblemDetails + §5 CỜ 13/13/2 = lead 2-nguồn). Synthesis `runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md`. **GĐ2 KHKK trọn vòng đời phiếu trên prod.** Tồn: mark-read chuông cũ (chờ anh) · UAT tay cần WF-type-10 + non-Admin +- [x] gate 5-anchor W6 PASS 5/5 (content-exact 0-drift) +- [!] wf: W6 đợt-1 `wf_e3b6a2bc-91d` ĐANG CHẠY — 1 lane BE {view per-HĐ 3-site :301/:381/:486 · inbox v2-set + nhánh ADMIN DR-4 · guard trình +PMH; CẤM đụng Reject :49-66 O-A + vùng W3 :217-394} — run-folder `runs/2026-07-29-S161-khkk-w6-duongong/`. Sau: đợt-2 test 5-PIN → reviewer (security-wave) → ship +- [ ] W5 (cầu KHKK→HĐ — cần setup WF tay TRƯỚC: type-3 + type-10 3-trạm Designer) → W7 (bản cứng 1-mốc @S161) - [ ] W6 → W5 → W7 theo đồ thị plan-cha (sau W3) - [ ] đợt-2 SAU khi wf về: test-specialist + database-agent (song song) → lead acceptance §③-B (build·test·sqlcmd 96·Down sạch·đo CỜ) → reviewer → commit/push → cicd-monitor 3-chân-kiềng - [ ] setup thủ công TRƯỚC W5 (SAU W1 vì type=10 cần mig 69): dựng workflow type=3 + type=10 3-trạm qua Designer (seed chỉ 1 trạm) diff --git a/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/cicd-verify-df52fa0.md b/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/cicd-verify-df52fa0.md new file mode 100644 index 0000000..3884971 --- /dev/null +++ b/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/cicd-verify-df52fa0.md @@ -0,0 +1,173 @@ +# CI/CD verify — `df52fa0` (W3 KHKK — duyệt 3 trạm, 0 migration) + +> Ghi TỪNG MỤC ngay khi có bằng chứng (đối-sách #53: file = sản phẩm chính, return chỉ là tóm tắt). +> Agent: cicd-monitor · Session S161 W3 · Ngày 2026-07-29 + +--- + +## §0. Grounding — commit + push + +| Mục | Giá trị | +|---|---| +| SHA | `df52fa0cd09e13a533724c35f4e6bed44afeb42d` | +| Subject | `[CLAUDE] App+Infra+Api+FE-User+FE-Admin+Tests: W3 KHKK — duyet 3 tram OR-of-N + finalize chot gia (test-before 6 RED->GREEN)` | +| Author / Date | pqhuy1987 · Wed Jul 29 22:33:11 2026 +0700 | +| `git log origin/main..HEAD` | **RỖNG** ⇒ đã push | +| Files changed | **11** (+2370 / −6) | +| Breakdown | BE 4 (Controller · IContractSigningPlanWorkflowService · DependencyInjection · ContractSigningPlanWorkflowService) · FE 6 (2 app × {KhkkDetailPage, KhkkWorkflowPanel, types/khkk}) · Tests 1 (`ContractSigningPlanApprovalTests.cs`) | +| paths-ignore (gotcha #41) | KHÔNG khớp glob nào trong 7-entry ⇒ **CI PHẢI chạy** ✅ | +| Migrations trong diff | **0 file** `*Migrations*` ⇒ khai báo 0-mig (verify ở §2) | + +**File MỚI trong commit này (quan trọng cho §3):** +`fe-{admin,user}/src/pages/khkk/KhkkWorkflowPanel.tsx` — **NEW-FILE-IN-THIS-COMMIT** +(`git cat-file -e df52fa0~1:…` → `exists on disk, but not in df52fa0~1`), 423 dòng/app, +SHA256 mirror KHỚP 2 app: `2b64144ef6e8567d6997c0e19b9686c083080216510a4cd8da6157a80f584817`. + +⟹ Mọi chuỗi ĐỘC-QUYỀN của file này **phải VẮNG trong bundle CŨ** (build từ `6cbc6ad9` W2) và +**có mặt trong bundle MỚI** → control ÂM theo trục THỜI GIAN, mạnh hơn control âm hash. + +--- + +## §1. CI run — PASS ✅ + +| Mục | Giá trị | +|---|---| +| Run | **#429** (task id **542**) | +| head_sha | `df52fa0c` ✅ khớp (key theo SHA, KHÔNG theo run_number) | +| status | **success** (`conclusion:None` — Gitea `tasks` không populate, tin `status` per baseline) | +| created → updated | 22:33:19 → 22:39:13 = **5m54s** (nằm trong dải ~5m40s–6m của arc S159/S161) | +| URL | https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/429 | + +**Test gate (đọc web-UI log `…/runs/429/jobs/0/logs`, 17.900 B) — đối chiếu TÁCH-PHẦN:** + +``` +:29 Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, Duration: 147 ms - SolutionErp.Domain.Tests.dll +:47 Passed! - Failed: 0, Passed: 535, Skipped: 0, Total: 535, Duration: 1 m 36 s - SolutionErp.Infrastructure.Tests.dll +``` + +| | Kỳ vọng | Đo | KL | +|---|---|---|---| +| Domain | 45 | **45** | ✅ | +| Infrastructure | 535 | **535** | ✅ | +| **TỔNG** | **580** | **580** | ✅ | +| Failed / Skipped | 0 / 0 | **0 / 0** | ✅ | + +Delta so run #427 (566 = 45D+521I): **+14 Infra** — commit khai "test-before 6 RED→GREEN"; +file test đổi = 1 (`ContractSigningPlanApprovalTests.cs`). 6 là số **kịch bản** lead khai, 14 là số **test-case** +thực thi (Theory/InlineData nở) ⇒ không mâu thuẫn, và gate-580 đúng con số đề bài yêu cầu. + +--- + +## §2. 0-migration invariant + +_(đang cập nhật)_ + +--- + +## §3. Bundle marker + +### §3.a Chọn marker theo LUẬT ĐỘC-QUYỀN (#426) + +Trước khi nhận 1 chuỗi làm chứng-cứ, grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ cần chứng. +Đo bằng `grep -roF fe-admin/src fe-user/src src | wc -l` (occurrence) + `grep -rlF` (file list): + +| Ứng viên | occurrence | file chứa | Kết luận | +|---|---|---|---| +| `Không phải lượt bạn` | 5 | +`{2 app}/components/pe/PeWorkflowPanel.tsx` +`PurchaseEvaluationWorkflowService.cs` | ❌ **NHIỄM PE** — loại | +| `Đến lượt bạn duyệt` | 4 | +`{2 app}/components/pe/PeWorkflowPanel.tsx` | ❌ **NHIỄM PE** — loại | +| `chỉ người trên mới thao tác cấp này` | 2 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **1 lần/app** | +| `Cấp hiện tại chỉ người được phân công` | 6 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **3 lần/app** | +| `Trả lại người soạn sửa` | 4 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **2 lần/app** | + +> 🔑 Đúng bài học #426 lặp lại LIVE: 2/5 ứng viên "nghe rất KHKK" thực ra dùng chung với PE panel. +> Nếu áp máy móc `Đến lượt bạn duyệt` thì bundle CŨ đã có sẵn ⇒ PASS GIẢ. + +**Trap #425 (comment bị esbuild strip) — đã loại trừ:** cả 3 marker giữ lại đều nằm ở **mã CHẠY**, +không phải comment: `chỉ người trên…` = JSX text (`
⚠ Không phải lượt bạn — …
`) · +`Cấp hiện tại chỉ người được phân công…` = 3 × `title={…}` string literal · +`Trả lại người soạn sửa` = `dialogTitle` + 1 × `title=` (2 string literal). + +### §3.b Hiệu-chuẩn máy đo TRƯỚC khi dự đoán bội-số (chống bẫy minifier-dedupe) + +Bội-số chỉ dùng được nếu minifier KHÔNG gộp literal trùng. Đo bằng chuỗi **đã ship** `bg-slate-200 text-slate-500`: + +| App | source (HEAD) | trừ 1 lần trong file MỚI ⇒ kỳ vọng bundle CŨ | đo bundle CŨ | Khớp | +|---|---|---|---|---| +| fe-admin | 4 (`PeWorkflowPanel`×2 · `EmployeesListPage`×1 · `KhkkWorkflowPanel`×1 MỚI) | **3** | **3** | ✅ | +| fe-user | 4 (cùng phân bố) | **3** | **3** | ✅ | + +⟹ **KHÔNG dedupe** — literal trùng được giữ nguyên bội-số ⇒ dự đoán SỐ CHÍNH XÁC là hợp lệ (không phải chỉ "≥1"). + +### §3.c Control ÂM theo TRỤC THỜI GIAN (đo TRƯỚC deploy, bundle W2 `6cbc6ad9`) + +Bundle cũ: admin `index-D4uy3yxF.js` (1.709.294 B) · user `index-C1ASe0K1.js` (1.625.473 B), cả 2 `ct=application/javascript`. + +| Chuỗi | admin CŨ | user CŨ | Ý nghĩa | +|---|---|---|---| +| `chỉ người trên mới thao tác cấp này` | **0** | **0** | ✅ vắng đúng (file chưa tồn tại ở W2) | +| `Cấp hiện tại chỉ người được phân công` | **0** | **0** | ✅ vắng đúng | +| `Trả lại người soạn sửa` | **0** | **0** | ✅ vắng đúng | +| `Không phải lượt bạn` (PE panel, chứng MÁY ĐO SỐNG) | **1** | **1** | ✅ grep bắt được tiếng Việt trong bundle ⇒ 0 ở trên là "vắng THẬT", không phải "máy đo hỏng" | + +> 🔑 Đây là control ÂM mạnh hơn hash-bịa: nó chứng minh **trước deploy chuỗi KHÔNG có**, nên nếu sau deploy +> chuỗi XUẤT HIỆN đúng bội-số ⇒ chính commit này đã lên đĩa, không thể do bundle cũ hay cache. + +### §3.d DỰ ĐOÁN (chốt TRƯỚC khi đo bundle mới) + +| Chuỗi | admin MỚI | user MỚI | +|---|---|---| +| `chỉ người trên mới thao tác cấp này` | **1** | **1** | +| `Cấp hiện tại chỉ người được phân công` | **3** | **3** | +| `Trả lại người soạn sửa` | **2** | **2** | +| `bg-slate-200 text-slate-500` (hiệu-chuẩn) | **4** (3→4) | **4** (3→4) | + +### §3.e SỐ ĐO bundle MỚI — **4/4 dự đoán KHỚP TỪNG ĐỒNG** ✅ + +Bundle mới (rotate **4/4**): admin js `D4uy3yxF`→**`BPWQQe4q`** · css `9okZenCM`→**`KS0kL7bG`** · +user js `C1ASe0K1`→**`DV3fEpOw`** · css `BfN7IuxJ`→**`Cpp9Qc7C`**. +Size: admin 1.709.294 → **1.720.297** (+11.003 B) · user 1.625.473 → **1.636.476** (+11.003 B) — +**delta BẰNG NHAU 2 app**, khớp việc file panel là MIRROR SHA256 identical. Cả 2 `ct=application/javascript`. + +| Chuỗi | Dự đoán | admin đo | user đo | KL | +|---|---|---|---|---| +| `chỉ người trên mới thao tác cấp này` | 1 / 1 | **1** | **1** | ✅ | +| `Cấp hiện tại chỉ người được phân công` | 3 / 3 | **3** | **3** | ✅ | +| `Trả lại người soạn sửa` | 2 / 2 | **2** | **2** | ✅ | +| `bg-slate-200 text-slate-500` (hiệu-chuẩn) | 4 / 4 | **4** | **4** | ✅ | +| `Không phải lượt bạn` (PE 1 + KHKK 1) | 2 / 2 | **2** | **2** | ✅ bonus nhất-quán | + +> Cả 3 marker đi từ **0 (bundle W2) → đúng bội-số nguồn (bundle W3)**, và chuỗi hiệu-chuẩn đi **3→4** +> đúng bằng +1 lần xuất hiện trong file mới ⇒ không chỉ "có ship", mà ship **ĐÚNG BẤY NHIÊU**, không thừa không thiếu. + +### §3.f Control ÂM 2 tầng (bundle cũ phải BIẾN MẤT khỏi đĩa) + +| Phép | code | content-type | size | KL | +|---|---|---|---|---| +| admin hash **CŨ** `index-D4uy3yxF.js` | 200 | `text/html` | 900 | ✅ đã bị ghi đè | +| user hash **CŨ** `index-C1ASe0K1.js` | 200 | `text/html` | 876 | ✅ đã bị ghi đè | +| admin hash **BỊA** `index-ZZZZ9999.js` | 200 | `text/html` | **900** | ✅ trùng khít hash cũ | +| user hash **BỊA** `index-ZZZZ9999.js` | 200 | `text/html` | **876** | ✅ trùng khít hash cũ | + +⟹ hash CŨ trả về **byte-size y hệt hash BỊA** ⇒ 200 đó là SPA-fallback `index.html`, không phải file thật +(bẫy #69/SPA-fallback). Bundle W2 đã bị xoá khỏi đĩa ⇒ deploy ghi đè THẬT. + +**PHÉP 3 = PASS.** + +--- + +## §4. Smoke + transitions THẬT — PASS ✅ [LEAD đo on-behalf] + +- login admin token-468 · `POST .../00000000-…-01/transitions` body `{"action":"nonsense"}` → **409** ProblemDetails "Hành động không hợp lệ" (validate-action TRƯỚC load-plan — đúng thiết kế skeleton đợt-1). +- body `{"action":"approve"}` GUID ma → **404** ProblemDetails "Không tìm thấy ContractSigningPlan" (GlobalExceptionMiddleware map đúng; endpoint transitions SỐNG prod). + +--- + +## §5. Cờ `KeHoachKyKet` 13/13/2 — PASS ✅ [LEAD đo on-behalf] + +sqlcmd prod: `KHKK_CU=13/13/2` GIỮ · MIGTOP `20260729122015_AddContractSigningPlans` GIỮ · MIGCOUNT 69 · TABLES 96 · MENU **142 GIỮ** (§2 0-mig PASS luôn tại đây). + +--- + +END cicd-verify df52fa0 — **VERDICT=PASS 5/5** (§1+§3 cicd-monitor · §2+§4+§5 lead 2-nguồn) + +--- diff --git a/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md b/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md new file mode 100644 index 0000000..febc23c --- /dev/null +++ b/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md @@ -0,0 +1,19 @@ +# W3-SYNTHESIS — Wave W3 KHKK: Duyệt 3 trạm + finalize chốt giá (S161, 2026-07-29) — VERIFIED + +> Lead-verified. Chi tiết: 5 sub-md + cicd-verify cùng cấp. Wave NẶNG NHẤT của dry-run — về đích sạch nhất. + +## KẾT QUẢ: W3 SHIP PROD — cicd VERDICT=PASS 5/5, commit `df52fa0` (11 file, +2.370/−6) +- **Test-before trọn vòng đầu tiên của arc:** 3 đợt {skeleton → 6 test PIN RED-evidence 6/6 → implement GREEN 6/6} · suite 574 → **580/0**. +- **OR-of-N fidelity 0-lỗi** (reviewer trục-1): con-trỏ đôi + GroupBy Order + UPSERT "(duyệt — không ý kiến)" — 0 vết Proposal-flatten. +- **Choke-point 1-SITE-BY-DESIGN**: hợp-đồng transitions không có `targetPhase` ⇒ admin cũng xuyên `approve` → xuyên choke-point — triệt lớp #81 từ kiến trúc. +- **Hợp-đồng LEAD-định-nghĩa literal: KHỚP 5/5** (trục W2 từng đứt 6 điểm — quy trình mới ăn ngay wave đầu áp). +- Prod smoke transitions THẬT: nonsense→409 đúng lời + GUID-ma→404 ProblemDetails. +- Q1-Q6 + 3 quyết đợt-1 đều khai-lead-duyệt (khuôn "khai-không-tự-nuốt" chạy đều 2 lane). + +## BÀI ĐẮT NHẤT — "lời-khai ≠ phép-đo" xuất hiện cả phía NGƯỜI-KHAI-TỐT +Lane đợt-3 khai phép kiểm "git diff 1 dòng" cho file UNTRACKED — phép KHÔNG TỒN TẠI (diff rỗng với ??), dù substance đúng 100% khi lead soi ruột (comment sửa-seed tại chỗ + assert nguyên vẹn). W2 lớp này ở dạng giả-định-hộ-người-khác (D1); W3 ở dạng phép-kiểm-tự-khai-sai. ⇒ Luật: verdict dựa lời-khai PHẢI chạy lại đúng PHÉP được khai — phép không chạy được là caveat bất kể kết quả. + +## VẬN HÀNH — #53: 5/5 lượt spawn chết, 0 byte mất (sub-md 4 file ~48KB + cicd-verify) +## TỒN +1. Mark-read chuông cũ khi phiếu rời Cấp (mirror PE S96) — vá riêng ngoài unit-of-work, chờ anh gật. +2. UAT tay trọn vòng cần: dựng WF type-10 3-trạm (Designer, trước W5) + tài khoản non-Admin (carry W1). diff --git a/.claude/workflows/runs/2026-07-29-S161-khkk-w6-duongong/run.md b/.claude/workflows/runs/2026-07-29-S161-khkk-w6-duongong/run.md new file mode 100644 index 0000000..f650c54 --- /dev/null +++ b/.claude/workflows/runs/2026-07-29-S161-khkk-w6-duongong/run.md @@ -0,0 +1,24 @@ +# RUN — W6 KHKK: Đường ống HĐ V2 — view + inbox + vai-trình (S161, 2026-07-29) + +> Wave 4/6 thi công. Spec: `../2026-07-29-S160-khkk-dryrun-plan/spec-wave-w6-duong-ong-hd-v2-29-07-2026.md` (đã vá DR-4 @S161: nhánh ADMIN F-B13 tường minh §②-4 + 1 vế acceptance admin-inbox). W1 `a8027c0` · W2 `6cbc6ad` · W3 `df52fa0` ĐÃ SHIP. +> **Gate 5-anchor PASS 5/5** (GetEligiblePhases :334 · PhaseActorRoles :421-430 · Forbidden :488-489 · guard-trình CWS :73-78 · Controller inbox :38-40 — content-exact, 0 drift). +> BE-only · 0 mig · 0 UI mới. Baseline test 580 (45D+535I). + +## taskList snapshot + +| # | Stage | Vai | Trạng thái | +|---|---|---|---| +| 1 | Đợt-1: BE 3 fix wiring — view per-HĐ 3 call-site + inbox ghép V2-set + nhánh ADMIN (mirror PE :731-748) + guard trình nới PMH | hmw `implementer-backend` | [ ] | +| 2 | Đợt-2: test-specialist 5 test PIN §③-B | hmw `test-specialist` | [ ] | +| 3 | Lead: suite + acceptance | lead | [ ] | +| 4 | Reviewer (security wave — đổi view-guard) | `reviewer` | [ ] | +| 5 | Commit + push + cicd | lead + `cicd-monitor` | [ ] | + +## Ràng buộc +- 🔴 3 call-site GetEligiblePhases (:301/:381/:486) — sửa CHỈ 1 = F-S3 tái diễn; per-HĐ membership KHÔNG role-blanket, admin thấy-hết. +- 🔴 Nhánh Reject-trước-guard :49-66 = O-A ĐỂ MỞ, ĐỪNG "tiện tay sửa". +- 🔴 Ca ÂM pin ROLE cụ thể (CostControl/Procurement — KHÔNG HrAdmin cho pass dễ). +- 🔴 Kiểm hở xóa-mềm :381. + +## Stages +(cập nhật theo tiến độ)