Files
solution-erp/.claude/workflows/runs/2026-07-29-S160-khkk-dryrun-plan/plan-cha-dry-run-toan-trinh-29-07-2026.md
2026-07-29 19:03:31 +07:00

15 KiB
Raw Blame History

PLAN CHA — DRY-RUN TOÀN TRÌNH ĐẾN HỢP ĐỒNG CỨNG (S160, 2026-07-29)

Lệnh anh (verbatim): run.md §"LỆNH ANH". Tóm: dry-run luôn đến Hợp đồng cứng · spec KHKK cũ ĐÚNG (ratified) · ra Plan cha + mỗi wave 1 spec-chi-tiết-cách-làm + checklist · /fable-clone review · /fable-real review chốt · hmw Opus-5-MAX chạy từng wave theo Plan cha + kiểm. Nguồn: spec cũ RATIFIED runs/2026-07-28-S157-ke-hoach-ky-ket-hd/spec-ke-hoach-ky-ket-hd-28-07-2026.md (+NOTE W1 @S160) · lane-1 sub-investigator-codebase-1.md (25 mục F-01→F-24) · lane-2 sub-investigator-codebase-2.md (8 mục §0-§7) · đo tươi @S160 (lead): prod Contracts 0 active + 0 deleted (admin-bypass verify ContractFeatures.cs:298/:440). Trạng thái: CHỜ /fable-clone reviewer + /fable-real reviewer chốt cuối → rồi hmw thi công.


