# run — S157 · "KẾ HOẠCH KÝ KẾT HỢP ĐỒNG" — khúc CÒN THIẾU giữa Duyệt NCC và HĐ NTP/NCC

> **run-id:** `2026-07-28-S157-ke-hoach-ky-ket-hd` · mở 2026-07-28 (phiên-LOGIC L7, window 4)
> **Lệnh anh (verbatim):** *"Nhớ cái quy trình còn thiếu hôm qua ko? Cái spec cũ còn hôm qua. `/fable-real` Invest điều tra quy trình chỗ còn thiếu. Quy trình còn thiếu giữa Duyệt NCC - Kế hoạch ký kết Hợp đồng (Còn thiếu) - Hợp đồng NTP/NCC. Sau đó cho `/fable-clone` review lại thêm 1 lần cái spec đó → Ra cái spec mới đầy đủ chi tiết nhất, bao gồm cách làm. Chia wave rõ ràng. Cho tao cái plan đó và Wave chạy thế nào luôn nhé."*
> **Anh chỉ nguồn:** `D:\Dropbox\CONG_VIEC\SOLUTION\` có 2 folder **FORM** (8 file) + **QUY_TRINH** (1 file).
> **Anh chốt cùng ngày:** *"chỗ hợp đồng cứ từ từ nhé"* ⇒ lỗ hổng an ninh HĐ **KHÔNG** nằm trong run này.

---

## 0. Nguồn — 2 tài liệu gốc, LẦN ĐẦU đưa vào vòng điều tra

Wave S156 hôm qua **chỉ có PDF sơ đồ**. Run này bổ sung **2 tài liệu ISO gốc của công ty** — đây là
delta nguồn quan trọng nhất so với hôm qua.

| Nguồn | Trích ra | Vai trò |
|---|---|---|
| `QUY_TRINH\QT TRINH KY HOP DONG TP-NCC.docx` | `src-QT-TRINH-KY-HD.txt` (14.425 B · 38 para · 2 bảng) | **Quy trình ISO 9 bước** trình ký HĐ TP/NCC/Tổ đội — chuẩn đang áp dụng |
| `FORM\SOL-CCM-FO-002.01.v01 Bang kiem tra hop dong.docx` | `src-FO-002.01-bang-kiem-tra-HD.txt` (21.287 B · bảng 40r×13c) | **Tờ "Chấp thuận Hợp đồng"** — vật mang chữ ký qua từng trạm (bản giấy của workflow) |
| 7 form còn lại trong `FORM\` | *(chưa trích — 6 mẫu HĐ + RG-001 mã HĐ)* | Đã có bản parse ở `docs/forms-spec.md` (Phase 0) |
| PDF sơ đồ 21 bước | `runs/2026-07-27-S156-bch-post-ceo-flow/run.md` | Nguồn hôm qua, GIỮ NGUYÊN |

---

## 1. 🔴 GROUNDING LEAD ĐO TRƯỚC KHI PHÓNG — phát hiện lật khung vấn đề

### 1.1 Quy trình ISO 9 bước (trích `src-QT-TRINH-KY-HD.txt` bảng 2)

| # | Bước ISO | Trách nhiệm | SLA |
|---|---|---|---|
| 1 | Lựa chọn NTP/NCC | PB/BCH CT | — *(trỏ `SOL-PRO-SP-001` Quy trình Cung ứng)* |
| 2 | Soạn thảo hợp đồng | QS/NV.PB · TBP/TPB | 07 ngày |
| 3 | Góp ý nội dung | PD/PM/PRO/CCM/FIN/ACT | 07 ngày |
| 4 | Đàm phán, thương thảo | QS/NV.PB · TBP/TPB · PD/PM | 07 ngày |
| 5 | In hợp đồng *(NTP in 2 mặt, ký, đóng dấu → PD/PM/TPB ký nháy + ký cover FO-002.01)* | QS/NV.PB | 07 ngày |
| 6 | Kiểm tra *(CCM ký nháy từng HĐ + ký cover)* | CCM | 03 ngày |
| 7 | Duyệt *(xem xét + ký duyệt HĐ)* | BOD / NĐUQ | 01 ngày |
| 8 | Đóng dấu hợp đồng | HRA / ISO | — |
| 9 | Phát hành + Lưu trữ *(scan gửi CCM · gửi bản gốc NTP · lưu Server Filing System)* | PB/BCH CT · CCM | — |

### 1.2 🔴 PHÁT HIỆN A — 9 bước ISO ↔ 9 giá trị `ContractPhase` 1-9 KHỚP 1:1 ĐÚNG THỨ TỰ

Lead tự đọc `src/Backend/SolutionErp.Domain/Contracts/ContractPhase.cs` (28 dòng, đọc TRỌN):

| # ISO | Bước ISO | `ContractPhase` | Trạng thái enum |
|---|---|---|---|
| 1 | Lựa chọn NTP/NCC | `DangChon = 1` | `[LEGACY]` |
| 2 | Soạn thảo HĐ | `DangSoanThao = 2` | 🟢 **SỐNG** (Nháp) |
| 3 | Góp ý nội dung | `DangGopY = 3` | `[LEGACY]` |
| 4 | Đàm phán | `DangDamPhan = 4` | `[LEGACY]` |
| 5 | In hợp đồng / ký nháy | `DangInKy = 5` | `[LEGACY]` |
| 6 | Kiểm tra CCM | `DangKiemTraCCM = 6` | `[LEGACY]` |
| 7 | Duyệt BOD/NĐUQ | `DangTrinhKy = 7` | `[LEGACY]` |
| 8 | Đóng dấu | `DangDongDau = 8` | `[LEGACY]` |
| 9 | Phát hành + lưu trữ | `DaPhatHanh = 9` | 🟢 **SỐNG** (terminal) |

⇒ **7 phase `[LEGACY]` KHÔNG phải rác kiến trúc — chúng là quy trình ISO được mã-hoá CỨNG.**
Post-Mig 21 / Session 17 thay bằng `ChoDuyet = 10` + con-trỏ `CurrentWorkflowStepIndex` chạy trên
**workflow V2 admin-config** — tức chuyển từ *mã-hoá cứng 9 bước* sang *cấu-hình-được N bước*.

🔑 **Hệ quả lên verdict hôm qua:** verdict `LAI` (b.13→21 tái dùng V2) **KHÔNG đổi**, nhưng **lý do
mạnh hơn hẳn**: V2 sinh ra CHÍNH ĐỂ biểu diễn quy trình ISO này dưới dạng cấu hình. Hôm qua invest chỉ
lập luận được *"phase bị gỡ = trạm của b.13→21"*; nay có **tài liệu ISO gốc** chứng minh **vì sao** 9 trạm
đó tồn tại. Đây là **chứng cứ mới**, không phải diễn giải lại.

### 1.3 🔴 PHÁT HIỆN B — khoảng trống nằm ĐÚNG giữa ISO-1 và ISO-2, và ISO doc KHÔNG có nó

Quy trình ISO đi thẳng **bước 1 (Lựa chọn NTP/NCC) → bước 2 (Soạn thảo HĐ)**, KHÔNG có bước trung gian.
Sơ đồ PDF (bản `14/2026`, mới hơn) chèn **b.7→12** đúng vào chỗ đó:

```
ISO-1  Lựa chọn NTP/NCC   ≡  PE "Duyệt NCC"  (PE.DaDuyet=7, PDF b.1→6)     🟢 ĐÃ CÓ
   └─────────────  ⬛ KHOẢNG TRỐNG = "KẾ HOẠCH KÝ KẾT HỢP ĐỒNG"  ⬛  ─────────────┐
                   PDF b.7→12: mail giao BCH · duyệt mẫu+shopdrawing với TVGS ·   │ 🔴 THIẾU
                   tổng hợp hồ sơ + so sánh giá → đề xuất GIÁ TRỊ ký HĐ ·          │  CẢ Ở
                   PMH kiểm tra → CCM kiểm tra → CEO ký / CCM đóng dấu approval    │  DOC LẪN
   ┌─────────────────────────────────────────────────────────────────────────────┘  CODE
