wal: flush 20260801T0921

This commit is contained in:
pqhuy1987
2026-08-01 09:21:16 +07:00
parent ce15c649b3
commit 21908b445f
3 changed files with 89 additions and 2 deletions

View File

@ -1,5 +1,7 @@
# Implementer-Frontend Agent — Persistent Memory
- **S166 (08-01) K4a-FE regex 42 leaf KHKK + single-source nhãn nhóm [artifact `runs/2026-07-31-S164-4gd-khkk-fanout/sub-implfe-k4a.md`]:** 🔴 **Khuôn S164 "đo đĩa TRƯỚC khi gõ" ăn tiếp 2 lần trong CÙNG 1 đề bài** — cả 2 tiền-đề lead đều sai theo hướng *"tưởng chưa có / tưởng có"*: ① đề bài bảo export `KHKK_GROUP_LABELS` **mới**, đĩa đã có `KHKK_APPROVAL_GROUP_LABELS` (`types/khkk.ts:129`, K2 land, **5 call-site**) ⇒ đẻ map-2 là **phá đúng acceptance-5 (single-source) mà nó phục vụ**; K2 còn để sẵn uỷ-quyền trong comment `:125-127`. Đo thêm: nhãn BE ≡ `` `${n}. ${short}` `` cho **8/8** ⇒ giải bằng **DERIVE `khkkGroupMenuLabel(n)`, KHÔNG hardcode lần 2, 0 call-site cũ bị đụng** (hardcode lại = double-numbering "N2 - 2. …" ở select). ② comment vá-8 bảo "gỡ `KeHoachKyKet` khỏi ẩn-admin ⇒ phải nới regex trước", nhưng `isAdminHidden:194` = `key.startsWith('Ct_')` — KHKK **chưa bao giờ bị ẩn** ⇒ ràng buộc ĐANG hiệu lực chứ không phải tương lai; viết comment theo ĐĨA + FLAG "7 nhóm rỗng" (`MenuGroup` chỉ xét `children.length>0`, không xét con resolve được ⇒ header hiện, thân rỗng). **BÀI MỚI đáng giữ: chứng regex bằng `new Function()` chạy CHÍNH khối text đã ship** (`indexOf('const khkkMatch')` → slice → eval), key sinh từ `KhkkGroupNumbers`/`KhkkLeafActions` **đọc thẳng MenuKeys.cs** ⇒ 42/42 resolve, 0 drop, **+3 control-âm** (G9→null · action bogus→null · `Khkk_List` nhóm-1-không-infix→null vì chặn ở staticMap trước). Nhãn cũng kèm control-âm (chèn 'x' vào N4 → phép so FLAG) — 0-hit trần vô nghĩa. Ghi chú khuôn: `Khkk_G1` + 6 leaf **KHÔNG-infix** (S159, cấm đổi = mồ côi permission-row), 42 leaf infix chỉ là nhóm **2..8**; giữ `[1-8]` theo spec = rộng hơn tập seed 1 nấc, cố ý. `group`/`filter`/`view` ∉ `TRANSIENT_QUERY_KEYS:311` ⇒ active-state phân biệt (bài `view=approved` S155). SHA-pair types `eba649cc`→**`7a99b865`** ×2 IDENTICAL; Layout 2 app **cố ý KHÔNG mirror** (user +34 regex · admin +13 comment-only, 0 dòng xoá). Build ×2 PASS (user 1950mod `index-B2v0kn5F` 20.8s · admin 1961mod `index-84zDBHE-` 8.2s). 0 `.cs` (MenuKeys/DbInitializer M = lane BE), 0 chạm KhkkListPage/CreatePage/WorkflowPanel/DetailPage. 3 FLAG treo (tên const · `?group=` chưa có consumer → K4b quyết "vắng group = nhóm 1 hay tất cả" · 7 nhóm rỗng admin). Tag `[s166, khkk-k4a-regex-42-leaf, tien-de-lead-sai-x2, derive-khong-hardcode-lan-2, new-function-chay-text-da-ship, control-am-bat-buoc, nhom1-khong-infix, layout-co-y-khong-mirror]`
- **S164/S165 (07-31) K2-FE KHKK nhóm-duyệt N1N8 [relaunch p2 sau p1 chết #53 — chi tiết `runs/2026-07-31-S164-4gd-khkk-fanout/sub-implfe-k2.md` §1-§5]:** 🔴 **BÀI CHÍNH — tiền-đề lead SAI, đo `git diff` TRƯỚC khi gõ:** lead khai CreatePage "mid-wire, 8 khai báo chưa vào JSX" (TS6133 sẽ đỏ) ⇒ đo đĩa thật thì **8/8 ĐÃ có call-site**; Detail cũng land đủ. Việc thật ≈ **1/4** mô tả — chỉ ListPage dở (p1 kịp thêm mỗi dòng import). Khuôn S114 "WRITE-lane garble ≠ mất code" xác nhận lần nữa: lead đọc transcript dở-dang → kết luận theo Ý ĐỊNH đang chạy, không theo đĩa. **Viết lại phần đã đúng = phá.** ⇒ p2 chỉ sửa ListPage 3 điểm: badge `N{g}` NHÉT VÀO ô "Mã kế hoạch" (không đẻ cột — bảng đã cuộn ngang @1366 do cây GĐ 19rem, ghi chú S162 nằm sẵn trong file) · +cột "Tổng duyệt" Σ`totalApprovedAmount` (vá-8 spec, BE trả **0** cho phiếu chưa duyệt ⇒ ép `—` kẻo đọc nhầm "đã duyệt 0 đ") · **`colSpan` 7→8 hai chỗ** (loading + empty row — quên = lỗi CÂM tới lúc bảng rỗng). `npm run build` = `tsc -b && vite build` + `noUnusedLocals:true` ⇒ build LÀ phép thử TS6133 thật, không cần tin IDE (#68). cp 4 file → SHA-pair **5/5 IDENTICAL** (Panel không sửa = **đối chứng dương**, hash `2B64144EF6E8` BẰNG baseline ⇒ chứng phép đo đúng thứ). diff-stat đối xứng 269+/36 ×2 app. 0 `.cs` (13 `.cs` M/?? là lane BE), 0 route/menu (K4a). Tag `[s164, khkk-nhom-duyet, do-dia-truoc-khi-go, colspan-loi-cam, badge-trong-o-khong-de-cot, panel-doi-chung-duong]`
- **S161 (07-29) ARC W1+W2+W3đ1 KHKK FE — 3 lượt, chi tiết = sub-md `runs/2026-07-29-S161-khkk-*/` (mọi lượt #53, đĩa cứu trọn):** **W1** Designer type-10: containment **2-LỚP render+payload** (`levelFlagsPayload(e, lock)` ép false 2/2 call-site — chỉ `disabled` = containment GIẢ vì `copyFromDefinition` tuồn state); 2 tiền-đề đề-bài SAI tự bẻ (FE không có bảng nhãn — nhãn từ BE `applicableTypeLabel`; khuôn type-9 không tồn tại → mirror `Contract:3`). **W2** 3 page + types ×2 SHA-pair; types-theo-ENTITY khi BE song song; header types = HỢP-ĐỒNG 12-endpoint (reviewer đối chiếu ra 6 đứt → lead vá; bài: hợp-đồng phải LEAD-định-nghĩa literal); WfView 2-app-2-đường (user matrix?type=10 whitelist+10 · admin Designer deep-link); place-3 menuKeys SKIP-có-khai (0 consumer). **W3đ1** `KhkkWorkflowPanel` mirror PE-panel 1063-dòng theo bảng **GIỮ/BỎ tường minh** (BỎ đủ 2 đường cấm + price-picker/budget/4-radio); cây workflow THÔ — **FE tự suy ✓/●/○ từ con-trỏ đôi** (StepIndex 0-based vs Level.Order giá-trị); bổ `approverUserId` opinion (W2 khai thiếu). Tag `[s161, khkk-fe-3-wave, containment-2-lop, types-theo-entity, giu-bo-tuong-minh, fe-suy-status-con-tro]`

View File

@ -1,4 +1,4 @@
IMPLFE-K4A: IN-PROGRESS
IMPLFE-K4A: DONE
# Lane FE K4a — route regex 42 leaf + single-source nhãn nhóm (S166, 2026-08-01)
@ -41,5 +41,64 @@ SPEC PIN: `spec-cum2-chi-tiet-31-07-2026.md` vá 1/8/15 + `sub-invest-fable-b2-c
**(b) `isAdminHidden` KHÔNG hề ẩn `KeHoachKyKet`.** `fe-admin/Layout.tsx:194-196` = `return key.startsWith('Ct_')` — chỉ ẩn `Ct_*`. ⇒ mệnh đề "gỡ `KeHoachKyKet` khỏi ẩn-admin ⇒ phải nới regex trước" **mô tả một điều kiện tương lai KHÔNG tồn tại**; ràng buộc thật đã **ĐANG hiệu lực NGAY** (fe-admin đang hiện KHKK). Comment phải viết theo đĩa, không theo tiền-đề.
## §2 THỰC THI (append sau MỖI file)
## §2 THỰC THI
### F1 — `fe-user/src/components/Layout.tsx` (+34 / 0)
Nhánh `khkkMatch` đặt **SAU** khối `peMatch`, **TRƯỚC** `return null` cuối `resolvePath`. Regex ĐÚNG literal spec `/^Khkk_G([1-8])_(WfView|List|Create|Pending|Approved|Deleted)$/`. 6 route (đọc từ App.tsx thật, không tin literal spec):
`WfView → /khkk/workflow-matrix?type=10&group={n}` · `List → /khkk/list?group={n}` · `Create → /khkk/create?group={n}` · `Pending → …&filter=ChoDuyet` · `Approved → …&filter=DaDuyet` · `Deleted → …&view=deleted`.
+comment khai lệch fe-admin (không có `WorkflowMatrixViewPage`, lead chốt 2026-07-27) + khai `[1-8]` rộng hơn tập seed `[2-8]` là cố ý + khai `group` không transient nên active-state phân biệt được.
### F2 — `fe-admin/src/components/Layout.tsx` (+13 / 0, COMMENT-ONLY)
Ràng buộc ngược đặt ngay trên `isAdminHidden` `:194`. **KHÔNG nới regex** (diff 0 dòng xoá, 0 dòng code — chỉ comment). Nội dung viết theo ĐĨA chứ không theo tiền-đề lead (xem §1.6b).
### F3 — `types/khkk.ts` ×2 app (+25 / +25, SHA-pair)
KHÔNG đẻ `KHKK_GROUP_LABELS` (sẽ thành nguồn thứ 2 — xem §1.6a). Thay bằng 2 export DERIVE trên map sẵn có:
- `khkkGroupMenuLabel(n)` → `` `${n}. ${KHKK_APPROVAL_GROUP_LABELS[n]}` `` , fallback `Nhóm {n}`. Comment khai TO: **không phải nguồn sidebar** (sidebar đọc `/api/menus/me` → `MenuItems.Label`, admin còn override `displayLabel` Mig 27); dùng cho cây K5 / leaf-title / WfView.
- `khkkGroupWorkflowCode(n) => \`KHKK-N${n}\`` (O-2) — khớp regex BE `^KHKK-N([1-8])$` `Features.cs:420`.
0 call-site cũ bị đụng ⇒ 5 chỗ đang dùng `KHKK_APPROVAL_GROUP_LABELS` giữ nguyên hành vi, ô select `N{g} - {label}` không bị lặp số.
## §3 CHỨNG (đo bằng lệnh, kèm control-âm)
**A. Nhãn byte-exact 8/8** — script trích chuỗi từ `DbInitializer.cs` (`Khkk_G1` tuple `:1960` + dict `:2127-2136`) và từ `types/khkk.ts`, so `"{n}. "+short` với BE:
```
OK N1..N8 -> --- byte-exact 8/8 khop, 0 lech
CONTROL(âm giả, thêm 'x' vào N4): OK-phep-do-bat-duoc-lech
```
N2 có "phá dỡ" ✅. Control-âm chứng phép so có RĂNG (không phải happy-path mù).
**B. Regex ăn đủ 42 leaf** — `new Function()` chạy CHÍNH khối text đã ship trong `Layout.tsx` (không chép tay), key sinh từ `KhkkGroupNumbers`/`KhkkLeafActions` đọc thẳng `MenuKeys.cs`:
```
BE nhom=[2,3,4,5,6,7,8] actions=[WfView,List,Create,Pending,Approved,Deleted]
--- 42 leaf, 0 tra null (drop im lang)
CONTROL Khkk_G9_List -> null
CONTROL Khkk_G2_Bogus -> null
CONTROL Khkk_List -> null (đúng: nhóm 1 không-infix đi staticMap, chặn trước regex)
```
**C. SHA-pair types (acceptance-5)**
| file | sha256 |
|---|---|
| baseline trước K4a (cả 2 app) | `eba649cc6fc7eccfeec5262f2e4d58265dbf8caaac4d53c6bc7120fc8065976d` |
| `fe-user/src/types/khkk.ts` | `7a99b865189480933c57a46a9d9aac9be525d14a78e7743f3a82293b706f22b6` |
| `fe-admin/src/types/khkk.ts` | `7a99b865189480933c57a46a9d9aac9be525d14a78e7743f3a82293b706f22b6` |
→ **IDENTICAL**. Layout.tsx 2 app KHÁC NHAU by-design (fe-user +34 có regex · fe-admin +13 comment-only) — không mirror, đúng chủ đích.
**D. Build ×2 PASS, 0 TS error** (`npm run build` = `tsc -b && vite build`, `noUnusedLocals:true` ⇒ build LÀ phép thử TS6133 thật, không tin IDE — gotcha #68)
| app | modules | bundle js | css | time |
|---|---|---|---|---|
| fe-user | 1950 | `index-B2v0kn5F.js` 1,640.21 kB (gzip 414.27) | `index-my6T4K7V.css` 92.62 kB | 20.75s |
| fe-admin | 1961 | `index-84zDBHE-.js` 1,723.20 kB (gzip 428.44) | `index-Ct6-3cYU.css` 86.80 kB | 8.17s |
Warning >500KB + `INEFFECTIVE_DYNAMIC_IMPORT realtime.ts` = PRE-EXISTING cả 2 app.
**E. Rào** — `git status` sau lượt: 4 file của tôi. `MenuKeys.cs` + `DbInitializer.cs` M nhưng là **lane BE land trước** (tôi chỉ Read/Grep, 0 Edit). `KhkkListPage.tsx` · `KhkkCreatePage.tsx` · `KhkkWorkflowPanel.tsx` · `KhkkDetailPage.tsx` **KHÔNG có trong diff**. `KhkkGroupMenuSeedTests.cs` untracked = lane test. **0 commit.**
## §4 FLAG cho lead (3 — cần quyết, KHÔNG tự quyết)
**FLAG-1 (MAJOR, đã tự bẻ — báo để lead soát lại spec):** đề bài yêu cầu export `KHKK_GROUP_LABELS` mới, nhưng đĩa đã có `KHKK_APPROVAL_GROUP_LABELS` (`types/khkk.ts:129`, K2 land, 5 call-site). Đẻ map thứ 2 là **phá đúng acceptance-5 mà nó phục vụ**. K2 còn để sẵn uỷ quyền trong comment `:125-127` ("nếu K4a land nhãn khác thì SỬA Ở ĐÂY (1 const, 2 app)"). Tôi đi đường DERIVE. **Nếu lead vẫn muốn đúng tên `KHKK_GROUP_LABELS`** thì đó là đổi TÊN của const sẵn có (+ sửa 5 import), không phải thêm const — 1 lượt nhỏ, nói là làm.
**FLAG-2 (MAJOR, bàn giao K4b/K5):** `?group=n` **chưa có ai đọc**. `KhkkListPage:61-62` chỉ đọc `filter` + `view`; `KhkkCreatePage` lấy nhóm từ state default, không đọc URL. ⇒ 42 leaf điều hướng đúng + sáng đúng, nhưng trang **hiện toàn bộ nhóm**. Câu hỏi treo cho K4b: **leaf "Danh sách" của NHÓM 1 (`Khkk_List` → `/khkk/list`, KHÔNG có `group=`) nghĩa là "nhóm 1" hay "tất cả"?** Nếu K4b coi vắng-`group` = nhóm 1 thì mất đường xem-tất-cả; nếu coi = tất cả thì leaf nhóm 1 nói dối tên nó. Đây là quyết định UX ⇒ tôi KHÔNG tự chọn, và cố ý KHÔNG sửa 6 dòng staticMap nhóm 1.
**FLAG-3 (MINOR, hệ quả đã biết của vá-15/`:94`):** `isAdminHidden` chỉ ẩn `Ct_*` ⇒ fe-admin ĐANG hiện root KHKK. Sau khi BE seed land, sidebar admin sẽ có **7 nhóm rỗng** (`Khkk_G2..G8` render header nhưng 42 leaf con trả null → thân rỗng), vì `MenuGroup` chỉ xét `children.length > 0` chứ không xét con có resolve được không. Nhóm 1 vẫn đủ 6 mục. Nếu lead thấy 7 nhóm rỗng là nhiễu thì có 2 đường (đều 1 lượt nhỏ): (a) nới regex admin, `WfView` trỏ Designer `AwV2_KhkkN{n}`; (b) thêm `Khkk_G` vào `isAdminHidden`. **Không tự chọn.**
IMPLFE-K4A-END

View File

@ -0,0 +1,26 @@
GATE-K4A: IN-PROGRESS
# Gate K4a — adversarial review wave K4a (49 row menu KHKK 8-nhóm)
- Spawn: S166 2026-08-01, HEAD `7a903cf`, diff CHƯA commit.
- Artifact ghi TỪNG MỤC (anti-#53). Dòng-1 = verdict.
## Mốc đo (neo — sẽ re-đo trước verdict, bài S166 cây-phình)
- HEAD THẬT lúc review = `ce15c64` ("wal: flush 20260801T0914"), KHÔNG phải `7a903cf` như đề bài.
Đã kiểm `git show --stat ce15c64`: chỉ chạm `.claude/**` (WAL + agent-memory + run-folder) ⇒
KHÔNG có code src/fe lọt vào commit đó. Đề bài lệch 1 commit governance = vô hại, ghi để neo.
- `git diff --stat -- src fe-user fe-admin` @T0 = **6 file, +213 / 5**.
- `git status --porcelain -- src fe-user fe-admin tests` @T0 = 6 M + 1 `??`
(`tests/SolutionErp.Infrastructure.Tests/Application/KhkkGroupMenuSeedTests.cs`) — khớp kỳ vọng 7 file.
- Ngoài scope code: 5 file `.claude/**` M (memory/run-folder/session-counter) — KHÔNG tính cây-phình
code, nhưng lead PHẢI `git add` có chọn lọc (đừng `git add -A` kéo `.session-counter.json` vào commit code).
## Mục 7 — thứ tự static initializer (ĐO)
`MenuKeys.cs`: `KhkkGroupNumbers` :72 → `KhkkLeafActions` :73 → `KhkkGroup/KhkkLeaf` :76-77 →
`KhkkGroupMenuKeys` :81-84 → spread `.. KhkkGroupMenuKeys` trong `All` :244. Thứ tự văn bản ĐÚNG.
Nếu ai dời khai báo xuống dưới `All`: spread mảng `null` → NRE trong static ctor →
`TypeInitializationException` ở BẤT KỲ truy cập `MenuKeys.*` ⇒ T1+T2 (và ~mọi test chạm MenuKeys) ĐỎ.
⇒ có răng, tuy răng là "nổ" chứ không phải assert-đẹp. PASS.