Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-reviewer-clone-l1-b1b.md
2026-07-31 11:55:53 +07:00

20 KiB
Raw Blame History

lens1-cov — coverage + owner-gate

Đối tượng chấm: spec-4gd-khkk-tong-quat-31-07-2026.md (viết tắt spec:N) Yêu cầu gốc: draft-yeu-cau-owner.md (viết tắt draft:N) Lăng kính: (Q1) phủ đủ 5 mảnh scope + 2 yêu cầu bổ sung? · (Q6) OG list đủ chưa — có chốt lậu không?

Q1 — bảng mảnh → wave phủ → lỗ

# Mảnh (draft §3) Wave spec Trạng thái
(i) Master data danh mục (draft:46) K1 (spec:22, :36) ⚠️ nguồn extract KHÔNG TỒN TẠI theo tên (F-1); acceptance chỉ đo SỐ DÒNG, 0 đo cột (F-14)
(ii) eOffice sidebar 8 nhóm × 6 leaf (draft:48) K4 (spec:23, :39) ⚠️ thiếu deliverable FE route-map ×2 app (F-9); số 48 vs 42 + 2 dạng key (F-8)
(iii) Cây toàn trình mirror sidebar (draft:50) K5 (spec:23, :40) nền có thật cho cả GĐ3 (Ct_*) lẫn GĐ4 (Hdc_* 7 leaf, DbInitializer.cs:1868,:1981-1987)
(iv) Admin thu gọn (draft:52) K6 (spec:23, :41) + K3 vỡ 2 nửa: whitelist giữ đúng 2 mục owner bảo ẩn (F-2); nửa "8 designer" 0 wave 0 acceptance (F-3)
(v) Dry-run E2E (draft:54) K8 (spec:24, :43) ⚠️ chạy prod, tác dụng phụ không xoá được + ping user thật, 0 gate (F-13)
bổ sung 1 "Tạo luôn master data danh mục" (lời 10, draft:16) K1 = (i), xem F-1/F-14
bổ sung 2 "yêu cầu là dry-run luôn" (lời 10) K8 = (v), xem F-13

Đối chiếu 10 lời chốt verbatim §0 draft → wave/quyết định nào ăn

Lời Nội dung Ăn ở đâu Verdict
1 (draft:7) PE bự → bổ hạng mục nhỏ QĐ2 + K2 (spec:13)
2 (draft:8) hạng mục ≠ loại HĐ ≠ 5 form; "đặt tên field tách bạch" (draft:27) ⚠️ F-15 (kỷ luật đặt tên rơi; spec vẫn xài "loại HĐ" 2 nghĩa trong cùng file)
3 (draft:9) duyệt xong → "đưa vào loại hợp đồng gì" QĐ1 (spec:12) chỉ chốt CARDINALITY ⚠️ F-15: cơ chế CHỌN loại HĐ/khuôn lúc bắc cầu K7 không giao cho ai
4 (draft:10) GĐ3 chỉ điều khoản spec:7 (cố ý ngoài scope)
5 (draft:11) ký nháy = mực trên bản cứng; "in khối ký đúng pattern" (draft:25) chỉ nằm trong ngoặc lý do QĐ4 (spec:15) F-11: 0 wave, 0 checklist
6 (draft:12) fan-out A1/A2 + chú thích ngắn K4 (chú thích ngắn không có phép đo — LOW, gộp F-8)
7 (draft:13) "Ẩn hết… chỉ còn Quy trình duyệt (Mới)" + chừa User + "theo nhóm duyệt" QĐ7/K6 + QĐ2 F-2 (whitelist mâu thuẫn) + F-3 (8 designer)
8 (draft:14) thêm sub-folder + sliderbar giống nhau K5
9 (draft:15) giống nhau, chỉ khác form, đừng chế spec:7 + acceptance SHA K5 (spec:40)
10 (draft:16) dry-run + master data K8 + K1 có wave (chất lượng: F-1, F-13)

Findings