ISO-2  Soạn thảo HĐ  ≡  Contract `DangSoanThao=2`  (PDF b.13)               🟢 ĐÃ CÓ
```

⇒ **"Còn thiếu" theo nghĩa MẠNH: thiếu ở CẢ HAI tầng** — không có trong quy trình ISO đang ban hành,
và không có trong code. Không phải "code chưa làm theo doc"; là **doc cũng chưa có**.
🔴 ⇒ spec ra từ run này **vừa là spec phần mềm, vừa là đề xuất bổ sung quy trình ISO** cho anh duyệt.

### 1.4 Đối chiếu SLA — 2 nguồn, 2 độ mịn (cần hoà giải, KHÔNG tự chọn)

| Nguồn | SLA ghi | Ghi chú |
|---|---|---|
| ISO doc | 07 · 07 · 07 · 07 · 03 · 01 ngày (bước 2→7) | tổng ≈ **32 ngày** cho khúc soạn→duyệt |
| PDF sơ đồ | `10-14 ngày` (b.1→4) · `3 ngày` (BCH gửi full info) · `7-10 ngày` (b.13→18) | mịn hơn ở khúc BCH |
| Code hiện tại | `AddDays(7)` **hardcode** | lỗ L3 hôm qua — thụt lùi so V1, lỗ toàn-V2 (cả PE) |

### 1.5 Tờ `FO-002.01` = bản giấy của workflow duyệt

Bảng 40r×13c, các khối ký theo phòng: **PHÒNG BAN/DỰ ÁN (ĐỀ XUẤT)** → **PHÒNG CUNG ỨNG** (điều khoản HĐ ·
điều khoản thanh toán · rủi ro pháp lý) → … mỗi khối có `Họ tên` + `Ngày` + cột `Ý KIẾN`.
⇒ Ánh xạ thẳng sang `ApprovalWorkflowStep` (Phòng) × `ApprovalWorkflowLevel` (Cấp) + `LevelOpinions`
đã có sẵn ở V2 — **cần invest xác nhận độ khớp, đừng để lead tự kết luận.**

### 1.6 Nợ mang sang từ S156 — invest MỚI phải hấp thụ, không lặp lại

6 việc sửa bản invest cũ (`runs/2026-07-27-S156-bch-post-ceo-flow/review-synthesis.md` §G):
1. Claim SAI: *"hardcoded policy fallback"* → thật là **`ConflictException` `:115-116`** ⇒ HĐ sinh từ phiếu
   **KẸT CỨNG `ChoDuyet`**, hỏng CỨNG. **Gốc lỗi: invest tin skill-doc hơn ĐĨA.**
2. Siết biên: vùng phase-đã-gỡ là **b.14→19**, KHÔNG phải b.13→21.
3. Thiếu Q vai người TRÌNH — `ContractWorkflowService.cs:70-79` đòi `Drafter|DeptManager`, PMH mang
   `Procurement` ⇒ **403** ở b.13/b.17.
4. Cảnh báo lỗ hổng reject = **việc RIÊNG**, anh đã chốt *"cứ từ từ"* ⇒ **NGOÀI scope run này**.
5. Q5 thiếu phương án **(d) `skipToFinal` + `AllowApproverSkipToFinal :322`** — ĐÃ WIRE, 0 code BE.
6. **Q2 phải viết lại theo 2 TRỤC + 3 số đo cùng đơn vị** (số bảng mới · LOC BE · LOC FE) **lấy từ twin
   thật trong repo**, không ước cảm tính.

---

## 1.7 🔴 OWNER CHỐT TRONG CỬA (2026-07-28, anh trả lời trực tiếp báo-cáo grounding)

Lead trình 2 điểm ở §1.5 và §1.4; anh chốt **cả hai**. Đây là **quyết định owner**, không phải suy luận lead.

### (O-1) Cấu trúc trình ký — **GIỐNG**, khác duy nhất ở NỘI DUNG

> **anh (verbatim):** *"Đúng chính xác, cấu trúc trình ký giống, chỉ khác nội dụng thôi."*

⇒ Trả lời cho §1.5 (form `FO-002.01` ↔ `ApprovalWorkflowStep` × `Level` × `LevelOpinions`).
🔑 **Hệ quả kiến-trúc — MẠNH, chốt trước cả khi invest trả bài:**
- Phiếu "Kế hoạch ký kết Hợp đồng" **TÁI DÙNG khung duyệt V2 đang chạy** (Quy trình > Bước=Phòng > Cấp=NV
  cụ thể, OR-of-N cùng cấp, `LevelOpinions` UPSERT khi duyệt) — **giống hệt PE và Contract V2 đang làm**.
- Cái **DỰNG MỚI = NỘI DUNG phiếu** (các trường của "kế hoạch ký kết": căn cứ b.8-9 + so sánh giá +
  giá trị đề xuất), **KHÔNG phải cơ-chế duyệt**.
- 🔻 **Q2 hôm qua (kiến trúc khúc 8-12, reviewer chấm `THIEU-PHUONG-AN` + thiên-vị) gần như TỰ ĐÓNG:**
  tranh luận 3 phương án hôm qua xoay quanh *"có dựng cơ-chế duyệt riêng không"*. Anh vừa trả lời:
  **không dựng cơ-chế mới, dùng lại khung**. ⇒ option-space thu về **chỉ còn trục NỘI DUNG**
  (phiếu riêng ⟂ mở rộng PE ⟂ entity con của Contract). **Invest vẫn phải trình 3 số đo cho trục còn lại**,
  nhưng KHÔNG cần bàn lại trục cơ-chế.
- Đây cũng là **đối chứng ngoài-code cho verdict `LAI`**: khung V2 gánh được vì bản GIẤY vốn cùng hình dạng.

### (O-2) SLA — **THAM KHẢO thôi**, không phải ràng buộc

> **anh (verbatim):** *"Cái này để tham khảo thôi, ko vấn đề j, đa số là trễ."*

⇒ Trả lời cho §1.4 (ISO 07/07/07/07/03/01 vs PDF 3 + 7-10 vs code hardcode `AddDays(7)`).
🔑 **Hệ quả:**
- **KHÔNG dựng SLA-engine**, KHÔNG auto-approve-on-timeout, KHÔNG cảnh báo chặn. SLA = **hiển thị tham khảo**.
- Không cần hoà giải 2 nguồn số ⇒ **gỡ một câu hỏi khỏi bộ câu hỏi trình anh**.
- 🔸 Lỗ **L3** (`AddDays(7)` hardcode, hôm qua xếp "thụt lùi so V1, lỗ toàn-V2") **TỤT ƯU TIÊN** —
  vẫn là số hiển thị sai, nhưng **không gây hại vận-hành** vì không ai enforce theo nó. Ghi nhận, đừng
  nhét vào wave thi công của run này.
- 🔴 **Đừng đọc quá lời anh:** anh nói SLA *không quan trọng*, KHÔNG nói *bỏ hiển thị deadline*. Giữ hiển thị.

## 2. taskList snapshot

### Wave 1 — `/fable-real invest` (SINGLE deep-pass, engine-đắt Fable, KHÔNG fan-out)

```
[1] investigator-codebase (Fable, effort max)
    → §A  quy trình chi tiết khúc CÒN THIẾU (đối chiếu 3 nguồn: ISO doc · PDF · FO-002.01)
    → §B  cách wire vào codebase (entity · migration · CQRS · controller · FE 2-app · menu/permission)
    → §C  chia WAVE thi công + checklist ĐO ĐƯỢC từng wave
    → §D  6 việc sửa của review cũ đã hấp thụ thế nào (từng cái, đối chiếu ĐĨA không tin doc)
    propose-only; spec-file do LEAD ghi sau khi verify (H21 ① honest-note c)
