# invest-synthesis — S112 PE sign-off save+advance

> 🔄 **partial-honest — CHUẨN-HOÁ VỊ-TRÍ @S122 (2026-07-15), KHÔNG PHẢI VIẾT MỚI.**
>
> Thân synthesis dưới = **trích từ `run.md:21-41`**, đã tồn-tại từ **2026-07-12** (vào git qua `d170904` = `wal: flush 20260712T1419`, 2026-07-12T14:19:19+07; 4 sub-MD cùng commit đó; spec vào qua `a57cb1d` 13:57:40).
> 🔴 **Bản gốc trong `run.md` GIỮ NGUYÊN, và bản gốc mới là CHUẨN** — file này là bản-sao chuẩn-hoá vị-trí. Không cắt, không rewrite history (tinh-thần C8 `workflows/README.md:19`).
>
> **Vì sao file này ra đời:** orphan-authority (`workflows/README.md:20`) đo **TÊN FILE**, không đo **nội-dung** ⇒ synthesis-trong-run.md vô-hình với nó. Đo @S122: `naive 13 / dual-accept 8 / C8 cứu 5` — **0/7 là việc mất**. Anh chủ-dự-án chốt @S122: **chuẩn-hoá + tri-accept**.

---

## [TRÍCH `run.md:21-41` — bản gốc là chuẩn]

### synthesis (em-main — wf_fd8f2bfe-9f6, 4/4 clean, Opus 4.8)

> sub-file naming = journal-order ≠ lane-order: `sub-invest-B`=Lane A (current-flow) · `sub-invest-C`=Lane B (change-design) · `sub-invest-A`=Lane C (reject) · `sub-reviewer`=reviewer.

**REVIEWER VERDICT: PASS_WITH_CONCERNS.** 3 lane khớp source thật 100% (mọi file:line verify đúng). Thiết kế sound, 0 vỡ 5-state.

#### Cốt lõi (bất ngờ tốt): yêu cầu = sửa 1 CHỖ, cơ chế đã có sẵn
- "comment-in-own-box → save → advance" ĐÃ tồn tại trong dialog Duyệt (`ApproveV2Async` UPSERT opinion `:763-790` + advance `:927`, cùng 1 call).
- 🔴 ĐIỂM CHẶN = **`ApplyDrafterBypassOnSubmitAsync`** (`PurchaseEvaluationWorkflowService.cs:571-681`, gọi `:260-261`): lúc creator (=DrafterUserId=PRO) submit, nó TỰ ký hộ ô Cấp-1 bằng comment CANNED "(duyệt tự động…)" `:619` + advance qua → creator mất ô comment thật của mình (đúng cái screenshot Cấp-1 Bình muốn).
- 🔴 Đây là feature UAT **S60** (anh Kiệt cũ: "TP tạo thì bypass — NV khỏi duyệt lại"). Yêu cầu mới **NGƯỢC lại** → **đảo hành vi S60, cần sign-off**.
- **FIX:** gỡ/gate bypass → pointer đứng `(0,1)` → creator gõ comment thật + Duyệt → `ApproveV2Async` lo phần còn lại. **0 đổi ApproveV2Async · FE ~0**. Giữ **1-nút** (save=advance); 2-nút draft = thừa (cần schema+endpoint+DTO).

#### Reject (item 3)
Phần lớn ĐÃ có (mode `Assignee` — về NV đã ký, giữ ChoDuyet, re-comment UPSERT, forward). 3 gap: default=Drafter(full-restart) · phải admin bật Allow*-per-slot · rejecter pick tay.

#### Governance
creator-sign Cấp-1 = bước ĐỀ-XUẤT hợp lệ (CCM/CEO cấp trên mới approval thật, phân-tách nhiệm-vụ giữ). Lỗ CHỈ khi slot creator bật `AllowApproverFinalize`/`SkipToFinal` → self-finalize bỏ CEO (hiện 0 guard → đề-xuất guard B2, đã tồn-tại hôm nay qua bypass single-step-terminal).

#### 🔴 EDGE-5 (reviewer nâng latent→REACHABLE, MAJOR pre-existing)
Drafter forge `Reject+TargetPhase=TraLai` trên phiếu **DaDuyet của chính mình** (đã chốt ApprovedPrice) → mở lại → sửa → gửi lại. Controller `:130-143` chỉ `[Authorize]` class-level + handler `FEAT:510-539` KHÔNG guard fromPhase + `EnsureCanRejectV2Async` early-return khi Phase≠ChoDuyet `:321`. Vùng reject-return CHÍNH LÀ scope sửa → nên bịt luôn (guard `fromPhase∈{DaDuyet,TuChoi}→throw`).