F-L1-1 [HIGH] — Nguồn dữ liệu của K1 không tồn tại theo cái tên spec ghi

  • Claim: "việc ĐẦU K1" = extract file gốc SOL-CCM-SP-002 (spec:19) trỏ vào một tên file 0 hit trên toàn cây D:\Dropbox\CONG_VIEC\SOLUTION.
  • Evidence: find . -iname "*SP-002*"0 hit; control-dương cùng lệnh cùng cây -iname "*FO-002*"7 hit (FORM/SOL-CCM-FO-002.01…07) ⇒ không phải thước hỏng. QUY_TRINH/ chỉ có 1 file: QT TRINH KY HOP DONG TP-NCC.docx (141.036 B). Draft:42 cũng ghi path …\QUY_TRINH\SOL-CCM-SP-002….
  • Vì sao HIGH: K1 là wave nền của cụm 1; K2 (CatalogEntryId), K4 (ApprovalGroup) đều phụ thuộc. OG-5 (spec:30) chỉ phủ ca "extract vẫn mơ hồ", KHÔNG phủ ca "không tìm thấy file".
  • Đề nghị: pin TÊN FILE THẬT + kích thước vào spec trước khi K1 chạy; nếu QT TRINH KY HOP DONG TP-NCC.docx chính là SP-002 thì khai đính chính; acceptance K1 thêm "trích được bảng 3.5 với N dòng, N khai trước khi seed".

F-L1-2 [HIGH] — Whitelist "System subtree" GIỮ LẠI đúng 2 mục owner ra lệnh ẩn

  • Claim: QĐ7 "chừa System subtree + AwV2" (spec:18) mâu thuẫn trực tiếp draft:52 ("+ 2 mục quy trình cũ (Quy trình Duyệt NCC · Quy trình HĐ)" nằm trong danh sách ẨN) và lời 7 (draft:13 "chỉ còn cái Quy trình duyệt (Mới) thôi").
  • Evidence (đĩa): DbInitializer.cs:1795 (MenuKeys.Workflows, "Quy trình HĐ", MenuKeys.System, 95, …) · :1798 (MenuKeys.PeWorkflows, "Quy trình Duyệt NCC", MenuKeys.System, 95, …) · :1801 (MenuKeys.ApprovalWorkflowsV2, "Quy trình duyệt (Mới)", MenuKeys.System, 96, …). ⇒ cả 3 đều là CON của System; whitelist cả subtree = giữ nguyên 2 mục cũ. Vế "+ AwV2" trong QĐ7 còn thừa (AwV2 vốn ở trong System).
  • Acceptance không bắt được: K6 (spec:41) "sidebar admin chỉ còn HỆ THỐNG + Quy trình duyệt (Mới)" — 2 mục cũ nằm BÊN TRONG "HỆ THỐNG" nên câu này vẫn đọc là PASS. Đây là dòng acceptance không phân biệt được đúng/sai.
  • Đề nghị: whitelist ở mức KEY (System, Users, Roles, Permissions, MenuVisibility, ApprovalWorkflowsV2 + con của AwV2), KHÔNG "subtree"; acceptance đổi thành liệt kê ĐỦ tên mục còn lại và ghi rõ Workflows/PeWorkflows phải VẮNG.

F-L1-3 [HIGH] — Nửa "+= 8 designer nhóm-duyệt" của mảnh (iv) không có wave, không có acceptance

  • Claim: draft:52 đòi "Quy trình duyệt (Mới) += 8 designer nhóm-duyệt (khuôn y Duyệt NCC (Mới): Bước—Phòng—Cấp, versioned + archived history)". Spec chỉ có 2 chữ "designer entry" trong mô tả K3 (spec:22) và "+ 8 designer" trong §① (spec:7) — 0 dòng checklist đo nó; sub-file invest còn chốt "0 designer mới" (sub-invest-fable-b1a.md:53).
  • Evidence nền: tiền lệ là 2 leaf con của AwV2 (DbInitializer.cs:1802-1803 AwV2_DuyetNcc / AwV2_DuyetNccPhuongAn); route FE là allowlist HARDCODE 3 code (fe-admin/src/components/Layout.tsx:169: code === 'DuyetNcc' || 'DuyetNccPhuongAn' || 'Contract') ⇒ 8 designer nhóm cần +8 MenuItem +8 nhánh route, không tự có.
  • Acceptance hiện tại đo trật: K3 (spec:38) chỉ đo GET /approval-workflows-v2?applicableType=10 trả 8 — API trả 8 mà admin UI vẫn 0 mục designer nhóm thì vẫn PASS.
  • Đề nghị: hoặc thêm dòng checklist "8 leaf AwV2_KHKK_N1..N8 hiện dưới Quy trình duyệt (Mới), click mở đúng designer của Code tương ứng", hoặc khai TỪ CHỐI phạm vi (1 designer type-10 dùng chung) và cho owner biết vì đó là thứ anh nhìn thấy.

