| `Gate reviewer lens-wave s157` | Wave-plan có khả thi không · acceptance có **ĐO ĐƯỢC thật** không hay chỉ nghe như đo được · wave có deploy độc lập thật không | `spec-ke-hoach-ky-ket-hd-28-07-2026.md` · `runs/2026-07-27-S155-pe-delete-approver/run.md` |
| `Gate reviewer lens-fidelity s157` | Spec có trung thực với **3 nguồn gốc** không — bịa bước / rơi bước / gán sai vai / nống biên | `spec-*.md` · `src-QT-TRINH-KY-HD.txt` · `src-FO-002.01-bang-kiem-tra-HD.txt` |
| `Gate reviewer lens-schema s157` | **7 bảng** thừa/thiếu · loose-Guid vs FK · UNIQUE filtered · enum mới có đúng không · biến thể 5 bảng | `spec-*.md` · `ApprovalWorkflow.cs` · `PurchaseEvaluation.cs` |
| `Gate reviewer lens-claims s157` | Verify ĐỘC LẬP mọi claim `file:line` trong §2 — có dương-giả không | `spec-*.md` · `ProposalFeatures.cs` · `MenuKeys.cs` |
**taskList snapshot (wave 2):** 4 lane · `role: reviewer`×4 · `tier: 'opus'` explicit từng lane (belt-and-suspenders
theo GAP#6 — worker-tier-pin S124 đã che, nhưng lệnh này tự định nghĩa là "ensemble tier-2") · `maxTurns: 25` ·
lane RETURN-only, lead = single-writer refute+synthesize @P3/P4.
### Wave 3 — lead synthesize → `spec-ke-hoach-ky-ket-hd-28-07-2026.md` + **PLAN WAVE thi công trình anh**
@ -172,10 +183,28 @@ Lead trình 2 điểm ở §1.5 và §1.4; anh chốt **cả hai**. Đây là **
- [x] S1 — lead grounding: đọc TRỌN `ContractPhase.cs` → **phát hiện A** (9 ISO ↔ 9 enum khớp 1:1) +
**phát hiện B** (khoảng trống nằm giữa ISO-1 và ISO-2, thiếu ở CẢ doc lẫn code)
`DangInKy=5`↔In HĐ · `DangKiemTraCCM=6`↔Kiểm tra CCM · `DangTrinhKy=7`↔Duyệt BOD · `DangDongDau=8`↔Đóng dấu ·
`DaPhatHanh=9`↔Phát hành. Post-Mig 21/S17 thay bằng `ChoDuyet=10` + con-trỏ chạy trên workflow V2 admin-config
⇒ chuyển từ *cứng 9 bước* sang *cấu-hình N bước*. **Khung V2 sinh ra CHÍNH ĐỂ biểu diễn quy trình ISO này.**
**(B) Khoảng trống nằm ĐÚNG giữa ISO-1 và ISO-2** (xem 1.1).
### 1.4 🔴 OWNER ĐÃ CHỐT (2026-07-28) — ràng buộc cứng của spec
| # | Anh nói (verbatim) | Hệ quả spec |
|---|---|---|
| **O-1** | *"Đúng chính xác, cấu trúc trình ký giống, chỉ khác nội dụng thôi."* | **TÁI DÙNG khung duyệt V2** (`ApprovalWorkflow`>Step=Phòng>Level=NV, OR-of-N, `LevelOpinions`). **0 bảng approval mới.** Dựng mới = **NỘI DUNG phiếu**. ⇒ trục tranh luận Q2 hôm qua **ĐÓNG**. |
| **O-2** | *"Cái này để tham khảo thôi, ko vấn đề j, đa số là trễ."* (SLA) | **KHÔNG SLA-engine**, không auto-approve-on-timeout, không cảnh báo chặn, **không wave nào cho SLA**. Giữ hiển thị deadline. Lỗ `AddDays(7)` hardcode = ghi nhận, ngoài scope. |
| **O-3** | *"Chỗ hợp đồng cứ từ từ nhé."* | Lỗ hổng an ninh `ContractWorkflowService.cs:48-66` + controller HĐ class-trần: **NGOÀI SCOPE**, treo có chủ đích. Wave nào chạm module Contract phải hỏi lại anh. |
### 1.5 Quy trình chi tiết — 6 bước (b.7→12)
Role hệ thống có thật (`AppRoles.cs:5-16`): `Procurement` (PMH) · `CostControl` (CCM) · `Director`+`AuthorizedSigner`
🔸 **"BCH dự án X" KHÔNG có model** (`Department.ManagerUserId` 0-row) ⇒ né bằng: **BCH = người tạo phiếu**
(`CreatedBy`); PMH/CCM/CEO = **đích danh user trong Level** của workflow V2 (đúng triết lý V2, **0 model mới**).
| b | Việc | Ai | Đầu vào | Đầu ra | Chuyển bước | Nhánh lỗi |
|---|---|---|---|---|---|---|
| 7 | PMH chuyển thông tin cho BCH | Procurement | PE `DaDuyet` (winners `IsWinner`, giá `SUM Quote.IsSelected`, HoSoLink) | BCH biết việc | **Pull-model**: màn *"PE đã duyệt — chờ lập KH"* lọc `Phase==DaDuyet && chưa có plan` (khuôn `CreateContractFromEvaluationFeatures.cs:173`) + notify in-app. **Email ra ngoài = ngoài scope** (SMTP TODO toàn hệ thống) | PE thiếu winner → không hiện |
| 8 | Duyệt mẫu + shopdrawing với TVGS | BCH **nhập hộ** (TVGS ngoài hệ thống) | Mẫu + shopdrawing từ NTP/NCC (offline) | Danh mục **CĂN CỨ** trong phiếu: {Kind, NCC, Status, TvgsName, ngày, scan} | Vòng đời **per-item**: `ChuaNop→DaNop→TvgsDuyet\|TvgsBac`; `TvgsBac→DaNop` (nộp lại) — 🔴 **sơ đồ KHÔNG vẽ vòng lặp này, thực tế có** | Item bị bác = đổi status + note, **KHÔNG đụng state machine phiếu** |
| 9 | Tổng hợp + so sánh giá → **ĐỀ XUẤT giá trị** | BCH (Drafter phiếu) | Căn cứ b.8 + báo giá PE (**snapshot** `PeReferenceAmount` lúc tạo — nguyên tắc freeze Mig 67) | Phiếu đủ dòng giá đề xuất per-winner + file so sánh → **TRÌNH** | Guard trình: đủ dòng giá per-winner (mirror completeness-guard PE `PurchaseEvaluationWorkflowService.cs:180-212`); căn cứ chưa đủ `TvgsDuyet` → **cảnh báo mềm** (tiền lệ S62) — **O-Q1 owner quyết mềm/cứng** | Ghi chú sơ đồ *"hồ sơ sai sót → gửi mail làm rõ"* = comment + item `TvgsBac` |
| 10 | PMH kiểm tra, xác nhận giá trị | Procurement (đích danh Level) | Phiếu `ChoDuyet` Bước 1 | Duyệt → Bước 2; ý kiến vào `LevelOpinions` (UPSERT khuôn `ContractWorkflowService.cs:292-316`) | OR-of-N trong Cấp (`ApprovalWorkflow.cs:81-94`) | Trả lại → `TraLai`, hoặc 4 return-mode per-level (cờ CÓ SẴN `ApprovalWorkflowLevel.cs:116-125`) |
| 11 | CCM kiểm tra | CostControl | Bước 2 | Duyệt → Bước 3 | như trên | như trên |
| 12 | **CEO ký HOẶC CCM đóng dấu** | Director / cơ chế kết thúc sớm | Bước 3 (hoặc kết thúc tại Bước 2) | 🔴 **GIÁ TRỊ KÝ KẾT CHỐT** per-winner (`ApprovedAmount`) ghi tại **finalize choke-point** (mirror `ApplyApprovedPriceOnFinalize` PE `:973-1002` + RULE `:1008`*mọi nhánh set DaDuyet phải gọi helper*) | Terminal `DaDuyet` | Từ chối → `TuChoi`; trả lại → `TraLai` |
**Rẽ nhánh b.12 "hoặc" — 4 đường ĐỀU CÓ SẴN trong khung V2, 0 migration:**
(i) `CeoApprovalThreshold` + CCM tích "duyệt done miễn CEO" (PE `:892-929`, fail-closed: đòi threshold + role
|2|`ContractSigningPlanLines`(giáper-winner)|`PlanId`FKCascade·`SupplierId`loose·**`PeReferenceAmount`decimal(18,2)SNAPSHOTlúctạo**·`ProposedAmount`·`ApprovedAmount?`(chỉghitạifinalize)·`Note`|UNIQUEfiltered`(PlanId, SupplierId) WHERE IsDeleted=0`(gotcha#57)|
|6|`ContractSigningPlanChangelogs`|`PlanId`·Action·PhaseAtChange·UserId·Summary·ContextNote|**có từ ngày 1**—tiềnlệPE:Changelogslànguồntransition-marker/backfill(Mig60/61)|
**vẫn SỐNG trên prod**, anh chốt *"từ từ"*. Nhắc đúng 1 dòng cho khỏi quên.
- **FO-002.01 auto-pass** (*"quá hạn xem như đã thông qua"*) — mâu thuẫn mô hình duyệt-chặn V2. O-2 ⇒ ghi nhận.
---
## ④ §D — HẤP THỤ 6 việc sửa của `review-synthesis.md` §G (S156)
| # | Việc review yêu cầu | Xử lý trong spec này |
|---|---|---|
| 1 | Claim SAI *"hardcoded policy fallback"* → thật là `ConflictException:115-116` (HĐ **kẹt cứng**`ChoDuyet`) | ✅ **Đã sửa** — §2.5(b) ghi đúng: pin V1-only ⇒ HĐ V2-less **KẸT CỨNG**, hỏng **cứng** không degrade êm. Lead tự xác minh trên đĩa. |
| 2 | Siết biên `b.14→19`, không phải `b.13→21` | ✅ Spec này **không nhắc lại biên cũ**; phạm vi khai rõ = **b.7→12**, khúc 13→21 để nguyên verdict `LAI` S156. |
| 3 | Thiếu Q **vai người TRÌNH** (PMH `Procurement` bị 403 `:70-79`) | ✅ **Đã xử ở thiết kế**, không đẩy thành câu hỏi: §2.3 guard trình = `CreatedBy ∨ DeptManager ∨ Admin`**cố ý khác** khuôn role-based, kèm lối thoát nếu owner muốn đồng nhất. |
| 5 | Q5 thiếu phương án **(d) `skipToFinal`** đã wire | ✅ Có mặt — §1.5 liệt **4 đường rẽ b.12**, trong đó (iii) `AllowApproverSkipToFinal``Contract:320-352`. |
| 6 | Viết lại Q2 theo **2 trục + 3 số đo cùng đơn vị từ twin thật** | ⚠️ **Trục cơ-chế ĐÓNG bởi O-1** (anh chốt tái dùng khung) ⇒ chỉ còn **trục NỘI DUNG**. Bảng dưới. |
### Trục NỘI DUNG — 3 nhánh, 3 số cùng đơn vị
> Số twin **đo thật**: `Proposal` = **4 bảng · 849 LOC BE · 1.956 LOC FE** (invest `wc`/`grep` trực tiếp).
> Số cho từng nhánh = **ngoại suy** từ twin đó — khai rõ đâu là đo, đâu là ước.
| Nhánh | Bảng mới | LOC BE (ước) | LOC FE (ước) | Đánh giá |
|---|---|---|---|---|
| **(A) Phiếu độc lập** ⬅ *spec này chọn* | **7** (5 nếu cắt) | ~1.100–1.400 | ~2.000–2.400 | Vòng đời riêng, xóa/soft-delete riêng, workflow riêng type 10. **Đắt nhất về bảng, rẻ nhất về rủi ro.** |
| **(B) Mở rộng PE** (thêm cột + bảng con vào phiếu PE) | ~3 | ~600–800 | ~900–1.200 | Rẻ hơn, **nhưng**: PE `DaDuyet` là **terminal thành công** — mở lại vòng duyệt thứ 2 trên phiếu đã đóng ⇒ phá bất-biến PE, đụng cả `budgetFrozen` snapshot Mig 67. **Rủi ro cao nhất.** |
| **(C) Entity con của Contract** | ~4 | ~700–900 | ~1.100–1.400 | Kéo khúc 7→12 vào module HĐ — mà anh vừa chốt **"chỗ hợp đồng cứ từ từ"**; đồng thời HĐ chưa tồn tại ở b.7-12 (HĐ mới sinh ở b.13) ⇒ **sai thứ tự nghiệp vụ**. |
**Lý do chọn (A)** — không phải vì rẻ, mà vì: nó là **PHIẾU** theo đúng phát biểu mục đích của anh (có đối tượng
được duyệt + 3 trạm + người chốt); (B) phá bất-biến của PE đang chạy ổn; (C) sai thứ tự nghiệp vụ và chạm vùng
anh vừa yêu cầu để yên. **Nếu owner ưu tiên cắt chi phí thì cắt trong (A)** (7→5 bảng), đừng đổi sang (B)/(C).
---
<!-- END · 5 WAVE · 7 BANG · 3 CHAN-BOI-OWNER (W3-mem/W4/W5) · 5 CAU-HOI-OWNER -->
> Đối chứng: `runs/2026-07-27-S155-pe-delete-approver/run.md` (tiền lệ chia 2 đợt đã chạy THẬT).
> 4 trục tấn công: (a) acceptance đo được thật? (b) wave deploy độc lập thật? (c) thứ tự wave? (d) cờ CHẶN sai?
## Verdict
_(đang soi — điền cuối)_
## Điểm HIGH
## Điểm MED
## Điểm LOW
## Điểm CỦNG CỐ
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.