```

### Wave 2 — `/fable-clone reviewer` ensemble 4 lane (đóng gói C2: ≤3 file/lane · ép khung rỗng lượt 1-2 · trần 25)

**Label C3 4-thành-phần — NEO TẠI ĐÂY** (panel ephemeral, không neo thì không tái lập/audit được):

| Label (neo C3) | Lăng kính | File được đọc (≤3) |
|---|---|---|
| `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**

---

## 3. Stages

- [x] S0 — lead trích 2 tài liệu gốc (`src-QT-TRINH-KY-HD.txt` 14.425 B · `src-FO-002.01-*.txt` 21.287 B)
- [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)
- [x] S2 — scaffold run-folder + `run.md` (file này)
- [x] S3 — `/fable-real investigator-codebase` deep-pass — **3 lượt, 2 sự-cố, PARTIAL-HONEST**:
      · lượt 1 **`skeleton-ruột-rỗng`**: 202K tok / 35 tool-use, đĩa chỉ **1.661 B khung rỗng 4 mục `[PENDING]`**
        (return garble `#53` = mẩu "Đọc tiếp 3 file S156"). **Ghi-đĩa-trong-lúc-làm = CẦN KHÔNG ĐỦ** — phải
        verify RUỘT có chữ. Header ĐÃ hấp thụ O-1/O-2 ⇒ SendMessage giữa chừng ăn.
      · lượt 2 (resume, **cắt còn 2 mục** theo khuôn cứu S156) → **§A + §B CLEAN**, đĩa 1.661→**23.085 B**,
        return khớp đĩa.
      · lượt 3 (resume §C/§D) — **tiến-trình CLI thoát giữa chừng**, agent stopped no-completion-record.
        Đĩa **KHÔNG đổi** (23.085 B, mtime 10:55) ⇒ §C/§D **chưa từng được ghi**. Mất = phần chưa làm, **0 mất
        dữ-liệu đã có**. **KHÔNG resume lần 3** (nguyên-nhân ngoại-cảnh, nhưng H21 ① đã cho phép: engine
        propose-only, **spec do LEAD ghi**; §A/§B CHÍNH LÀ phần propose).
