wal: flush 20260731T1420
This commit is contained in:
@ -17,7 +17,7 @@
|
||||
| 2.c2-r | Review cụm-2 — `WF reviewer c2-{evi,cov,seq} s164` | /fable-clone (opus ×3) | ✅ l1 PWF 2-MAJOR · l2 PWF 3H/7M · 🔴 l3 CHẾT-RUỘT 188B (opus đầu tiên gãy — phủ bù lead-note có khai) → **spec-cum2-final 15 vá** |
|
||||
| 2.c3 | Cụm-3 K7+K8 — `WF invest-fable b2c3 s164` | /fable-real invest | ✅ SẠCH 22.9KB (K7 8v/8test BÁC tiền-đề 3-lỗ-S156-đã-vá · K8 17 bước · HỐ-1-KHKK mới) |
|
||||
| 2.c3-r | Review cụm-3 — `WF reviewer c3-{evi,cov,seq} s164` | /fable-clone (opus ×3) | ✅ 3/3 sạch · L1 7/7-ĐÚNG PWF 4M · L2 FAIL 5H (K8 chưa-chạy-được-như-viết) · L3 FAIL 4H (authz hội-2-khóa · Contracts.Create 0-vai) → **spec-cum3-final 16 vá** |
|
||||
| 3 | Chốt spec cuối — `WF review-fable b3-chot s164` wf_567c4b38-405 | /fable-real review | ⏳ (đối chiếu chéo 4 spec: mâu-thuẫn liên-spec · vá-đè-vá · build-order · GO/NO-GO · digest owner) |
|
||||
| 3 | Chốt spec cuối — `WF review-fable b3-chot s164` | /fable-real review | ✅ **GO-WITH-SPEC-FIXES**: GO 9/10 (K8 by-design) · 8 mâu-thuẫn (3 nặng A-1/A-4/A-5) · 0 vá-đè-vá/43 · build-order K1→K2→K3→K4a→K4b→K5→K4c→K6→K7→K8 · 8 fix lead ÁP XONG |
|
||||
| 4 | Fan-out build bám spec+checklist | Opus 5 MAX (hmw) | ☐ |
|
||||
| 5 | Dry-run E2E toàn trình | theo spec wave cuối | ☐ |
|
||||
|
||||
@ -27,6 +27,6 @@
|
||||
- [x] B1a — att-1 wf_22e8949b-afa CHẾT ngược-#53 (207K tok, 0 byte) · att-2 wf_bc04352b-6a4 A-D đầy + spec-file lead kết tinh `spec-4gd-khkk-tong-quat-31-07-2026.md` (8 verdict · 8 wave K1-K8 · 3 cụm · OG-1/2/3/5)
|
||||
- [x] B1b — wf_8eb13087-5f9 3/3 lane sạch (l1 FAIL 5H · l2 6/6 chịu-lực ĐÚNG +l2-F1 rào-1-PE · l3 FAIL 6H + bác 6 nghi) → `b1b-review-synthesis.md` 14 vá + OG-6/OG-7 → spec v2 (hội tụ 2-lane: admin-hide tập-key tường minh; ApprovalGroup K2-chủ + backfill=1; 8 designer có phép đo; nguồn K1 = 7 ảnh [file đĩa 6-trang không bảng])
|
||||
- [x] B2 — 3 cụm TRỌN: c1 (33KB + 12 vá) · c2 (5/5 + 15 vá; l3 chết-ruột phủ-bù) · c3 (22.9KB 7/7-đúng + 16 vá) = 43 vá tổng, 3 spec final
|
||||
- [ ] B3 — fable-real review chốt
|
||||
- [x] B3 — GO-WITH-SPEC-FIXES (sub-review-fable-b3.md 6 section; 3 anchor re-grep đĩa khớp; 8 fix áp vào 3 spec) — SPEC ĐÓNG BĂNG cho B4
|
||||
- [ ] B4 — fan-out build
|
||||
- [ ] B5 — dry-run E2E
|
||||
|
||||
@ -6,17 +6,17 @@
|
||||
|
||||
Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA, đã chạy) → GĐ2 KHKK = **duyệt HẠNG MỤC theo 8 NHÓM DUYỆT** (trình ký số trạm-by-trạm y Duyệt NCC; ký nháy = mực trên bản cứng GĐ4) → GĐ3 điều khoản → GĐ4 bản cứng 1-mốc. Scope 5 mảnh: master-data danh mục · sidebar 8 nhóm × 6 leaf · cây mirror sidebar · admin thu gọn + 8 designer · dry-run E2E. 🔴 Luật khuôn: **GIỐNG NHAU — CHỈ KHÁC FORM — ĐỪNG CHẾ THÊM**. 🔸 Khai thẳng (B1b l3-F4): đợt này **8 nhóm = đơn vị HIỂN THỊ + luồng duyệt**, KHÔNG phải đơn vị authz — mọi endpoint KHKK giữ 1 bộ policy `KeHoachKyKet.{R,C,U,D}` per-action (`ContractSigningPlansController.cs:28+`); authz-per-nhóm nếu anh muốn = wave riêng sau.
|
||||
|
||||
## ② Cách implement — 8 quyết định (v2)
|
||||
## ② Cách implement — 9 quyết định (v2; B3-A0b sửa đếm)
|
||||
|
||||
1. **[OG-1]** Cardinality "đưa vào loại HĐ" default **GỘP theo cặp (NCC × dòng-danh-mục)** — N line chung `ContractId` (hợp khuôn `ContractSigningPlanLine.cs:25`, index không-unique `Configuration:26`); đảo 1-1 được cùng máy.
|
||||
2. Phiếu KHKK = **per NHÓM** (1 phiếu = 1 nhóm, N hạng mục). Lines per-hạng-mục: Mig +`CatalogEntryId Guid?` +`TenHangMuc`, UNIQUE → (PlanId, SupplierId, CatalogEntryId) filtered. 🔴 **+2 vá B1b:** (a) **đổi rào 1-PE-1-phiếu** (`ContractSigningPlanFeatures.cs:342-347` + picker `:1201-1202`) → (PeId, ApprovalGroup) **[OG-7]** — FE tree đã chịu N-phiếu/PE (`usePipelineStages.ts:110-121`); (b) **bất-biến tiền**: `PeReferenceAmount` = snapshot per-NCC-toàn-phiếu (`Line.cs:6,:16-20`) — repurpose per-hạng-mục PHẢI định nghĩa lại semantics + Σ trước == Σ sau mig, acceptance rà **16 consumer** (10 BE `.Lines` + 6 file FE — danh sách l3-F18).
|
||||
2. Phiếu KHKK = **per NHÓM** (1 phiếu = 1 nhóm, N hạng mục). Lines per-hạng-mục: Mig +`CatalogEntryId Guid?` +`TenHangMuc`, UNIQUE → (PlanId, SupplierId, CatalogEntryId) filtered. 🔴 **+2 vá B1b:** (a) **đổi rào 1-PE-1-phiếu** (`ContractSigningPlanFeatures.cs:342-347` + picker `:1201-1202`) → (PeId, ApprovalGroup) **[OG-7]** — FE tree đã chịu N-phiếu/PE (`usePipelineStages.ts:110-121`); (b) **bất-biến tiền**: `PeReferenceAmount` = snapshot per-NCC-toàn-phiếu (`Line.cs:6,:16-20`) — repurpose per-hạng-mục PHẢI định nghĩa lại semantics + Σ trước == Σ sau mig, acceptance rà **18 consumer** (17 grep-verified cụm-1 + `Features.cs:712-713` Σ Proposed — số chốt theo cụm-1 vá-8; B3-A-x).
|
||||
3. Workflow = **1 type-10 + 8 Code `KHKK-N1..N8`**; only-ONE-active VÔ HẠI (chứng 2 mắt xích l2: create chỉ check type `:209-220`; overview không lọc IsActive `:117-134`, POST không đụng IsUserSelectable `:341-353`). 🔴 Cột `ApprovalGroup` **K2 là CHỦ DUY NHẤT** (l3-F6) — K3 chỉ đọc (map Code↔group + validator phiếu-pin-đúng-nhóm).
|
||||
4. Vai catalog = 2 tầng: danh mục lưu chuỗi vai TEXT (in khối ký GĐ4) ⟂ workflow Levels lưu NGƯỜI THẬT. 🔸 Khai limitation (l1-F12): TEXT không ràng buộc máy với người-duyệt-thật — chấp nhận đợt này, khai trong doc K1.
|
||||
5. NĐUQ = cột THAM KHẢO text **[OG-3]**; enforce (`CeoApprovalThreshold`) = wave opt-in sau (0 consumer CỐ Ý — `WorkflowService.cs:44`).
|
||||
5. NĐUQ = cột THAM KHẢO text **[OG-3 nâng cấp]**; enforce máy = **KHÔNG BAO GIỜ** (human-gate vĩnh viễn — a Chương quyết; B3-A0a: xóa nốt vế "wave opt-in sau" sót ở đây).
|
||||
6. Menu: GIỮ `Khkk_G1` + 6 leaf cũ, đổi LABEL = nhóm 1 (labelBackfill khuôn S155). Nhóm 2-8 = **42 leaf MỚI + 7 group-key mới (49 row menu mới; 48 leaf TỔNG)** — sửa số l1-F8/l2-F5. 🔴 Phiếu cũ: **backfill `ApprovalGroup = 1`** (l3-F5 — mirror bài `EvaluationType` không rỗng; acceptance đếm `COUNT(phiếu) == Σ COUNT 8 folder`).
|
||||
7. Admin ẩn = fe-admin **`isAdminHidden` MỞ RỘNG TẬP KEY TƯỜNG MINH** (giữ blacklist — KHÔNG đảo whitelist, tránh đổi default menu-mới; vá hội tụ l1-F2 ⨯ l3-F1/F2): ẩn thêm {`Dashboard?`→giữ, các root nghiệp vụ: `DuyetNcc-root keys`, `KeHoachKyKet`, HR/Office/Personal, `Contracts`(đã ẩn `Ct_*`), `HardCopies`, `Forms`, `Reports`, `Catalogs/Master`, **`Workflows` (:1795)**, **`PeWorkflows` (:1798)**} — CHỪA {`System` + 4 leaf quản trị + **`ApprovalWorkflowsV2` (:1801, con System)** + subtree}. Danh sách key CHÍNH XÁC = việc B2-cụm-2 liệt từ `DbInitializer` seed; acceptance = **liệt kê đúng N mục lá còn thấy** (l3-F2).
|
||||
8. Nguồn danh mục: **file đĩa `QUY_TRINH/QT TRINH KY HOP DONG TP-NCC.docx` = ĐÚNG SOL-CCM-SP-002.v01 (mã ở word/header1.xml) NHƯNG bản 6-trang KHÔNG chứa bảng** (lead đo). Nguồn bảng = **7 ảnh anh gửi @S164 (trang 5-9, trọn 5.1 A/B/C + 5.2 CEO)** → transcribe → **[OG-6] anh soát bảng seed trước land** (hoặc anh gửi file 15-trang). "/" trong ô vai = OR-of-N.
|
||||
9. 🆕 **KHÓA BUDGET TẠI FINALIZE (owner @S164, verbatim: "Cái tính năng chuyển CEO và duyệt kết thúc hợp đồng -> Là khóa luôn cái budget rồi, người quyết sẽ là a Chương, Trưởng phòng CCM"):** khi phiếu KHKK được **duyệt-kết-thúc tại CCM (a Chương finalize) HOẶC CEO duyệt final** ⇒ **freeze số** (ApprovedAmount/giá chốt/NS tham chiếu) — phiếu DaDuyet đọc SNAPSHOT, không đọc live. **Mirror nguyên khuôn PE Mig 67** (`AddPeApprovedBudgetSnapshot` S133): snapshot chốt tại finalize choke-point + display-gate `frozen` + 🔴 né **#81-EXT**: grep MỌI Phase-assignment-site (kể cả admin-override + seeder) kẻo bypass hook — bài đã trả giá 1 lần bên PE. Người quyết finalize-hay-CEO = **TP.CCM Phan Văn Chương** (cấp 2 CCM đội hình `QT-DN-V2-001`). ⚠️ MERGE-PENDING: B2-cụm-1 lane phóng TRƯỚC lời này — lead merge vào spec chi tiết khi lane về (schema cột snapshot → K2, hook finalize → K3).
|
||||
9. 🆕 **KHÓA BUDGET TẠI FINALIZE (owner @S164; văn SỬA theo B3-A4 — thiết kế THẬT do cụm-1/cụm-3 chốt, cha theo con):** khi phiếu KHKK **finalize tại CCM (a Chương) HOẶC CEO duyệt final** ⇒ số KHÓA. 🔴 **KHÔNG chép khuôn 11-cột Mig 67** — máy freeze per-line ĐÃ CÓ SẴN: `PeReferenceAmount` copy-at-create (`Line.cs:17-20`) + `ApprovedAmount ??=` tại choke-point (`WorkflowService.cs:301-305`, 1-site-DaDuyet verified `:129/:278/:289-292`) ⇒ việc còn lại = **phase-guard line-edit sau DaDuyet (K2) + test-khóa 1-site (K2) + phép đo 2-nhánh TRƯỢT-ĐƯỢC (K8 — sửa nguồn → reload → số KHÔNG đổi, đo cả nhánh CCM-finalize lẫn CEO)** + cột runtime `EndedByLevelFinalize` (K2 item-6 đẻ, K3 tiêu thụ — 3 spec cùng 1 cột ✓). Người quyết = **TP.CCM Phan Văn Chương**. Né #81-EXT: sweep site gán Phase — đã liệt 4 site, GỠ nghi án `WorkflowService.cs:342` (comment đọc-đủ-khối: CỐ Ý không có site gán-qua-biến).
|
||||
|
||||
## ③ Wave K1-K8 (v2 — PRE-gate + acceptance có răng)
|
||||
|
||||
@ -27,7 +27,7 @@ Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA,
|
||||
|
||||
**Cụm 2 (UI):** *(l3-F8: tách phụ thuộc thật — K4a chạy song song cụm 1 được)*
|
||||
- **K4a Menu+grant** (0 phụ thuộc): 49 row menu + grant 3 SITE (`:1780` seed · `SeedKeHoachKyKetAccessAsync:2415` · **`KhkkKeys():2185` — site-3 l2-F6**, comment `:2204` "quên 1 bên = quyền lệch"). **K4b 4 leaf list + Thao tác** (chờ K2 param). **K4c leaf WfView/Create** (chờ K3): WfView mang `?group=` lọc theo workflow Code nhóm (hiện `WorkflowMatrixViewPage:52-71` chỉ lọc type — l2-F3). DoD: 48 leaf render đúng · leaf lọc đúng group **kể cả WfView/Create** · **2 chiều theo bảng kỳ-vọng 13 role** (seeder hiện phủ 7 vai `:2671-2675` — 6 vai còn lại khai kỳ vọng TRƯỚC, l3-F13) · key cũ 0 mồ côi.
|
||||
- **K5 Cây sub-folder**: GĐ2 group-by `approvalGroup` · GĐ3/4 group-by `c.type` (đã có `:240`); thêm tầng `groups` vào `PipelineStage` (mở rộng khuôn — bẫy `content` phải truyền `count` tay `:74-75`). DoD: sub-folder khớp sidebar · **2 file đích danh SHA-identical ×2 app** (`usePipelineStages.ts` + `PipelineTreePanel.tsx` — l3-F19) · build ×2 PASS.
|
||||
- **K5 Cây sub-folder**: GĐ2 group-by `approvalGroup` · GĐ3/4 group-by `c.type` (đã có `:240`); thêm tầng `groups` vào `PipelineStage` (mở rộng khuôn — bẫy `content` phải truyền `count` tay `:74-75`). DoD: sub-folder khớp sidebar · **4 file pipeline SHA-identical ×2 app** (đối chiếu cụm-2 — usePipelineStages · PipelineStageFolders · PipelineTreePanel · trang nhúng; B3 sửa đếm) · build ×2 PASS.
|
||||
- **K6 Admin thu gọn** (độc lập NHƯNG l3-F9: kéo sớm TRƯỚC K3 thì 8 designer chưa tồn tại — nếu kéo sớm, acceptance "đếm 8 designer" dời sang sau K3): QĐ7 tập-key tường minh. DoD: **liệt kê đúng N mục lá còn thấy (đủ tên, dư/thiếu 1 = FAIL)** · fe-user KHÔNG đổi = **`git diff --stat <base>..<head> -- fe-user/src` = 0 file** (KHÔNG đo bundle-hash #69 — l3-F12).
|
||||
|
||||
**Cụm 3 (nối + chạy):**
|
||||
@ -36,7 +36,7 @@ Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA,
|
||||
|
||||
**Mọi wave:** cicd PASS; **byte-verify #77 CHỈ wave có FE-ship** — wave BE-only = smoke API (l3-F17); mig = 3-file rule.
|
||||
|
||||
## ④ [OWNER-GATE] — 4 cũ + 2 mới (nối vào PRE từng wave ở trên)
|
||||
## ④ [OWNER-GATE] — 8 hàng, cập nhật sống (B3-A0b sửa đếm)
|
||||
|
||||
| OG | Câu hỏi | Trạng thái | Chặn wave |
|
||||
|---|---|---|---|
|
||||
|
||||
@ -5,7 +5,7 @@ K1 master-data danh mục (86 row) · K2 phiếu mang hạng-mục + nhóm + fre
|
||||
|
||||
## ② 12 vá (build ĐỌC CẢ nền LẪN vá)
|
||||
|
||||
1. 🔴 **[3-lane hội tụ] Menu key PHẢI VÀO `MenuKeys.All`** — nền khai `ContractCatalog` + 8 `AwV2_KhkkN*` "ngoài All" ⇒ **0 permission row ⇒ sidebar chết** (loop grant `DbInitializer.cs:2058` nguồn = All; khuôn THẬT: 5 leaf catalog hiện hành `MenuKeys.cs:168` + 3 leaf AwV2 `:182` đều TRONG All). Fix: cả 9 key **VÀO All** + KHAI drift canonical (Menu keys 55→64 · Policies 220→256 — khai 2 row STATUS cùng lúc, đừng Goodhart giữ-số-đứng-yên). Acceptance += "login Admin THẤY leaf trong sidebar ×2 app" + 1 test seed-grant.
|
||||
1. 🔴 **[3-lane hội tụ] Menu key PHẢI VÀO `MenuKeys.All`** — nền khai `ContractCatalog` + 8 `AwV2_KhkkN*` "ngoài All" ⇒ **0 permission row ⇒ sidebar chết** (loop grant `DbInitializer.cs:2058` nguồn = All; khuôn THẬT: 5 leaf catalog hiện hành `MenuKeys.cs:168` + 3 leaf AwV2 `:182` đều TRONG All). Fix: cả 9 key **VÀO All** + KHAI drift dạng **DELTA per-wave** (B3-A1 — cấm neo tuyệt-đối vì thứ tự ship: K1 = +1 key/+4 policy · K3 = +8 key/+32 policy; mỗi commit kèm lệnh đếm lại `MenuKeys.All` thực tế + cập nhật 2 row STATUS, đừng Goodhart giữ-số-đứng-yên). Acceptance += "login Admin THẤY leaf trong sidebar ×2 app" + 1 test seed-grant.
|
||||
2. 🔴 **[L1-F5] GỠ phương án (i) tại site `:342`** — nền đọc NGƯỢC comment (`WorkflowService.cs:36-43` mô tả NGUỒN COPY và khẳng định KHKK CỐ Ý không có site gán-qua-BIẾN; `:342` nằm trong `ReturnOrRejectAsync` chỉ nhận TraLai/TuChoi literal — DaDuyet **unreachable** qua đó). GIỮ phương án (ii): test khóa khẳng định điều đó. Cấm "sửa" :342.
|
||||
3. 🔴 **[L2-H2] K3 thêm việc (d): sweep cụm ép-false** — `grep -rn "AllowApproverFinalize|AllowApproverSkipToFinal"` toàn src + fe-*: gỡ đủ **CREATE ép-false server-side** `ApprovalWorkflowV2AdminFeatures.cs:380-381` + **PUT Conflict** `:591-594`/`:605-610` + **FE `levelFlagsPayload`** `ApprovalWorkflowsV2Page.tsx:247-258` (`earlyFinalizeLocked :638`) — không chỉ note `:151-152`. Test mới: "tạo version qua CreateCommand type-10 GIỮ được cờ".
|
||||
4. 🔴 **[L2-H3] `KhkkCreatePage` ×2 app PHẢI SỬA** (mâu thuẫn nền: command +`ApprovalGroup` required nhưng page ghi "KHÔNG-ĐỔI") — body POST thêm `approvalGroup` + picker nhóm. Acceptance += "tạo phiếu nhóm 2 **TỪ UI** ×2 app" (curl-only không đủ).
|
||||
@ -19,7 +19,9 @@ K1 master-data danh mục (86 row) · K2 phiếu mang hạng-mục + nhóm + fre
|
||||
12. **[L1-F3/F4] Trích dẫn `:44-46` ĐỦ + khai supersede**: nguyên văn có "chủ dự án phán 'PHÁ VỠ' @S155" — spec PHẢI khai K3 = **ĐẢO phán quyết cũ theo lời owner @S164**, kèm việc (e): sửa comment `:36-43`/`:44-46` + 2 lệnh tự-kiểm `:292-293` dán PR + cập nhật `KhkkWorkflowPanel.tsx:8` ×2 app + HANDOFF:77. ✅ **[OG-9 CHỐT @S164]** anh xác nhận TƯỜNG MINH: *"đúng, chỗ budget chốt chặn là a Chương… vậy bài toán trần budget xem như đóng"* ⇒ đảo "PHÁ VỠ" @S155 hợp lệ — **K3 (a)-(e) HẾT CHẶN**. Kèm: NĐUQ = human-gate VĨNH VIỄN (không còn wave enforce-máy nào; xóa mọi ý "opt-in sau").
|
||||
|
||||
## ③ Checklist final cụm-1
|
||||
- [ ] K1: 7 mục nền + **"Admin thấy leaf sidebar ×2 app"** + test seed-grant + drift 2 row STATUS khai cùng commit.
|
||||
- [ ] K1: 7 mục nền + **"Admin thấy leaf sidebar ×2 app"** + test seed-grant + drift DELTA khai cùng commit.
|
||||
- [ ] K2 (+B3-A6): nút **"Tạo thêm cho nhóm khác"** (OG-7 UI-hướng-1) CHỦ = K2, site picker/PE-flow `ContractSigningPlanFeatures.cs:1201-1202` + PE-detail — acceptance TỪ UI: PE có phiếu → thấy phiếu + nút phụ, bấm → form preset nhóm khác → 201.
|
||||
- [ ] K3 (+B3-B3 câu-ranh): fe-admin `resolvePath` nới **CHỈ họ `AwV2_KhkkN*`** — **CẤM nới họ `Khkk_*`** (fe-admin thiếu WorkflowMatrixViewPage; phép-âm: grep route Khkk_ fe-admin = 0).
|
||||
- [ ] K2: 8 mục nền + **submit-guard null-CatalogEntryId (test ÂM trên phiếu có line)** + phase-guard line-edit + Σ×3 nhất quán + Mig-71 6 item + 3-file + backfill=1 + **UI tạo-phiếu-nhóm-2 ×2 app** + bảng 18 consumer (17 nền + :712-713).
|
||||
- [ ] K3 (SAU OG-9): 6 mục nền + sweep ép-false ≥4 site + test giữ-cờ-qua-CreateCommand + đo danh tính roster + comment/panel/HANDOFF cập nhật + verify LIVE trước seed.
|
||||
- [ ] Mọi wave: test ≥590+k khai k · cicd PASS · BE-only smoke API (#77 chỉ khi FE-ship).
|
||||
|
||||
@ -25,7 +25,7 @@ K4 sidebar 8 nhóm × 6 leaf (49 row menu mới) · K5 cây sub-folder groups ·
|
||||
- [ ] K4a (ship 1 khối): 49 row menu VÀO All + labelBackfill G1 + route regex resolvePath ×(fe-user; fe-admin GHI RÀNG BUỘC) + 3-site grant (+dòng site-4 đã-soi) + nhãn N2 sửa + comment :1959/:179 vá. Acceptance: Admin + 1 user thường THẤY 8 group sidebar fe-user; 42 leaf BẤM ĐƯỢC (không null-route); drift DELTA khai + đo lại All; SQL JOIN đếm designer đúng N; restart ×2 số row menu/permission KHÔNG đổi (idempotent + revoker-proof).
|
||||
- [ ] K4b: 4 leaf list + Thao tác preset — derive phase+group từ searchParams; `queryKey` += group; acceptance bấm leaf→leaf ĐỔI kết quả không cần F5; URL G1 6 leaf mang `group=1`.
|
||||
- [ ] K4c (sau K3): WfView lọc `Code==='KHKK-N'+n`.
|
||||
- [ ] K5: `groups` mang leaves thật (không đường `content`) + GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` + HIỆN ĐỦ 8 + fallback chưa-phân-nhóm + Σ sub-folder == tổng phiếu; SHA-identical 4 file pipeline ×2 app (lệnh đo từng file); build ×2 PASS.
|
||||
- [ ] K5: `groups` mang leaves thật (không đường `content`) + GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` + HIỆN ĐỦ 8 + fallback chưa-phân-nhóm + Σ sub-folder == tổng phiếu; SHA-identical 4 file pipeline ×2 app (lệnh đo từng file); build ×2 PASS. **+forward-provision (B3-A5, việc cụm-3 vá-4b đẻ cho K5):** builder GĐ3/GĐ4 nối qua **TẬP `lines[].contractId` ∪ `pe.contractId` legacy** — không thì HĐ thứ 2+ (OG-1 UI-1-1, N HĐ/PE) vô hình trên cây.
|
||||
- [ ] K6: blacklist 12-key tường minh + acceptance liệt kê ĐÚNG N mục lá (tên + đếm, dư/thiếu 1 = FAIL) + `git diff --stat -- fe-user/src` = 0 file + comment ràng-buộc-ngược land.
|
||||
- [ ] Test (lead-note bù L3): seed-menu idempotent ×2 · labelBackfill đổi-label-không-nhân-row · route-map FE có leaf nào null-path = FAIL (unit nhỏ nếu khuôn có; không thì acceptance tay + chụp). Baseline ≥590+k khai k.
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
# impl-be K1
|
||||
|
||||
## Tiến độ
|
||||
- [ ] Đọc spec (4 nguồn)
|
||||
|
||||
## Lệch spec (nếu có)
|
||||
_(chưa có)_
|
||||
|
||||
## Kết quả build/test
|
||||
_(chưa chạy)_
|
||||
|
||||
(ĐANG LÀM)
|
||||
@ -24,39 +24,102 @@
|
||||
- **Rủi ro thật:** comment `:2204` *"quên 1 bên = quyền lệch"* + cụm-2 vá-15 dạy khuôn TRONG-All có thể xúi builder "cho đủ bộ" nhét cả 9 key vào `KhkkKeys()`. **Fix 1 dòng:** thêm vào cụm-1 vá-1: *"9 key này KHÔNG vào `KhkkKeys()`/site-2/3 — chỉ All (+Admin-loop)"*. Verdict: KHÔNG mâu thuẫn, cần 1 câu chốt ranh.
|
||||
- Designer fe-user: KHÔNG thấy và KHÔNG NÊN — fe-user không route System subtree; đường thấy duy nhất = fe-admin (K6 CHỪA `ApprovalWorkflowsV2 :1801`).
|
||||
|
||||
### A-3. Chuỗi ApprovalGroup K2→K4b→K5 — (nháp sau cụm-2, chờ cụm-3 vá-5 T2)
|
||||
- K2 CHỦ (cột + backfill=1 + param `group` + DTO `:34` + picker create cụm-1 vá-4) → K4b tiêu thụ (queryKey += group `spec-cum2:10` vá-3 · phase+group từ searchParams vá-5 · preset `?group=` vá-6) → K5 group-by `approvalGroup` + hiện đủ 8 + fallback NULL-group (vá-9). Chuỗi schema→API→list→tree ĐỦ 1 đường tính đến cụm-2. Chờ soi cụm-3 vá-5 "T2-sau-K2" rồi chốt.
|
||||
### A-3. Chuỗi ApprovalGroup K2→K4b→K5→K7 — **VẼ ĐỦ 1 ĐƯỜNG** ✅
|
||||
- K2 CHỦ DUY NHẤT (cột + backfill=1 + DROP-unique-cũ + param `group` + DTO `:34` + picker create cụm-1 vá-4; luật l3-F6 "K3 chỉ đọc" giữ nguyên `spec-tong:13`) → K4b tiêu thụ (queryKey += group `spec-cum2:10` vá-3 · phase+group từ searchParams vá-5 · preset `?group=` vá-6) → K5 group-by `approvalGroup` + hiện đủ 8 + fallback NULL-group (vá-9) → K7 test T2 (gộp 2 line cùng NCC) khai tường minh phụ-thuộc Mig-71-DROP-unique, chạy SAU K2 (`spec-cum3:15` vá-5 — chính cụm-3 tự vá cái sót của nền mình). Verdict: chuỗi schema→API→list→tree→test KHÉP KÍN, không mắt xích nào vô chủ.
|
||||
|
||||
### A-4. Freeze QĐ9 — nháp sau cụm-1 (chờ cụm-3 vá-10)
|
||||
- Cột runtime `EndedByLevelFinalize`: tổng `:46` OG-3-SỬA "(b) forward-provision vào Mig 71 ⇒ K3 0-mig" **KHỚP** `spec-cum1:14` vá-7 (Mig 71 item 6 + tên mig `AddKhkkApprovalGroupCatalogAndFinalizeRuntime` + khai ghost-window K2→K3). ✅ cùng 1 cột.
|
||||
- ⚠️ **Snapshot budget (QĐ9 "phiếu DaDuyet đọc SNAPSHOT, mirror Mig 67 11-cột") KHÔNG THẤY trong cụm-1**: Mig 71 chỉ 6 item (1-5 nền + EndedByLevelFinalize), KHÔNG có cột snapshot; freeze cụm-1 = tổ hợp {vá-2 test-khóa :342-unreachable (`WorkflowService.cs`) + vá-6 phase-guard line-edit kéo về K2 + vá-8 "list thêm Σ Approved sau freeze"} ⇒ thiết kế freeze = **immutability-live** chứ KHÔNG snapshot-read. MERGE-PENDING `:19` của tổng **CHƯA merge** vào cụm-1 final. Chờ cụm-3 vá-10 rồi phán.
|
||||
- 🪤 Bẫy **":342 hai file khác nhau"**: tổng QĐ2 dùng `:342-347` = `ContractSigningPlanFeatures.cs` (rào 1-PE-1-phiếu, K2 ĐỔI); cụm-1 vá-2 dùng `:342` = `WorkflowService.cs` (`ReturnOrRejectAsync`, CẤM sửa — DaDuyet unreachable). Builder đọc lướt sẽ sửa nhầm site. Cần 1 câu định-danh-file trong spec build.
|
||||
### A-4. Freeze QĐ9 — cột runtime KHỚP 3 spec ✅ · **tổng hứa snapshot+display-gate mà KHÔNG cụm nào nhận** 🔴
|
||||
- Cột runtime `EndedByLevelFinalize`: tổng `:46` OG-3-SỬA "(b) forward-provision vào Mig 71 ⇒ K3 0-mig" **KHỚP** `spec-cum1:14` vá-7 (Mig 71 item 6 + tên mig + ghost-window K2→K3) **KHỚP** `spec-cum3:17` vá-7 (B6 đổi neo, thừa nhận "vật K3 MỚI ĐẺ, hiện 0 hit"). ✅ 3 spec cùng 1 cột trên bảng plan KHKK.
|
||||
- 🔴 **Snapshot + display-gate của QĐ9 tổng (`:19` "mirror nguyên khuôn PE Mig 67: snapshot 11 cột + display-gate `frozen`") KHÔNG AI LÀM**: Mig 71 cụm-1 chỉ 6 item — 0 cột snapshot; không vá nào ở 3 cụm nhắc display-gate. Thiết kế THẬT trong cụm = **copy-at-create + immutability**: line đã mang bản chép (`PeReferenceAmount` `Line.cs:6,:16-20` + `TenHangMuc` + `ApprovedAmount` per-line) + phase-guard line-edit kéo về K2 (cụm-1 vá-6) + test-khóa 1-site-DaDuyet (cụm-1 vá-2 — verify đĩa: `ContractSigningPlanWorkflowService.cs:37-38` khai "ĐÚNG MỘT nhánh set DaDuyet", `:129/:134` ReturnOrReject chỉ TraLai/TuChoi, `:278` site duy nhất, `:289-292` helper choke-point + lệnh grep tự-kiểm) + **răng đo = cụm-3 vá-10** (`spec-cum3:22` sửa NGUỒN sau finalize → reload → số KHÔNG đổi, đo CẢ 2 nhánh CCM-finalize VÀ lên-CEO — phép đo TRƯỢT ĐƯỢC ✓ đạt sàn-sự-thật).
|
||||
- **Phán:** thiết kế cụm HỢP LÝ HƠN khuôn Mig 67 (KHKK line vốn denormalized-at-create, PE thì display JOIN live nên mới cần snapshot) — nhưng tổng QĐ9 đang là VĂN STALE hứa vật không ai giao. Fix: sửa đoạn QĐ9 tổng thành "freeze KHKK = copy-at-create + phase-guard + test-khóa 1-site + phép đo 2-nhánh vá-10; KHÔNG mig snapshot mới; nếu vá-10 đo FAIL (lộ chỗ display đọc live) → lúc đó mới mở mig snapshot bổ sung". Không sửa thì builder K2 sẽ đi tìm "11 cột snapshot" không tồn tại trong cụm-1. Verdict: **MÂU THUẪN #2 — phải vá TỔNG theo cụm trước build.**
|
||||
- 🪤 Bẫy **":342 hai file khác nhau"**: tổng QĐ2 dùng `:342-347` = `ContractSigningPlanFeatures.cs` (rào 1-PE-1-phiếu, K2 ĐỔI); cụm-1 vá-2 dùng `:342` = `ContractSigningPlanWorkflowService.cs` (`ReturnOrRejectAsync`, CẤM sửa — DaDuyet unreachable). Builder đọc lướt sẽ sửa nhầm site. Spec build phải ghi TÊN FILE cạnh mọi ":342".
|
||||
|
||||
### A-5. Cây GĐ3: cụm-3 ĐẺ VIỆC cho K5 mà spec cụm-2 KHÔNG BIẾT 🔴
|
||||
- `spec-cum3:14` vá-4(b) gắn nhãn tường minh "**K5-liên-đới**: builder GĐ3/GĐ4 nối qua TẬP `lines[].contractId` của các phiếu KHKK thuộc gói (∪ `pe.contractId` legacy)" — nhưng `spec-cum2:28` checklist K5 chỉ có "GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` (đã có `:240`)", **0 chữ về `lines[].contractId`**. Cây hiện đi `pe.contractId` ĐƠN (`usePipelineStages.ts:214-218`, khớp giới-hạn HĐ[0] đã khai S162 `CreateContractFromEvaluationFeatures.cs:145`).
|
||||
- Hậu quả nếu không vá: K5 (land trước) build đúng spec cụm-2 → K7 bridge ghi `Line.ContractId` per-line → HĐ thứ 2+ **vô hình trên cây** (vá-4(a) `pe.ContractId ??=` chỉ cứu HĐ đầu); muốn sửa phải chạm lại 2 file pipeline SAU K5 → re-run SHA-identical + build ×2 ngoài kế hoạch.
|
||||
- **Fix 1 dòng vào cụm-2 K5:** "GĐ3/4 nguồn HĐ = ∪ `lines[].contractId` ∪ `pe.contractId` legacy (forward-provision — trước K7 tập lines rỗng, cây không đổi hành vi)" + acceptance "phiếu 2 line 2 HĐ → cây hiện 2" (chạy được từ K7). Verdict: **MÂU THUẪN #3 — phải vá cụm-2 trước build K5.**
|
||||
|
||||
### A-x. Drift consumer-count tổng ⟂ cụm-1
|
||||
- Tổng `:12` QĐ2: *"acceptance rà **16 consumer** (10 BE + 6 FE — l3-F18)"* ⟂ `spec-cum1:23` checklist K2: *"bảng **18 consumer** (17 nền + :712-713)"*. Cụm-1 THẮNG theo luật vá (nền 17 + vá-8 thêm 1 = 18) nhưng tổng chưa sửa số ⇒ builder đọc tổng trước sẽ rà thiếu 2. Fix 1 dòng ở tổng khi ship.
|
||||
|
||||
### A-6. OG-7 UI-hướng-1 — 2 cửa tạo phiếu nhóm 2 KHÔNG chỏi, nhưng NÚT PHỤ chưa có chủ (nháp sau cụm-2)
|
||||
- Cửa 1: KhkkCreatePage + picker nhóm (cụm-1 vá-4, thuộc K2). Cửa 2: leaf "Thao tác" preset `?group=` (cụm-2 vá-6, K4b — 0 phụ thuộc K3, chỉ cần picker vá-4). 2 cửa cùng đổ về 1 form — KHÔNG trùng/chỏi.
|
||||
- ⚠️ Nhưng OG-7 tổng `:45` hứa UX cụ thể: *"PE có phiếu rồi → hiện phiếu + **nút phụ 'Tạo thêm cho nhóm khác'** (thay 409 chặn hẳn)"* — grep cả cụm-1 lẫn cụm-2: KHÔNG vá nào nhận việc "nút phụ" này (cụm-1 vá-4 = picker nhóm; K2 đổi picker PE `:1201-1202` = gỡ filter PE-đã-có-phiếu; cụm-2 vá-6 = preset group). Acceptance cụm-1 "tạo phiếu nhóm 2 TỪ UI ×2 app" đo được OUTCOME nhưng không ép UX hướng-1. → LỖ CHỦ-VIỆC nhỏ: cần 1 dòng gán "nút phụ + hiện-phiếu-thay-chặn" về K2 (cùng site picker) hoặc tuyên bố 2-cửa-là-đủ-default và hạ câu OG-7 xuống mô tả hành vi picker. Chờ cụm-3 xem có ai nhận không.
|
||||
- ⚠️ Nhưng OG-7 tổng `:45` hứa UX cụ thể: *"PE có phiếu rồi → hiện phiếu + **nút phụ 'Tạo thêm cho nhóm khác'** (thay 409 chặn hẳn)"* — soi CẢ 43 vá 3 cụm: KHÔNG vá nào nhận việc "nút phụ" này (cụm-1 vá-4 = picker nhóm; K2 đổi picker PE `:1201-1202` = gỡ filter PE-đã-có-phiếu; cụm-2 vá-6 = preset group; cụm-3 = K7/K8 không đụng). Acceptance cụm-1 "tạo phiếu nhóm 2 TỪ UI ×2 app" đo OUTCOME nhưng không ép UX hướng-1 mà owner đã ratify verbatim. **Verdict: LỖ CHỦ-VIỆC (mâu thuẫn hứa⟂giao) — fix 1 dòng gán về K2** (cùng site picker `:1201-1202`: chọn PE đã-có-phiếu → hiện danh sách phiếu hiện có + nút "Tạo thêm cho nhóm khác" thay vì message chặn); không nên hạ lời OG-7 vì đó là lời chốt của owner.
|
||||
|
||||
## B. Vá-đè-vá (vá cụm sau có phá vá cụm trước?)
|
||||
(ĐANG LÀM — cặp nghi tính đến cụm-2; chờ cụm-3 để chốt 43 vá)
|
||||
## B. Vá-đè-vá (vá cụm sau có phá vá cụm trước?) — soi 43 vá (12+15+16), 7 cặp nghi
|
||||
|
||||
| # | Cặp | Verdict nháp |
|
||||
| # | Cặp | Verdict |
|
||||
|---|---|---|
|
||||
| B-1 | cụm-1 vá-6 (kéo phase-guard line-edit K4b→K2) ⟂ cụm-2 K4b checklist | ✅ SẠCH — cụm-2 final K4b (`spec-cum2:26`) KHÔNG còn nhắc phase-guard ⇒ move đã được cụm-2 tôn trọng, không mồ côi không trùng |
|
||||
| B-2 | cụm-2 vá-6 (Thao tác preset VỀ K4b) ⟂ tổng K4b "chờ K2 param" | ✅ SẠCH — dependency K2 giữ nguyên, chỉ gỡ phụ thuộc K3 giả |
|
||||
| B-3 | tổng K3 "mở resolvePath **fe-admin** `Layout.tsx:166-172` nhận code mới" ⟂ cụm-2 vá-8 "**KHÔNG nới regex fe-admin** đợt này" | ⚠️ KHÔNG phá nhau NHƯNG dễ đọc nhầm thành phá: 2 câu nói về 2 HỌ key khác nhau trên CÙNG file/hàm — K3 nới cho `AwV2_KhkkN*` (designer, System subtree, vẫn hiện sau K6) · vá-8 cấm nới cho `Khkk_*` 48-leaf (KeHoachKyKet bị ẩn admin + fe-admin THIẾU `WorkflowMatrixViewPage`). Cần 1 câu ranh trong spec build: "fe-admin resolvePath: THÊM pattern AwV2_KhkkN* — CẤM thêm pattern Khkk_*" kẻo builder K3 tiện tay nới cả hai |
|
||||
| B-4 | cụm-1 vá-2 (CẤM sửa `WorkflowService.cs:342`) ⟂ tổng QĐ2 "đổi rào :342-347" | ✅ KHÔNG đụng nhau về máy — 2 file khác nhau trùng số dòng (`Features.cs:342-347` rào 1-PE-1-phiếu PHẢI đổi · `WorkflowService.cs:342` unreachable CẤM đụng); nhưng là bẫy-đọc-lướt đã ghi ở A-4, spec build phải ghi TÊN FILE cạnh mọi ":342" |
|
||||
| B-1 | cụm-1 vá-6 (kéo phase-guard line-edit K4b→K2) ⟂ cụm-2 K4b checklist | ✅ SẠCH — cụm-2 final K4b (`spec-cum2:26`) KHÔNG còn nhắc phase-guard ⇒ move được cụm-2 tôn trọng, không mồ côi không trùng |
|
||||
| B-2 | cụm-2 vá-6 (Thao tác preset VỀ K4b) ⟂ tổng K4b "chờ K2 param" | ✅ SẠCH — dependency K2 giữ nguyên, chỉ gỡ phụ thuộc K3 giả; đúng điều kiện "chỉ cần picker vá-4 cụm-1" |
|
||||
| B-3 | tổng K3 "mở resolvePath **fe-admin** `Layout.tsx:166-172`" ⟂ cụm-2 vá-8 "**KHÔNG nới regex fe-admin** đợt này" | ⚠️ KHÔNG phá nhau NHƯNG dễ đọc nhầm thành phá: 2 HỌ key khác nhau trên CÙNG file/hàm — K3 nới cho `AwV2_KhkkN*` (designer, System subtree, vẫn hiện sau K6) · vá-8 cấm nới cho `Khkk_*` 48-leaf (KeHoachKyKet bị ẩn admin + fe-admin THIẾU `WorkflowMatrixViewPage` — L1-BÁC-2). **Cần 1 câu ranh:** "fe-admin resolvePath: THÊM pattern `AwV2_KhkkN*` — CẤM pattern `Khkk_*`" kẻo builder K3 tiện tay nới cả hai |
|
||||
| B-4 | cụm-1 vá-2 (CẤM sửa `WorkflowService.cs:342`) ⟂ tổng QĐ2 "đổi rào :342-347" | ✅ KHÔNG đụng về máy — 2 file trùng số dòng (`Features.cs:342-347` rào 1-PE-1-phiếu PHẢI đổi · `WorkflowService.cs:342` unreachable CẤM đụng — verify đĩa `:129/:134/:278`); bẫy-đọc-lướt, spec build ghi TÊN FILE cạnh mọi ":342" |
|
||||
| B-5 | cụm-3 vá-4(b) (K5 nối `lines[].contractId`) ⟂ cụm-2 K5 checklist | 🔴 KHÔNG phá vá cũ nhưng ĐẺ VIỆC vào wave cụm-2 mà spec cụm-2 không chứa = A-5 mâu-thuẫn #3 — vá spec cụm-2 trước build K5 |
|
||||
| B-6 | cụm-3 vá-7 (B6 đổi neo `EndedByLevelFinalize` "vật K3 mới đẻ") ⟂ cụm-1 vá-7 (cột vào Mig 71/K2, K3 wire) | ✅ SẠCH — nhất quán: cột đẻ ở K2-mig (nằm im, ghost-window đã khai), K3 wire, K7-B6 neo tùy nhánh; 3 spec cùng 1 cột (A-4 ý 1) |
|
||||
| B-7 | cụm-3 vá-12 (TRƯỚC K2 rào per-PE ⇒ phiếu ZZTEST khóa TOÀN BỘ PE thật) ⟂ cụm-1 K2 đổi rào | ✅ SẠCH — cụm-3 nhận thức đúng thứ tự (K8 CUỐI sau mọi wave + nghiêng phương án (b) PE-ZZTEST-riêng); không đè, chỉ ràng thêm điều kiện chạy-sau |
|
||||
|
||||
**Verdict B: 0 vá cụm sau LÀM VÔ HIỆU vá cụm trước.** 7 cặp nghi xét: 5 sạch · 2 cần câu-ranh/vá-spec (B-3 câu ranh 2-họ-key · B-5 = A-5).
|
||||
|
||||
## C. Build-order cuối + gate
|
||||
(ĐANG LÀM)
|
||||
|
||||
## D. Rủi ro còn hở
|
||||
(ĐANG LÀM)
|
||||
**Thứ tự chốt: K1 → K2 → K3 → K4a → K4b → K5 → K4c → K6 → K7 → K8** (10 đơn vị build; khớp đề xuất lead, KHÔNG đổi trình tự — chỉ siết gate). Lý do giữ K4a SAU K3 dù "0 phụ thuộc code" (l3-F8 cho song song): tránh cửa-sổ-prod 8-leaf-chưa-lọc (trước K2 API không có param `group` ⇒ 42 leaf hiện CÙNG nội dung) + nhãn 8 group cần anh gật (cụm-2 vá-7) — kéo song song chỉ khi owner chấp nhận 2 điều đó tường minh.
|
||||
|
||||
| Wave | PRE-gate owner | Mig | Restart BE | Deploy | Test-k |
|
||||
|---|---|---|---|---|---|
|
||||
| K1 | **OG-6 ✅ (soát 86 dòng — chặn SEED, code build trước được) + OG-5 hỏi-khi-gặp** | Mig 70 (3-file) | ✅ | BE + FE ×2 (leaf catalog) → #77 | +k khai (seed-idempotent, CRUD) |
|
||||
| K2 | 0 (OG-1/7 ✅ rồi) — PRE-spec-fix A-1 (lead) | Mig 71 (6 item, DROP unique cũ, backfill=1) | ✅ | BE + FE ×2 (picker+create) → #77 | +k (Σ trước==sau · 409-có-line · UI-nhóm-2 · 18-consumer) |
|
||||
| K3 | OG-2 ✅ + **verify đội hình LIVE trước seed** + OG-9 ✅ | 0-mig (cột đã forward-provision K2) | ✅ (seed 8 WF + sweep ép-false) | BE + fe-admin (designer + resolvePath AwV2) → #77 | +k (8 WF · pin-sai-nhóm 409 · giữ-cờ-qua-Create · danh-tính roster · finalize 2-nhánh) |
|
||||
| K4a | **8 nhãn đính file OG-6 — anh gật** | 0-mig | ✅ (seed 49 row + 3-site) | BE + fe-user (route regex) → #77 | +k (idempotent ×2 restart · SQL JOIN designer · 42 leaf bấm được) |
|
||||
| K4b | 0 (sau K2) | 0 | — | FE ×2 → #77 | acceptance leaf→leaf đổi kết quả không F5 |
|
||||
| K5 | 0 (sau K2) — PRE-spec-fix A-5 (lead) | 0 | — | FE ×2 → #77 | SHA-identical 4 file ×2 app + Σ sub-folder == tổng |
|
||||
| K4c | 0 (sau K3) | 0 | — | fe-user → #77 | WfView lọc `Code==='KHKK-N'+n` |
|
||||
| K6 | 0 (sau K3 — acceptance đếm 8 designer) | 0 | — | fe-admin → #77; `git diff --stat -- fe-user/src` = 0 | liệt kê ĐÚNG N mục lá (dư/thiếu 1 = FAIL) |
|
||||
| K7 | câu III không chặn code (default dialog); acceptance "ai bấm" treo [CHỜ-ANH] | 0 | ✅ (grant `Contracts.Create`) | BE + FE ×2 → #77 | 8+2 authz 2-chiều + idempotency-double-click + cây 2-HĐ |
|
||||
| K8 | **câu V (nghiêng (b) PE-ZZTEST-riêng) + câu III + B0-form 14/14 fail-closed + dặn team notification** | 0 | — | 0 code | 17 bước chụp + QĐ9 đo 2 nhánh + rollback theo ID |
|
||||
|
||||
**3 spec-fix bắt buộc TRƯỚC wave tương ứng (lead tự làm, không cần owner):** ① A-1 cụm-1 vá-1 → DELTA per-wave (trước K1-commit-STATUS) · ② A-4 tổng QĐ9 → khai thiết kế copy-at-create thay snapshot-hứa (trước K2) · ③ A-5 cụm-2 K5 +1 việc `lines[].contractId` (trước K5). **5 vá 1-dòng cùng đợt:** A-0a sweep "opt-in sau" · A-0b đếm header tổng · A-x 16→18 consumer · A-6 nút-phụ gán K2 · SHA 2-file→4-file thống nhất (tổng `:30` theo cụm-2 `:28`).
|
||||
|
||||
## D. Rủi ro còn hở (top-5 sau 43 vá — mỗi cái 1 guard)
|
||||
|
||||
1. **QĐ9 không có snapshot dự phòng** — nếu phép đo 2-nhánh (cụm-3 vá-10) FAIL vì lộ chỗ display đọc live (kiểu PE pre-Mig-67) → phát sinh mig ngoài kế hoạch giữa chuỗi wave. *Guard:* chạy phép đo 2-nhánh trên **Dev NGAY SAU K3 land** (integration test hoặc tay), đừng để nó xuất hiện lần đầu ở K8-prod.
|
||||
2. **Ghost-window K2→K3 + seed cờ sớm = config-lie #78** — `AllowApproverFinalize=true` cấp CCM-Chương seed TRƯỚC khi nhánh (a) land thì designer nói dối. *Guard:* K3 checklist đặt "seed cờ" là mục CUỐI + gate `grep AllowApproverFinalize=true` 0-hit trước mục đó (đúng thứ tự OG-3 tổng `:46` đã ghi — giữ nguyên, đừng để builder đảo).
|
||||
3. **fe-admin resolvePath 2-họ-key, 2 wave chạm cùng hàm** (B-3) — builder K3 nới luôn `Khkk_*` → 48 leaf hiện trên fe-admin thiếu `WorkflowMatrixViewPage` → leaf chết. *Guard:* acceptance K3 thêm phép-âm "fe-admin sidebar đếm group `Khkk_*` = 0".
|
||||
4. **Bridge authz chỉ gate FE = giả-an-toàn** — cụm-3 vá-1 nói "gate nút = HỘI 2 policy" + test 403, nhưng không câu nào bắt ENDPOINT bridge mang policy server-side; nếu builder gate FE-only, test 403 viết theo FE cũng giả-pass. *Guard:* 1 câu spec K7 "endpoint bridge mang CẢ 2 `[Authorize]` attribute (stack = AND: `KeHoachKyKet.Read` + `Contracts.Create`)" + test = **curl trần bỏ FE**.
|
||||
5. **OG-6 transcribe gõ-tay-từ-ảnh, 4 ô ⚠️** — seed sai tên/vai → labelBackfill churn + khối ký GĐ4 in sai vai (TEXT không ràng máy — limitation QĐ4 đã khai). *Guard:* 4 ô ⚠️ phải được anh chốt TƯỜNG MINH trong lượt soát OG-6 (không để builder tự đoán); acceptance K1 "lệch giải trình từng dòng" giữ nguyên có răng.
|
||||
|
||||
*(Ngoài top-5, đã có guard sẵn trong spec: B0-form fail-closed vá-9 · rollback theo ID vá-11/13 · phiếu-ZZTEST-khóa-PE-thật vá-12 nghiêng phương án (b).)*
|
||||
|
||||
## E. GO/NO-GO per wave
|
||||
(ĐANG LÀM)
|
||||
|
||||
## F. Digest trình owner
|
||||
(ĐANG LÀM)
|
||||
| Wave | Verdict | Điều kiện |
|
||||
|---|---|---|
|
||||
| K1 | **GO (code) + GATE seed** | Seed land CHỈ SAU OG-6 ✅ (86 dòng + 4 ô ⚠️ anh chốt); code/mig/test build trước được |
|
||||
| K2 | **GO** | OG-1/OG-7 ✅ rồi; PRE = spec-fix A-1 (1 dòng, lead) |
|
||||
| K3 | **GO** | OG-2/OG-9 ✅; verify đội hình LIVE + sweep ép-false ≥4 site + seed-cờ mục CUỐI (D-2) |
|
||||
| K4a | **GO + GATE nhãn** | 8 nhãn (kèm N2 sửa "phá dỡ") anh gật trong file OG-6 trước seed menu |
|
||||
| K4b | **GO** | Sau K2 |
|
||||
| K5 | **GO** | Sau K2; PRE = spec-fix A-5 (1 dòng, lead) |
|
||||
| K4c | **GO** | Sau K3 |
|
||||
| K6 | **GO** | Sau K3 (acceptance đếm 8 designer) |
|
||||
| K7 | **GO** | Sau K2+K3; câu III chỉ treo acceptance "ai bấm" [CHỜ-ANH], không chặn code (default dialog người-có-quyền); server-side hội-2-khóa theo D-4 |
|
||||
| K8 | **NO-GO tới khi đủ 4 điều kiện** | (1) mọi wave land · (2) câu V chốt — nghiêng (b) PE-ZZTEST-riêng · (3) câu III chốt · (4) B0-form 14/14 điền đủ (fail-closed) — NO-GO này là ĐÚNG THIẾT KẾ (wave cuối), không phải lỗi spec |
|
||||
|
||||
**Tổng: GO = 9/10 · NO-GO = 1/10 (K8, by-design).** Toàn chuỗi GO cho B4 với điều kiện 3 spec-fix nặng (A-1/A-4/A-5) + 5 vá 1-dòng land TRƯỚC wave tương ứng — tất cả lead tự làm được, owner-gate còn lại: OG-6 (K1-seed + K4a-nhãn) · câu III/V (K7-acceptance/K8).
|
||||
|
||||
## F. Digest trình owner (≤15 dòng)
|
||||
|
||||
1. Em rà chéo 4 spec final (tổng v2 + cụm-1 12 vá + cụm-2 15 vá + cụm-3 16 vá = 43 vá): **GO 9/10 wave — chỉ K8 dry-run chờ anh** (câu V + câu III + form 14 người), đúng thiết kế wave cuối.
|
||||
2. Thứ tự build chốt: **K1→K2→K3→K4a→K4b→K5→K4c→K6→K7→K8** (bảng gate/mig/deploy ở mục C).
|
||||
3. Phát hiện **8 mâu-thuẫn liên-spec — 0 cái chạm máy-đã-chốt, toàn vá được bằng sửa chữ spec**: 3 nặng phải vá trước build + 5 nhẹ 1-dòng.
|
||||
4. Nặng ①: cụm-1 còn neo số tuyệt đối (55→64) trong khi cụm-2 cấm đúng kiểu neo đó — đổi cụm-1 sang khai DELTA per-wave.
|
||||
5. Nặng ②: tổng QĐ9 hứa "snapshot 11 cột + display-gate mirror PE Mig 67" nhưng KHÔNG cụm nào nhận việc này — thiết kế thật trong cụm (copy-at-create + khóa sửa + phép đo 2 nhánh trượt-được) HỢP LÝ HƠN, em đề nghị sửa văn tổng theo cụm.
|
||||
6. Nặng ③: cụm-3 giao thêm việc cho cây K5 (nối HĐ qua `lines[].contractId`) mà spec cụm-2 không biết — thêm 1 dòng vào K5 kẻo HĐ thứ 2 trở đi vô hình trên cây.
|
||||
7. Vá-đè-vá: soi 7 cặp nghi trên 43 vá — **0 vá cụm sau phá vá cụm trước**; 2 chỗ cần câu ranh giới (regex fe-admin 2 họ key · ":342" trùng số dòng ở 2 file khác nhau).
|
||||
8. OG còn treo: **OG-6** (anh soát 86 dòng danh mục + 8 nhãn menu — chặn seed K1 + K4a) · OG-5 (hỏi khi gặp) · câu III "ai bấm bridge" · câu V "PE test riêng hay PE thật".
|
||||
9. Rủi ro #1: nếu phép đo freeze 2-nhánh FAIL (lộ chỗ đọc live) → phát sinh mig ngoài kế hoạch — em đề nghị chạy phép đo này trên Dev ngay sau K3, không đợi K8.
|
||||
10. Rủi ro #2: cầu KHKK→HĐ phải khóa quyền ở SERVER (2 tầng policy), không chỉ ẩn nút FE — test bằng curl trần.
|
||||
11. Rủi ro #3: quyền `Contracts.Create` hiện chưa cấp cho vai nào ngoài Admin — K7 sẽ cấp cho Drafter + Procurement (default, anh đổi được ở câu III).
|
||||
12. Test: baseline 590 (STATUS:472) — mỗi wave khai +k, không wave nào được giảm.
|
||||
|
||||
## END
|
||||
|
||||
END sub-review-fable-b3 — TOTAL: 8 mâu-thuẫn (3 nặng A-1/A-4/A-5 + 5 nhẹ-1-dòng) · 0 vá-đè-vá (7 cặp xét, 2 cần câu-ranh) · GO=9/NO-GO=1
|
||||
|
||||
Reference in New Issue
Block a user