F-L1-4 [HIGH] — 4 OWNER-GATE được khai nhưng KHÔNG nối vào wave nào ⇒ không chặn được gì

  • Claim: §② liệt OG-1/OG-2/OG-3/OG-5 (spec:26-30) nhưng §③ checklist (spec:36-44) 0 dòng nhắc tới gate; bảng wave (spec:22-24) cũng không ghi tiền-điều-kiện.
  • Cụ thể OG-2 (roster map vai→user): phải gật TRƯỚC K3 (wave seed 8 workflow, spec:22) — spec nói "cần anh gật trước khi seed" (spec:28) nhưng DoD K3 (spec:38) không có dòng đó. Fan-out B4 dặn worker "bám sát spec-chi-tiết + checklist" (draft:86) ⇒ worker đọc §③, nơi gate vô hình.
  • Rơi hẳn: cảnh báo ⚠️ của draft:52 "verify bản LIVE không phải archived trước khi wire" không xuất hiện ở bất kỳ đâu trong spec ⇒ nguy cơ seed roster từ bản workflow đã archive.
  • Đề nghị: mỗi wave có gate thì DoD mở đầu bằng "[BLOCKED-BY OG-n] — chưa có gật thì không chạy"; thêm 1 dòng checklist "OG-1/2/3/5 đã có phán quyết bằng văn bản (link) trước khi cụm tương ứng khởi động"; OG-2 kèm bước verify workflow QT-DN-V2-001 bản LIVE.

F-L1-5 [HIGH] — Repurpose Lines per-hạng-mục phá nghĩa PeReferenceAmount, checklist 0 bất-biến tài chính

  • Claim: QĐ2 (spec:13) đổi Lines từ 1-row-per-NCC sang N-row-per-(NCC × hạng mục). Entity hiện tại nói rõ "1 row = 1 NCC (winner của PE nguồn)"PeReferenceAmount = SNAPSHOT tổng báo giá của NCC này trên phiếu PE (SUM Quote.IsSelected) — một con số PER-NCC-TOÀN-PHIẾU.
  • Evidence: src/Backend/SolutionErp.Domain/ContractSigningPlans/ContractSigningPlanLine.cs:6 (comment "1 row = 1 NCC"), :16-20 (PeReferenceAmount snapshot), :9-10 (UNIQUE (PlanId, SupplierId) filtered WHERE IsDeleted=0).
  • Hệ quả: sau khi nhân dòng, mọi nơi SUM PeReferenceAmount theo phiếu sẽ nhân N lần (cùng NCC lặp lại trên N hạng mục). Spec tự gọi đúng tên lớp lỗi (S87/S88, spec:32) nhưng guard duy nhất là quy trình ("grep MỌI consumer"), còn acceptance K2 (spec:37) chỉ đo tạo phiếu / 409 / mở phiếu cũ / test validator âm — không có một phép so tiền nào.
  • Đề nghị: thêm dòng acceptance đo được: "trên ≥1 phiếu KHKK có sẵn, tổng tiền hiển thị/API TRƯỚC và SAU Mig 71 bằng nhau (chụp số)"; và chốt luôn ngữ nghĩa mới của PeReferenceAmount ở cấp dòng (chia? lặp? NULL?).

F-L1-6 [MED] — Acceptance K7 giaTri == ApprovedAmount mâu thuẫn chính default OG-1

  • Claim: OG-1 default = GỘP N line → 1 HĐ (spec:12) nhưng acceptance K7 viết số ít giaTri == ApprovedAmount (spec:42); gộp thì phải là SUM(ApprovedAmount) của các line cùng (NCC × dòng-danh-mục).
  • Evidence: ContractSigningPlanLine.cs:24 public decimal? ApprovedAmountnullable, "CHỈ ghi tại choke-point finalize" ⇒ gộp khi có line NULL chưa được định nghĩa (bỏ qua? coi 0? chặn?).
  • Thiếu thêm: phạm vi gộp không khai — trong 1 phiếu, trong 1 PE cha, hay toàn cục theo (SupplierId, CatalogEntryId)? Đọc thẳng mặt chữ "gộp theo cặp (NCC × dòng-danh-mục)" có thể gộp xuyên phiếu/xuyên dự án.
  • Đề nghị: viết lại acceptance thành giaTri == SUM(ApprovedAmount) các line thuộc nhóm gộp + khai rõ khoá gộp gồm cả ContractSigningPlanId (hoặc PE cha) + xử lý NULL.