1. RANH + NHÃN (chốt @S159, spec cũ :27 — CẤM tự chế lại)

  • GĐ1 Duyệt NCC = PE (live) · GĐ2 Kế hoạch ký kết HĐ = b.7→12 (b.7 email BỎ — Q8 ĐÓNG) · GĐ3 Duyệt hợp đồng = b.13→18 (tận dụng Contract V2) · GĐ4 Hợp đồng cứng = b.19→21, ký cứng UPLOAD-ONLY.
  • Khúc b.13→21 = span verdict-LAI (toàn bộ tái dùng Contract), KHÔNG phải span GĐ3 (lane-1 F-09 bắt drift này trong chính run.md).
  • Nhãn GĐ2 2 đời: "Đề xuất ký kết hợp đồng" (sáng @S159, còn trong spec cũ :27) → superseded "Kế hoạch ký kết HĐ" (chốt cuối @S159, prod Khkk_G1 seeder). Mọi label VN mới = "Kế hoạch ký kết HĐ"; class/bảng English ContractSigningPlan* GIỮ.
  • Nuance lane-1 F-11: bản cứng vật lý SINH ở b.17-18 (∈GĐ3). 🔄 @S161 anh rút GĐ4 còn 1 MỐC hệ-thống (default #8): b.19/20/21 làm trên giấy, hệ thống chỉ ghi nhận upload scan bộ cứng = xong; khối readonly GĐ3 chỉ còn LevelOpinions (duyệt điện tử), KHÔNG attachment ký nháy.

2. BỨC TRANH WAVE (hợp nhất 2 lane — đánh số GIỮ W1-W5 của spec ratified, nối W6-W8)

Wave Tên Mig? Độ lớn Spec file Trạng thái
W1 Schema + permission + Designer type-10 GĐ2 Mig 69 (7 bảng — mig DUY NHẤT toàn plan) BE nặng spec-wave-w1-*.md sẵn chạy
W2 CRUD phiếu nháp + căn cứ b.8-9 + FE 3 page ×2 app GĐ2 FE nặng spec-wave-w2-*.md sẵn chạy (sau W1)
W3 Duyệt 3 trạm + finalize chốt giá 🔴 nặng nhất GĐ2 BE nặng spec-wave-w3-*.md sẵn chạy (sau W2)
W4 Gate + checklist per-phòng FO-002.01 GĐ2 (1 mig nếu số hoá checkbox) KHÔNG có spec — DEFERRED chặn O-Q1/O-Q2; dry-run chạy default (comment tự do + cảnh báo mềm, 0 dev — lane-1 F-18)
W5 Cầu KHKK→HĐ + pin V2 (sửa bridge cũ 1 file) GĐ2→3 2 BE + 2 FE spec-wave-w5-*.md anh ĐÃ MỞ gate chạm HĐ @S160
W6 Đường ống HĐ V2 (view + inbox + vai-trình) GĐ3 2-3 BE spec-wave-w6-*.md sẵn chạy (độc lập W1-W3)
W7 Bản cứng Hdc_* 7 leaf trang thật GĐ4 (option A derive; B = 1 mig nếu anh muốn field tường minh) FE nặng + 1-2 BE spec-wave-w7-*.md sẵn chạy (build song song; verify cần HĐ phase-9 từ W5/W6)
W8 Authz khoanh vùng Contract cross spec-wave-w8-*.md (= biên bản quyết định) GỠ KHỎI DRY-RUN — anh chốt O-A @S160 (để mở, không siết; đúng ❹ "hiển thị hết để góp ý" + O-3 "hợp đồng cứ từ từ"). Rủi ro (Reject-trước-guard + attachment IDOR + Create ăn số) = chấp nhận có ý thức, khoanh bằng ZZTEST + backup DB (§4)
W9 Hồ sơ hoàn tất + thống kê lưu trữ GĐ4 KHÔNG có spec — DEFERRED không chặn vòng chạy (lane-1 F-19)

Thứ tự thi công (đồ thị phụ thuộc):

W1 → W2 → W3 ──┐              (GĐ2: phiếu KHKK sống trọn vòng)
               ├→ W5 → [E2E]  (cầu: HĐ sinh từ KHKK, pin V2, hết kẹt ConflictException)
W6 ───────────┘              (đường ống HĐ V2: mở view+inbox ChoDuyet (GĐ3 approver) VÀ view
                              DaPhatHanh phase-9 (GĐ4 actor bản-cứng) — PHẢI trước W5/W7 VẬN HÀNH;
                              build song song W1-W3 được vì 0 đụng file KHKK)
W7 (build song song từ đầu; 🔴 VERIFY PHỤ THUỘC W6-view — không có W6 mở phase-9 thì trang
    Bảng cứng RỖNG + 403 cho HRA/BOD/CCM non-admin: F-C2/F-01)
W8: GỠ (O-A — anh chốt để mở @S160)

Dry-run E2E đạt khi: W1+W2+W3+W6+W5+W7 xong — 1 phiếu PE DaDuyet (dự án ZZTEST) → phiếu KHKK → 3 trạm duyệt → HĐ per-winner pin V2 → 3 trạm HĐ → DaPhatHanh → trang Bảng cứng upload scan ký/dấu/lưu. Toàn bộ 1 migration duy nhất (Mig 69, W1) — GĐ3+GĐ4 = 0 mig (lane-2 §6). 🔴 CẠNH ĐỒ THỊ THÊM (review F-C2/F-01/F-06): W7-verify đòi W6-đã-mở-view-phase-9; b.14-16 (soạn/góp ý/đàm phán) = trạng thái Nháp HĐ + comment + update-draft trong W5/W6 (KHÔNG wave riêng — default #13). Cần dựng 1 ApprovalWorkflow type=3 THẬT 3-trạm qua Designer (seed chỉ 1 trạm — §4 bước mới).

3. BASELINE ĐO TƯƠI @S160 (căn mọi acceptance vào đây, KHÔNG chép số cũ)

  • Prod: Contracts = 0 active + 0 deleted (curl admin 6 phase + tổng + /deleted; admin bypass ContractFeatures.cs:298) — sổ S156 "7 HĐ V1 thật" đã STALE. ⇒ lỗ Reject chưa có nạn nhân thật; anh chốt O-A (để mở) ⇒ W8 GỠ, rủi ro khoanh bằng ZZTEST + backup.
  • Menu 142 key (root 12) · Khkk_* = 7 key (G1 + 6 leaf, CanRead 13/13, leaf → /coming-soon) · Hdc_* = 7 leaf per-ContractType (KHÔNG phải 6-leaf — lane-2 §3 sửa grounding) · Ct_* 21 key mới.
  • Test 562 (45D+517I) — acceptance neo TÍNH-CHẤT: "PASS 0 fail + số-sau ≥ số-trước-đo-ngay-trước-wave + N + tên test tồn tại", CẤM literal "562+N" (lane-2 §7).
  • Mig cuối = 68 · 89 bảng · mig kế = 69 (chỉ W1).
  • Bundle: admin D0sXA0fe/DWDbm5As · user Y6dW_5CM/6YIAufJR.
  • MenuKeys.KeHoachKyKet const CÓ (MenuKeys.cs:41 + comment dặn tái dùng) nhưng NGOÀI All ⇒ 0 policy KeHoachKyKet.* runtime (đo @S160). Contracts ∈ All :168 ⇒ 4 policy Contracts.* sống sẵn.

4. CHIẾN LƯỢC DATA DRY-RUN (lane-2 §4 + đo mới)

  1. Dự án test ZZTEST + 1-2 NCC test tạo qua UI (0 code): mã HĐ dry-run ăn sequence per-prefix riêng (ContractCodeGenerator.cs:33,:40-53) — không đụng chuỗi số dự án thật; NGOÀI seed-list ⇒ xóa mềm không bị re-seed (#75/#76). CẤM đặt Code trùng seed-list (twin FLOCK-01). 🔴 CẤM tạo HĐ loại HopDongMuaBan (anh bỏ "MB" @S161 — default #7).
  2. PE side có data THẬT — phiếu KHKK dry-run tạo từ PE test mới (mỗi vòng thử cần PE mới vì idempotency pe.ContractId :59-60,:145). 2-bis. 🔴 DỰNG WORKFLOW type=3 3-TRẠM (review F-02 — bắt buộc E2E): seed prod chỉ có QT-HD-V2-001 = 1 trạm CCM (DbInitializer.cs:239-265, approver binh.le). E2E hứa 3 trạm (PRO→CCM→CEO) + b.19 BOD ⇒ admin phải tự dựng 1 ApprovalWorkflow ApplicableType=3 3 Bước qua Designer (0 code — Designer type-3 đã có) TRƯỚC khi chạy W5. Tương tự KHKK type=10 cần 1 workflow 3-trạm (W1 Designer). Ghi là bước setup thủ công, không phải code wave.
  3. KHÔNG cờ IsDryRun (blast cardinality mọi list/inbox — bài S87/S88).
  4. Hố rollback khai trước: HĐ ≥ phase 5 KHÔNG xóa được qua API (ContractFeatures.cs:632-633 so sánh SỐ) → HĐ test DaPhatHanh nằm lại (lọc bằng ZZTEST) hoặc admin-override về DangSoanThao (ContractWorkflowService.cs:191-198) rồi xóa. Phiếu KHKK/PE DaDuyet cũng không xóa (allow-list). Sequence không rollback (gap số chấp nhận — comment repo :113-115).
  5. Notification bắn cho user thật (in-app, không tắt per-record) — dặn team trước đợt dry-run.
  6. Backup DB trước đợt (scripts/backup-sql.ps1).
  7. 🔴 HỐ AUTHZ CHẤP NHẬN CÓ Ý THỨC (O-A anh chốt @S160 — review F-S2/F-O1) — disclose để không ai tưởng đã kín: vì để mở, trong dry-run mọi user đăng nhập: (i) TraLai/TuChoi bất kỳ HĐ bất kỳ phase (Reject-trước-guard ContractWorkflowService.cs:49-66); (ii) upload/xóa/tải attachment (kể cả scan đã ký) của HĐ bất kỳ — 3 handler ContractAttachmentFeatures.cs:56-152 0 IDOR + 0 phase-guard; (iii) Create HĐ ăn sequence thật nếu chọn dự án thật. ⇒ CHỈ chạy dry-run trên ZZTEST + backup trước; đây là rủi ro anh nhận, KHÔNG phải lỗ chưa biết. (Khác KHKK GĐ2: module MỚI vẫn build authz 2-tầng đúng #82 — "để mở" chỉ áp module Contract sẵn có.)

5. BẢNG DEFAULT 13 QUYẾT ĐỊNH (dry-run chạy bằng default ĐẢO ĐƯỢC — anh veto lúc nào cũng kịp; #11 ĐÃ RESOLVED O-A)

# Câu treo DEFAULT dry-run Đảo thế nào Nguồn
1 Q3 điều kiện rẽ b.12 KHÔNG rẽ sớm — đường THƯỜNG 3 trạm, CEO ký thật (2 đường sớm anh từng phán "PHÁ VỠ" S155) bật cờ workflow (0 code) spec cũ :67-71, W3 :362-365
2 Q6 giá vào HĐ ApprovedAmount KH thắng + ContextNote lệch vào changelog đổi 1 nhánh if trong bridge spec cũ §2.5 + lane-2 §2(b)
3 Q11 tạo HĐ khi chưa có KH cảnh báo mềm — 2 đường song song (PE→HĐ tắt vẫn sống) nâng 409 chặn cứng lane-2 §2(d)
4 O-Q1 căn cứ thiếu TvgsDuyet cảnh báo mềm khi trình 409 spec cũ W4
5 O-Q2 checkbox per-phòng comment tự do LevelOpinions (W4 DEFERRED, 0 dev) số hoá checkbox (wave riêng) lane-1 F-18
6 Mã phiếu KHKK RESOLVED — anh OK @S161: KHKK/{YYYY}/{Seq:D3} qua WorkflowAppCodeSequence (RG-001 v02 CÂM về phiếu); phép đo format thêm @W1 §③-B + W2 §③-B (review A6: quyết owner-visible phải có acceptance) đổi format 1 chỗ CodeGen lane-1 F-07 + spec cũ :128 + owner @S161
7 Viết tắt "MB" (Mua bán) — codegen tự chế, KHÔNG có trong RG-001 v02 RESOLVED — anh chốt @S161 (verbatim): "Bỏ cái MB đi" ⇒ (i) dry-run CẤM tạo HĐ HopDongMuaBan — không mã MB nào được sinh (guard W5 §③-C); (ii) ContractCodeGenerator.cs:25 "MB" = nợ đã tuyên án, format thay thế (PO-format theo comment :18 hay khác) làm CHUNG đợt sửa Contract service — O-3 "cứ từ từ" còn hiệu lực, KHÔNG đổi codegen giữa dry-run đổi 1 case switch khi anh chốt format thay lane-1 F-06/F-21 + owner @S161
8 GĐ4 vật mang RESOLVED — anh chốt @S161 (verbatim): "trình ký sẽ hiển thị full form doc có sẵn trong mục FORM -> điền đầy đủ vào luôn -> Duyệt qua (Nếu có) -> Upload file cứng lên -> Là xem như xong"A-RÚT-GỌN 1-MỐC: 0-mig + 0 enum-extend — badge duy nhất "Đã lưu bản cứng" = has(SealedCopy SẴN); InitialSigned=4/CoverChecklist=5 BỎ; b.19/b.20 diễn ra NGOÀI hệ thống (vẫn KHÔNG ScannedSigned — F-C6/gotcha #71). Option B RETIRED nâng field 4-mốc nếu vận hành thật đòi — backfill từ attachment sẵn lane-2 §3 + owner @S161
9 Số bộ gốc / nơi lưu / ngày giao note TÙY CHỌN khi upload SealedCopy (hạ từ "bắt buộc" theo 1-mốc @S161 — "upload = xong", không chặn thao tác) option B field tường minh lane-1 F-13/F-14 (nguồn câm)
10 Thời điểm gán mã HĐ (QT đòi b.17, máy gen ở create + terminal) GIỮ máy hiện trạng (create-time ContractFeatures.cs:113-118 — có mã TRƯỚC khi in, sớm hơn cả QT đòi) + khai lệch trình tự so QT dời site gen lane-1 F-16 + lane-2 §1-b.13
11 Authz Contract RESOLVED — anh chốt O-A @S160: ĐỂ MỞ, không siết. W8 GỠ. Rủi ro disclose §4.7 (anh đổi ý lúc nào cũng kịp — bật lại W8 = 1-2 file) owner @S160
12 Grant quyền KHKK (W1) 🔴 UPGRADE-if-exists (SeedProcurementMasterAccessAsync:2367-2374 khuôn), chạy SAU revoke — KHÔNG insert (row KeHoachKyKet/Khkk_* seed CanRead-only sẵn ⇒ insert = skip-existing no-op ⇒ 403 giết dry-run, review F-S1/F-O3/F-O4). Cấp CanCreate/CanUpdate cho 13/13 role (đúng O-A "hiển thị hết") + Delete cho Drafter/Admin siết nhóm hẹp hơn nếu muốn review 4-lane hội tụ
13 b.14-16 (soạn/góp ý/đàm phán HĐ) Nháp HĐ + comment thread + update-draft trong W5/W6 — KHÔNG wave riêng thêm Bước workflow admin-config (0 code) nếu muốn trạm thật lane-1 F-19 + review F-06

6. GATE 5-ANCHOR (bắt buộc TRƯỚC MỖI WAVE — HANDOFF, reviewer đề @S157, gotcha-proof)

Trước thi công wave: mở 5 anchor của wave đó (danh sách trong từng spec-wave §③) — ≥1 trượt ⇒ chấm lại TOÀN BỘ anchor wave đó rồi mới code. Anchor per-wave lấy từ lane-2 §7 (đã re-verify 07-29) + spec cũ.

7. KHUÔN ACCEPTANCE + CICD (mọi wave)

  • Test: dotnet test SolutionErp.slnx PASS 0 fail · baseline = số test đo NGAY TRƯỚC wave bằng chính lệnh đó (KHÔNG literal "562" — nó tự lão-hoá; review F-B8) · số-sau ≥ baseline + N · tên test pin cụ thể theo KHUÔN REPO (anh chốt @S160: English-predicate + danh-từ-VN-không-dấu, vd ApproveV2_LastLevel_TransitionsToDaPhatHanh — KHÔNG vị-ngữ-thuần-Việt; census repo 0/460 tên kiểu cũ, review F-B7).
  • FE: npm run build ×2 app PASS; mirror SHA khi cookie-cutter.
  • Deploy: cicd 3-chân-kiềng — CI run PASS · bundle byte-marker (#77, control ÂM phải ĐỘC QUYỀN — bài đợt-5) · data prod verify bằng curl API (SSH-SQL client chết S134/S148; sqlcmd chỉ để local/Dev).
  • Menu/permission: CHỈ qua seeder (gotcha #84) — mọi thay đổi grant đi cùng commit wave.

8. PIPELINE CÒN LẠI (đúng lệnh anh)

  1. 2 /fable-real invest (xong, verified) → 2 Plan cha + specs (file này + 7 spec-wave) → 3 /fable-clone reviewer (ensemble N-lane chấm bộ plan+spec) → 4 /fable-real reviewer chốt cuối → 5 hmw Opus-5-MAX: mỗi wave = 1 đợt hmw, args con-trỏ vào ĐÚNG spec-wave file (B6 args-mỏng), worker đọc spec + thi công + tự chạy checklist §③; lead + cicd-monitor verify 3-chân-kiềng sau mỗi wave; gate 5-anchor chạy TRƯỚC mỗi đợt.
  • Điều KHÔNG tự làm khi chưa có gật riêng: O-C (vá ContractWorkflowService.cs:49 Reject-guard — chạm service HĐ, O-3 còn hiệu lực cho phần SỬA service) · số hoá W4 · option B GĐ4.