` → `1. Thông tin gói thầu` `:402` → `2. Hạng mục + Báo giá NCC (…)` `:405` (template-literal) → `3. Đơn vị NCC/TP được chọn` `:418` → `
` trần "4. Thông tin chọn thầu" `:423` → **`5. Ý kiến cấp duyệt (sign-off theo workflow)` `:426`** (dưới cùng).
§5 của bản đó xếp KHKK: Section 1 Thông tin → 2 Dòng giá → 3 Căn cứ hồ sơ → 4 File đính kèm → **5 Ý KIẾN CẤP DUYỆT** (dưới cùng). **Đúng thứ-tự mẫu, đúng câu owner.** ✅
### 3.2 Claim P2-4 "dời khối ý-kiến từ panel 3 sang panel 2" — ✅ HELD
Đo: khối ý-kiến KHKK hiện nằm trong `KhkkWorkflowPanel.tsx:376-412` (panel duyệt), render `` **1 cột** `text-[11px]`, mỗi `- ` gộp `signedByFullName · Bước n — tên · Cấp m · giờ`, badge `duyệt thay` `:398-402`, placeholder `(duyệt — không ý kiến)` `:407`. Mẫu PE là `md:grid-cols-2` card emerald (`PeDetailTabs.tsx:738-772`).
⇒ Vừa **sai panel** vừa **sai hình**, đúng như bản đó nói. Claim đứng vững, và đây chính là ô owner khoanh đỏ. ✅
### 3.3 🔴 F-4 — nhưng acceptance A-7b ĐO SAI: chạy trên chính MẪU thì FAIL
A-7b: *"`grep -oE 'title="[0-9]\. [^"]+"' KhkkDetailContent.tsx` → **5 dòng**"*.
Tôi chạy đúng lệnh đó trên **mẫu** `PeDetailTabs.tsx`: **3 hit** (`:402 :418 :426`), không phải 5 — vì Section 2 dùng `title={\`2. …(${n} hạng mục)\`}` và Section 4 là `` trần.
Hệ-quả THẬT (không phải bắt bẻ chữ): Section 2 của KHKK gần như chắc-chắn cũng cần đếm động (*"Dòng giá per-NCC (N NCC)"*) ⇒ implementer viết ĐÚNG sẽ **FAIL A-7b**, và cách duy-nhất để PASS là **bỏ số đếm động đi cho vừa regex** — tức Goodhart: sửa hiện-vật cho vừa thước đo.
Sửa: `rg -c '{!selectedId && (
{'Quy trình duyệt sẽ hiện khi chọn phiếu.'}
)}`; GĐ3 `ContractsListPage.tsx:249` = `{!selectedId && }`.
⇒ Đây là **miễn-trừ THỨ 7, không được khai**, và nó nằm đúng vào khối owner nhìn thấy ở Ảnh 1. Cả 6 dòng KHÁC kia đều được nêu tên và biện-hộ; dòng này thì **đổi âm-thầm giữa §3 và §5**, rồi acceptance đóng đinh bản đã đổi. Đây là dạng nguy nhất theo luật owner: *không phải khác — mà là khác mà không nói*.
Cách vá 2 dòng, không tốn gì: panel 3 khi `!selectedId` render **hộp dashed y PE** (đúng Ảnh 1) và đẩy `PipelineTreePanel currentStage={2}` xuống **dưới hộp đó** (hoặc để nguyên ở panel 1 như KHKK đang làm). Nếu owner thích bản GĐ3 hơn thì đó là **quyết-định của owner**, phải hỏi — không phải mặc-định của implementer.
### 3.5 🔴 F-7 — §5 tự mâu-thuẫn về bề-rộng panel 1, và A-4 không bắt được
§5 sơ-đồ ghi `Panel 1 **400px**` (`:253`) = số của PE. Nhưng Điều-kiện 1 (`:246`) bảo *"lấy khuôn từ GĐ3, không phải từ PE"*, mà GĐ3 tôi đo là **`340px`** (`ContractsListPage.tsx:125`). Hai chỉ-dẫn cho hai số khác nhau.
A-4 acceptance: `grep -nE "lg:grid-cols-\[" … → khớp ^.*lg:grid-cols-\[[0-9]+px_1fr_[0-9]+px\]` — **chấp mọi con số**, kể cả `[200px_1fr_200px]`. Với hiến-pháp *"giống nhất với duyệt NCC"*, thước đo phải ghim **`[400px_1fr_360px]`** literal. Hiện tại acceptance đo "có 3 panel", không đo "giống PE".
---
## 4. Câu (4) — Nhóm 5 "chờ owner": hoãn đúng hay hoãn lẩn?
| Món | Owner đã ngầm yêu-cầu qua ảnh? | Verdict |
|---|---|---|
| **A-15** upload file khi duyệt | Ảnh 2 CÓ khối `File đính kèm khi duyệt` — nhưng ảnh chỉ chứng-minh **khối hiển-thị**, không chứng-minh **quyền upload** | ✅ **hoãn ĐÚNG** (tách hiển-thị ⟂ năng-lực là tách đúng) — nhưng có lỗ, xem F-6 |
| **A-16** readOnly cứng + workspace KHKK | Đây là P2-7 đóng gói lại | ⚠️ **hoãn HỢP-LỆ, lý-do SAI** — hỏi owner thì đúng, nhưng phải hỏi kèm phương-án "host truyền `readOnly`" (mục 1.2), đừng trình như lưỡng-nan |
| **A-17** overlay "Xem mở rộng" | Nút `Maximize2` là `opacity-0 group-hover` (`:607-620`) ⇒ **không hiện trong screenshot**; owner chưa hề thấy | ✅ **hoãn ĐÚNG**, và bản đó còn cross-ref P1-7 → §7. Sạch |
### 🔴 F-6 — A-15 hoãn đúng, nhưng acceptance A-8c biến khối đó thành **UI CHẾT mà vẫn PASS**
Đo enum: `src/Backend/SolutionErp.Domain/ContractSigningPlans/ContractSigningPlanAttachment.cs:9-12` — `DossierScan = 1 · PlanDocument = 2 · Other = 99`, comment ghi rõ *"Append-only khi cần thêm mục đích mới"*. Không có giá-trị nào mang nghĩa "file người duyệt tải lên".
Bản đó khuyến-nghị (P3-8): *"dựng khối, đọc `purpose=Other`, đợi owner chốt vế upload"* + P3-8 ghi khối PE **tự-ẩn khi rỗng** (`PeWorkflowPanel.tsx:928-967`).
Ghép 3 sự-thật: (a) không có đường ghi attachment lúc duyệt ở KHKK (§2.3 tự khai "VẮNG"), (b) khối tự-ẩn khi rỗng, (c) A-8c chỉ đo `grep -c "File đính kèm khi duyệt" ≥1` — **trên mã nguồn**.
⇒ Khối sẽ **không bao giờ render** trên UAT, trong khi acceptance **PASS 100%**. Owner mở fe-user, không thấy khối trong Ảnh 2, mà checklist báo xanh. Đây đúng lớp bài học *"claim mạnh hơn việc đã làm"*.
Sửa rẻ: A-8c phải là acceptance **RUNTIME** — *"phiếu đã duyệt có ≥1 attachment `purpose=Other` ⇒ khối hiện; nếu prod chưa có bản-ghi nào thì ghi thẳng vào spec: **khối này chưa sống được cho tới khi owner chốt A-15**"*. Đừng để nó nằm im ở nhóm 3 như một món đã-làm-xong.
---
## 5. Chỗ bản đó ĐÚNG mà owner có thể tưởng là SAI (bảo vệ kết-luận đúng)
1. **"Việc này không phải sửa CSS mà là đổi lớp kiến-trúc" (§8.1) — ĐÚNG, và tôi xác-nhận độc-lập.** KHKK list hiện là `space-y-5` cuộn-body 2 panel (`KhkkListPage.tsx:161,197`), trong khi cả GĐ1 (`PurchaseEvaluationsListPage.tsx:381,397`) lẫn GĐ3 (`ContractsListPage.tsx:106,125`) đều là `h-[calc(100vh-4rem)]` + 3 cột. Owner nhìn ảnh sẽ nghĩ "đổi bố-cục" — chi-phí thật lớn hơn cảm-giác, và **lý-do lớn hơn đó là chính-đáng**, không phải agent vẽ việc.
2. **P2-3 (nội-dung Section khác) không phải là "làm khác cho tiện".** GĐ2 thật-sự không có báo-giá/so-sánh NCC (đã chốt ở GĐ1) — ép 5 Section trùng tên PE sẽ đẻ ra 2 Section rỗng. "Giống nhau" ở đây là **giống KHUNG** (đánh số, `divide-y`, ý-kiến dưới cùng), không phải giống chữ. Bản đó chọn đúng.
3. **P3-3 phán "ĐÃ GIỐNG (hình), không ép BE precompute status" — ĐÚNG.** Hình giống là điều owner yêu-cầu; ép đồng-bộ tầng dữ-liệu sẽ chạm đường duyệt PE đang chạy prod. Đây là chỗ dễ bị chê "làm ẩu" nhưng thực-ra là kiềm-chế đúng chỗ.
4. **Phương-án A (chép khuôn) thay vì B (generic hoá) — ĐÚNG với `CLAUDE.md`** (*"duplicate giữa 2 app là CÓ CHỦ ĐÍCH"*), và Điều-kiện 2 (ghi nợ kỹ-thuật vào đầu file kèm điều-kiện thoát) biến trùng-lặp thành quyết-định có kỳ-hạn. Owner có thể tưởng đây là lười; nó không phải.
---
## 6. Đo bổ-sung cho P3-12 (tiền-đề "3 trạm ngắn")
*(kết quả đo ghi ở đây — xem mục 8 nếu chưa đo được)*
---
## 7. Bảng tổng-kết verdict
| # | Claim của bản đó | Verdict | Bằng-chứng tôi tự đo |
|---|---|---|---|
| N-1 | tally 27/6/2 | **HELD** | 35 dòng bảng §3, tự phân loại lại: 27/6/2 |
| N-2 | khuôn GĐ3 `:125` `:249` | **HELD** | `ContractsListPage.tsx:106,125,249` |
| N-3 | PE 5 khối, ý-kiến dưới cùng | **HELD** (thứ-tự) | `PeDetailTabs.tsx:402,405,418,423,426` |
| N-4 | ý-kiến KHKK ở panel 3, list phẳng | **HELD** | `KhkkWorkflowPanel.tsx:376-412` |
| P1-4 | KHÁC-buộc-phải-khác | **HELD lý-do / SAI nhãn** | dòng tự viết "CHỖ ĐẶT phải giống" |
| P2-3 | KHÁC-buộc-phải-khác | **HELD** | — |
| P2-7 | KHÁC-buộc-phải-khác | 🔴 **BROKE** | `readOnly` là prop của host (`PurchaseEvaluationsListPage.tsx:663`, `PeDetailTabs.tsx:427`) |
| P3-7 | KHÁC-buộc-phải-khác | **HELD** | — |
| P3-12 | KHÁC-buộc-phải-khác | 🔴 **BROKE tiền-đề** | "ngoài phạm-vi" = lý-do chi-phí; "3 trạm" chưa đo (mục 6) |
| P3-13 | KHÁC-buộc-phải-khác | **HELD** | cardinality per-Line ≠ 1-giá |
| P2-4 | ý-kiến phải dời panel | **HELD** | đo 2 đầu |
| §5 thứ-tự Section | content trên / ý-kiến dưới | **HELD** | — |
| §5 panel-3 empty | *(âm-thầm đảo P3-16)* | 🔴 **BROKE** (F-5) | `:204` vs `:261-262` vs A-8e |
| A-7b | acceptance 5 dòng | 🔴 **BROKE** (F-4) | mẫu PE chỉ 3 hit |
| A-4 | acceptance grid | ⚠️ **YẾU** (F-7) | regex chấp mọi số; §5 400px vs GĐ3 340px |
| A-8c | acceptance file-khi-duyệt | 🔴 **BROKE** (F-6) | enum `:9-12` không có purpose; khối tự-ẩn ⇒ PASS mà không hiện |
| A-15/A-17 | hoãn | **HELD** | — |
| A-16 | hoãn | **HELD (hành-vi) / BROKE (lý-do)** | mục 1.2 |
| — | **bỏ-sót F-1** empty-state panel 2 | 🔴 **bắt thêm** | `PurchaseEvaluationsListPage.tsx:644-656` |
| — | **bỏ-sót F-2** chip `⚑ Kết thúc` trên card | 🔴 **bắt thêm** | P1-5 vs §1.1 `:43`; dữ-liệu có sẵn (D-1) |
| — | **bỏ-sót F-3** liệt-kê NV/Cấp | 🔴 **bắt thêm** | `PeWorkflowPanel.tsx:453-465` có, §3 không có dòng |
---
## 8. Lỗ-hổng tôi KHÔNG đo được (khai thật)
(đang bổ-sung)
END reviewer-lens-fidelity-s171 — VERDICT=? HELD / ? BROKE / ? bỏ-sót-bắt-thêm