F-L1-7 [MED] — Treo #6 (phiếu KHKK cũ) chỉ được trả lời nửa MENU, rơi hẳn nửa DỮ LIỆU

  • Claim: draft:76 hỏi "Mục '1. Kế hoạch ký kết HĐ (NCC-TP)' cũ (đã có phiếu?) → migrate/giữ/ẩn thế nào". QĐ6 (spec:17) trả lời phần MENU (giữ key, đổi label). Phần DỮ LIỆU: QĐ3 thêm cột ApprovalGroup **int** (spec:14 — mặt chữ = non-null) mà không có backfill/default cho phiếu đã tồn tại.
  • Hệ quả đo được: K4 (spec:39) "leaf lọc đúng ApprovalGroup" ⇒ phiếu cũ mang group mặc định 0 sẽ không thuộc leaf nào trong 8 nhóm = biến mất khỏi điều hướng mới. K2 (spec:37) "phiếu cũ mở nguyên vẹn" chỉ nói CatalogEntryId=NULL, không đả động ApprovalGroup.
  • Đề nghị: chốt ApprovalGroup int? (nullable) + quy tắc hiển thị phiếu chưa gán nhóm (leaf "Chưa phân nhóm" hoặc backfill về nhóm 1 kèm bằng chứng đếm row trước/sau).

F-L1-8 [MED] — Số leaf 48 vs 42 + hai dạng key song song (hệ quả của QĐ6, không ai đo)

  • Claim: QĐ6 (spec:17) viết "nhóm 2-8 = key mới Khkk_G{n}_* (48 leaf)" — nhóm 2-8 là 7 nhóm × 6 = 42 leaf mới; 48 là TỔNG (khớp checklist spec:39 "8 mục + 48 leaf").
  • Evidence hình dạng thật: DbInitializer.cs:1780 Khkk_G1GROUP dưới root KeHoachKyKet; 6 leaf con là Khkk_WfView/List/Create/Pending/Approved/Deleted (:1782-1787) — không có infix G1_. Giữ key cũ ⇒ tồn tại song song 2 dạng (Khkk_ListKhkk_G2_List), mọi parser/route-map/seeder-grant phải xử 2 nhánh.
  • Đề nghị: khai rõ tổng 8 group + 48 leaf, trong đó 42 leaf mới + 7 group mới = 49 MenuItem mới; thêm acceptance "0 chỗ nào parse key bằng cách cắt cứng prefix" hoặc chấp nhận rename có backfill label (khuôn S155 đã nhắc).

F-L1-9 [MED] — K4 thiếu deliverable "route-map FE ×2 app"; acceptance K4 không ghi ×2 app

  • Claim: leaf không có route ⇒ biến mất im lặng, không lỗi. Spec K4 (spec:23, :39) không nhắc gì tới static route map.
  • Evidence: fe-user/src/components/Layout.tsx:59-62,:82-83fe-admin/src/components/Layout.tsx:35-40 đều hardcode đúng 6 key Khkk_*; fe-admin/src/components/Layout.tsx:270 if (!path) return null (leaf tự rụng); comment ngay tại fe-admin/…/Layout.tsx:40: "[S159-đợt5 FLAG-1] thiếu là leaf drop SILENT (gotcha #50)"; run S159 đã dính thật ("fe-admin thiếu 2 route Khkk → FIX +2 staticMap").
  • Thêm: K2/K5 có chữ "×2 app" trong acceptance, K4 không ⇒ rớt 1 app vẫn PASS. (Lưu ý tương tác: nếu K6 whitelist land trước, nhánh admin của 42 leaf thành vô ích — spec nên nói rõ K4 chỉ làm fe-user hay cả 2.)

