12 KiB
REVIEWER-GATE-K3: PASS-WITH-FLAGS — 8 finding (3 MAJOR / 5 MINOR, 0 blocker build-test)
Reviewer gate K3 — 8 workflow nhóm + port finalize + designer
Ghi-đĩa TRONG LÚC LÀM (chống #53). Đo từ ĐĨA, HEAD 2967c43, 25 file M / +908 −102; 2 untracked chỉ ở .claude/auto-memory/.
§1 Build / test / npm — số NGUYÊN VĂN
| Phép | Lệnh | Kết quả nguyên văn |
|---|---|---|
| BE build | dotnet build SolutionErp.slnx |
Build succeeded. · 0 Warning(s) · 0 Error(s) |
| BE test #1 | dotnet test SolutionErp.slnx |
🔴 Failed! - Failed: 1, Passed: 568, Skipped: 0, Total: 569 - SolutionErp.Infrastructure.Tests.dll |
| BE test #2 | dotnet test SolutionErp.slnx |
Passed! - Failed: 0, Passed: 45, Total: 45 - Domain.Tests + Passed! - Failed: 0, Passed: 569, Total: 569 - Infrastructure.Tests ⇒ 614/0 |
| BE test #3 | --filter ~ContractSigningPlan |
Passed! - Failed: 0, Passed: 34, Total: 34 |
| npm fe-admin | npm run build |
✓ 1961 modules transformed · ✓ built in 19.63s · 0 TS error |
| npm fe-user | npm run build |
✓ built in 7.81s · 0 TS error |
⇒ 614/0 = 45D+569I khớp claim ở lượt #2/#3; lượt #1 FAIL → F-4.
§2 Code-vs-spec K3 (5 điểm)
- Seed 8 wf khớp ROSTER §0 —
DbInitializer.cs:526-688. 3 Steps (Phòng Cung Ứng/P. Kiểm soát Chi phí/Ban Giám đốc), 11 emailDistinctkhớp từng dòng bảng §0sub-implbe-k3.md; Cấp 1 OR-4 / OR-4 / OR-1, Cấp 2tra.bui/chuong.phan;AllowApproverFinalize=truechỉ ở(CCM, Cấp 2, chuong.phan)đặt PER-ROW; idempotentAnyAsync(w.Code == code); UNGATED demo-seed. ✅ - Finalize qua choke-point + 2-lệnh-grep LUẬT — chạy CẢ HAI:
Phase = ContractSigningPlanPhase.DaDuyet→:280,:322(+:336là dòng doc)ApplyApprovedValuesOnFinalize→:279,:321(+ doc/def/comment) ⇒ cùng khớp: 2 site gán DaDuyet ↔ 2 site gọi helper, helper đứng NGAY TRƯỚC gán ở cả hai. ✅
- Rào (v) —
ContractSigningPlanFeatures.cs:411-420, regex"^KHKK-N([1-8])$"neo 2 đầu, khớp literal seeder$"KHKK-N{n}"n=1..8; so vớiapprovalGroup(:395=request.ApprovalGroup ?? Default); code ngoài họ → cho qua. ✅ - 8 key VÀO All + DELTA (đếm MÁY) —
MenuKeys.All= 64 (HEAD2967c43= 56) ⇒ +8; policies DERIVED = 256 (HEAD 224) ⇒ +32. 8 menu-rowDbInitializer.cs:1980-1989order 3..10 dướiApprovalWorkflowsV2. ✅ mã — ❌ khai (F-3). - FE phép-âm
Khkk_= 0-hit + control dương —git diff -U0 | grep -E "^\+.*Khkk_[A-Za-z]+: *'"= 0; control dương cùng regex trên cảLayout.tsx= 6 hit ⇒ mẫu CÓ RĂNG. Nhánh mớiLayout.tsx:181/^KhkkN[1-8]$/nằm TRONGawV2Match, đặt SAU whitelist 3 code cũ. ✅
§3 Phán 3 quyết-định lead
- (i) GIỮ PUT-Conflict (spec vá-3 bảo gỡ) — LEAD ĐÚNG, spec vá-3 LIỆT NHẦM.
UpdateAwDefinitionCommandHandler(:515-649) 0 lần tham chiếutypeEnum/ContractSigningPlan; grep 2 token toàn file cho hit ở:97/:125/:126/:331/:341/:349/:387— tất cả thuộc list/create, KHÔNG hit nào trong thân PUT. Guard:598-603(echo cờ) ·:612-617(dòng mới) ·:627-632(bỏ người giữ cờ) là luật versioning CHUNG mọi ApplicableType; gỡ = nới rào cho PE/Contract/Proposal = regression ngoài scope K3. Thêm: gỡ FE-lock (đúng) đã đủ để cờ seedtruekhông đẻ 409 lúc PUT vì payload nay echo giá trị THẬT. - (ii) GIỮ ép-false
AllowApproverSkipToFinaltype-10 (O-1) — LEAD ĐÚNG ở BE, nhưng sweep BẤT ĐỐI XỨNG (F-2). Tự verify: tokenAllowApproverSkipToFinaltrongContractSigningPlanWorkflowService.cs= 1 hit duy nhất:47, và là COMMENT ⇒ service 0 lần đọc cờ; control dương: cùng token trongPurchaseEvaluationWorkflowService.cs= 3 hit (code thật) ⇒ grep có răng. Echo cờ cho type-10 = đẻ config-lie #78 mới ⇒ giữ ép-false ĐÚNG. - (iii) Seed cờ cùng-commit ≠ config-lie #78 — ĐÚNG, nhánh THẬT tồn tại.
ContractSigningPlanWorkflowService.cs:276-289:if (actingLevel.AllowApproverFinalize && applyLevelFinalize)→EndedByLevelFinalize=true→ApplyApprovedValuesOnFinalize(plan)→Phase=DaDuyet→ xoá 2 con-trỏ → log →return. Cờ seed CÓ máy tiêu thụ trong cùng diff. ✅ (nhưng đường ĐI NGƯỢC — bỏ tick để trình CEO — chết ở tầng UI: F-1)
§4 Ranh giới
ReturnOrRejectAsync(:354+),ApplyApprovedValuesOnFinalize(:345-349), nhánh advance thường (:293-329):git diff -U0trên service chỉ 5 hunk =@@-37,10(comment) ·@@-89,0(thêm param) ·@@-124(truyền param) ·@@-245(chữ ký private) ·@@-266,0 +270,21(khối finalize MỚI) ⇒ 0 dòng nội-dung đổi trong 3 vùng trên. ✅- Submit-guard K2 / file K1: không có trong
git diff --name-only. ✅ - 0 migration mới:
git diff --name-only | grep -i migration= 0;git status --porcelain -- src tests | grep '^??'= rỗng. ✅ - Route/menu-row NGOÀI 8
AwV2_KhkkN*: DbInitializer thêm đúng 8 row; Layout thêm đúng 1 nhánh regex họAwV2_. ✅ - Rào (v) chỉ ở CREATE —
UpdateContractSigningPlanCommandHandlerkhông chạmApprovalWorkflowId/ApprovalGroup(0 hit trong thân) ⇒ không có lỗ update-lách. ✅
§5 Test lane (mở ruột 2 test)
- T-a
ApproveV2_CapMangCoKetThuc_ChotPhieuNgay_KhongTrinhTiepBuocSau(ContractSigningPlanApprovalTests.cs:944-994): đo hành-vi THẬT qua service. Sanity 3 vế TRƯỚC (ShouldBeAt(ChoDuyet,1,2)·EndedByLevelFinalize=false·StepCountAsync == 3kèm lý-do "Cấp mang cờ KHÔNG được là cấp cuối — nếu là cấp cuối thì phiếu kết thúc ở CẢ HAI thế giới và test này xanh mà không chứng minh gì" = anti-tautology guard). Đo SAU 5 trục: phase + 2 con-trỏ · cờ runtime ·ApprovedAmount3 dòng gồm ca??=giữ 300 · opinion signer. Kèm chứng-nhân song sinhWitnessAtFlagLevelbất động (cả cờ lẫn giá). ✅ - T-e
CreateAwDefinition_LoaiKhkk_GiuNguyenCoKetThucTaiCap_KhongConEpFalse(:1079-1104): 3 vế — (i) tick ⇒true; (ii) không tick ⇒false(chặn "bật bừa"); (iii) đối-chứng type khácDuyetNcccũngtrue⇒ phân biệt "gỡ ép-false" với "đổi thành ép-true". Đi quaCreateAwDefinitionCommandHandlerTHẬT. ✅ - 0 đè test cũ:
git diff -- tests/ | grep -c '^-[^-]'= 2, cả 2 là cùng một sửa cơ-họcTransitionAsync(..., CancellationToken.None)→(..., ct: CancellationToken.None)(named-arg vì thêm param) — không nới assert nào.
§6 FINDING (8)
MAJOR
- F-1
fe-{user,admin}/src/pages/khkk/KhkkWorkflowPanel.tsx:136-142— opt-outapplyLevelFinalizeKHÔNG có tầng UI ⇒ trạm CEO chết ở 8/8 workflow seed. Body POST là literal đúng 2 field{action, comment};grep applyLevelFinalize fe-*/src= 0 hit ở KHKK. ControllerContractSigningPlansController.cs:213?? true⇒ mọi lượt Chương bấm "Duyệt" đều finalize. Seeder cắm cờ chochuong.phanở cả 8 workflow ⇒ Step 3 «Ban Giám đốc» (truong.nguyen) không đường nào tới. Đối-chứng chứng minh đây KHÔNG phải khuôn PE:fe-*/src/components/pe/PeWorkflowPanel.tsx:63=useState(false)+:259LUÔN gửi tường minh ⇒ PE mặc-định KHÔNG kết-thúc-sớm (opt-in tại UI); KHKK mặc-định LUÔN kết-thúc-sớm. Lời owner OG-3/OG-9 ("a Chương sẽ quyết định là cái đó cần CEO ko") không thực thi được từ UI. Kèm: commentKhkkWorkflowPanel.tsx:15-17khẳng định "không có gì để panel render thêm" — tiền-đề SAI, chính wave này vừa đẻ tham số để người duyệt quyết. Acceptance: thêm ô tick opt-out ở panel (mirrorPeWorkflowPanel.tsx:778), HOẶC khai tường minh lên HANDOFF rằng "trình CEO" hiện chỉ làm được bằng admin bỏ cờ ở Designer. - F-2
ApprovalWorkflowV2AdminFeatures.cs:387⟂fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx:263+:1300-1310— sweep ép-false bất-đối-xứng ⇒ tick bị NUỐT IM LẶNG. FE gỡ khoá cả 2 ô (gồmallowApproverSkipToFinal), BE giữ ép-falseSkipToFinalcho type-10. Admin tick "Cho phép duyệt thẳng Cấp cuối" trên quy trình KHKK → CREATE lưufalse, UI không báo gì. Đây đúng class mà comment vừa bị xoá đã cảnh báo ("màn hình nói một đằng dữ liệu một nẻo"), chỉ đảo chiều. 0 test phủ (T-e chỉ đoFinalize). Acceptance: giữdisabledriêng ô SkipToFinal cho type-10, HOẶC bỏ ép-false BE + port nhánh. - F-3
docs/STATUS.md:6— DELTA đo được nhưng chưa khai. Máy:All56→64 (+8); policies 224→256 (+32); STATUS vẫn ghi "Policies 224 · Menu keys 56". Spec cụm-1 vá-1 bắt "mỗi commit kèm lệnh đếm lại + cập nhật 2 row STATUS". Tái phát y hệt finding ④ của gate K1 cùng phiên.
MINOR / khai-thật
- F-4 Suite flake 1/3 lượt:
dotnet test SolutionErp.slnxlượt #1Failed: 1, Passed: 568—ContractSigningPlanCrudTests.DeleteContractSigningPlan_SoftDeletes_KeepsChangelog_ThenCreateAgainSucceedschết ởKhkkFixture..ctor():62EnsureCreated()→CallSiteRuntimeResolver. Fixture có từ W2 ⇒ không phải K3 đẻ, nhưng câu "614/0 tươi" chỉ đúng 2/3 lượt — đừng khai trần. - F-5
DbInitializer.cs:665— seeder idempotent per-Code thuần skip, 0 nhánh UPDATE: roster đổi (người nghỉ / đổi phòng) ⇒ phải UPDATE tay trên prod. Cùng lớp seeder SP-002 ở K1. - F-6
DbInitializer.cs:637-640—Descriptionkhai "Admin có thể chỉnh người/quyền tại chỗ hoặc tạo version mới": nửa sau đúng, nửa đầu sai với cờ finalize —ApprovalWorkflowV2AdminFeatures.cs:598-600chặn đổi cờ,:627-629chặn bỏ người giữ cờ khi sửa tại chỗ. Chuỗi này hiển thị ra UI admin. - F-7
ContractSigningPlan.cs:51+fe-*/src/types/khkk.ts:260—EndedByLevelFinalizeđược GHI nhưng chưa expose DTO (chính FE type tự khai). Test T-a lý-giải "FE/GĐ3 đọc cột này" — hiện chưa ai đọc; ghost-window đã-khai, không phải bug, nhưng câu biện-minh mạnh hơn sự thật. - F-8
ContractSigningPlanWorkflowService.cs:37-42+:335-337— 2 lệnh grep tự-kiểm in ra gồm cả chính dòng///doc (:336,:337) ⇒ người chạy sau đếm 3 vs 5 rồi tưởng lệch. Nên nêu rõ "bỏ dòng///khi đếm".
§7 Verdict
PASS-WITH-FLAGS — build 0W/0E · suite 614/0 (lượt tươi) · npm ×2 sạch; 5/5 điểm code-vs-spec khớp; 3/3 quyết-định lead ĐÚNG về kỹ-thuật; ranh giới sạch (0 mig, 0 đổi hành-vi vùng cấm, 0 route ngoài họ). 0 blocker kỹ-thuật, nhưng F-1 + F-2 là nợ HÀNH-VI: F-1 làm mất đúng cái quyền quyết mà owner vừa chốt (OG-3/OG-9); F-2 tái tạo class "UI nói một đằng DB một nẻo" ở ô còn lại. F-3 là acceptance chưa đóng. Owner/lead quyết ship-rồi-vá hay vá-trước-ship.
END sub-reviewer-gate-k3 — TOTAL: 8 finding (3 MAJOR / 5 MINOR) · 0 blocker build-test · verdict PASS-WITH-FLAGS