#### 6 quyết định owner (anh Kiệt)
(1) A1/A2 gỡ-bypass · (2) guard-B2 self-finalize · (3) EDGE-5-fix · (4) 1-nút/2-nút · (5) stale-comment-khi-trả-lại · (6) migrate-data-cũ-bypass.

**Harvest:** pending @closeout — investigator-codebase + reviewer, stamp `[engine: fable-clone-ensemble · Opus-S112]`.

---

## Verify độc-lập @S122 (lead — KHÔNG tin thẳng return sub)

**VERDICT: LANDED** (design-deliverable ĐÃ dùng; code land qua run kế-tiếp)

- **Design-deliverable:** synthesis ghi INLINE `run.md:21-41` → vào git qua `d170904` (`wal: flush 20260712T1419`). 4 sub-MD cùng commit.
- **Code downstream:** land qua run kế `2026-07-12-S112-pe-signoff-close-review` (`wf_7df56b89-7bb`) — run đó tự khai base = *"investigation `wf_fd8f2bfe-9f6` + 6 decision anh Kiệt chốt"* (`close-review/run.md:6`) ⇒ **chuỗi 2 run nối nhau, KHÔNG đứt**.
- **Commit:** `a829d0d` · 2026-07-12T16:13:46+07:00 · 2 file +513/−148 (`PurchaseEvaluationWorkflowService.cs` 163 dòng + `PeSubmitGuardAndBypassTests.cs` 498 dòng) · `Co-Authored-By: Claude Fable 5`.

**Disposition TỪNG DÒNG 6 decision** (`run.md:39`) — verify trên code HIỆN TẠI:

| # | Decision | Land? | Evidence |
|---|---|---|---|
| 1 | A1/A2 gỡ-bypass | ✅ **A1** | `SVC:583` method · `:607` `minOwn=drafterSlots.Min(Order)` · `:609` `bypassedOrders = o < minOwn` · `:628-643` pointer STOP tại minOwn · `:574,:634` xử non-contiguous. Test `PeSubmitGuardAndBypassTests.cs:523/565/597/632/711/765/812` |
| 2 | guard-B2 self-finalize | ❌ **BÁC** (owner oQ1) | grep `DrafterUserId` toàn SVC = chỉ `:569` comment + `:586` bypass + `:1098`/`:1173` **notify** ⇒ **0 guard** tại `:855` `AllowApproverFinalize`. Neo: session-log:18 *"no-finalize-guard (theo quyền `AllowApproverFinalize`)"* + `implementer-backend/MEMORY.md` *"C3 no self-finalize (owner oQ1 permission-driven)"* |
| 3 | EDGE-5-fix | ✅ **REFINED** | `SVC:58-72` guard TOP (kèm `!isAdmin && !isSystem` = owner reconcile) |

🔴 **Decision 2 bị BÁC là quyết-định CÓ CHỦ-ĐÍCH của owner**, không phải quên. Nhưng hệ-quả kỹ-thuật (self-finalize bỏ CEO) **vẫn còn mở** — xem gap #1.

### Gap KHÔNG chứng minh được (khai thẳng)

1. **CEO-skip surface vẫn mở** — decision 2 BÁC theo oQ1 ⇒ slot creator bật `AllowApproverFinalize` vẫn self-finalize bỏ CEO được. Đây là **rủi-ro owner đã chấp-nhận có ý-thức**, KHÔNG phải bug chưa biết. Nhưng S122 **không có verbatim anh Kiệt** trong run-folder — chỉ neo qua session-log do em-main ghi.
2. **Decision 4/5/6** (1-nút/2-nút · stale-comment · migrate-data-cũ) — S122 **không truy** ⇒ **KHÔNG XÁC ĐỊNH ĐƯỢC** có land hay bị drop.
3. **458 test PASS** — S122 KHÔNG chạy `dotnet test`.

### Lệch convention của chính folder này (ghi để không lặp)

- Sub-MD naming = **journal-order ≠ lane-order** (`sub-invest-A/B/C` KHÔNG khớp Lane A/B/C) — synthesis tự khai, harvest phải đọc **nội-dung** không tin **tên**. Đây là lỗi hệ-thống, tái-diễn ở `supplier-excel-import` + `supplier-import-close-review`.
- Synthesis ghi vào **thân `run.md`** ⇒ **dạng-3**, nguyên-nhân gốc false-orphan.

---
*Chuẩn-hoá vị-trí @S122 `/tiep` · run `2026-07-15-S122-retro-harvest-7-orphan` · wf `wf_5ce007c4-980` lane `retro:S112-pe-signoff-save-advance` · lead Opus 4.8 · sub read-only, lead single-writer (B6)*