F-L1-10 [MED] — "only-ONE-active-per-type VÔ HẠI" chưa chứng đủ, và acceptance K3 không thể phát hiện nếu sai

  • Claim: spec:14 khẳng định vô hại vì "create chỉ check type, picker lọc isUserSelectable" — biện luận này phủ 2 consumer, không phủ hết.
  • Evidence: SolutionErp.Application/ApprovalWorkflowsV2/ApprovalWorkflowV2AdminFeatures.cs:341-343.Where(w => w.ApplicableType == typeEnum && w.IsActive) rồi foreach (var old in actives) old.IsActive = false; ⇒ mỗi lần tạo bản mới tắt toàn bộ workflow cùng type; sau khi seed 8 nhóm sẽ còn 1 active / 7 inactive, và mỗi lần admin tạo version cho nhóm X thì 7 nhóm kia lại bị tắt (hazard LẶP, không chỉ lúc seed). Consumer khác vẫn đọc cờ này: :210 versions.FirstOrDefault(v => v.IsActive).
  • Acceptance mù: K3 (spec:38) chỉ đếm GET …?applicableType=10 trả 8 — trả 8 bản kể cả 7 bản IsActive=false thì vẫn PASS.
  • Đề nghị: acceptance K3 thêm "8 bản đều isActive=true sau seed" "tạo version mới cho nhóm 5 xong, 7 nhóm còn lại vẫn active" (đây mới là phép làm TRƯỢT nếu 'vô hại' sai).

F-L1-11 [MED] — "App in khối ký nháy" không có chủ sở hữu

  • Claim: lời 5 (draft:11) + draft:25 "app in khối ký đúng pattern"; spec chỉ để nó trong ngoặc lý do của QĐ4 ("hiển thị/in khối ký", spec:15). Không wave nào nhận, không dòng checklist nào đo. GĐ4 đã chốt 1-mốc xong từ S161 ⇒ không có wave GĐ4 để rơi vào.
  • Đề nghị: hoặc gắn vào K1 (render khối ký từ chuỗi vai của dòng danh mục) với acceptance "in thử 1 phiếu, khối ký khớp cột chuỗi-nháy", hoặc khai defer công khai.

