wal: flush 20260731T1720

This commit is contained in:
pqhuy1987
2026-07-31 17:20:31 +07:00
parent f851f1015f
commit 07cc86c2f0
7 changed files with 312 additions and 57 deletions

View File

@ -38,12 +38,15 @@ chain:
(xoá-mềm-chặn + reflection ?group=) · F-2/F-5/F-7/F-8/F-9 comment-honest (lý-do-thật filtered-index
khả-thi, thì-tương-lai K4b, Down-data-dependent, default-0-SQL-thô) · F-3 STATUS 607→609 · F-4 SKILL 97.
Suite 609/0 (45D+564I) · npm ×2 (comment-only ⇒ bundle hash giữ) · SHA-pair ✓
[x] commit K2 0779f2d 23-file PUSH 89b5bbe..0779f2d (lần 1 FAIL PS5.1-quote-trap → -F file; wal-push
xen giữa vô hại) — cicd-monitor K2 chạy nền (sub-cicd-verify-k2.md)
[!] wf: K3-BE wf_a04124a7-0fe ĐANG CHẠY (bước-0 fail-closed verify đội-hình QT-DN-V2-001 LIVE prod →
seed 8 workflow KHKK-N1..N8 resolve-EMAIL + port finalize [tiêu thụ EndedByLevelFinalize K2 đẻ] +
sweep ép-false 3-site-BE + validator pin-đúng-nhóm + 8 MenuKeys AwV2_KhkkN* + seed cờ CCM-Chương
cùng-commit #78). Song song: cicd-K2 verify nền. Sau BE: K3-FE + K3-test → gate K3 → push
[x] commit K2 0779f2d 23-file PUSH (lần 1 FAIL PS5.1-quote-trap → -F file) → cicd-K2 PARTIAL 5/6
deploy-KHỎE (run #435 · gate-CI 609 tách-phần · Mig71 prod-top+restart-proof · bundle 4/4 rotate ·
smoke 6/6 ?group= wired; mục-4 backfill/Σ = CHÂN-LÝ-RỖNG prod-0-phiếu — đo lại khi K8 đẻ phiếu thật.
cicd #53 return-garble tiếp, artifact trọn)
[!] wf: K3-BE p2 ĐANG CHẠY (p1 wf_a04124a7 = engine-process-exit 0-delta-0-artifact; LEAD tự chạy bước-0:
prod = localhost\SQLEXPRESS [ghi lại — localhost/tcp:1433 đều fail], QT-DN-V2-001 LIVE 1-active+2-
archived type-1, ROSTER 3-trạm PRO→CCM→CEO 11 người ghi nguyên văn sub-implbe-k3.md §0, vá-11 danh-
tính phân giải bằng dept, chuong.phan = giữ cờ finalize; p2 seed từ bảng verified — khỏi ssh).
Song song: cicd-K2 verify nền. Sau BE: K3-FE + K3-test → gate K3 → push
[ ] MANDATE còn lại (🔴 owner @PAUSE-2 "chạy 1 mạch ko ngừng"): K2(FE+test sau BE)→gate→push → K3 →
K4a→K4b→K5→K4c→K6 → K7 → K8-prep (form 14 người fail-closed = điểm dừng hợp lệ duy nhất).
Mỗi wave: build+test+reviewer-gate rồi lăn; DỪNG chỉ khi FAIL cứng. OG-6 = soát-SAU (HẾT chặn push).

View File

@ -1,16 +1,17 @@
# CI/CD Monitor Agent — Persistent Memory
- **07-31 verify `50e6d8c` S164 K1 SP-002 danh-mục-loại-HĐ (20 file: 11 BE + 6 FE + 1 test + 2 docs, +Mig 70):** **PASS 6/6** — Run **#434** (id=547) success **6m31s** (dài nhất 4-run gần đây: #431/#432/#433 ~5m50; hợp lý vì +Mig+seed-86+8-test — chưa tới ngưỡng escalate). Gate **598 = 45D + 553I** (0 fail/skip) — Domain **GIỮ 45**, Infra **545→553 = +8** ⇒ delta rơi TRỌN vào Infra đúng nơi file test mới nằm (đối-chiếu TÁCH-PHẦN bắt được điều tổng-số giấu). Mig 70 `20260731072441_AddContractCatalogEntries` **TOP prod**, `sys.tables` 96→**97** khớp `grep -c CreateTable`=**1**. 🔑 **TAM-GIÁC 3 NGUỒN ĐỘC-LẬP** cho seed: source-parse `DbInitializer` == sqlcmd prod == **API materialize qua EF** — cả 3 ra `86` + `1:5·2:10·3:5·4:23·5:14·6:15·7:13·8:1` y hệt; nguồn 3 mạnh nhất vì đi trọn Domain→Infra→Api (200, 25.374 B, distinct-code 86). Serilog `Seeded 86 contract catalog entries (S164 SP-002)` @15:52:27 + control-ÂM findstr chuỗi-bịa 0 hit. Bundle **4/4 ROTATE** (admin `B43R6Y17``CKgq0YlH`, user `NLI5umBg``CHMCU35C`) + **4/4 hash CŨ rơi `text/html` 876/900 B** = ghi-đè thật; LM 15:51:06/15:52:07 in-window. Smoke 8/8: `/health` bare **404** (control) · `/health/{ready,live}` 200 · endpoint mới không-token **401** kèm **2 route BỊA 404** ⇒ 401 CÓ NGHĨA. w3wp PID 2644 StartTime 15:52:13 in-window + log dòng-đầu `Applying migrations...` ⇒ đo SAU recycle (né #423). ⚠️ **BÀI MỚI — 0-hit là DƯƠNG-GIẢ tới khi soi format**: grep `Passed!` lần đầu **0 hit** chỉ vì log dùng 2-khoảng-trắng (`Passed! - Failed: 0`); suýt báo "không thấy dòng test". Cùng class: parse seeder lần 1 ra **78** (regex line-anchored, tuple xuống dòng) — vứt số, parse lại ra 86 + cross-check `raw code-literal`=86. ⚠️ **hash CI ≠ hash local build** (local dự-báo `BE7zE81C`/`DSXJJbJq`, CI ra khác) ⇒ CẤM lấy hash local làm mốc kỳ-vọng prod, luôn re-snapshot LIVE. Evidence: `runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k1.md`. Tag `[run-434, pass-6-6, tam-giac-3-nguon, 0-hit-la-duong-gia, gate-598, mig-70, hash-CI-khac-local]`
- **07-31 verify `0779f2d` S164 K2 SP-002 KHKK mang hạng-mục + nhóm duyệt N1-8 (23 file: 9 BE + 8 FE + 3 test + Mig 71 ×3 + 2 ignored-path):** ⚠️ **PARTIAL 5/6** deploy KHỎE, điểm trừ = **phép đo không có răng**, không phải lỗi ship. Run **#435** (id=548) success **6m12s**. Gate **609 = 45D + 564I** (0 fail/skip) — Domain **GIỮ 45**, Infra 553→**564 = +11** khớp TỪNG VẾ kỳ-vọng "9 lane + 2 gate-fix". Mig 71 `20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime` TOP prod (MIGCOUNT=71), `sys.tables` **97 GIỮ NGUYÊN** khớp `grep -c CreateTable`=**0** (control dương `grep -c AddColumn`=4). 🔴 **BÀI LỚN NHẤT — ACCEPTANCE RƠI VÀO CHÂN-LÝ-RỖNG**: `ContractSigningPlans` prod **0 dòng cả PRE lẫn POST** ⇒ cả 3 acceptance mục 4 (`COUNT(group=1)==COUNT(*)``0==0`; `NOT BETWEEN 1 AND 8`=0; Σ tiền `NULL==NULL`) đều "xanh" mà **0 bit thông tin** — backfill hụt sẽ trông Y HỆT. Tác giả Mig 71 đã khai bẫy này ở comment ("đo local Σ = tập RỖNG hai phía… phép đo prod mới có răng") — nay prod cũng rỗng nốt ⇒ phép đo prod CŨNG hết răng. KHÔNG hạ FAIL (không có gì sai) nhưng CẤM đọc thành PASS. 🔑 **Đối-sách khi acceptance rỗng → thay bằng bằng-chứng KHÔNG-phụ-thuộc-số-dòng**: (a) 4 cột đúng kiểu/null/default qua `INFORMATION_SCHEMA`; (b) **hoán-đổi index chứng bằng LIỆT KÊ TRỌN HỌ 14 index** — 3-cột unique filtered `([IsDeleted]=(0))` CÓ + 2-cột cũ MẤT, vắng-mặt suy từ danh-sách-đầy-đủ nên là vắng-mặt ĐO ĐƯỢC (mạnh nhất mục 4); (c) Σ bất-biến chứng theo **CẤU TRÚC**: grep cột tiền trên Mig 71 ra 2 hit **đều là comment `//` dòng 23-24** ⇒ 0 câu lệnh thực thi, đúng kể cả khi có dữ liệu; (d) EF materialize 200-không-500. 🔑 **MỚI — chứng query-param ĐƯỢC WIRE bằng bind-error**: `?group=abc`**400** (param lạ mà bị nuốt thì ASP.NET trả 200) + khớp nguồn `Controller:42 [FromQuery(Name="group")] int? group`; `?group=1/2/8` chỉ ra `{"items":[],"total":0}` = VACUOUS. Áp bài K1: soi **thân RAW** trước khi tin parser ⇒ rỗng THẬT. Control DƯƠNG đường-ống list: `/api/catalogs/contract-catalog` **86 item** (seed K1 nguyên) ⇒ ống chạy, `items:[]` là bảng rỗng thật. Bundle **4/4 ROTATE** (admin `CKgq0YlH``DVQEwGwf`, user `CHMCU35C``CZAYiWWa`) + hash CŨ **và hash BỊA** cùng rơi `text/html` 900/876 B ⇒ `text/html` thật sự nghĩa "không tồn tại"; LM 17:10:20/17:11:20 in-window. Smoke: `/health/{ready,live}` 200 + bare `/health` **404** control · no-token **401** kèm **2 route BỊA 404**. w3wp **PID 5364 = `SolutionErp-Api`** (map PID→pool bằng `appcmd list wp` vì VPS có 6 w3wp chung VIETREPORT — CẤM đoán PID) StartTime 17:11:25 + Serilog dòng-đầu `Applying migrations...` 17:11:27 ⇒ mọi đo DB từ 17:12+ = SAU recycle. Quan sát cho K4b: `?group=999`**200** (biên API không chặn ngoài-miền 1..8, hiện vô hại); ghost-window `EndedByLevelFinalize` luôn 0 tới khi K3 land = ĐÚNG hiện trạng. Evidence: `runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k2.md`. Tag `[run-435, partial-5-6, chan-ly-rong-vacuous, liet-ke-tron-ho-index, wire-proof-bang-bind-400, gate-609, mig-71, map-PID-pool]`
- _(**07-31 `50e6d8c` S164 K1 SP-002 danh-mục-loại-HĐ +Mig 70 — PASS 6/6**: run #434 6m31s, gate 598, `sys.tables` 96→97. 🔑 **TAM-GIÁC 3 NGUỒN ĐỘC-LẬP** cho seed (source-parse `DbInitializer` == sqlcmd prod == **API materialize qua EF**, cả 3 ra 86 + phân-bố `1:5·2:10·3:5·4:23·5:14·6:15·7:13·8:1`; nguồn 3 mạnh nhất vì đi trọn Domain→Infra→Api). ⚠️ **BÀI: 0-hit là DƯƠNG-GIẢ tới khi soi format** — grep `Passed!` ra 0 chỉ vì log dùng 2-khoảng-trắng; cùng class parse seeder ra 78 (regex line-anchored, tuple xuống dòng) → vứt số, parse lại 86. ⚠️ **hash CI ≠ hash local build** ⇒ CẤM lấy hash local làm mốc kỳ-vọng prod. verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**07-30 `bfc7b79` S162 cây-4-folder-GĐ FE-ONLY — PASS 5/5**: run #432 5m35s, gate 590. 🔴 **LUẬT CẤM `HEAD~1`** — Stop-hook WAL auto-commit giữa lúc verify làm `HEAD~1` đổi nghĩa ⇒ tao kết SAI "marker vô giá trị"; đo lại bằng SHA tuyệt đối `X^..X` thì 0 hit ⇒ marker hợp lệ. 🔑 **ĐẾM TRỌN HỌ bằng 1 REGEX** `pipeline-[a-z-]{0,24}index` ra đúng 3 phần tử khớp source element-wise (vừa vế DƯƠNG vừa tự chứng regex không quét bừa). ⚠️ suýt FAIL-OAN: nhãn cũ 8/app sống hợp lệ — control ÂM phải ĐỘC-QUYỀN. verbatim → `runs/2026-07-30-S162-cay-4-folder-gd/sub-cicd-monitor-2.md`)_
- **07-30 verify `bfc7b79` S162 cây-4-folder-GĐ (FE-ONLY, 17 file, 12 FE = 6+6 đối xứng ×2 app):** ✅ **PASS 5/5** — Run **#432** (id=545) success **5m35s**; gate **590 = 45D+545I** (0 fail/skip). 0 mig/0 BE ⇒ không chân EF. Bundle **4/4 ROTATE** (admin js `BBQKvUMa``DXoYDy7R` · user js `BV5--mPf``o8KDluD1`, css cả 2 đổi); `index.html` LM 10:09:07 in-window + `Cache-Control:no-cache`. 🔴 **BẪY MỚI — MOVING-TARGET `HEAD~1`:** phiên có Stop-hook WAL **tự commit giữa lúc verify**`HEAD~1` đổi nghĩa từ 'cha commit đích' thành 'chính commit đích' trong ~6 phút. Tao đã kết SAI '2 marker có sẵn ở parent ⇒ vô giá trị'; đo lại bằng SHA tuyệt đối `8eba137` thì **cả 2 = 0 hit** ⇒ marker hợp lệ. **LUẬT: verify commit X luôn neo `X^..X` bằng SHA, CẤM dùng `HEAD~1`** (mọi repo có hook auto-commit). 🔑 **Khuôn MỚI 'ĐẾM TRỌN HỌ bằng 1 REGEX'**: `pipeline-[a-z-]{0,24}index` quét bundle ra **đúng 3 phần tử** `{contract×2, khkk×1, pe×1}` khớp source element-wise ⇒ vừa là vế DƯƠNG, vừa tự chứng regex không quét bừa (mạnh hơn đếm chuỗi rời). Dự-đoán-trước-khi-đo khớp từng đồng: `contract-index`=2 (= số FILE trong diff) · VN `Kế hoạch Hợp đồng`=**1** (source 3 **2 comment**) · raw-UTF8 không escape. ⚠️ **suýt FAIL OAN lần nữa:** `Kế hoạch ký kết HĐ` (nhãn strip cũ) = **8/app** — KHÔNG dùng làm control ÂM được vì synthesis ghi rõ nhãn folder GĐ2 **cố ý khác** nhãn strip; 1-mới + 8-cũ cùng sống = chứng phân-biệt-phiên-bản. Control ÂM: chuỗi-BỊA `pipeline-hardcopy-index`=0 (source cũng 0) + hash BỊA & **hash CŨ cả 2 app** đều `ct=text/html` **876B/900B trùng khít size index.html** ⇒ bundle cũ biến mất = ghi đè thật. Smoke 4×200 + bare `/health` **404** (control). WAL-commit `a07b942` (3 file `.md`) bị `paths-ignore` nuốt ⇒ không đẻ run rác. Evidence: `runs/2026-07-30-S162-cay-4-folder-gd/sub-cicd-monitor-2.md`. Tag `[run-432, pass-5-5, CAM-HEAD~1-neo-SHA, dem-tron-ho-1-regex, control-am-DOC-QUYEN-lan-2, gate-590, fe-only]`
- _(**#427 S161 W1 KHKK `a8027c0` +Mig 69 `AddContractSigningPlans` — PASS 6/6**: gate 566, 5m40s; `sys.tables` **89→96** (+7 khớp 7 CreateTable), MenuItems 142 GIỮ. 🔑 **khuôn ĐO-CỜ không đếm ROW** (row tồn tại sẵn ⇒ đếm row = 0-bit; đo PRE/POST **cờ** 7 key 13/0/0/0→13/13/13/2) + 🔑 **control ÂM NỘI-HỌ: `Khkk_G1` bị seeder CỐ Ý bỏ khỏi tập** ⇒ phải đứng yên, và nó đứng yên ⇒ chứng 'đúng NGƯỜI, đúng TẬP'. Đọc seeder **dự đoán `0 added + 91 upgraded` TRƯỚC khi đo → log prod khớp từng đồng**. verbatim → `archive/2026-07.md` substring:"a8027c0` W1 KHKK")_
- _(**#426 S159 đợt-5 `ea962b1` menu 6-leaf + `GET /contracts/deleted` — PASS 9/9**: gate 562. 🔑 **LUẬT gốc control-ÂM-phải-ĐỘC-QUYỀN** (cứu false-fail: chuỗi brief bảo phải vắng vẫn sống hợp lệ ở `aria-label` ⇒ grep repo-wide TRƯỚC; chuỗi dùng-chung chỉ làm marker DƯƠNG). 🔑 **SEEDER-INSERT delta khớp TOÁN**: MenuItems **119→142 = +23 = 7+7+7+2**. Endpoint mới 401 **kèm route bịa 404** ⇒ 401 CÓ NGHĨA. ⚠️ bẫy phạm-vi query: `Ct_*` đẻ thêm 21 key ⇒ `LEFT(MenuKey,3)` không so được với đợt trước. verbatim → `archive/2026-07.md` substring:"#426 S159 đợt-5")_
- _(**S159 arc đợt-1→4 (#422 `b5799fc` · #423 `1a47a61` · #424 `2a72695` · #425 `a2bbcb9`) + S157 #419 `a52a91e`** — gate 562. 🔴 **ĐÍNH CHÍNH @S162 (H2 F-02 HIGH):** câu cũ ở đây viết *"verbatim → `archive/2026-07.md` via `_INDEX`"* cho CẢ 5 run — **SAI**: `#423`/`#424`/`#419` có trong archive ✅ nhưng **`#422 b5799fc``#425 a2bbcb9` CHƯA TỪNG vào archive** (`git log -S"b5799fc" -- .claude/agent-memory/cicd-monitor/archive/` **RỖNG toàn lịch sử**). Mất **lớp đã chưng cất**, KHÔNG mất nguyên-liệu — còn nguyên ở `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-b5799fc.md` (9.930 B) + `cicd-verify-a2bbcb9.md` (9.860 B); re-distill khi retro-harvest folder đó (HANDOFF NEXT-em #2). **Bài: stub tự khai "đã archive" là một CLAIM, phải đo mới được viết** — cùng class với F-03 (trích verbatim chuỗi không tồn tại) trong cùng phiên. Bài-học CÒN DÙNG: 🔴 **#423 PARTIAL 8/9 = phát hiện lớn nhất arc** `RevokeTemporarilyHiddenModulesAsync` UNGATED lật 447/494 row grant SQL tay; tao sót vì **đo TRƯỚC recycle** (query lúc `running` = trạng thái CŨ) → đã nâng thành luật 3-CHÂN-KIỀNG ở 'Recurring bug patterns'; đóng ở #424 (guard 2-vế StillHidden/Reopened, 494/494 sống qua restart ×3). 🔑 #425 **comment-strip dự-đoán-trước-rồi-mới-đo** (source=2 đều trong comment → dự đoán bundle=0 → đúng 0); marker phổ-thông chỉ dùng '≥1' (`Không tìm thấy` bundle 10 > source 3). 🔑 #425 **FROZEN vẫn lành tính nếu LM in-window** (#69 mode-B). 🔑 #422 **marker PHÂN-BIỆT-PHIÊN-BẢN** (cặp chữ cũ/mới sau review: `Toàn trình`=1 & `Pipeline`=0 ⇒ prod chạy bản ĐÃ-FIX); ⚠️ **LỆCH-số phải truy PHẠM-VI-QUERY trước khi hô drift** (`LEFT(,3)` vs `LIKE 'Pe%'`). 🔑 #419 byte-marker **count = SỐ FILE trong diff** ('đúng-BỘI-SỐ' > 'tìm thấy ≥1') + control âm 2 tầng fake-hash & hash-CŨ → `text/html`)_
- _(**S159 arc đợt-1→4 (#422 · #423 · #424 · #425) + S157 #419** — gate 562. 🔴 **#423 PARTIAL 8/9 = phát hiện lớn nhất arc**: `RevokeTemporarilyHiddenModulesAsync` UNGATED lật 447/494 row grant SQL tay; tao sót vì **đo TRƯỚC recycle** → đã nâng thành luật 3-CHÂN-KIỀNG ở 'Recurring bug patterns'; đóng ở #424 (guard 2-vế, 494/494 sống qua restart ×3). 🔑 #425 comment-strip **dự-đoán-trước-rồi-mới-đo**; FROZEN vẫn lành tính nếu LM in-window (#69 mode-B). 🔑 #422 **marker PHÂN-BIỆT-PHIÊN-BẢN** (cặp chữ cũ/mới ⇒ chứng prod chạy bản ĐÃ-FIX); ⚠️ **LỆCH-số phải truy PHẠM-VI-QUERY trước khi hô drift**. 🔑 #419 byte-marker **count = SỐ FILE trong diff**. ⚠️ **ĐÍNH CHÍNH: `#422`/`#425` CHƯA TỪNG vào archive** (mất lớp chưng-cất, KHÔNG mất nguyên-liệu — còn ở `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-{b5799fc,a2bbcb9}.md`); **bài: stub tự khai "đã archive" là CLAIM, phải đo mới được viết**. verbatim (#423/#424/#419) → `archive/2026-07.md`)_
- _(**#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`)_

View File

@ -71,3 +71,8 @@
- **07-29 verify `a8027c0` W1 KHKK — Mig 69 `AddContractSigningPlans` [S161, 30 file +8987/22]:** ✅ **PASS 6/6** — Run **#427** (id=540) success **5m40s**; gate **566 = 45D+521I** (0 fail/skip, +4 test W1). Mig 69 APPLIED-PROD: MIGTOP `20260729122015_AddContractSigningPlans` · MIGCOUNT 68→**69** · `sys.tables` **89→96 (+7 khớp 7 CreateTable)** · 7 bảng `ContractSigningPlan{s,Lines,DossierItems,LevelOpinions,Attachments,Changelogs,Approvals}`. MenuItems **142→142 GIỮ** (policy-key ⟂ menu-key). 🔑 **KHUÔN ĐO-CỜ (không đếm ROW) — tái dùng cho mọi seeder UPGRADE-if-exists:** row đã tồn tại CanRead-only ⇒ đếm row = 0-bit; đo PRE/POST **cờ** 8 key: 7 key đích 13/0/0/0 → **13/13/13/2**, vế ÂM liệt-kê-toàn-bộ `CanDelete=1` = **đúng 14 row = {Admin,Drafter}×7** (11 role kia D=0), Drafter (non-Admin) C/U/D=1. 🔑 **Control ÂM NỘI-HỌ mạnh nhất từ trước tới nay: `Khkk_G1` bị seeder CỐ Ý bỏ khỏi danh sách 7 key** ⇒ nó phải đứng yên 13/**0/0/0** — và nó đứng yên ⟹ chứng "đúng NGƯỜI làm, đúng TẬP", không phải thứ gì lật bừa cả họ. **Đọc seeder DỰ ĐOÁN `0 added + 91 upgraded` (91=7×13) TRƯỚC khi đo → log prod khớp từng đồng** (`added=0` = đúng đường upgrade, F-S1 đóng). Marker `QT-KHKK-V2-001` grep repo TRƯỚC ⇒ độc quyền 1 site fe-admin ⇒ dự đoán admin=1/user=0, đo đúng; **control ÂM 3 TẦNG**: hash CŨ `D0sXA0fe``ct=text/html` 900B **trùng khít hash BỊA** ⇒ 200 là SPA-fallback, bundle cũ đã bị ghi đè. admin js+css rotate (`M8SDA7Ps`/`C3xzT0H9`); user FROZEN nhưng **LM 20:10:00 in-window**#69 mode-B lành tính. Restart chứng bằng **w3wp pid=4980 StartTime 20:10:05 TRÙNG dòng CI `App pool started`** + DLL mtime 20:07:50. Label F-7 sống: `?applicableType=10``"applicableTypeLabel":"Kế hoạch ký kết HĐ"`, `active:null/history:[]` + sqlcmd `ApplicableType=10`=0 ⇒ chưa dựng WF (đúng W1). Smoke 4 endpoint 200 + **route bịa 404** (chứng 200 CÓ NGHĨA). Durability `Ct_` **637/637** CanRead, root 12, DUPKEYS 0. Evidence: `runs/2026-07-29-S161-khkk-w1-schema/cicd-verify-a8027c0.md`. Tag `[run-427, pass-6-6, do-CO-khong-dem-ROW, control-am-noi-ho-key-bi-bo-sot, du-doan-91-upgraded-khop, control-am-3-tang-bundle, mig69-96-bang, gate-566]`
- _(**#426 S159 đợt-5 `ea962b1` menu 6-leaf + `GET /contracts/deleted` + bỏ hero — PASS 9/9**: gate 562, 5m38s. JS rotate cả 2 app (admin `CC1pGE1F``D0sXA0fe` · user `CLfAftby``Y6dW_5CM` +css `B6bUSFBt``6YIAufJR`); admin-css FROZEN nhưng **LM 14:44:29 in-window** ⇒ lành tính (#69 mode-B, khuôn đợt-4 dùng lại được ngay). 🔑 **CỨU FALSE-FAIL — luật MỚI về control ÂM:** brief bảo `Toàn trình 4 giai đoạn` phải VẮNG; tao grep repo-wide TRƯỚC khi đo → chuỗi vẫn sống hợp lệ ở `PePipelineStrip.tsx:24` **`aria-label`** (cả 2 app, có từ đợt-2) ⇒ **dự đoán bundle=1 chứ không 0**, đo đúng 1. Áp máy móc là FAIL OAN. Thay bằng `Quy trình mua sắm` (eyebrow hero) — `grep -rc` 2 app = **0 hit mọi file** ⇒ ĐỘC QUYỀN ⇒ bundle=0 = chứng hero đã gỡ (kèm `UserDashboardPage` 63.124→50.142 B). ⟹ **LUẬT: trước khi nhận 1 chuỗi làm control ÂM phải grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ mình muốn chứng vắng; chuỗi dùng-chung chỉ làm marker DƯƠNG.** 🔑 **SEEDER-INSERT delta khớp TOÁN (khuôn mạnh, tái dùng):** đo baseline TRƯỚC deploy rồi so SAU restart — `Ct_%_WfView` 0→**7** · `_Approved` 0→**7** · `_Deleted` 0→**7** · `Khkk_%` 5→**7** · nhãn `Ct_%_Pending`=`Đang%` 0→**7** · Dashboard `%quy tr%` 0→**1** · **MenuItems 119→142 = +23 = 7+7+7+2 khớp từng đồng** · root 12 · DUPKEYS 0 · **21 key mới đủ 13/13 canread** (nhánh reviewKeys skip-existing ăn vì key HOÀN TOÀN MỚI — khác đợt-2/3 nơi row `false` sẵn có không được nâng). **Endpoint mới:** `GET /api/contracts/deleted`**401** + **control route bịa → 404** ⇒ 401 CÓ NGHĨA, không phải catch-all (đừng chỉ đo 401 trần). ⚠️ brief ghi `/contracts/deleted` thiếu prefix — route thật có `[Route("api/contracts")]`. **Durability lần 3:** 38-key **494/494** · control âm Hrm/Off/Personal=0 · `Pe%` 197/185 · `Hdc_` nhãn 7 · 3 root ẩn. ⚠️ **Bẫy phạm-vi mới: `Ct_*` nay đẻ thêm 21 key ⇒ `LEFT(MenuKey,3)='Ct_'` cho ra 59 key, KHÔNG so được với đợt trước — phải NOT LIKE 3 hậu tố mới để giữ đúng tập 38 gốc.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-ea962b1.md`. Tag `[run-426, pass-9-9, control-am-phai-DOC-QUYEN, seeder-delta-khop-toan, 401-voi-control-404, durability-restart-3, query-scope-re-anchor, gate-562]`
- **07-31 verify `50e6d8c` S164 K1 SP-002 danh-mục-loại-HĐ (20 file: 11 BE + 6 FE + 1 test + 2 docs, +Mig 70):** ✅ **PASS 6/6** — Run **#434** (id=547) success **6m31s** (dài nhất 4-run gần đây: #431/#432/#433 ~5m50; hợp lý vì +Mig+seed-86+8-test — chưa tới ngưỡng escalate). Gate **598 = 45D + 553I** (0 fail/skip) — Domain **GIỮ 45**, Infra **545→553 = +8** ⇒ delta rơi TRỌN vào Infra đúng nơi file test mới nằm (đối-chiếu TÁCH-PHẦN bắt được điều tổng-số giấu). Mig 70 `20260731072441_AddContractCatalogEntries` **TOP prod**, `sys.tables` 96→**97** khớp `grep -c CreateTable`=**1**. 🔑 **TAM-GIÁC 3 NGUỒN ĐỘC-LẬP** cho seed: source-parse `DbInitializer` == sqlcmd prod == **API materialize qua EF** — cả 3 ra `86` + `1:5·2:10·3:5·4:23·5:14·6:15·7:13·8:1` y hệt; nguồn 3 mạnh nhất vì đi trọn Domain→Infra→Api (200, 25.374 B, distinct-code 86). Serilog `Seeded 86 contract catalog entries (S164 SP-002)` @15:52:27 + control-ÂM findstr chuỗi-bịa 0 hit. Bundle **4/4 ROTATE** (admin `B43R6Y17``CKgq0YlH`, user `NLI5umBg``CHMCU35C`) + **4/4 hash CŨ rơi `text/html` 876/900 B** = ghi-đè thật; LM 15:51:06/15:52:07 in-window. Smoke 8/8: `/health` bare **404** (control) · `/health/{ready,live}` 200 · endpoint mới không-token **401** kèm **2 route BỊA 404** ⇒ 401 CÓ NGHĨA. w3wp PID 2644 StartTime 15:52:13 in-window + log dòng-đầu `Applying migrations...` ⇒ đo SAU recycle (né #423). ⚠️ **BÀI MỚI — 0-hit là DƯƠNG-GIẢ tới khi soi format**: grep `Passed!` lần đầu **0 hit** chỉ vì log dùng 2-khoảng-trắng (`Passed! - Failed: 0`); suýt báo "không thấy dòng test". Cùng class: parse seeder lần 1 ra **78** (regex line-anchored, tuple xuống dòng) — vứt số, parse lại ra 86 + cross-check `raw code-literal`=86. ⚠️ **hash CI ≠ hash local build** (local dự-báo `BE7zE81C`/`DSXJJbJq`, CI ra khác) ⇒ CẤM lấy hash local làm mốc kỳ-vọng prod, luôn re-snapshot LIVE. Evidence: `runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k1.md`. Tag `[run-434, pass-6-6, tam-giac-3-nguon, 0-hit-la-duong-gia, gate-598, mig-70, hash-CI-khac-local]`
- **07-30 verify `bfc7b79` S162 cây-4-folder-GĐ (FE-ONLY, 17 file, 12 FE = 6+6 đối xứng ×2 app):** ✅ **PASS 5/5** — Run **#432** (id=545) success **5m35s**; gate **590 = 45D+545I** (0 fail/skip). 0 mig/0 BE ⇒ không chân EF. Bundle **4/4 ROTATE** (admin js `BBQKvUMa``DXoYDy7R` · user js `BV5--mPf``o8KDluD1`, css cả 2 đổi); `index.html` LM 10:09:07 in-window + `Cache-Control:no-cache`. 🔴 **BẪY MỚI — MOVING-TARGET `HEAD~1`:** phiên có Stop-hook WAL **tự commit giữa lúc verify**`HEAD~1` đổi nghĩa từ 'cha commit đích' thành 'chính commit đích' trong ~6 phút. Tao đã kết SAI '2 marker có sẵn ở parent ⇒ vô giá trị'; đo lại bằng SHA tuyệt đối `8eba137` thì **cả 2 = 0 hit** ⇒ marker hợp lệ. **LUẬT: verify commit X luôn neo `X^..X` bằng SHA, CẤM dùng `HEAD~1`** (mọi repo có hook auto-commit). 🔑 **Khuôn MỚI 'ĐẾM TRỌN HỌ bằng 1 REGEX'**: `pipeline-[a-z-]{0,24}index` quét bundle ra **đúng 3 phần tử** `{contract×2, khkk×1, pe×1}` khớp source element-wise ⇒ vừa là vế DƯƠNG, vừa tự chứng regex không quét bừa (mạnh hơn đếm chuỗi rời). Dự-đoán-trước-khi-đo khớp từng đồng: `contract-index`=2 (= số FILE trong diff) · VN `Kế hoạch Hợp đồng`=**1** (source 3 **2 comment**) · raw-UTF8 không escape. ⚠️ **suýt FAIL OAN lần nữa:** `Kế hoạch ký kết HĐ` (nhãn strip cũ) = **8/app** — KHÔNG dùng làm control ÂM được vì synthesis ghi rõ nhãn folder GĐ2 **cố ý khác** nhãn strip; 1-mới + 8-cũ cùng sống = chứng phân-biệt-phiên-bản. Control ÂM: chuỗi-BỊA `pipeline-hardcopy-index`=0 (source cũng 0) + hash BỊA & **hash CŨ cả 2 app** đều `ct=text/html` **876B/900B trùng khít size index.html** ⇒ bundle cũ biến mất = ghi đè thật. Smoke 4×200 + bare `/health` **404** (control). WAL-commit `a07b942` (3 file `.md`) bị `paths-ignore` nuốt ⇒ không đẻ run rác. Evidence: `runs/2026-07-30-S162-cay-4-folder-gd/sub-cicd-monitor-2.md`. Tag `[run-432, pass-5-5, CAM-HEAD~1-neo-SHA, dem-tron-ho-1-regex, control-am-DOC-QUYEN-lan-2, gate-590, fe-only]`

View File

@ -141,4 +141,5 @@
- 2026-07-23 · S155 #407 `4510cea` App chuan-hoa ma du-an normalize + PE attach-gate FE both-apps… · PASS 5/5 · `2026-07.md` · substring:"Run #407 `4510cea` (2026-07-23)"
- 2026-07-27 · S155 #416 `b1bae77` Workflow duyet-TAI-CHO + co F6 AllowApproverDelete… · PASS · `2026-07.md` · substring:"Run #416 `b1bae77` (2026-07-27)"
- 2026-07-28 · S157 #419 `a52a91e` PE canh-bao amber o Dia-diem khi du-an thieu Location… · PASS 9/9 · `2026-07.md` · substring:"Run #419 `a52a91e` (2026-07-28)"
- 2026-07-29 · S159 #423 `1a47a61` dot-2 tab strip 4GD + menu 4-GD — PARTIAL 8/9, bat regression revoker an 447/494 row · `2026-07.md` · substring:"Run #423 `1a47a61` (2026-07-29"
- 2026-07-29 · S159 #423 `1a47a61` dot-2 tab strip 4GD + menu 4-GD — PARTIAL 8/9, bat regression revoker an 447/494 row · `2026-07.md` · substring:"Run #423 `1a47a61` (2026-07-29"- 2026-07-30 · S162 #432 `bfc7b79` cay-4-folder-GD FE-ONLY — PASS 5/5, LUAT cam HEAD~1 (neo SHA X^..X) + dem-tron-ho 1 regex · `2026-07.md` · substring:"07-30 verify `bfc7b79` S162"
- 2026-07-31 · S164 #434 `50e6d8c` K1 SP-002 danh-muc loai-HD + Mig 70 — PASS 6/6, tam-giac 3 nguon doc-lap cho seed 86 + bai "0-hit la duong-gia toi khi soi format" · `2026-07.md` · substring:"07-31 verify `50e6d8c` S164 K1"

View File

@ -1,9 +1,10 @@
CICD-K2: IN-PROGRESS0/6 mục (đang đo)
CICD-K2: PARTIAL5/6 mục (mục 4 = CHÂN-LÝ-RỖNG, không phải sạch)
# CI/CD verify K2 SP-002 — commit `0779f2d`
> Artifact chống #53 — ghi TỪNG MỤC NGAY KHI ĐO. Kết bằng `END … VERDICT=`.
> Vai: cicd-monitor (READ-only). Ngày: 2026-07-31.
> Artifact chống #53 — ghi TỪNG MỤC NGAY KHI ĐO. Vai: cicd-monitor (READ-only). Ngày: 2026-07-31.
> Deploy KHỎE, KHÔNG khuyến nghị rollback. Điểm trừ duy nhất = **phép đo mục 4 không có răng**
> (bảng rỗng), không phải lỗi deploy.
---
@ -17,67 +18,202 @@ $ git log origin/main..HEAD --oneline
(RỖNG — đã push trọn)
```
`git diff --name-only 0779f2d^..0779f2d` = **23 file**:
- BE 9: Controller `ContractSigningPlansController.cs` · `ContractSigningPlanFeatures.cs` · Domain `ContractSigningPlan.cs` + `ContractSigningPlanLine.cs` · 2 Configuration · Service `ContractSigningPlanWorkflowService.cs` (+2 mig file dưới)
- Mig 71: `20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime.cs` + `.Designer.cs` + `ApplicationDbContextModelSnapshot.cs`
- FE 8: fe-admin ×4 (Khkk{Create,Detail,List}Page.tsx + types/khkk.ts) · fe-user ×4 (đối xứng)
- Test 3: `ContractSigningPlanApprovalTests.cs` · `ContractSigningPlanGroupAndCatalogTests.cs` · `ContractSigningPlanSchemaTests.cs`
- paths-ignore 2 (KHÔNG chặn vì ≥1 file code): `docs/STATUS.md` · `.claude/skills/ef-core-migration/SKILL.md`
⇒ CI **PHẢI** chạy (không rơi SKIPPED-DOCS). Neo commit bằng SHA tuyệt đối `0779f2d^..0779f2d` (LUẬT S162: cấm `HEAD~1` vì Stop-hook WAL auto-commit).
---
`git diff --name-only 0779f2d^..0779f2d` = **23 file**: BE 9 · Mig 71 ×3 file (3-file rule đủ) ·
FE 8 (admin ×4 + user ×4 đối xứng) · test 3 · paths-ignore 2 (`docs/STATUS.md`,
`.claude/skills/ef-core-migration/SKILL.md` — KHÔNG chặn vì ≥1 file code).
Neo bằng SHA tuyệt đối `0779f2d^..0779f2d` (LUẬT S162: cấm `HEAD~1`, Stop-hook WAL auto-commit).
## Mục 0b — SNAPSHOT PRE-MIGRATE (đo lúc run #435 còn `running`, 17:07)
```
$ ssh vietreport-vps "sqlcmd ... -Q 'SELECT MAX(MigrationId)...; COUNT(*)...; SUM(...)'"
MIGTOP=20260731072441_AddContractCatalogEntries <- Mig 70 (K1), Mig 71 CHƯA áp
PLANS=0
LINES=0
SUMPE=NULL|SUMPROP=NULL
SYSTABLES=97
```
Bundle PRE (khớp mốc K1 run #434 do em main đưa):
```
PLANS=0 · LINES=0 · SUMPE=NULL|SUMPROP=NULL · SYSTABLES=97
admin /assets/index-CKgq0YlH.js + /assets/index-DD3xQhNt.css
eoffice /assets/index-CHMCU35C.js + /assets/index-CdXRNT7E.css
eoffice /assets/index-CHMCU35C.js + /assets/index-CdXRNT7E.css (khớp mốc K1 #434)
```
🔴 **KHAI TRƯỚC — MỤC 4 SẼ RỖNG, KHÔNG PHẢI SẠCH.** `ContractSigningPlans` prod có **0 dòng**
TRƯỚC migrate. ⇒ 3 acceptance của mục 4 rơi vào **chân-lý-rỗng (vacuous)**:
`COUNT(group=1) == COUNT(*)` thành `0 == 0`; `COUNT(NOT BETWEEN 1 AND 8)` thành `0`; Σ tiền
`NULL == NULL`. Cả ba đều "xanh" mà **không mang thông tin nào** về việc backfill có chạy đúng.
Chính tác giả Mig 71 đã khai bẫy này ở comment ("đo local Σ = tập RỖNG hai phía … phép đo prod
mới có răng") — nay prod cũng rỗng nốt, nên **phép đo prod cũng KHÔNG có răng**.
Đối-sách: thay bằng bằng-chứng KHÔNG-rỗng ở mục 4 (xem dưới): cột tồn tại đúng kiểu/nullability
(`INFORMATION_SCHEMA`), **hoán-đổi index có/mất** (`sys.indexes` — đây là phép đo CÓ RĂNG THẬT
vì không phụ thuộc số dòng), default-constraint, và **EF materialize qua API** (nếu cột thiếu
thì `SELECT` của EF ném 500 chứ không trả 200 ⇒ 200 = chứng cột tồn tại end-to-end).
🔴 **KHAI TRƯỚC — MỤC 4 SẼ RỖNG, KHÔNG PHẢI SẠCH.** Xem mục 4.
---
## Mục 1 — Gitea Actions run
## Mục 1 — Gitea Actions run ✅ PASS
(đang đo — run #435 id=548 `0779f2d4` status=running, created 17:05:33)
| | |
|---|---|
| Run | **#435** (id=548), `0779f2d4` |
| Status | **success** |
| Cửa sổ | created `17:05:33` → updated `17:11:45` = **6m12s** |
| URL | https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/435 |
## Mục 2 — Test gate 609 (45D + 564I)
Poll 6 vòng (17:08:31 → 17:12:26), running×5 → success. 6m12s ≈ K1 #434 (6m31s) — hợp lý cho
+Mig +11 test, chưa tới ngưỡng escalate.
(chưa đo)
## Mục 2 — Test gate 609 ✅ PASS (khớp TÁCH-PHẦN, không chỉ khớp tổng)
## Mục 3 — EF migration prod + chứng-restart
Log web-UI `.../actions/runs/435/jobs/0/logs` (18.677 B), grep nới `Passed![^\r\n]*`:
```
Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, Du
Passed! - Failed: 0, Passed: 564, Skipped: 0, Total: 564, Du
```
| | Domain | Infra | Tổng |
|---|---|---|---|
| K1 #434 | 45 | 553 | 598 |
| K2 #435 | **45** | **564** | **609** |
| delta | **0** | **+11** | +11 |
(chưa đo)
Kỳ vọng 609 = 598 + 9 lane + 2 gate-fix ⇒ khớp **từng vế**: Domain đứng yên, +11 rơi TRỌN vào
Infra — đúng nơi 3 file test mới nằm (`ContractSigningPlanApprovalTests` /
`~GroupAndCatalogTests` / `~SchemaTests`). 0 fail, 0 skipped.
Control ÂM: grep chuỗi bịa `ZZZ_KHONG_TON_TAI_9x7` = **0 hit**.
⚠️ Dùng regex nới ngay từ đầu vì bài K1: log dùng **2 khoảng trắng** sau `Passed!`.
## Mục 4Data prod sau migrate
## Mục 3EF migration prod + chứng-restart ✅ PASS
(chưa đo)
```
MIGTOP=20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime <- TOP, đúng Mig 71
MIGCOUNT=71
SYSTABLES=97 (GIỮ NGUYÊN — Mig 71 có 0 CreateTable)
```
`sys.tables` 97 == 97 khớp phép đo nguồn `grep -c "CreateTable"` = **0** (control dương:
`grep -c "AddColumn"` = **4** ⇒ grep có tìm được thứ có thật).
## Mục 5 — Bundle ×2 app
**3-CHÂN-KIỀNG (né bẫy #423 đo-trước-recycle):**
1. *Restart thật:* `appcmd list wp``WP "5364" (applicationPool:SolutionErp-Api)`;
`Get-Process w3wp` → PID **5364 StartTime 17:11:25** ∈ cửa sổ deploy (17:05:3317:11:45).
(5 w3wp còn lại là pool VIETREPORT/Default — đã map PID→pool để không nhận nhầm.)
2. *Dòng ĐẦU Serilog:* `2026-07-31 17:11:27.310 +07:00 [INF] Applying migrations...`
3. *Mọi phép đo DB dưới đây chạy từ 17:12+* ⇒ SAU mốc recycle.
(chưa đo)
## Mục 4 — Data prod sau migrate ⚠️ PARTIAL — **CHÂN-LÝ-RỖNG**
## Mục 6 — Smoke
Số đo nguyên văn (POST-migrate, sau recycle):
```
TOTAL=0 · GROUP1=0 · OUTOFRANGE=0 · LINES=0 · SUMPE=NULL|SUMPROP=NULL
CTRL_SUPPLIERS=60 · CTRL_CATALOG=86 <- control dương: bộ đếm CÓ đếm được
```
| Acceptance yêu cầu | Kết quả | Giá trị bằng chứng |
|---|---|---|
| `COUNT(ApprovalGroup=1) == COUNT(*)` | `0 == 0` ✅ | **RỖNG — 0 bit thông tin** |
| `COUNT(ApprovalGroup NOT BETWEEN 1 AND 8) = 0` | `0` ✅ | **RỖNG** |
| Σ `PeReferenceAmount`/`ProposedAmount` | `NULL\|NULL` (PRE cũng `NULL\|NULL`) | **RỖNG hai phía** |
(chưa đo)
🔴 `ContractSigningPlans` prod có **0 dòng cả TRƯỚC lẫn SAU**. Ba acceptance "xanh" nhưng
**không mang thông tin nào** về việc backfill có chạy đúng — backfill hụt sẽ trông y hệt.
Chính tác giả Mig 71 đã khai bẫy này ("đo local Σ = tập RỖNG hai phía … phép đo prod mới có
răng"); nay prod cũng rỗng ⇒ **phép đo prod cũng KHÔNG có răng**. Không hạ thành FAIL (không có
gì sai), nhưng CẤM đọc thành PASS.
**Bằng chứng THAY THẾ — không phụ thuộc số dòng (CÓ RĂNG):**
*(a) 4 cột, đúng kiểu/nullability/default (`INFORMATION_SCHEMA.COLUMNS`):*
```
ContractSigningPlans |ApprovalGroup |int |null=NO |def=((0))
ContractSigningPlans |EndedByLevelFinalize|bit |null=NO |def=(CONVERT([bit],(0)))
ContractSigningPlanLines |CatalogEntryId |uniqueidentifier|null=YES|def=-
ContractSigningPlanLines |TenHangMuc |nvarchar(500) |null=YES|def=-
```
*(b) HOÁN-ĐỔI INDEX — chứng bằng **liệt kê TRỌN HỌ** (14 index cả 2 bảng), không bằng grep-rỗng:*
```
✅ CÓ : IX_ContractSigningPlanLines_ContractSigningPlanId_SupplierId_CatalogEntryId
unique=1 | filter=([IsDeleted]=(0)) | cols=ContractSigningPlanId,SupplierId,CatalogEntryId
✅ CÓ : IX_ContractSigningPlanLines_CatalogEntryId (cols=CatalogEntryId)
✅ CÓ : IX_ContractSigningPlans_ApprovalGroup_Phase (cols=ApprovalGroup,Phase)
❌ MẤT: IX_ContractSigningPlanLines_ContractSigningPlanId_SupplierId (unique 2-cột cũ)
```
Vắng-mặt của index cũ suy ra từ **danh sách đầy đủ 14 index có thật**, nên đây là vắng-mặt ĐO
ĐƯỢC chứ không phải "truy vấn trả rỗng đọc thành sạch". Đây là phép đo mạnh nhất của mục 4.
*(c) Bất-biến Σ tiền — chứng theo CẤU TRÚC bằng phép ĐO nguồn:*
`grep -nE "PeReferenceAmount|ProposedAmount|ApprovedAmount"` trên Mig 71 → chỉ **2 hit, cả 2 ở
dòng 23-24 và đều là comment `//`** ⇒ **0 câu lệnh thực thi** chạm cột tiền. `migrationBuilder.Sql`
= đúng **1** câu (dòng 61, backfill `ApprovalGroup=1`). Σ bất biến đúng kể cả khi bảng có dữ liệu.
*(d) Materialize qua EF:* xem mục 6 — `?group=N` trả **200** (không 500) ⇒ cột `ApprovalGroup`
tồn tại & query được xuyên Domain→Infra→Api trên DB thật.
## Mục 5 — Bundle ×2 app (#77) ✅ PASS — 4/4 ROTATE
| app | asset | TRƯỚC (K1 #434) | SAU (K2 #435) |
|---|---|---|---|
| admin | js | `CKgq0YlH` | **`DVQEwGwf`** |
| admin | css | `DD3xQhNt` | **`D050EVYG`** |
| eoffice | js | `CHMCU35C` | **`CZAYiWWa`** |
| eoffice | css | `CdXRNT7E` | **`DX1FRk5n`** |
*Hash CŨ chết (control âm tầng-2 — bundle cũ biến mất khỏi đĩa):*
```
admin /assets/index-CKgq0YlH.js -> 200|text/html|900 (SPA fallback, không phải JS)
eoffice/assets/index-CHMCU35C.js -> 200|text/html|876
admin /assets/index-ZZBIADAT.js -> 200|text/html|900 <- hash BỊA, cùng dấu hiệu
```
Hash bịa cho ra ĐÚNG dấu hiệu của hash cũ ⇒ `text/html` thật sự nghĩa là "file không tồn tại"
(né bẫy SPA-fallback-200 S72; dùng `Content-Type` chứ không neo byte).
*Last-Modified in-window:* admin `10:10:20 GMT` = 17:10:20 +07 · eoffice `10:11:20 GMT` =
17:11:20 +07 — cả hai ∈ (17:05:33, 17:11:45). `Cache-Control: no-cache` cả 2 (hardening S88).
## Mục 6 — Smoke ✅ PASS
| Phép đo | Kỳ vọng | Thực tế |
|---|---|---|
| `/health/ready` | 200 | **200** |
| `/health/live` | 200 | **200** |
| `/health` trần | (control) | **404** ⇒ 200 ở trên có nghĩa |
| `GET /api/contract-signing-plans?group=2` KHÔNG token | 401 | **401** |
| route BỊA `/api/contract-signing-plans-KHONG-TON-TAI?group=2` | 404 | **404** |
| route BỊA 2 `/api/zzz-fake-9x7` | 404 | **404** |
| admin.solutions.com.vn | 200 | **200** |
| eoffice.solutions.com.vn | 200 | **200** |
401 (route có thật, có gác) tương phản 404 ×2 (route không có) ⇒ **401 CÓ NGHĨA**.
*Có token admin* (login `/api/auth/login`, `accessToken` len=468):
```
?group=1 -> 200 {"items":[],"total":0,"page":1,"pageSize":20,"totalPages":0,...}
?group=2 -> 200 (thân y hệt)
?group=8 -> 200 (thân y hệt)
inbox -> 200 deleted -> 200
```
"mọi item `approvalGroup==1`" ⇒ **VACUOUS (0 item)** — không tính là bằng chứng.
⚠️ Đã soi **thân RAW** (không tin bộ parse) đúng bài K1 "0-hit là dương-giả tới khi soi format":
thân thật là `{"items":[],"total":0}` ⇒ rỗng THẬT, không phải lỗi đọc format.
**Chứng `group` ĐƯỢC WIRE (không bị nuốt im lặng):**
```
?group=abc -> 400 <- bind int THẬT; nếu param không tồn tại, ASP.NET bỏ qua query lạ và trả 200
```
Khớp nguồn: `ContractSigningPlansController.cs:42``[FromQuery(Name = "group")] int? group = null`
`:49` truyền vào `ListContractSigningPlansQuery(..., group)`.
**Control DƯƠNG cho đường ống list:** `GET /api/catalogs/contract-catalog`**86 item**
(seed K1 còn nguyên) ⇒ token + serializer + đường ống list CHẠY, nên `items:[]` của KHKK là
bảng rỗng thật, không phải ống vỡ.
---
## Lệch / quan sát (không chặn deploy)
1. **`?group=999` → 200** (không 400). Miền nghiệp vụ là 1..8 nhưng biên API không chặn
ngoài-miền; hiện vô hại (trả rỗng) và mục 4 đã xác nhận 0 dòng ngoài 1..8. Ghi cho K4b cân
nhắc cùng lớp với validator `CatalogEntryId` bắt buộc mà Mig 71 đã hẹn.
2. **Ghost-window `EndedByLevelFinalize`** — tác giả khai trước: K2 đẻ cột, K3 tiêu thụ; tới khi
K3 land cột luôn = 0. Đã xác minh cột tồn tại `bit NOT NULL default 0`; **không** coi
"toàn 0" là dữ liệu hỏng.
3. **Mục 4 rỗng** — xem trên. Khi có phiếu KHKK thật trên prod, cần đo LẠI 3 acceptance đó thì
mới có răng; hiện chưa thể kết luận backfill đúng/sai từ dữ liệu.
## Bảng tổng
| # | Mục | Verdict |
|---|---|---|
| 1 | Gitea run `0779f2d` success | ✅ PASS |
| 2 | Test gate 609 = 45D + 564I | ✅ PASS |
| 3 | Mig 71 TOP + chứng-restart | ✅ PASS |
| 4 | Data prod sau migrate | ⚠️ **PARTIAL — vacuous** (schema/index CÓ răng ✅) |
| 5 | Bundle ×2 app rotate + hash cũ chết | ✅ PASS |
| 6 | Smoke 401/404/200 + group wired | ✅ PASS |
**Không ghi gì lên prod ngoài đọc** (toàn bộ là SELECT / curl GET / login POST lấy token).
END — VERDICT=PARTIAL 5/6 (mục 4 vacuous, deploy khỏe, không rollback)

View File

@ -0,0 +1,39 @@
K3-BE: IN-PROGRESS — bước-0 XONG (lead), §1-8 p2 đang chạy
# sub-implbe-k3 — K3 BACKEND (S165, wave 3/8: 8 workflow nhóm + finalize + sweep)
> 🔴 **KHAI VẾT:** p1 wf_a04124a7-0fe = class *engine-process-exit* (35 tool-use/458s nhưng **0 delta đĩa
> + 0 artifact + return rỗng** — lượt chạy coi như chưa từng tồn tại; #53 tally cả wave). Bước-0 dưới đây
> = **LEAD tự chạy** (ssh + sqlcmd trực tiếp), p2 seed từ bảng ĐÃ VERIFY này, không cần ssh lại.
## §0 [LEAD] FAIL-CLOSED verify đội-hình QT-DN-V2-001 LIVE — PASS
- Instance prod = `localhost\SQLEXPRESS` (named instance — `-S localhost`/`tcp:1433` đều fail; ghi lại cho
mọi lane sau đỡ dò). Windows-auth `-E` qua `ssh vietreport-vps` chạy được.
- `ApprovalWorkflows WHERE Code='QT-DN-V2-001'` = **3 row: 2 archived (IsActive=0) + 1 LIVE (IsActive=1)**,
ApplicableType=**1** (Duyệt NCC/PE — nguồn đội-hình, đúng OG-2 + note owner slot-54 "lấy đúng bộ người
duyệt đang cấu hình ở workflow Duyệt NCC prod"). TotalWf active toàn hệ = 7.
- **ROSTER bản LIVE (nguyên văn sqlcmd, mojibake console đã chuẩn hoá dấu theo email đã biết):**
| Bước | Dept | Cấp | Email | Tên |
|---|---|---|---|---|
| 1 «Phòng 1» | Phòng Cung Ứng (PRO) | 1 (OR-4) | phuong.nguyen@solutions.com.vn | Nguyễn Thị Bích Phượng |
| 1 | Phòng Cung Ứng | 1 | long.chau@solutions.com.vn | Châu Tạ Kim Long |
| 1 | Phòng Cung Ứng | 1 | duy.nguyen@solutions.com.vn | Nguyễn Văn Duy |
| 1 | Phòng Cung Ứng | 1 | binh.lethanh@solutions.com.vn | Bình Lê Thanh |
| 1 | Phòng Cung Ứng | 2 | tra.bui@solutions.com.vn | Bùi Lê Thủy Trà |
| 2 «Phòng 2» | P. Kiểm soát Chi phí (CCM) | 1 (OR-4) | luu.tran@solutions.com.vn | Trần Xuân Lưu |
| 2 | P. Kiểm soát Chi phí | 1 | truong.letrandang@solutions.com.vn | Lê Trần Đăng Trường |
| 2 | P. Kiểm soát Chi phí | 1 | binh.le@solutions.com.vn | Lê Văn Bình |
| 2 | P. Kiểm soát Chi phí | 1 | nguyen.ho@solutions.com.vn | Hồ Thị Nữ Nguyên |
| 2 | P. Kiểm soát Chi phí | 2 | chuong.phan@solutions.com.vn | **Phan Văn Chương** (TP.CCM — giữ cờ finalize OG-3/OG-9) |
| 3 «Phòng 3» | Ban Giám đốc (CEO) | 1 | truong.nguyen@solutions.com.vn | Nguyễn Văn Trường |
- **Vá-11 danh-tính (phân giải bằng dept trên bản LIVE):** `truong.letrandang` (CCM C1) ⟂ `truong.nguyen`
(BGĐ C1 = CEO) — 2 người khác dept, không nhầm; `binh.lethanh` (PRO C1) ⟂ `binh.le` (CCM C1) — khác dept,
không nhầm. Cặp "tring.le"/"thanh.lethanh" trong câu-đố spec KHÔNG xuất hiện trên roster LIVE ⇒ là bẫy
chính-tả từ ảnh, roster email là chân lý.
-**Mô-hình 3 trạm PRO → CCM → CEO** với OR-of-N cấp 1 mỗi trạm + cấp 2 = trưởng phòng. Seed 8 workflow
KHKK-N1..N8 mirror ĐÚNG cấu trúc này (3 Steps × Levels như bảng), resolve user theo EMAIL.
(§1-8 p2 ghi tiếp bên dưới)

View File

@ -26,7 +26,7 @@
```
## Tick 0-8 (cap nhat dan)
- [ ] 0. FAIL-CLOSED verify doi-hinh LIVE prod (OG-2)
- [x] 0. FAIL-CLOSED verify doi-hinh LIVE prod (OG-2)**THAY: workflow LIVE ton tai** (chi tiet duoi)
- [ ] 1. Seed 8 workflow KHKK-N1..N8 type-10
- [ ] 2. Port nhanh LEVEL-FINALIZE vao ContractSigningPlanWorkflowService
- [ ] 3. Sweep ep-false va-3 (>=3 site BE)
@ -37,3 +37,73 @@
- [ ] 8. build 0W/0E + test FULL (baseline 609)
---
# Muc 0 — FAIL-CLOSED verify doi-hinh LIVE (OG-2) — **PASS, workflow LIVE co that**
## Cach do (READ-ONLY, 0 ghi prod)
`ssh vietreport-vps``sqlcmd -S '.\SQLEXPRESS' -d SolutionErp -E` (integrated auth `-E`, KHONG cham password vrapp — khuon S147).
Nhan tieng Viet doc qua `CONVERT(varchar(N), CAST(col AS varbinary(N)), 2)` → hex → decode `utf-16-le` phia client
(khuon cicd-verify-dot2: sqlcmd mangle `Duy?t` khong phan biet duoc dau).
⚠️ 3 lech vs tai lieu, da tu sua khi do (khong bao "khong query duoc"):
1. De-bai ghi `QT-DN-V2-001` **type 3** → LIVE la **ApplicableType=1** (DuyetNcc). Type 3 = `QT-HD-V2-001` (HD). Doi-hinh dung van la QT-DN-V2-001.
2. Bang Identity ten **`Users`** khong phai `AspNetUsers` (rename Mig 1).
3. FK ten **`ApprovalWorkflowLevels.ApprovalWorkflowStepId`** khong phai `StepId`.
## Ban do LIVE — `QT-DN-V2-001` **Version 4** (IsActive=1)
Chung "khong phai archived": 3 version tren prod — v2 `IsActive=0`, v3 `IsActive=0`, **v4 `IsActive=1` + IsUserSelectable=1**.
```
QT-DN-V2-001|2|1|0|0
QT-DN-V2-001|3|1|0|0
QT-DN-V2-001|4|1|1|1 <- LIVE
```
### BANG ROSTER NGUYEN VAN (11 slot, decode tu hex)
| Ver | Buoc | Dept | Cap | Email | Fin | Skp | Bud | Ho ten (LIVE) | Chuc danh (LIVE) |
|---|---|---|---|---|---|---|---|---|---|
| 4 | 1 | PRO | 1 | `binh.lethanh@solutions.com.vn` | 0 | 0 | 1 | Binh Le Thanh | Nhân viên |
| 4 | 1 | PRO | 1 | `duy.nguyen@solutions.com.vn` | 0 | 0 | 1 | Nguyễn Văn Duy | Nhân viên Cung ứng |
| 4 | 1 | PRO | 1 | `long.chau@solutions.com.vn` | 0 | 0 | 1 | Châu Tạ Kim Long | Nhân viên Cung ứng |
| 4 | 1 | PRO | 1 | `phuong.nguyen@solutions.com.vn` | 0 | 0 | 1 | Nguyễn Thị Bích Phượng | Nhân viên Cung ứng |
| 4 | 1 | PRO | 2 | `tra.bui@solutions.com.vn` | 0 | 1 | 1 | Bùi Lê Thủy Trà | TP Cung ứng |
| 4 | 2 | CCM | 1 | `binh.le@solutions.com.vn` | 0 | 0 | 1 | Lê Văn Bình | Nhân viên Kiểm soát Chi phí |
| 4 | 2 | CCM | 1 | `luu.tran@solutions.com.vn` | 0 | 0 | 1 | Trần Xuân Lưu | Nhân viên Kiểm soát Chi phí |
| 4 | 2 | CCM | 1 | `nguyen.ho@solutions.com.vn` | 0 | 0 | 1 | Hồ Thị Nữ Nguyên | Nhân viên Kiểm soát Chi phí |
| 4 | 2 | CCM | 1 | `truong.letrandang@solutions.com.vn` | 0 | 0 | 1 | Lê Trần Đăng Trường | Nhân viên |
| 4 | 2 | CCM | 2 | `chuong.phan@solutions.com.vn` | **1** | 1 | 1 | Phan Văn Chương | TP Kiểm soát Chi phí |
| 4 | 3 | BOD | 1 | `truong.nguyen@solutions.com.vn` | 0 | 1 | 1 | Nguyễn Văn Trường | Tổng Giám đốc (CEO) |
⇒ Hinh dang = **PRO C1 OR-of-4 + C2 ×1 · CCM C1 OR-of-4 + C2 ×1 · BOD C1 ×1** — KHOP y nguyen K3.a nen.
`AllowApproverFinalize=1` **DA CO SAN tren prod** dung o chuong.phan (CCM C2) — tien le song, khong phai co-che moi.
⇒ Ten Buoc tren LIVE la "Phòng 1/2/3" (nhat nheo); K3.a nen dat ten mo-ta ("Phòng Cung ứng"/"Phòng KSCP"/"Ban Giám đốc") — **ten = display-only, danh tinh = Dept + ApproverUserId** ⇒ dung ten nen, khai lech o day.
## VA-11 — DO DANH TINH 2 CAP GAN-TRUNG: **CA 2 DEU LA TRUNG-TAI-KHOAN THAT tren prod**
Phat hien nang: **prod co 2 tai khoan cho CUNG 1 nguoi**, va **workflow LIVE dung tai khoan TAO TAY, khong phai tai khoan seeder**.
| Cap | Tai khoan A (DbInitializer seed) | Tai khoan B (tao tay tren prod) | LIVE workflow dung | Phan giai |
|---|---|---|---|---|
| PRO "Thanh/Bình" | `thanh.lethanh@` — PRO — "Lê Thanh Bình" — *Nhân viên Cung ứng* (`DbInitializer.cs:1617`) | `binh.lethanh@` — PRO — "Binh Le Thanh" (**khong dau**) — *Nhân viên* | **B `binh.lethanh@`** | Cung dept PRO, cung nguoi; chuc danh khac ("Cung ứng" vs tran). Phan giai bang **bang LIVE**: slot Buoc1/Cap1 tro toi B. |
| CCM "Trưởng" | `truong.le@` — CCM — "Lê Trần Đăng Trường" — *Nhân viên Kiểm soát Chi phí* (`DbInitializer.cs:1626`) | `truong.letrandang@` — CCM — "Lê Trần Đăng Trường" (**ten y het**) — *Nhân viên* | **B `truong.letrandang@`** | Ten TRUNG KHIT ⇒ khong the match bang ten. Phan giai bang **bang LIVE**: slot Buoc2/Cap1 tro toi B. |
3 ung vien nhieu loan da loai dut khoat bang **dept**:
- `tring.le@` = "Lê Tự Đăng Trình" (CCM) — **nguoi KHAC han**, KHONG co trong workflow LIVE ⇒ loai.
- `truong.nguyen@` = "Nguyễn Văn Trường" (**BOD**, CEO) — o Buoc 3, khong phai CCM ⇒ khong nham voi `truong.le*`.
- `binh.le@` = "Lê Văn Bình" (**CCM**) vs `binh.lethanh@` (**PRO**) — tach bang dept, ca 2 DEU trong roster nhung khac buoc.
Kiem ton tai + active (prod): **11/11 email = IsActive 1**. 3 dept `PRO`/`CCM`/`BOD` deu `IsDeleted=0`.
### 🔴 QUYET-DINH ky thuat rut ra (khai de owner soi)
Seeder **KHONG the hardcode 1 email duy nhat/slot**: email LIVE (`binh.lethanh@`, `truong.letrandang@`) **khong ton tai tren Dev/local/test** (DbInitializer chi tao `thanh.lethanh@`/`truong.le@`) ⇒ seed se fail-soft bo qua toan bo, Dev 0 workflow.
⇒ Dung **chuoi uu-tien alias/slot**: thu email LIVE TRUOC, khong co thi lui ve email seeder. Prod → khop dung nguoi dang duyet that; Dev/test → khop tai khoan seeder. Ca 2 vang mat moi fail-soft. Moi lan dung alias-du-phong deu `LogWarning` neu ro → co dau vet.
⚠️ Day KHONG phai quyet dinh danh-tinh moi: uu tien 1 = **dung nguoi tren ban LIVE** (OG-2). Chi la duong lui cho moi truong khong co ban sao tay.
⚠️ De-xuat cho owner (NGOAI pham vi wave nay, khong tu lam): don trung 2 cap tai khoan tren prod (vo hieu 1 ben) — hien 1 nguoi 2 tai khoan la nguon nham lan that.
## Muc 0 — VERDICT
**PASS** — workflow LIVE `QT-DN-V2-001` v4 ton tai (IsActive=1, khong archived), roster 11 slot ghi nguyen van o tren,
2 cap gan-trung phan giai xong bang dept + chuc danh + vi tri slot tren ban LIVE. **Duoc phep seed.**
Doi chung nen: prod hien **0** workflow `ApplicableType=10`, **0** Code `KHKK-N%` ⇒ seed lan dau se tao dung 8.
---