- [x] S4 — lead verify ĐỘC LẬP 4 claim load-bearing trên ĐĨA (không tin return):
      · **B.1 Proposal-lite phá OR-of-N** → ✅ THẬT: `ProposalFeatures.cs` `SelectMany` flatten `:427-429` +
        `ElementAtOrDefault` **1 row** `:433` + so đúng **1** `ApproverUserId` `:439`; comment code TỰ THÚ
        *"Lite version: assume 1 step per workflow"*.
      · **slot enum 10 trống** → ✅ THẬT: `ApprovalWorkflow.cs:53-67` dừng ở `TravelRequest = 9`.
      · **`Off_DeXuat` 4 key ĐỀU trong `All`** → ✅ THẬT `MenuKeys.cs:171`; **`Pe_*` sinh bằng factory
        `:150`/`:154` NẰM NGOÀI `All`** ⇒ policy per-action không tồn tại — bẫy claim đúng.
      · **Mig cuối = 68** → ✅ khớp `docs/STATUS.md` CURRENT STATE.
- [x] S5 — lead ghi spec `spec-ke-hoach-ky-ket-hd-28-07-2026.md` (3 heading H21 ①) — §A/§B từ invest
      (đã verify) + **§C wave-plan + §D do LEAD viết** (đúng H21: propose ⟂ spec).
