@ -51,4 +51,6 @@ Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA,
> 🔴 **OG-3 NÂNG CẤP @S164 (cùng lời chốt OG-9):** *"vậy bài toán trần budget xem như ĐÓNG. Vì người chốt chặn budget là anh Chương."* ⇒ NĐUQ/ngưỡng tiền = **HUMAN-GATE VĨNH VIỄN** (TP.CCM Phan Văn Chương quyết cái gì cần CEO) — **XÓA ý "enforce máy = wave opt-in sau"** khỏi mọi spec; cột NĐUQ trên danh mục thuần ghi chú. Không còn wave threshold nào trong backlog.
END spec v2 — 8 wave · 8 quyết định · 6 OG · 14 vá B1b áp đủ.
**BACKLOG giai-đoạn-sau (owner @S164, không làm đợt này):** (1) authz-per-nhóm KHKK (OG-8) · (2) **phiếu điều chỉnh/thay thế** cho chứng từ đã duyệt — khuôn amendment ERP, áp PE/KHKK/HĐ (*"Nếu xóa thì có thể làm 1 tính năng điều chỉnh phiếu để cập nhật điều chỉnh/thay thế - ko xóa phiếu đã duyệt. Cái này để giai đoạn sau."*) · (3) bung-gộp UI (OG-1/OG-7 nửa sau — máy đã sẵn).
END spec v2 — 8 wave · 9 quyết định · OG đủ · backlog 3 mục giai-đoạn-sau.
@ -21,7 +21,7 @@ K7 cầu KHKK→HĐ (bridge 8v/8test — đường ống S156 ĐÃ vá @W6-S161,
9. 🔴 **[L2-H5] B0 = FORM NGƯỜI THẬT fail-closed**: bảng 14 dòng {bước · người · email · tài khoản} PHẢI ĐIỀN ĐỦ trước giờ-G (12/14 bước đang trống); nguồn = K3-acceptance LIVE; thiếu 1 dòng = KHÔNG chạy.
10. 🔴 **[L2-H2] Phép đo QĐ9 phải TRƯỢT ĐƯỢC**: sau finalize → **sửa NS/giá nguồn** (PE hoặc catalog) → reload phiếu → số **KHÔNG đổi** = PASS (đổi = FAIL); đo **CẢ 2 nhánh** (a-Chương finalize-CCM VÀ lên-CEO-Trường duyệt) — hiện phép đo 0-bit.
11. 🔴 **[L2-H3] Dấu ZZTEST cho phiếu KHKK**: mã phiếu auto-gen (`KHKK/2026/xxx`) KHÔNG mang ZZTEST — bản ghi sống-vĩnh-viễn lại không dấu. Vá: nhét `ZZTEST` vào field hiển thị được trên list (tên kế hoạch/ghi chú — soi DTO chọn field) + **rollback theo DANH SÁCH ID** ghi lại từng bước, không theo prefix.
12.🔴**[L2-H4 ⨯ L1-F5] Câu giờ-G (V) trình anh ĐỦ 2 hệ quả**: (i) phiếu KHKK DaDuyet trên PE thật **không xóa được kể cả Admin** (sqlcmd là lối duy nhất); (ii) 🔴 **TRƯỚC K2 rào là per-PE**⇒ phiếu ZZTEST khóa **TOÀN BỘ**`PE/2026/A/049` (không phải chỉ nhóm-4) — nghiêng mạnh về **phương án (b) PE ZZTEST riêng**; nếu anh chọn (a) PE thật thì bắt buộc chạy SAU K2.
12.✅**[CHỐT @S164 — câu V] "Phiếu đã duyệt không xóa" = THIẾT KẾ ĐÚNG, owner ratified** (verbatim: *"đồng ý luôn, hiện tất cả các phiếu nếu đã duyệt gần như ko xóa đc. Đồng ý cái này đúng với thiết kế ERP."*) ⇒ (i) delete allow-list `{DangSoanThao, TuChoi}`**GIỮ NGUYÊN — CẤM B4 "sửa" nó** (nó không phải bug); (ii) hệ quả vận hành: phiếu test đã duyệt BẤT TỬ ⇒ **K8 CHỐT dùng bộ PE ZZTEST RIÊNG**(để phiếu bất tử nằm trên gói test, không phải gói thật `A/049` — trước K2 rào per-PE còn khóa nguyên gói); (iii) 🆕 **BACKLOG giai-đoạn-sau (lời anh):** tính năng **"phiếu điều chỉnh/thay thế"** — cập nhật chứng từ đã duyệt bằng chứng từ điều chỉnh, KHÔNG xóa gốc (khuôn amendment ERP; áp được cả PE/KHKK/HĐ) — ghi nhận, KHÔNG làm đợt này.
13.**[L3-H4] B16 rollback HĐ = NO-OP hiện tại** (numeric guard chặn xóa cả khi TuChoi) — rollback plan ghi rõ: HĐ test dọn bằng **sqlcmd soft-delete** (lệnh cụ thể per bảng: Contracts + ContractApprovals + Changelogs + Line.ContractId=NULL + pe.ContractId=NULL), thứ tự ngược.
14.**[L2-M10] Câu III treo → acceptance "ai bấm" để [CHỜ-ANH]** — không chốt trong DoD tới khi anh trả; default dialog + người-có-quyền.
15.**[L2-M12] DoD cardinality đo được**: sau bridge UI-1-1 — đếm `SELECT COUNT(DISTINCT ContractId) FROM Lines WHERE PlanId=X AND ContractId IS NOT NULL` == số lần bấm; gộp (sau này) = N line 1 ContractId.
(ĐANG LÀM — nháp sau spec tổng, chờ đối chiếu 3 cụm)
### A-0. Nội-bộ spec tổng (phát hiện khi đọc lượt 1)
- **[A-0a] QĐ5 vs OG-3-nâng-cấp TỰ MÂU THUẪN trong CÙNG file:** `spec-4gd-khkk-tong-quat:15` QĐ5 còn nguyên *"enforce (`CeoApprovalThreshold`) = wave opt-in sau"* trong khi `:52` ra lệnh *"**XÓA ý 'enforce máy = wave opt-in sau' khỏi mọi spec**"*. Spec tổng tự vi phạm lệnh của chính nó → phải sweep cụm 1-3 xem câu này còn rớt ở đâu.
- **[A-0b] Đếm sai nội bộ:** header ② ghi "8 quyết định (v2)" nhưng liệt 9 items (:11-19, QĐ9 budget-freeze mới @S164); END `:54` ghi "6 OG" nhưng bảng ④ có 8 hàng (OG-1/2/3/5/6/7/8/9). Con số header/footer chưa sync sau khi chèn QĐ9 + OG-8/9.
- **[A-0c] QĐ9 mang cờ "⚠️ 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ề" (`:19`) → kiểm tra cụm-1/cụm-3 đã nhận merge chưa (schema snapshot → K2, hook finalize → K3).
### A-1. Drift số menu/policy — **MÂU THUẪN THẬT, cụm-1 CHƯA nhất quán với cụm-2** 🔴
-`spec-cum1:8` vá-1 neo **TUYỆT ĐỐI**: *"Menu keys 55→64 · Policies 220→256 — khai 2 row STATUS cùng lúc"* ⟂ `spec-cum2:9` vá-2 **CẤM đúng kiểu neo đó**: *"Drift khai DELTA (+49/+196), CẤM neo 2 mốc tuyệt đối (64→113 chỉ đúng nếu cụm-1 land trước — thứ tự ship đang cho song song)"*. Cụm-2 BIẾT về mốc 64 của cụm-1 và phòng hộ cho mình, nhưng **cụm-1 không được sửa ngược** → 2 spec dạy builder 2 luật ngược nhau về CÙNG 2 row STATUS.
- Thêm: 9 key của cụm-1 trải 2 wave (`ContractCatalog` = K1 +1 · 8 `AwV2_KhkkN*` = K3 +8) ⇒ "55→64" chỉ đúng tại K3-land; khai trọn ở K1 = STATUS nói dối suốt cửa sổ K1→K3.
- Số học nội bộ tự khớp (9×4=36: 220→256 ✓ · 49×4=196: 256→452 ✓) — lỗi KHÔNG nằm ở arithmetic mà ở **kiểu neo**.
- **Fix 1 dòng (trước B4):** sửa cụm-1 vá-1 thành DELTA per-wave (+1 @K1 · +8 @K3) + mọi commit khai drift kèm lệnh đo lại `MenuKeys.All` thực tế (mượn nguyên câu cụm-2 vá-2). Verdict: **MÂU THUẪN #1 — phải vá spec trước build.**
### A-2. 3-site grant cụm-2 ⟂ 9-key cụm-1 — NHẤT QUÁN về máy, THIẾU 1 câu ranh giới
- Cụm-2 3-site (`spec-cum2:25` — seed `:1780` · `SeedKeHoachKyKetAccessAsync:2415` · `KhkkKeys():2185`) áp cho **49 row KHKK user-facing**. Cụm-1 vá-1 (`spec-cum1:8`) chỉ đưa 9 key **VÀO All** — KHÔNG nói vào `KhkkKeys()`. Đọc máy: đúng như vậy là CHUẨN —
- 8 `AwV2_KhkkN*` = menu-con dưới `ApprovalWorkflowsV2` (System subtree, admin-only theo QĐ7 tổng `:17` CHỪA System + AwV2); grant qua **All-loop-Admin `DbInitializer.cs:2058`** là đủ. Đưa vào `KhkkKeys()` ⇒ 13 vai thường được CanRead menu designer = quyền-lệch (fe-user không có route → #50 drop im lặng, không vỡ UI nhưng bẩn grant + họ #85 menu-rộng-hơn-API).
-`ContractCatalog` = leaf nhánh Catalogs/Master, KHÔNG thuộc cây `KeHoachKyKet` → không có lý do vào `KhkkKeys()`. Acceptance cụm-1 chỉ đo "login **Admin** thấy leaf ×2 app" — tức đợt này user thường KHÔNG thấy danh mục (chưa grant role thường). Chấp nhận được (danh mục = master admin nhập) nhưng nên khai 1 câu để owner biết.
- **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`).
- 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-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.
## B. Vá-đè-vá (vá cụm sau có phá vá cụm trước?)
(ĐANG LÀM)
(ĐANG LÀM — cặp nghi tính đến cụm-2; chờ cụm-3 để chốt 43 vá)
| # | Cặp | Verdict nháp |
|---|---|---|
| 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" |
## C. Build-order cuối + gate
(ĐANG LÀM)
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.