F-L1-12 [MED] — QĐ4 (vai TEXT 2 tầng) là ứng viên OWNER-GATE bị tự chốt (chốt lậu ứng viên #1)

  • Claim: QĐ4 (spec:15) quyết định rằng chuỗi vai (TBP.CCM, QS…) chỉ là TEXT trên danh mục, còn người duyệt thật nằm ở V2 Levels — không có ràng buộc nào giữa 2 tầng. Hệ quả nghiệp vụ: giấy in ra ghi "TBP.CCM ký" trong khi người bấm duyệt có thể là ai khác; hệ thống không phát hiện, không có phép đo.
  • Vì sao là quyền owner: đây là thứ owner nhìn thấy trên bản cứng và là lý do tồn tại của SP-002 (ai được ký). 4 quyết định khác được dán nhãn OG (1/2/3/5); QĐ4 thì không, dù mức độ nhìn-thấy-được cao hơn OG-3 (NĐUQ tham khảo).
  • Đề nghị: gán [OWNER-GATE] hoặc khai LIMITATION tường minh + 1 dòng acceptance đối chiếu (ví dụ: cảnh báo mềm khi người duyệt ở Level không khớp vai ghi trên dòng danh mục).

F-L1-13 [MED] — K8 dry-run chạy PROD với 2 tác dụng phụ tự khai mà 0 gate

  • Claim: spec:32 tự liệt rủi ro K8: "HỐ-1 S160 (HĐ DaPhatHanh không xóa được qua API)" + "notification bắn user thật"; acceptance K8 (spec:43) đòi "mã phiếu thật" ⇒ chạy trên dữ liệu thật. Draft:54 để ngỏ "prod/UAT". Không có OG nào cho việc tạo bản ghi không xoá được và ping nhân viên thật.
  • Đề nghị: thêm [OWNER-GATE] "dry-run chạy prod hay UAT; nếu prod thì chấp nhận N bản ghi ZZTEST tồn tại vĩnh viễn + ai bị notify" — hỏi TRƯỚC K8, không hỏi sau.

F-L1-14 [LOW] — Acceptance K1 chỉ đo số dòng ⇒ bảng thiếu cột vẫn PASS

  • Claim: draft:46 liệt cột bắt buộc: "mã nhóm A1…C3 + tên VN/EN + nhóm-duyệt 1-8 + người-ký + chuỗi nháy" (+ cột NĐUQ tham khảo theo QĐ5). Acceptance K1 (spec:36) chỉ đo N dòng + CRUD 200 + seed idempotent + dotnet test.
  • Cụ thể rơi: "tên EN" không xuất hiện một lần nào trong spec.
  • Đề nghị: liệt kê tập cột tối thiểu ngay trong dòng acceptance.

F-L1-15 [MED] — Lời 2+3 (3 trục độc lập / "đưa vào loại hợp đồng gì") chỉ được ăn một nửa

  • Claim (a): draft:27 cảnh báo "Chữ 'loại HĐ' trong hội thoại mang 2 nghĩa — đặt tên field tách bạch". Spec không mang cảnh báo này sang, và chính spec dùng cả "đưa vào loại HĐ" (spec:12, nghĩa = dòng danh mục SP-002) lẫn "7 loại HĐ" (spec:7, nghĩa = ContractType) trong cùng một file ⇒ đúng cái bẫy owner cảnh báo.
  • Claim (b) nặng hơn: cơ chế CHỌN loại HĐ/khuôn form lúc bắc cầu KHKK→HĐ không giao cho ai. K7 (spec:24, :42) chỉ nói bridge đọc ApprovedAmount + gộp theo OG-1; ai/ở đâu chọn ContractType (7 loại, quyết cả mã HĐ RG-001 lẫn workflow pin) thì trống. Lời 3 (draft:9) đòi đúng bước này.
  • Đề nghị: 1 dòng acceptance K7: "màn tạo HĐ từ KHKK bắt chọn ContractType (mặc định suy từ …), mã HĐ sinh đúng RG-001 theo loại đã chọn".

Điểm CHỊU ĐƯỢC soi (khai 2 chiều, chống Smart-Friend)

  • P1 — khai thiếu OG-4 là THẬT: spec:30 viết "Không có OG-4 trong sub-file — số nhảy là của lane, giữ nguyên không bịa". Đo lại: grep -n "OG-" sub-invest-fable-b1a.md → hit ở :36 (OG-1), :39 (OG-2), :40 (OG-3), :43 (OG-5), :53 (OG-2), :57 (OG-1)0 hit OG-4. Khai đúng, không bịa lấp chỗ trống.
  • P2 — tôi ĐÃ ĐỊNH flag sai và tự bác: dự định flag "GĐ4 không có sidebar 7 loại để mirror" ⇒ đo đĩa thì Hdc_* 7 leaf có thật (DbInitializer.cs:1868, nhãn :1981-1987) ⇒ BỎ finding, mảnh (iii) đứng vững.
  • P3 — QĐ7 gọi đúng tên hàm có thật: isAdminHidden (fe-admin/src/components/Layout.tsx:182-184, hiện chỉ chặn Ct_) + filterForAdmin (:186-190) + sidebar admin render 100% từ menu-tree động (:315) ⇒ cơ chế "1 file FE, 0 BE" khả thi. Lỗi của QĐ7 nằm ở tập whitelist (F-2), không ở cơ chế.
  • P4 — header spec khai rõ lane E/F chết + lead compile từ nhãn inline (spec:3) ⇒ truy được nguồn từng quyết định; đây là lý do lens này soi được §② nhanh.

Verdict

FAIL (spec chưa đủ chuẩn để mở fan-out B4 nguyên trạng) — 15 finding: 5 HIGH · 9 MED · 1 LOW.

Không phải bác toàn bộ: khung 8 wave / 3 cụm và 5/7 mảnh scope có wave phủ, luật khuôn được ràng bằng acceptance SHA. Nhưng 3 thứ phải sửa TRƯỚC khi worker cầm spec:

  1. F-2 + F-3 — mảnh (iv) đang thực thi ngược lời owner (giữ 2 designer cũ) và thiếu hẳn nửa "8 designer".
  2. F-4 — 4 owner-gate không nối vào wave nào ⇒ B4 sẽ chạy xuyên gate mà không ai chặn (đặc biệt OG-2 phải gật trước K3).
  3. F-1 + F-5 — K1 không có nguồn theo tên đã ghi; K2 đổi cardinality mà 0 bất-biến tiền tệ trong checklist.

Ba dòng acceptance đang không phân biệt được đúng/sai (mù): K6 (spec:41 — F-2), K3 (spec:38 — F-3 và F-10), K1 (spec:36 — F-14).

END — TOTAL: 15 finding (F-L1-1 → F-L1-15), 5 HIGH / 9 MED / 1 LOW.