wal: flush 20260731T1420
This commit is contained in:
@ -1,74 +1,38 @@
|
||||
# WAL — auto-generated, không sửa tay
|
||||
updated: 2026-07-31T12:35:00+07:00 | session: S164 (L9, window 2 — /tiep; lead=Fable) | branch: main
|
||||
updated: 2026-07-31T16:45:00+07:00 | session: S164 (L9, window 2 — /tiep; lead=Fable) | branch: main
|
||||
|
||||
goal: CHUỖI 4-GĐ SP-002 — B0 ✅ B1a ✅ B1b ✅ spec-v2 ✅ transcribe ✅ · NEXT = B2 (chờ anh liếc 6 OG, có default)
|
||||
goal: CHUỖI 4-GĐ SP-002 — SPEC ĐÓNG BĂNG (B0→B3 trọn) · B4 BUILD BẮT ĐẦU (wave K1-BE đang chạy)
|
||||
|
||||
chain:
|
||||
[x] /tiep + VÁ 12/12 + nạp spec SP-002 (6 nhịp + 3 hình + 2 bổ sung) — chi tiết _context/log
|
||||
[x] B0 draft-yeu-cau-owner.md (10 lời chốt + 8 nhóm + 5 mảnh + khuôn + 8 treo)
|
||||
[x] B1a ×2 att: att-1 ngược-#53 (207K/0-byte/resume-chết) · att-2 kỷ-luật-ghi CỨU A-D 18.277B →
|
||||
lead compile E/F + spot-check 4/4 → spec v1 (8 verdict · K1-K8 · 3 cụm)
|
||||
[x] B1b wf_8eb13087-5f9 — 3 lane reviewer opus 3-lens, 3/3 SẠCH 0-empty (C2 khung-rỗng ăn): l1 FAIL 5H ·
|
||||
l2 6/6 chịu-lực ĐÚNG + F1 rào-1-PE-1-phiếu (:342/:1201) · l3 FAIL 6H + bác-6-nghi. Hội tụ 2-lane:
|
||||
admin-hide "System-subtree" GIỮ NHẦM 2 mục cần ẩn (Workflows :1795 + PeWorkflows :1798 = CON System)
|
||||
[x] Lead synthesize b1b-review-synthesis.md (41 finding → 14 vá + OG-6/OG-7) → SPEC V2 10.012B
|
||||
(tập-key tường-minh · ApprovalGroup K2-chủ+backfill-1 · 8-designer đo được · K7 3-nấc · acceptance răng)
|
||||
[x] F-1 resolve: file đĩa = ĐÚNG SP-002.v01 (mã ở word/header1.xml) NHƯNG 6-trang KHÔNG bảng ⇒ nguồn =
|
||||
7 ảnh anh. Lead TRANSCRIBE danh-muc-sp002-transcribe.md: 85+1 row · 8 nhóm map · 4 ô-chưa-chắc [OG-6]
|
||||
[!] B2 — per cụm 3 wave (cụm-1 K1+K2+K3 · cụm-2 K4+K5+K6 · cụm-3 K7+K8): /fable-real invest sâu →
|
||||
/fable-clone review. PRE: 6 OG có DEFAULT (spec v2 §④) — chạy default nếu anh không đổi; build B4 mới chặn cứng
|
||||
[ ] B3 /fable-real review chốt · B4 fan-out Opus MAX · B5 dry-run E2E
|
||||
[ ] closeout: seed diary vai (C2 A∖B=∅) · tally garble (+ngược-#53 ev#4) · nhãn D · K3-STATUS-row
|
||||
[x] /tiep + VÁ 12/12 + spec SP-002 nạp (6 nhịp + 3 hình) — log cũ trong _context
|
||||
[x] B0 draft → B1a invest (att-2 cứu) → B1b clone-review 3-lane → spec-tổng v2
|
||||
[x] B2 TRỌN 3 cụm: invest fable ×3 (c1 33KB · c2 5/5 · c3 22.9KB) + review 3-lane ×3 → 3 spec-cụm final,
|
||||
43 vá. Sự cố đã xử: ngược-#53 ev#4 · skeleton-472B ×1 · chết-ruột-188B ×1 (opus) — đan-xen từ đó 5/5 SẠCH
|
||||
[x] OG CHỐT TRỌN 9: 1-gộp+UI-1-1 · 2-đội-hình-cũ · 3-NĐUQ-human-gate-VĨNH-VIỄN · 7-N-phiếu+UI-1 · 8-hiển-thị ·
|
||||
9-đảo-PHÁ-VỠ-S155 · QĐ9-freeze-tái-dùng-máy-sẵn · (V)-thiết-kế-ERP-đúng+PE-test-SOLUTION-PE-{n} ·
|
||||
BACKLOG 3 mục giai-đoạn-sau (amendment · authz-nhóm · bung-gộp)
|
||||
[x] B3 fable-review chốt: GO-WITH-SPEC-FIXES (GO 9/10 · 8 mâu-thuẫn · 0 vá-đè-vá/43 · build-order
|
||||
K1→K2→K3→K4a→K4b→K5→K4c→K6→K7→K8) → 8 fix lead ÁP XONG → SPEC ĐÓNG BĂNG 4 file
|
||||
[!] wf: B4 K1-BE wf_2569b79b-12f ĐANG CHẠY — implementer-backend: entity ContractCatalogEntry + config +
|
||||
Mig 70 3-file + seeder 86-row từ transcribe + MenuKeys+row + CQRS/controller authz-mirror-Catalogs +
|
||||
build slnx + test-không-vỡ-590. Output sub-implbe-k1.md. 🔴 KHÔNG commit/push — lead verify + OG-6 gate
|
||||
[ ] B4 tiếp: K1-FE (×2 app KIND_CONFIG) + K1-test → K2 → K3 → K4a... theo build-order; mỗi wave lead verify
|
||||
+ reviewer-gate trước commit; PUSH K1 chờ anh soát OG-6 (bảng transcribe + 8 nhãn)
|
||||
[ ] K8 dry-run: gói test SOLUTION-PE-{n} + B0-form 14 người thật (fail-closed) + đo freeze 2-nhánh
|
||||
[ ] closeout: seed diary vai (C2 A∖B=∅) · tally garble (+sự-cố hôm nay) · nhãn D · STATUS row S163/S164
|
||||
|
||||
next: 5/6 OG CHỐT (1 schema-GỘP+UI-1-1 · 2 đội-hình-cũ · 7 N-phiếu+UI-1 · 8 "cho hiển thị, phân quyền tính
|
||||
sau" · 3 NĐUQ-tham-khảo + lên-CEO = TÁI DÙNG level-finalize [a Chương quyết, y PE]). Còn OG-6 anh soát
|
||||
transcribe (chặn seed-land, KHÔNG chặn invest). wf: B2-cụm-1 wf_fe53e58b-361 ĐANG CHẠY (1 lane fable,
|
||||
sub-invest-fable-b2-cum1.md, skeleton-first) → về thì: verify đĩa → merge note OG-3-finalize vào spec
|
||||
chi-tiết → kết tinh → fable-clone review cụm-1. Nguyên tắc mới memory: "máy rộng, UI hẹp".
|
||||
🆕 QUYẾT ĐỊNH 9 (owner): KHÓA BUDGET tại finalize (a Chương TP.CCM) = mirror PE Mig 67 + né #81-EXT — spec §②.9.
|
||||
B2c1 att-1 skeleton-472B chết · att-2 wf_0b6b511f-76d ✅ SỐNG TRỌN (33.048B 5/5 section 17 test, luật
|
||||
ĐAN-XEN cứu; return CŨNG sạch). 3 QUYẾT spot-check 3/3 ĐẠT: freeze = 0-cột-mới (máy Line+??= sẵn, chỉ
|
||||
thêm răng #81-EXT site :342) · catalog authz mirror CatalogsController · MÂU THUẪN OG-3 THẬT (BE chưa
|
||||
port finalize — KHKK_EARLY_FINALIZE_NOTE system/ApprovalWorkflowsV2Page:151) → spec §④ OG-3 ĐÃ SỬA
|
||||
(K3 3 việc a/b/c). Roster ô ⚠️ "Trưởng" 3 ứng viên — verify LIVE trước seed.
|
||||
B2-r cụm-1 ✅ 3/3 lane (L1 2/9-claim-đúng GỠ-(i)-:342 [invest đọc-ngược-comment] · L2 FAIL 3H · L3 PWB
|
||||
5H) → spec-cum1-chi-tiet-31-07-2026.md FINAL (nền 33KB + 12 VÁ thắng-xung-đột; blocker: key-VÀO-All +
|
||||
sweep-ép-false-AllowApproverFinalize ≥4-site + KhkkCreatePage-×2-app + submit-guard-CatalogEntryId).
|
||||
OG-9 ✅ CHỐT (câu IV): anh xác nhận đảo "PHÁ VỠ" @S155 — "chỗ budget chốt chặn là a Chương" ⇒ K3 (a)-(e)
|
||||
HẾT CHẶN. + OG-3 NÂNG: trần budget = HUMAN-GATE VĨNH VIỄN (a Chương quyết cần-CEO-hay-không) — XÓA mọi
|
||||
ý "enforce máy wave sau" khỏi backlog. 7/7 OG nghiệp-vụ đã chốt; còn OG-6 soát-bảng (chặn seed) + OG-5.
|
||||
B2 cụm-2 invest ✅ wf_15a42015-aea SẠCH (5/5 section, K4 13v·K5 6v·K6 4v, 0-mig; BÁC 2 tiền-đề lead:
|
||||
13-role=13/13-R+C+U [:2427] · fe-admin khỏi-nới-regex [ẩn subtree :186-190]; lead spot-check 2/2 ĐẠT;
|
||||
drift chain 55→64→113 key · policies →452; precedent-split khai 2 khuôn ngoài-All⟂trong-All).
|
||||
B2-r cụm-2 ✅ (l1 PWF 4/7-đúng-0-sai 2-MAJOR [route-ship-cùng-K4a · drift-DELTA] · l2 PWF 3H/7M [queryKey
|
||||
+group · thứ-tự · nhãn-N2-mất-phá-dỡ · phase-mount-only] · 🔴 l3 CHẾT-RUỘT 188B = lane OPUS đầu tiên gãy,
|
||||
phủ-bù lead-note CÓ KHAI) → spec-cum2-chi-tiet-31-07-2026.md FINAL 15 vá.
|
||||
B2 cụm-3 invest ✅ wf_a21c8ff1-bc7 SẠCH (22.9KB 4/4: K7 8v/8test — BÁC tiền-đề "3 lỗ S156": ĐÃ VÁ @W6-S161
|
||||
[list :306-318 · inbox :532-543 · guard :73-92] ⇒ K7(b)→test-khóa; CẤM sửa GetEligiblePhases [:381-387 rò
|
||||
xóa-mềm]; bridge +ApprovalWorkflowId input [type-3 any-ContractType]; pe.ContractId ??= giữ cây; K8 17-bước
|
||||
B0-B16, B1→KHKK-N4, type NhaCungCap né hố-MB, đội hình từ K3-LIVE [Dev 0 QT-DN-V2-001]).
|
||||
🔴 HỐ-1-KHKK MỚI: phiếu KHKK DaDuyet KHÔNG XÓA nổi kể cả Admin (:1145-1148 allow-list SAU nhánh admin) +
|
||||
chiếm slot (PeId,group) VĨNH VIỄN — dry-run trên PE thật = phiếu-test nằm lại, dọn = sqlcmd ⇒ CÂU (V) cho anh.
|
||||
B2-r cụm-3 ✅ 3/3 (L1 7/7-ĐÚNG · L2 FAIL-5H K8-chưa-chạy-được [12/14 bước 0 người thật · QĐ9 đo-0-bit ·
|
||||
ZZTEST không hiện list · rollback-HĐ no-op] · L3 FAIL-4H [authz HỘI-2-khóa + Contracts.Create 0-VAI ĐƯỢC
|
||||
CẤP ⇒ nút chết 403 câm — 3-lane hội tụ]) → spec-cum3-chi-tiet-31-07-2026.md FINAL 16 vá.
|
||||
B2 ĐÓNG TRỌN: 3 spec final + 43 vá tổng. wf: B3 wf_567c4b38-405 ĐANG CHẠY (1 lane reviewer tier:FABLE
|
||||
đối chiếu chéo 4 spec → A mâu-thuẫn-liên-spec · B vá-đè-vá · C build-order · E GO/NO-GO · F digest-owner).
|
||||
Về → lead tổng → BẢNG TỔNG trình anh → B4 build K1 (anh pre-authorize "chốt kỹ rồi thì dry-run luôn";
|
||||
seed-land vẫn chờ OG-6+câu-II · K8 chờ câu-V).
|
||||
(V) ✅ CHỐT TRỌN: "phiếu đã duyệt không xóa" = THIẾT KẾ ĐÚNG ERP (CẤM B4 sửa allow-list) + phương án (b)
|
||||
ratified — K8 dựng gói test tên `SOLUTION-PE-1..n` đi trọn vòng, KHÔNG test trên phiếu thật (mã phiếu vẫn
|
||||
auto-gen RG-001; nhận diện qua TÊN GÓI + danh-sách-ID). +BACKLOG giai-đoạn-sau: phiếu điều-chỉnh/thay-thế
|
||||
(amendment, áp PE/KHKK/HĐ) + authz-per-nhóm + bung-gộp UI — spec tổng đã ghi 3 mục.
|
||||
CHỜ ANH: (I) bản-15-trang · (II) B2-14-dòng+"/" · (III) ai-bấm [default Drafter+Procurement+Admin] · OG-6.
|
||||
Sổ lane-chết: fable 3/8 · opus 1/12.
|
||||
next: đợi wf_2569b79b-12f → VERIFY ĐĨA (sub-file + git status + dotnet build/test THẬT — disk-truth
|
||||
WRITE-lane) → nếu sạch: phóng K1-FE + K1-test song song → reviewer-gate K1 → chờ OG-6 rồi commit-push.
|
||||
Chết giữa chừng: relaunch-cắt-gọt theo tiep.md §4 (git status cho biết file đã tạo).
|
||||
|
||||
verify:
|
||||
grep -c 'END spec v2' .claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/spec-4gd-khkk-tong-quat-31-07-2026.md
|
||||
grep -c '86 row' .claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/danh-muc-sp002-transcribe.md
|
||||
ls .claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/ | wc -l # >=9 file
|
||||
ls .claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/ | wc -l # 20 file (17 + sub-implbe-k1 + 2 review c3)
|
||||
git status --porcelain | head -20 # K1-BE files sau khi lane xong
|
||||
grep -c 'GO-WITH-SPEC-FIXES' .claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-review-fable-b3.md
|
||||
|
||||
notes: RÀNG BUỘC KHUÔN: GIỐNG NHAU—CHỈ KHÁC FORM—ĐỪNG CHẾ THÊM. 8 nhóm = HIỂN THỊ không phải authz (khai
|
||||
thẳng spec §①). Đội hình 3 trạm QT-DN-V2-001 memory (verify LIVE trước K3). Sự cố phiên: ngược-#53 ev#4
|
||||
(B1a att-1) + StructuredOutput-fail ×2 lần B1a (đĩa cứu) — tally @closeout. mind-check 1 cờ giữ chủ-đích.
|
||||
Chờ anh cũ: 54-62+42/43/44 (HANDOFF). Lead=Fable; ensemble lane pin tier:opus (GAP#6).
|
||||
notes: SPEC 4 file = spec-tổng v2 (9 QĐ + backlog-3) · spec-cum{1,2,3} final (12+15+16 vá). Câu-ranh builder:
|
||||
":342" trùng số dòng 2 file — Features.cs:342-347 PHẢI đổi ⟂ WorkflowService.cs:342 CẤM đụng (B3-B4).
|
||||
CHỜ ANH (không chặn K1-BE build): (I) bản-15-trang · (II) B2-14-dòng+"/"=hoặc · (III) ai-bấm-Đưa-vào-HĐ
|
||||
[default Drafter+Procurement+Admin] · OG-6 soát transcribe+8-nhãn [CHẶN push K1] · OG-5 hỏi-khi-gặp.
|
||||
Sổ lane-chết: fable 3/9 · opus 1/13 (đan-xen từ c1-att2: 6/6 sạch liên tiếp). Engine dùng: fable ×6 ·
|
||||
clone-ensemble ×9 lane · impl ×1 (đang). mind-check 1 cờ giữ chủ-đích (block refresh @cửa kế).
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
| 2.c2-r | Review cụm-2 — `WF reviewer c2-{evi,cov,seq} s164` | /fable-clone (opus ×3) | ✅ l1 PWF 2-MAJOR · l2 PWF 3H/7M · 🔴 l3 CHẾT-RUỘT 188B (opus đầu tiên gãy — phủ bù lead-note có khai) → **spec-cum2-final 15 vá** |
|
||||
| 2.c3 | Cụm-3 K7+K8 — `WF invest-fable b2c3 s164` | /fable-real invest | ✅ SẠCH 22.9KB (K7 8v/8test BÁC tiền-đề 3-lỗ-S156-đã-vá · K8 17 bước · HỐ-1-KHKK mới) |
|
||||
| 2.c3-r | Review cụm-3 — `WF reviewer c3-{evi,cov,seq} s164` | /fable-clone (opus ×3) | ✅ 3/3 sạch · L1 7/7-ĐÚNG PWF 4M · L2 FAIL 5H (K8 chưa-chạy-được-như-viết) · L3 FAIL 4H (authz hội-2-khóa · Contracts.Create 0-vai) → **spec-cum3-final 16 vá** |
|
||||
| 3 | Chốt spec cuối — `WF review-fable b3-chot s164` wf_567c4b38-405 | /fable-real review | ⏳ (đối chiếu chéo 4 spec: mâu-thuẫn liên-spec · vá-đè-vá · build-order · GO/NO-GO · digest owner) |
|
||||
| 3 | Chốt spec cuối — `WF review-fable b3-chot s164` | /fable-real review | ✅ **GO-WITH-SPEC-FIXES**: GO 9/10 (K8 by-design) · 8 mâu-thuẫn (3 nặng A-1/A-4/A-5) · 0 vá-đè-vá/43 · build-order K1→K2→K3→K4a→K4b→K5→K4c→K6→K7→K8 · 8 fix lead ÁP XONG |
|
||||
| 4 | Fan-out build bám spec+checklist | Opus 5 MAX (hmw) | ☐ |
|
||||
| 5 | Dry-run E2E toàn trình | theo spec wave cuối | ☐ |
|
||||
|
||||
@ -27,6 +27,6 @@
|
||||
- [x] B1a — att-1 wf_22e8949b-afa CHẾT ngược-#53 (207K tok, 0 byte) · att-2 wf_bc04352b-6a4 A-D đầy + spec-file lead kết tinh `spec-4gd-khkk-tong-quat-31-07-2026.md` (8 verdict · 8 wave K1-K8 · 3 cụm · OG-1/2/3/5)
|
||||
- [x] B1b — wf_8eb13087-5f9 3/3 lane sạch (l1 FAIL 5H · l2 6/6 chịu-lực ĐÚNG +l2-F1 rào-1-PE · l3 FAIL 6H + bác 6 nghi) → `b1b-review-synthesis.md` 14 vá + OG-6/OG-7 → spec v2 (hội tụ 2-lane: admin-hide tập-key tường minh; ApprovalGroup K2-chủ + backfill=1; 8 designer có phép đo; nguồn K1 = 7 ảnh [file đĩa 6-trang không bảng])
|
||||
- [x] B2 — 3 cụm TRỌN: c1 (33KB + 12 vá) · c2 (5/5 + 15 vá; l3 chết-ruột phủ-bù) · c3 (22.9KB 7/7-đúng + 16 vá) = 43 vá tổng, 3 spec final
|
||||
- [ ] B3 — fable-real review chốt
|
||||
- [x] B3 — GO-WITH-SPEC-FIXES (sub-review-fable-b3.md 6 section; 3 anchor re-grep đĩa khớp; 8 fix áp vào 3 spec) — SPEC ĐÓNG BĂNG cho B4
|
||||
- [ ] B4 — fan-out build
|
||||
- [ ] B5 — dry-run E2E
|
||||
|
||||
@ -6,17 +6,17 @@
|
||||
|
||||
Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA, đã chạy) → GĐ2 KHKK = **duyệt HẠNG MỤC theo 8 NHÓM DUYỆT** (trình ký số trạm-by-trạm y Duyệt NCC; ký nháy = mực trên bản cứng GĐ4) → GĐ3 điều khoản → GĐ4 bản cứng 1-mốc. Scope 5 mảnh: master-data danh mục · sidebar 8 nhóm × 6 leaf · cây mirror sidebar · admin thu gọn + 8 designer · dry-run E2E. 🔴 Luật khuôn: **GIỐNG NHAU — CHỈ KHÁC FORM — ĐỪNG CHẾ THÊM**. 🔸 Khai thẳng (B1b l3-F4): đợt này **8 nhóm = đơn vị HIỂN THỊ + luồng duyệt**, KHÔNG phải đơn vị authz — mọi endpoint KHKK giữ 1 bộ policy `KeHoachKyKet.{R,C,U,D}` per-action (`ContractSigningPlansController.cs:28+`); authz-per-nhóm nếu anh muốn = wave riêng sau.
|
||||
|
||||
## ② Cách implement — 8 quyết định (v2)
|
||||
## ② Cách implement — 9 quyết định (v2; B3-A0b sửa đếm)
|
||||
|
||||
1. **[OG-1]** Cardinality "đưa vào loại HĐ" default **GỘP theo cặp (NCC × dòng-danh-mục)** — N line chung `ContractId` (hợp khuôn `ContractSigningPlanLine.cs:25`, index không-unique `Configuration:26`); đảo 1-1 được cùng máy.
|
||||
2. Phiếu KHKK = **per NHÓM** (1 phiếu = 1 nhóm, N hạng mục). Lines per-hạng-mục: Mig +`CatalogEntryId Guid?` +`TenHangMuc`, UNIQUE → (PlanId, SupplierId, CatalogEntryId) filtered. 🔴 **+2 vá B1b:** (a) **đổi rào 1-PE-1-phiếu** (`ContractSigningPlanFeatures.cs:342-347` + picker `:1201-1202`) → (PeId, ApprovalGroup) **[OG-7]** — FE tree đã chịu N-phiếu/PE (`usePipelineStages.ts:110-121`); (b) **bất-biến tiền**: `PeReferenceAmount` = snapshot per-NCC-toàn-phiếu (`Line.cs:6,:16-20`) — repurpose per-hạng-mục PHẢI định nghĩa lại semantics + Σ trước == Σ sau mig, acceptance rà **16 consumer** (10 BE `.Lines` + 6 file FE — danh sách l3-F18).
|
||||
2. Phiếu KHKK = **per NHÓM** (1 phiếu = 1 nhóm, N hạng mục). Lines per-hạng-mục: Mig +`CatalogEntryId Guid?` +`TenHangMuc`, UNIQUE → (PlanId, SupplierId, CatalogEntryId) filtered. 🔴 **+2 vá B1b:** (a) **đổi rào 1-PE-1-phiếu** (`ContractSigningPlanFeatures.cs:342-347` + picker `:1201-1202`) → (PeId, ApprovalGroup) **[OG-7]** — FE tree đã chịu N-phiếu/PE (`usePipelineStages.ts:110-121`); (b) **bất-biến tiền**: `PeReferenceAmount` = snapshot per-NCC-toàn-phiếu (`Line.cs:6,:16-20`) — repurpose per-hạng-mục PHẢI định nghĩa lại semantics + Σ trước == Σ sau mig, acceptance rà **18 consumer** (17 grep-verified cụm-1 + `Features.cs:712-713` Σ Proposed — số chốt theo cụm-1 vá-8; B3-A-x).
|
||||
3. Workflow = **1 type-10 + 8 Code `KHKK-N1..N8`**; only-ONE-active VÔ HẠI (chứng 2 mắt xích l2: create chỉ check type `:209-220`; overview không lọc IsActive `:117-134`, POST không đụng IsUserSelectable `:341-353`). 🔴 Cột `ApprovalGroup` **K2 là CHỦ DUY NHẤT** (l3-F6) — K3 chỉ đọc (map Code↔group + validator phiếu-pin-đúng-nhóm).
|
||||
4. Vai catalog = 2 tầng: danh mục lưu chuỗi vai TEXT (in khối ký GĐ4) ⟂ workflow Levels lưu NGƯỜI THẬT. 🔸 Khai limitation (l1-F12): TEXT không ràng buộc máy với người-duyệt-thật — chấp nhận đợt này, khai trong doc K1.
|
||||
5. NĐUQ = cột THAM KHẢO text **[OG-3]**; enforce (`CeoApprovalThreshold`) = wave opt-in sau (0 consumer CỐ Ý — `WorkflowService.cs:44`).
|
||||
5. NĐUQ = cột THAM KHẢO text **[OG-3 nâng cấp]**; enforce máy = **KHÔNG BAO GIỜ** (human-gate vĩnh viễn — a Chương quyết; B3-A0a: xóa nốt vế "wave opt-in sau" sót ở đây).
|
||||
6. Menu: GIỮ `Khkk_G1` + 6 leaf cũ, đổi LABEL = nhóm 1 (labelBackfill khuôn S155). Nhóm 2-8 = **42 leaf MỚI + 7 group-key mới (49 row menu mới; 48 leaf TỔNG)** — sửa số l1-F8/l2-F5. 🔴 Phiếu cũ: **backfill `ApprovalGroup = 1`** (l3-F5 — mirror bài `EvaluationType` không rỗng; acceptance đếm `COUNT(phiếu) == Σ COUNT 8 folder`).
|
||||
7. Admin ẩn = fe-admin **`isAdminHidden` MỞ RỘNG TẬP KEY TƯỜNG MINH** (giữ blacklist — KHÔNG đảo whitelist, tránh đổi default menu-mới; vá hội tụ l1-F2 ⨯ l3-F1/F2): ẩn thêm {`Dashboard?`→giữ, các root nghiệp vụ: `DuyetNcc-root keys`, `KeHoachKyKet`, HR/Office/Personal, `Contracts`(đã ẩn `Ct_*`), `HardCopies`, `Forms`, `Reports`, `Catalogs/Master`, **`Workflows` (:1795)**, **`PeWorkflows` (:1798)**} — CHỪA {`System` + 4 leaf quản trị + **`ApprovalWorkflowsV2` (:1801, con System)** + subtree}. Danh sách key CHÍNH XÁC = việc B2-cụm-2 liệt từ `DbInitializer` seed; acceptance = **liệt kê đúng N mục lá còn thấy** (l3-F2).
|
||||
8. Nguồn danh mục: **file đĩa `QUY_TRINH/QT TRINH KY HOP DONG TP-NCC.docx` = ĐÚNG SOL-CCM-SP-002.v01 (mã ở word/header1.xml) NHƯNG bản 6-trang KHÔNG chứa bảng** (lead đo). Nguồn bảng = **7 ảnh anh gửi @S164 (trang 5-9, trọn 5.1 A/B/C + 5.2 CEO)** → transcribe → **[OG-6] anh soát bảng seed trước land** (hoặc anh gửi file 15-trang). "/" trong ô vai = OR-of-N.
|
||||
9. 🆕 **KHÓA BUDGET TẠI FINALIZE (owner @S164, verbatim: "Cái tính năng chuyển CEO và duyệt kết thúc hợp đồng -> Là khóa luôn cái budget rồi, người quyết sẽ là a Chương, Trưởng phòng CCM"):** khi phiếu KHKK được **duyệt-kết-thúc tại CCM (a Chương finalize) HOẶC CEO duyệt final** ⇒ **freeze số** (ApprovedAmount/giá chốt/NS tham chiếu) — phiếu DaDuyet đọc SNAPSHOT, không đọc live. **Mirror nguyên khuôn PE Mig 67** (`AddPeApprovedBudgetSnapshot` S133): snapshot chốt tại finalize choke-point + display-gate `frozen` + 🔴 né **#81-EXT**: grep MỌI Phase-assignment-site (kể cả admin-override + seeder) kẻo bypass hook — bài đã trả giá 1 lần bên PE. Người quyết finalize-hay-CEO = **TP.CCM Phan Văn Chương** (cấp 2 CCM đội hình `QT-DN-V2-001`). ⚠️ 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ề (schema cột snapshot → K2, hook finalize → K3).
|
||||
9. 🆕 **KHÓA BUDGET TẠI FINALIZE (owner @S164; văn SỬA theo B3-A4 — thiết kế THẬT do cụm-1/cụm-3 chốt, cha theo con):** khi phiếu KHKK **finalize tại CCM (a Chương) HOẶC CEO duyệt final** ⇒ số KHÓA. 🔴 **KHÔNG chép khuôn 11-cột Mig 67** — máy freeze per-line ĐÃ CÓ SẴN: `PeReferenceAmount` copy-at-create (`Line.cs:17-20`) + `ApprovedAmount ??=` tại choke-point (`WorkflowService.cs:301-305`, 1-site-DaDuyet verified `:129/:278/:289-292`) ⇒ việc còn lại = **phase-guard line-edit sau DaDuyet (K2) + test-khóa 1-site (K2) + phép đo 2-nhánh TRƯỢT-ĐƯỢC (K8 — sửa nguồn → reload → số KHÔNG đổi, đo cả nhánh CCM-finalize lẫn CEO)** + cột runtime `EndedByLevelFinalize` (K2 item-6 đẻ, K3 tiêu thụ — 3 spec cùng 1 cột ✓). Người quyết = **TP.CCM Phan Văn Chương**. Né #81-EXT: sweep site gán Phase — đã liệt 4 site, GỠ nghi án `WorkflowService.cs:342` (comment đọc-đủ-khối: CỐ Ý không có site gán-qua-biến).
|
||||
|
||||
## ③ Wave K1-K8 (v2 — PRE-gate + acceptance có răng)
|
||||
|
||||
@ -27,7 +27,7 @@ Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA,
|
||||
|
||||
**Cụm 2 (UI):** *(l3-F8: tách phụ thuộc thật — K4a chạy song song cụm 1 được)*
|
||||
- **K4a Menu+grant** (0 phụ thuộc): 49 row menu + grant 3 SITE (`:1780` seed · `SeedKeHoachKyKetAccessAsync:2415` · **`KhkkKeys():2185` — site-3 l2-F6**, comment `:2204` "quên 1 bên = quyền lệch"). **K4b 4 leaf list + Thao tác** (chờ K2 param). **K4c leaf WfView/Create** (chờ K3): WfView mang `?group=` lọc theo workflow Code nhóm (hiện `WorkflowMatrixViewPage:52-71` chỉ lọc type — l2-F3). DoD: 48 leaf render đúng · leaf lọc đúng group **kể cả WfView/Create** · **2 chiều theo bảng kỳ-vọng 13 role** (seeder hiện phủ 7 vai `:2671-2675` — 6 vai còn lại khai kỳ vọng TRƯỚC, l3-F13) · key cũ 0 mồ côi.
|
||||
- **K5 Cây sub-folder**: GĐ2 group-by `approvalGroup` · GĐ3/4 group-by `c.type` (đã có `:240`); thêm tầng `groups` vào `PipelineStage` (mở rộng khuôn — bẫy `content` phải truyền `count` tay `:74-75`). DoD: sub-folder khớp sidebar · **2 file đích danh SHA-identical ×2 app** (`usePipelineStages.ts` + `PipelineTreePanel.tsx` — l3-F19) · build ×2 PASS.
|
||||
- **K5 Cây sub-folder**: GĐ2 group-by `approvalGroup` · GĐ3/4 group-by `c.type` (đã có `:240`); thêm tầng `groups` vào `PipelineStage` (mở rộng khuôn — bẫy `content` phải truyền `count` tay `:74-75`). DoD: sub-folder khớp sidebar · **4 file pipeline SHA-identical ×2 app** (đối chiếu cụm-2 — usePipelineStages · PipelineStageFolders · PipelineTreePanel · trang nhúng; B3 sửa đếm) · build ×2 PASS.
|
||||
- **K6 Admin thu gọn** (độc lập NHƯNG l3-F9: kéo sớm TRƯỚC K3 thì 8 designer chưa tồn tại — nếu kéo sớm, acceptance "đếm 8 designer" dời sang sau K3): QĐ7 tập-key tường minh. DoD: **liệt kê đúng N mục lá còn thấy (đủ tên, dư/thiếu 1 = FAIL)** · fe-user KHÔNG đổi = **`git diff --stat <base>..<head> -- fe-user/src` = 0 file** (KHÔNG đo bundle-hash #69 — l3-F12).
|
||||
|
||||
**Cụm 3 (nối + chạy):**
|
||||
@ -36,7 +36,7 @@ Chuỗi 4 GĐ per-gói-thầu theo SOL-CCM-SP-002: GĐ1 Duyệt NCC (PE = CHA,
|
||||
|
||||
**Mọi wave:** cicd PASS; **byte-verify #77 CHỈ wave có FE-ship** — wave BE-only = smoke API (l3-F17); mig = 3-file rule.
|
||||
|
||||
## ④ [OWNER-GATE] — 4 cũ + 2 mới (nối vào PRE từng wave ở trên)
|
||||
## ④ [OWNER-GATE] — 8 hàng, cập nhật sống (B3-A0b sửa đếm)
|
||||
|
||||
| OG | Câu hỏi | Trạng thái | Chặn wave |
|
||||
|---|---|---|---|
|
||||
|
||||
@ -5,7 +5,7 @@ K1 master-data danh mục (86 row) · K2 phiếu mang hạng-mục + nhóm + fre
|
||||
|
||||
## ② 12 vá (build ĐỌC CẢ nền LẪN vá)
|
||||
|
||||
1. 🔴 **[3-lane hội tụ] Menu key PHẢI VÀO `MenuKeys.All`** — nền khai `ContractCatalog` + 8 `AwV2_KhkkN*` "ngoài All" ⇒ **0 permission row ⇒ sidebar chết** (loop grant `DbInitializer.cs:2058` nguồn = All; khuôn THẬT: 5 leaf catalog hiện hành `MenuKeys.cs:168` + 3 leaf AwV2 `:182` đều TRONG All). Fix: cả 9 key **VÀO All** + KHAI drift canonical (Menu keys 55→64 · Policies 220→256 — khai 2 row STATUS cùng lúc, đừng Goodhart giữ-số-đứng-yên). Acceptance += "login Admin THẤY leaf trong sidebar ×2 app" + 1 test seed-grant.
|
||||
1. 🔴 **[3-lane hội tụ] Menu key PHẢI VÀO `MenuKeys.All`** — nền khai `ContractCatalog` + 8 `AwV2_KhkkN*` "ngoài All" ⇒ **0 permission row ⇒ sidebar chết** (loop grant `DbInitializer.cs:2058` nguồn = All; khuôn THẬT: 5 leaf catalog hiện hành `MenuKeys.cs:168` + 3 leaf AwV2 `:182` đều TRONG All). Fix: cả 9 key **VÀO All** + KHAI drift dạng **DELTA per-wave** (B3-A1 — cấm neo tuyệt-đối vì thứ tự ship: K1 = +1 key/+4 policy · K3 = +8 key/+32 policy; mỗi commit kèm lệnh đếm lại `MenuKeys.All` thực tế + cập nhật 2 row STATUS, đừng Goodhart giữ-số-đứng-yên). Acceptance += "login Admin THẤY leaf trong sidebar ×2 app" + 1 test seed-grant.
|
||||
2. 🔴 **[L1-F5] GỠ phương án (i) tại site `:342`** — nền đọc NGƯỢC comment (`WorkflowService.cs:36-43` mô tả NGUỒN COPY và khẳng định KHKK CỐ Ý không có site gán-qua-BIẾN; `:342` nằm trong `ReturnOrRejectAsync` chỉ nhận TraLai/TuChoi literal — DaDuyet **unreachable** qua đó). GIỮ phương án (ii): test khóa khẳng định điều đó. Cấm "sửa" :342.
|
||||
3. 🔴 **[L2-H2] K3 thêm việc (d): sweep cụm ép-false** — `grep -rn "AllowApproverFinalize|AllowApproverSkipToFinal"` toàn src + fe-*: gỡ đủ **CREATE ép-false server-side** `ApprovalWorkflowV2AdminFeatures.cs:380-381` + **PUT Conflict** `:591-594`/`:605-610` + **FE `levelFlagsPayload`** `ApprovalWorkflowsV2Page.tsx:247-258` (`earlyFinalizeLocked :638`) — không chỉ note `:151-152`. Test mới: "tạo version qua CreateCommand type-10 GIỮ được cờ".
|
||||
4. 🔴 **[L2-H3] `KhkkCreatePage` ×2 app PHẢI SỬA** (mâu thuẫn nền: command +`ApprovalGroup` required nhưng page ghi "KHÔNG-ĐỔI") — body POST thêm `approvalGroup` + picker nhóm. Acceptance += "tạo phiếu nhóm 2 **TỪ UI** ×2 app" (curl-only không đủ).
|
||||
@ -19,7 +19,9 @@ K1 master-data danh mục (86 row) · K2 phiếu mang hạng-mục + nhóm + fre
|
||||
12. **[L1-F3/F4] Trích dẫn `:44-46` ĐỦ + khai supersede**: nguyên văn có "chủ dự án phán 'PHÁ VỠ' @S155" — spec PHẢI khai K3 = **ĐẢO phán quyết cũ theo lời owner @S164**, kèm việc (e): sửa comment `:36-43`/`:44-46` + 2 lệnh tự-kiểm `:292-293` dán PR + cập nhật `KhkkWorkflowPanel.tsx:8` ×2 app + HANDOFF:77. ✅ **[OG-9 CHỐT @S164]** anh xác nhận TƯỜNG MINH: *"đúng, chỗ budget chốt chặn là a Chương… vậy bài toán trần budget xem như đóng"* ⇒ đảo "PHÁ VỠ" @S155 hợp lệ — **K3 (a)-(e) HẾT CHẶN**. Kèm: NĐUQ = human-gate VĨNH VIỄN (không còn wave enforce-máy nào; xóa mọi ý "opt-in sau").
|
||||
|
||||
## ③ Checklist final cụm-1
|
||||
- [ ] K1: 7 mục nền + **"Admin thấy leaf sidebar ×2 app"** + test seed-grant + drift 2 row STATUS khai cùng commit.
|
||||
- [ ] K1: 7 mục nền + **"Admin thấy leaf sidebar ×2 app"** + test seed-grant + drift DELTA khai cùng commit.
|
||||
- [ ] K2 (+B3-A6): nút **"Tạo thêm cho nhóm khác"** (OG-7 UI-hướng-1) CHỦ = K2, site picker/PE-flow `ContractSigningPlanFeatures.cs:1201-1202` + PE-detail — acceptance TỪ UI: PE có phiếu → thấy phiếu + nút phụ, bấm → form preset nhóm khác → 201.
|
||||
- [ ] K3 (+B3-B3 câu-ranh): fe-admin `resolvePath` nới **CHỈ họ `AwV2_KhkkN*`** — **CẤM nới họ `Khkk_*`** (fe-admin thiếu WorkflowMatrixViewPage; phép-âm: grep route Khkk_ fe-admin = 0).
|
||||
- [ ] K2: 8 mục nền + **submit-guard null-CatalogEntryId (test ÂM trên phiếu có line)** + phase-guard line-edit + Σ×3 nhất quán + Mig-71 6 item + 3-file + backfill=1 + **UI tạo-phiếu-nhóm-2 ×2 app** + bảng 18 consumer (17 nền + :712-713).
|
||||
- [ ] K3 (SAU OG-9): 6 mục nền + sweep ép-false ≥4 site + test giữ-cờ-qua-CreateCommand + đo danh tính roster + comment/panel/HANDOFF cập nhật + verify LIVE trước seed.
|
||||
- [ ] Mọi wave: test ≥590+k khai k · cicd PASS · BE-only smoke API (#77 chỉ khi FE-ship).
|
||||
|
||||
@ -25,7 +25,7 @@ K4 sidebar 8 nhóm × 6 leaf (49 row menu mới) · K5 cây sub-folder groups ·
|
||||
- [ ] K4a (ship 1 khối): 49 row menu VÀO All + labelBackfill G1 + route regex resolvePath ×(fe-user; fe-admin GHI RÀNG BUỘC) + 3-site grant (+dòng site-4 đã-soi) + nhãn N2 sửa + comment :1959/:179 vá. Acceptance: Admin + 1 user thường THẤY 8 group sidebar fe-user; 42 leaf BẤM ĐƯỢC (không null-route); drift DELTA khai + đo lại All; SQL JOIN đếm designer đúng N; restart ×2 số row menu/permission KHÔNG đổi (idempotent + revoker-proof).
|
||||
- [ ] K4b: 4 leaf list + Thao tác preset — derive phase+group từ searchParams; `queryKey` += group; acceptance bấm leaf→leaf ĐỔI kết quả không cần F5; URL G1 6 leaf mang `group=1`.
|
||||
- [ ] K4c (sau K3): WfView lọc `Code==='KHKK-N'+n`.
|
||||
- [ ] K5: `groups` mang leaves thật (không đường `content`) + GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` + HIỆN ĐỦ 8 + fallback chưa-phân-nhóm + Σ sub-folder == tổng phiếu; SHA-identical 4 file pipeline ×2 app (lệnh đo từng file); build ×2 PASS.
|
||||
- [ ] K5: `groups` mang leaves thật (không đường `content`) + GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` + HIỆN ĐỦ 8 + fallback chưa-phân-nhóm + Σ sub-folder == tổng phiếu; SHA-identical 4 file pipeline ×2 app (lệnh đo từng file); build ×2 PASS. **+forward-provision (B3-A5, việc cụm-3 vá-4b đẻ cho K5):** builder GĐ3/GĐ4 nối qua **TẬP `lines[].contractId` ∪ `pe.contractId` legacy** — không thì HĐ thứ 2+ (OG-1 UI-1-1, N HĐ/PE) vô hình trên cây.
|
||||
- [ ] K6: blacklist 12-key tường minh + acceptance liệt kê ĐÚNG N mục lá (tên + đếm, dư/thiếu 1 = FAIL) + `git diff --stat -- fe-user/src` = 0 file + comment ràng-buộc-ngược land.
|
||||
- [ ] Test (lead-note bù L3): seed-menu idempotent ×2 · labelBackfill đổi-label-không-nhân-row · route-map FE có leaf nào null-path = FAIL (unit nhỏ nếu khuôn có; không thì acceptance tay + chụp). Baseline ≥590+k khai k.
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
# impl-be K1
|
||||
|
||||
## Tiến độ
|
||||
- [ ] Đọc spec (4 nguồn)
|
||||
|
||||
## Lệch spec (nếu có)
|
||||
_(chưa có)_
|
||||
|
||||
## Kết quả build/test
|
||||
_(chưa chạy)_
|
||||
|
||||
(ĐANG LÀM)
|
||||
@ -24,39 +24,102 @@
|
||||
- **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`).
|
||||
|
||||
### A-3. Chuỗi ApprovalGroup K2→K4b→K5 — (nháp sau cụm-2, chờ cụm-3 vá-5 T2)
|
||||
- K2 CHỦ (cột + backfill=1 + param `group` + DTO `:34` + picker create cụm-1 vá-4) → K4b tiêu thụ (queryKey += group `spec-cum2:10` vá-3 · phase+group từ searchParams vá-5 · preset `?group=` vá-6) → K5 group-by `approvalGroup` + hiện đủ 8 + fallback NULL-group (vá-9). Chuỗi schema→API→list→tree ĐỦ 1 đường tính đến cụm-2. Chờ soi cụm-3 vá-5 "T2-sau-K2" rồi chốt.
|
||||
### A-3. Chuỗi ApprovalGroup K2→K4b→K5→K7 — **VẼ ĐỦ 1 ĐƯỜNG** ✅
|
||||
- K2 CHỦ DUY NHẤT (cột + backfill=1 + DROP-unique-cũ + param `group` + DTO `:34` + picker create cụm-1 vá-4; luật l3-F6 "K3 chỉ đọc" giữ nguyên `spec-tong:13`) → K4b tiêu thụ (queryKey += group `spec-cum2:10` vá-3 · phase+group từ searchParams vá-5 · preset `?group=` vá-6) → K5 group-by `approvalGroup` + hiện đủ 8 + fallback NULL-group (vá-9) → K7 test T2 (gộp 2 line cùng NCC) khai tường minh phụ-thuộc Mig-71-DROP-unique, chạy SAU K2 (`spec-cum3:15` vá-5 — chính cụm-3 tự vá cái sót của nền mình). Verdict: chuỗi schema→API→list→tree→test KHÉP KÍN, không mắt xích nào vô chủ.
|
||||
|
||||
### A-4. Freeze QĐ9 — nháp sau cụm-1 (chờ cụm-3 vá-10)
|
||||
- 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-4. Freeze QĐ9 — cột runtime KHỚP 3 spec ✅ · **tổng hứa snapshot+display-gate mà KHÔNG cụm nào nhận** 🔴
|
||||
- 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 + ghost-window K2→K3) **KHỚP** `spec-cum3:17` vá-7 (B6 đổi neo, thừa nhận "vật K3 MỚI ĐẺ, hiện 0 hit"). ✅ 3 spec cùng 1 cột trên bảng plan KHKK.
|
||||
- 🔴 **Snapshot + display-gate của QĐ9 tổng (`:19` "mirror nguyên khuôn PE Mig 67: snapshot 11 cột + display-gate `frozen`") KHÔNG AI LÀM**: Mig 71 cụm-1 chỉ 6 item — 0 cột snapshot; không vá nào ở 3 cụm nhắc display-gate. Thiết kế THẬT trong cụm = **copy-at-create + immutability**: line đã mang bản chép (`PeReferenceAmount` `Line.cs:6,:16-20` + `TenHangMuc` + `ApprovedAmount` per-line) + phase-guard line-edit kéo về K2 (cụm-1 vá-6) + test-khóa 1-site-DaDuyet (cụm-1 vá-2 — verify đĩa: `ContractSigningPlanWorkflowService.cs:37-38` khai "ĐÚNG MỘT nhánh set DaDuyet", `:129/:134` ReturnOrReject chỉ TraLai/TuChoi, `:278` site duy nhất, `:289-292` helper choke-point + lệnh grep tự-kiểm) + **răng đo = cụm-3 vá-10** (`spec-cum3:22` sửa NGUỒN sau finalize → reload → số KHÔNG đổi, đo CẢ 2 nhánh CCM-finalize VÀ lên-CEO — phép đo TRƯỢT ĐƯỢC ✓ đạt sàn-sự-thật).
|
||||
- **Phán:** thiết kế cụm HỢP LÝ HƠN khuôn Mig 67 (KHKK line vốn denormalized-at-create, PE thì display JOIN live nên mới cần snapshot) — nhưng tổng QĐ9 đang là VĂN STALE hứa vật không ai giao. Fix: sửa đoạn QĐ9 tổng thành "freeze KHKK = copy-at-create + phase-guard + test-khóa 1-site + phép đo 2-nhánh vá-10; KHÔNG mig snapshot mới; nếu vá-10 đo FAIL (lộ chỗ display đọc live) → lúc đó mới mở mig snapshot bổ sung". Không sửa thì builder K2 sẽ đi tìm "11 cột snapshot" không tồn tại trong cụm-1. Verdict: **MÂU THUẪN #2 — phải vá TỔNG theo cụm trước build.**
|
||||
- 🪤 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` = `ContractSigningPlanWorkflowService.cs` (`ReturnOrRejectAsync`, CẤM sửa — DaDuyet unreachable). Builder đọc lướt sẽ sửa nhầm site. Spec build phải ghi TÊN FILE cạnh mọi ":342".
|
||||
|
||||
### A-5. Cây GĐ3: cụm-3 ĐẺ VIỆC cho K5 mà spec cụm-2 KHÔNG BIẾT 🔴
|
||||
- `spec-cum3:14` vá-4(b) gắn nhãn tường minh "**K5-liên-đới**: builder GĐ3/GĐ4 nối qua TẬP `lines[].contractId` của các phiếu KHKK thuộc gói (∪ `pe.contractId` legacy)" — nhưng `spec-cum2:28` checklist K5 chỉ có "GĐ2 by `approvalGroup` + GĐ3/4 by `c.type` (đã có `:240`)", **0 chữ về `lines[].contractId`**. Cây hiện đi `pe.contractId` ĐƠN (`usePipelineStages.ts:214-218`, khớp giới-hạn HĐ[0] đã khai S162 `CreateContractFromEvaluationFeatures.cs:145`).
|
||||
- Hậu quả nếu không vá: K5 (land trước) build đúng spec cụm-2 → K7 bridge ghi `Line.ContractId` per-line → HĐ thứ 2+ **vô hình trên cây** (vá-4(a) `pe.ContractId ??=` chỉ cứu HĐ đầu); muốn sửa phải chạm lại 2 file pipeline SAU K5 → re-run SHA-identical + build ×2 ngoài kế hoạch.
|
||||
- **Fix 1 dòng vào cụm-2 K5:** "GĐ3/4 nguồn HĐ = ∪ `lines[].contractId` ∪ `pe.contractId` legacy (forward-provision — trước K7 tập lines rỗng, cây không đổi hành vi)" + acceptance "phiếu 2 line 2 HĐ → cây hiện 2" (chạy được từ K7). Verdict: **MÂU THUẪN #3 — phải vá cụm-2 trước build K5.**
|
||||
|
||||
### 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.
|
||||
- ⚠️ 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)"* — soi CẢ 43 vá 3 cụm: 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; cụm-3 = K7/K8 không đụng). Acceptance cụm-1 "tạo phiếu nhóm 2 TỪ UI ×2 app" đo OUTCOME nhưng không ép UX hướng-1 mà owner đã ratify verbatim. **Verdict: LỖ CHỦ-VIỆC (mâu thuẫn hứa⟂giao) — fix 1 dòng gán về K2** (cùng site picker `:1201-1202`: chọn PE đã-có-phiếu → hiện danh sách phiếu hiện có + nút "Tạo thêm cho nhóm khác" thay vì message chặn); không nên hạ lời OG-7 vì đó là lời chốt của owner.
|
||||
|
||||
## B. Vá-đè-vá (vá cụm sau có phá vá cụm trước?)
|
||||
(ĐANG LÀM — cặp nghi tính đến cụm-2; chờ cụm-3 để chốt 43 vá)
|
||||
## B. Vá-đè-vá (vá cụm sau có phá vá cụm trước?) — soi 43 vá (12+15+16), 7 cặp nghi
|
||||
|
||||
| # | Cặp | Verdict nháp |
|
||||
| # | Cặp | Verdict |
|
||||
|---|---|---|
|
||||
| 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" |
|
||||
| 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ả; đúng điều kiện "chỉ cần picker vá-4 cụm-1" |
|
||||
| B-3 | tổng K3 "mở resolvePath **fe-admin** `Layout.tsx:166-172`" ⟂ 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 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` — L1-BÁC-2). **Cần 1 câu ranh:** "fe-admin resolvePath: THÊM pattern `AwV2_KhkkN*` — CẤ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 về máy — 2 file 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 — verify đĩa `:129/:134/:278`); bẫy-đọc-lướt, spec build ghi TÊN FILE cạnh mọi ":342" |
|
||||
| B-5 | cụm-3 vá-4(b) (K5 nối `lines[].contractId`) ⟂ cụm-2 K5 checklist | 🔴 KHÔNG phá vá cũ nhưng ĐẺ VIỆC vào wave cụm-2 mà spec cụm-2 không chứa = A-5 mâu-thuẫn #3 — vá spec cụm-2 trước build K5 |
|
||||
| B-6 | cụm-3 vá-7 (B6 đổi neo `EndedByLevelFinalize` "vật K3 mới đẻ") ⟂ cụm-1 vá-7 (cột vào Mig 71/K2, K3 wire) | ✅ SẠCH — nhất quán: cột đẻ ở K2-mig (nằm im, ghost-window đã khai), K3 wire, K7-B6 neo tùy nhánh; 3 spec cùng 1 cột (A-4 ý 1) |
|
||||
| B-7 | cụm-3 vá-12 (TRƯỚC K2 rào per-PE ⇒ phiếu ZZTEST khóa TOÀN BỘ PE thật) ⟂ cụm-1 K2 đổi rào | ✅ SẠCH — cụm-3 nhận thức đúng thứ tự (K8 CUỐI sau mọi wave + nghiêng phương án (b) PE-ZZTEST-riêng); không đè, chỉ ràng thêm điều kiện chạy-sau |
|
||||
|
||||
**Verdict B: 0 vá cụm sau LÀM VÔ HIỆU vá cụm trước.** 7 cặp nghi xét: 5 sạch · 2 cần câu-ranh/vá-spec (B-3 câu ranh 2-họ-key · B-5 = A-5).
|
||||
|
||||
## C. Build-order cuối + gate
|
||||
(ĐANG LÀM)
|
||||
|
||||
## D. Rủi ro còn hở
|
||||
(ĐANG LÀM)
|
||||
**Thứ tự chốt: K1 → K2 → K3 → K4a → K4b → K5 → K4c → K6 → K7 → K8** (10 đơn vị build; khớp đề xuất lead, KHÔNG đổi trình tự — chỉ siết gate). Lý do giữ K4a SAU K3 dù "0 phụ thuộc code" (l3-F8 cho song song): tránh cửa-sổ-prod 8-leaf-chưa-lọc (trước K2 API không có param `group` ⇒ 42 leaf hiện CÙNG nội dung) + nhãn 8 group cần anh gật (cụm-2 vá-7) — kéo song song chỉ khi owner chấp nhận 2 điều đó tường minh.
|
||||
|
||||
| Wave | PRE-gate owner | Mig | Restart BE | Deploy | Test-k |
|
||||
|---|---|---|---|---|---|
|
||||
| K1 | **OG-6 ✅ (soát 86 dòng — chặn SEED, code build trước được) + OG-5 hỏi-khi-gặp** | Mig 70 (3-file) | ✅ | BE + FE ×2 (leaf catalog) → #77 | +k khai (seed-idempotent, CRUD) |
|
||||
| K2 | 0 (OG-1/7 ✅ rồi) — PRE-spec-fix A-1 (lead) | Mig 71 (6 item, DROP unique cũ, backfill=1) | ✅ | BE + FE ×2 (picker+create) → #77 | +k (Σ trước==sau · 409-có-line · UI-nhóm-2 · 18-consumer) |
|
||||
| K3 | OG-2 ✅ + **verify đội hình LIVE trước seed** + OG-9 ✅ | 0-mig (cột đã forward-provision K2) | ✅ (seed 8 WF + sweep ép-false) | BE + fe-admin (designer + resolvePath AwV2) → #77 | +k (8 WF · pin-sai-nhóm 409 · giữ-cờ-qua-Create · danh-tính roster · finalize 2-nhánh) |
|
||||
| K4a | **8 nhãn đính file OG-6 — anh gật** | 0-mig | ✅ (seed 49 row + 3-site) | BE + fe-user (route regex) → #77 | +k (idempotent ×2 restart · SQL JOIN designer · 42 leaf bấm được) |
|
||||
| K4b | 0 (sau K2) | 0 | — | FE ×2 → #77 | acceptance leaf→leaf đổi kết quả không F5 |
|
||||
| K5 | 0 (sau K2) — PRE-spec-fix A-5 (lead) | 0 | — | FE ×2 → #77 | SHA-identical 4 file ×2 app + Σ sub-folder == tổng |
|
||||
| K4c | 0 (sau K3) | 0 | — | fe-user → #77 | WfView lọc `Code==='KHKK-N'+n` |
|
||||
| K6 | 0 (sau K3 — acceptance đếm 8 designer) | 0 | — | fe-admin → #77; `git diff --stat -- fe-user/src` = 0 | liệt kê ĐÚNG N mục lá (dư/thiếu 1 = FAIL) |
|
||||
| K7 | câu III không chặn code (default dialog); acceptance "ai bấm" treo [CHỜ-ANH] | 0 | ✅ (grant `Contracts.Create`) | BE + FE ×2 → #77 | 8+2 authz 2-chiều + idempotency-double-click + cây 2-HĐ |
|
||||
| K8 | **câu V (nghiêng (b) PE-ZZTEST-riêng) + câu III + B0-form 14/14 fail-closed + dặn team notification** | 0 | — | 0 code | 17 bước chụp + QĐ9 đo 2 nhánh + rollback theo ID |
|
||||
|
||||
**3 spec-fix bắt buộc TRƯỚC wave tương ứng (lead tự làm, không cần owner):** ① A-1 cụm-1 vá-1 → DELTA per-wave (trước K1-commit-STATUS) · ② A-4 tổng QĐ9 → khai thiết kế copy-at-create thay snapshot-hứa (trước K2) · ③ A-5 cụm-2 K5 +1 việc `lines[].contractId` (trước K5). **5 vá 1-dòng cùng đợt:** A-0a sweep "opt-in sau" · A-0b đếm header tổng · A-x 16→18 consumer · A-6 nút-phụ gán K2 · SHA 2-file→4-file thống nhất (tổng `:30` theo cụm-2 `:28`).
|
||||
|
||||
## D. Rủi ro còn hở (top-5 sau 43 vá — mỗi cái 1 guard)
|
||||
|
||||
1. **QĐ9 không có snapshot dự phòng** — nếu phép đo 2-nhánh (cụm-3 vá-10) FAIL vì lộ chỗ display đọc live (kiểu PE pre-Mig-67) → phát sinh mig ngoài kế hoạch giữa chuỗi wave. *Guard:* chạy phép đo 2-nhánh trên **Dev NGAY SAU K3 land** (integration test hoặc tay), đừng để nó xuất hiện lần đầu ở K8-prod.
|
||||
2. **Ghost-window K2→K3 + seed cờ sớm = config-lie #78** — `AllowApproverFinalize=true` cấp CCM-Chương seed TRƯỚC khi nhánh (a) land thì designer nói dối. *Guard:* K3 checklist đặt "seed cờ" là mục CUỐI + gate `grep AllowApproverFinalize=true` 0-hit trước mục đó (đúng thứ tự OG-3 tổng `:46` đã ghi — giữ nguyên, đừng để builder đảo).
|
||||
3. **fe-admin resolvePath 2-họ-key, 2 wave chạm cùng hàm** (B-3) — builder K3 nới luôn `Khkk_*` → 48 leaf hiện trên fe-admin thiếu `WorkflowMatrixViewPage` → leaf chết. *Guard:* acceptance K3 thêm phép-âm "fe-admin sidebar đếm group `Khkk_*` = 0".
|
||||
4. **Bridge authz chỉ gate FE = giả-an-toàn** — cụm-3 vá-1 nói "gate nút = HỘI 2 policy" + test 403, nhưng không câu nào bắt ENDPOINT bridge mang policy server-side; nếu builder gate FE-only, test 403 viết theo FE cũng giả-pass. *Guard:* 1 câu spec K7 "endpoint bridge mang CẢ 2 `[Authorize]` attribute (stack = AND: `KeHoachKyKet.Read` + `Contracts.Create`)" + test = **curl trần bỏ FE**.
|
||||
5. **OG-6 transcribe gõ-tay-từ-ảnh, 4 ô ⚠️** — seed sai tên/vai → labelBackfill churn + khối ký GĐ4 in sai vai (TEXT không ràng máy — limitation QĐ4 đã khai). *Guard:* 4 ô ⚠️ phải được anh chốt TƯỜNG MINH trong lượt soát OG-6 (không để builder tự đoán); acceptance K1 "lệch giải trình từng dòng" giữ nguyên có răng.
|
||||
|
||||
*(Ngoài top-5, đã có guard sẵn trong spec: B0-form fail-closed vá-9 · rollback theo ID vá-11/13 · phiếu-ZZTEST-khóa-PE-thật vá-12 nghiêng phương án (b).)*
|
||||
|
||||
## E. GO/NO-GO per wave
|
||||
(ĐANG LÀM)
|
||||
|
||||
## F. Digest trình owner
|
||||
(ĐANG LÀM)
|
||||
| Wave | Verdict | Điều kiện |
|
||||
|---|---|---|
|
||||
| K1 | **GO (code) + GATE seed** | Seed land CHỈ SAU OG-6 ✅ (86 dòng + 4 ô ⚠️ anh chốt); code/mig/test build trước được |
|
||||
| K2 | **GO** | OG-1/OG-7 ✅ rồi; PRE = spec-fix A-1 (1 dòng, lead) |
|
||||
| K3 | **GO** | OG-2/OG-9 ✅; verify đội hình LIVE + sweep ép-false ≥4 site + seed-cờ mục CUỐI (D-2) |
|
||||
| K4a | **GO + GATE nhãn** | 8 nhãn (kèm N2 sửa "phá dỡ") anh gật trong file OG-6 trước seed menu |
|
||||
| K4b | **GO** | Sau K2 |
|
||||
| K5 | **GO** | Sau K2; PRE = spec-fix A-5 (1 dòng, lead) |
|
||||
| K4c | **GO** | Sau K3 |
|
||||
| K6 | **GO** | Sau K3 (acceptance đếm 8 designer) |
|
||||
| K7 | **GO** | Sau K2+K3; câu III chỉ treo acceptance "ai bấm" [CHỜ-ANH], không chặn code (default dialog người-có-quyền); server-side hội-2-khóa theo D-4 |
|
||||
| K8 | **NO-GO tới khi đủ 4 điều kiện** | (1) mọi wave land · (2) câu V chốt — nghiêng (b) PE-ZZTEST-riêng · (3) câu III chốt · (4) B0-form 14/14 điền đủ (fail-closed) — NO-GO này là ĐÚNG THIẾT KẾ (wave cuối), không phải lỗi spec |
|
||||
|
||||
**Tổng: GO = 9/10 · NO-GO = 1/10 (K8, by-design).** Toàn chuỗi GO cho B4 với điều kiện 3 spec-fix nặng (A-1/A-4/A-5) + 5 vá 1-dòng land TRƯỚC wave tương ứng — tất cả lead tự làm được, owner-gate còn lại: OG-6 (K1-seed + K4a-nhãn) · câu III/V (K7-acceptance/K8).
|
||||
|
||||
## F. Digest trình owner (≤15 dòng)
|
||||
|
||||
1. Em rà chéo 4 spec final (tổng v2 + cụm-1 12 vá + cụm-2 15 vá + cụm-3 16 vá = 43 vá): **GO 9/10 wave — chỉ K8 dry-run chờ anh** (câu V + câu III + form 14 người), đúng thiết kế wave cuối.
|
||||
2. Thứ tự build chốt: **K1→K2→K3→K4a→K4b→K5→K4c→K6→K7→K8** (bảng gate/mig/deploy ở mục C).
|
||||
3. Phát hiện **8 mâu-thuẫn liên-spec — 0 cái chạm máy-đã-chốt, toàn vá được bằng sửa chữ spec**: 3 nặng phải vá trước build + 5 nhẹ 1-dòng.
|
||||
4. Nặng ①: cụm-1 còn neo số tuyệt đối (55→64) trong khi cụm-2 cấm đúng kiểu neo đó — đổi cụm-1 sang khai DELTA per-wave.
|
||||
5. Nặng ②: tổng QĐ9 hứa "snapshot 11 cột + display-gate mirror PE Mig 67" nhưng KHÔNG cụm nào nhận việc này — thiết kế thật trong cụm (copy-at-create + khóa sửa + phép đo 2 nhánh trượt-được) HỢP LÝ HƠN, em đề nghị sửa văn tổng theo cụm.
|
||||
6. Nặng ③: cụm-3 giao thêm việc cho cây K5 (nối HĐ qua `lines[].contractId`) mà spec cụm-2 không biết — thêm 1 dòng vào K5 kẻo HĐ thứ 2 trở đi vô hình trên cây.
|
||||
7. Vá-đè-vá: soi 7 cặp nghi trên 43 vá — **0 vá cụm sau phá vá cụm trước**; 2 chỗ cần câu ranh giới (regex fe-admin 2 họ key · ":342" trùng số dòng ở 2 file khác nhau).
|
||||
8. OG còn treo: **OG-6** (anh soát 86 dòng danh mục + 8 nhãn menu — chặn seed K1 + K4a) · OG-5 (hỏi khi gặp) · câu III "ai bấm bridge" · câu V "PE test riêng hay PE thật".
|
||||
9. Rủi ro #1: nếu phép đo freeze 2-nhánh FAIL (lộ chỗ đọc live) → phát sinh mig ngoài kế hoạch — em đề nghị chạy phép đo này trên Dev ngay sau K3, không đợi K8.
|
||||
10. Rủi ro #2: cầu KHKK→HĐ phải khóa quyền ở SERVER (2 tầng policy), không chỉ ẩn nút FE — test bằng curl trần.
|
||||
11. Rủi ro #3: quyền `Contracts.Create` hiện chưa cấp cho vai nào ngoài Admin — K7 sẽ cấp cho Drafter + Procurement (default, anh đổi được ở câu III).
|
||||
12. Test: baseline 590 (STATUS:472) — mỗi wave khai +k, không wave nào được giảm.
|
||||
|
||||
## END
|
||||
|
||||
END sub-review-fable-b3 — TOTAL: 8 mâu-thuẫn (3 nặng A-1/A-4/A-5 + 5 nhẹ-1-dòng) · 0 vá-đè-vá (7 cặp xét, 2 cần câu-ranh) · GO=9/NO-GO=1
|
||||
|
||||
Reference in New Issue
Block a user