- [x] S6 — `/fable-clone reviewer` ensemble chấm spec — **4 lăng kính CHẠY THẬT** (`d7eaece`): wave-plan **`SUA-TRUOC-W1`** 19đ (6H/8M/5L) ·
      fidelity `GO-WITH-FIXES` · schema `GO-WITH-FIXES` 5H · claims **39Đ/4S/5?**. *(ledger để `[ ]` tới @S159 mới tick — sai từ lúc viết)*
- [x] S7 — lead refute + synthesize → trình anh — **`review-synthesis.md`** (retro @S159). Refute 4 claim load-bearing trên ĐĨA **4/4 THẬT**;
      6 HIGH lens-wave: **4 phủ trọn · 2 CÒN HỞ** (❌ H5 `spec:353` `N` thả tự do — và `:284` đã vá còn `:353` sót, cùng-lớp;
      ❌ H6 dark-launch tự mâu thuẫn, rộng **3 site** `:224`·`:252`·`:443`). Gate 5-anchor đã di-trú `HANDOFF.md:8`.

> 🔴 **Luật của run này (vết S156):** CẤM điền sẵn kết-quả cho stage chưa chạy. Byte-count · verdict ·
> TOTAL chỉ được ghi SAU khi đo thật. Mọi stage chưa chạy giữ `[ ]`.
