Files
solution-erp/docs/changelog/sessions/2026-06-22-S83-h15v3-pe-require-workflow.md
pqhuy1987 f71654ff9e [CLAUDE] Docs: S83 closeout — STATUS/HANDOFF + session-log (H-15 v3 budget + PE require-workflow)
Test 354->356, bundle CsJetgZH/BVS0ApIm Run #333 (unchanged, #69-REFINE: no fe-src=Vite-deterministic-same-hash). spawn-records 3 sub (tooling/harvest/cicd all verified). State Mig 57/88 bang/356 test/gotcha 71.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 17:23:59 +07:00

73 lines
7.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# S83 (2026-06-22) — H-15 v3 memory-budget full-parity + PE require-workflow guard
**Anh:** `/session-start` → directive ngân-sách Tầng-1 "Giờ là 220k, đầu phiên nạp thêm cho đủ" + sub 60K/wf 50K + "tao đánh dấu User-mark" → forward screenshot phiếu PE/2026/A/040 "Sao cái này lại là quy trình cũ?" → (sau khi tự-khỏi) "Giờ thì lại được? do cache?" → **"(B) Vá guard BE (require workflow create+submit) + test-before → deploy. Thôi vá đi. Rồi Session-end."**
2 commit prod-verified: `2c7fd63` (governance H-15 v3, docs-only CI-skip) + `fc1f19d` (PE fix, **Run #333 PASS ~4m59s**).
---
## Part 1 — H-15 v3 memory-budget (anh owner-directive, 0 production code)
**Directive:** lead Tầng-1 **220K** · mem-sub **60K** · wf-sub **50K** = **full AI_INFRA parity**. Sửa self-shrink S82 (AI tự lập-luận "SE nhỏ hơn → 60K" = đúng cái `role_boundary_note` + mark `RC-…01-58-01` cấm: token-saving = quên-việc). + nguyên-tắc: khi SPAWN sub → nạp context tới budget bằng **prompt GIÀU** (relevant gotcha + state + full task-context + docs/memory), KHÔNG nạp rác; hot-load = token giá-trị-nhất.
**Implement (em-main single-writer D9, 4 file):**
- `memory-budget.json`: `token_governor.tier1_hotfeed_tokens` lead 200K→**220K** / mem-sub 20K→**60K** / wf-sub 16K→**50K** + NEW block **`spawn_fill_directive`** (rich-prompt-to-budget + quality_gate highest-value-distilled).
- `harness-11-engine.md`: NEW **§G.5** (v3 delta: full-parity + spawn-fill + byte-cap-là-1-lát correction) + §G.1/§G.4 số + adopt-delta S83 + header/table-row.
- `agents/README.md`: anti-truncation **retire `≤8K brief`** → rich INPUT to budget (#53 = RETURN-truncation, vá bằng memoryDelta return KHÔNG starve input).
- `ACTIVE-MARKS.md`: H-15 mark **v3-delta** stamp `RC-pqhuy1987-22-06-2026-16-35-37` (anh-directed; report-before-stamp).
**Correction cốt-lõi:** byte-cap MEMORY.md (30720B ~9.3K tok) CHỈ là 1 lát của Tầng-1 sub — **prompt-spawn em-main viết** nạp phần còn lại tới token-budget. ⟹ 60K/50K KHÔNG phải "headroom vô-dụng" (bác lập-luận S82 "byte-cap binds first").
**Self-gate:** JSON valid · detector **26 baseline (0 new drift)** · A7 GATE 217/217.
**Dogfood:** spawn cicd-monitor (Part 2) bằng prompt GIÀU theo `spawn_fill_directive` mới (relevant gotcha #41/#69/#65 + state bundle/Mig + full task-context) — đúng tinh-thần directive.
---
## Part 2 — PE require-workflow guard (fix "quy trình cũ", prod-verified)
**Diagnose (em-main, read-only):** banner "Phiếu này dùng quy trình cũ — workflow chi tiết không khả dụng" + "Lịch sử duyệt (0)" = FE [PeWorkflowPanel.tsx:333](../../../fe-user/src/components/pe/PeWorkflowPanel.tsx) render khi `flow = evaluation.approvalFlow` rỗng. BE dựng `approvalFlow` chỉ khi `ApprovalWorkflowId` pinned. Submit [PurchaseEvaluationWorkflowService.cs:226]: `CurrentApprovalLevelOrder = ApprovalWorkflowId is not null ? 1 : null`. ⟹ banner ⟺ phiếu **null-workflow** → nhánh V1-legacy.
**Root cause = validate BẤT ĐỐI XỨNG FE↔BE (họ gotcha #44):** FE create bắt buộc (`canSubmit = … && !!form.approvalWorkflowId`) nhưng BE `CreatePurchaseEvaluationCommand` chỉ validate NẾU-CÓ-TRUYỀN (`if (request.ApprovalWorkflowId is Guid awId)`) + submit không guard → null lọt vào ChoDuyet.
**Diagnostic heuristic (anh hỏi "do cache?"):** phiếu A/040 **tự-khỏi khi reload****cache** (TanStack stale detail bundle), KHÔNG phải data-hỏng (data-hỏng reload KHÔNG khỏi). Em KHÔNG đụng prod/data — chỉ đọc code. Đính-chính trung-thực: "ApprovalWorkflowId null" lúc đầu là **suy-luận từ màn FE**, chưa xác-nhận DB; tự-khỏi-khi-reload nghiêng hẳn về cache.
**Fix (anh chọn B — test-before BẮT BUỘC bug-fix):**
1. **TEST-BEFORE (RED confirmed):** 2 test repro (validator null + submit null) chạy code cũ = 2 FAIL.
2. **Validator** ([PurchaseEvaluationFeatures.cs](../../../src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs)): `RuleFor(x => x.ApprovalWorkflowId).NotEmpty()`.
3. **Submit guard** ([PurchaseEvaluationWorkflowService.cs](../../../src/Backend/SolutionErp.Infrastructure/Services/PurchaseEvaluationWorkflowService.cs)): `if (ApprovalWorkflowId is null) throw ConflictException(...)` đặt **SAU Section-3 block, TRƯỚC `Phase = ChoDuyet`** (orthogonal — ưu tiên báo thiếu data).
**Spec-conflict triage (bài học chính):** full-suite bắt **9 test đỏ** sau fix → triage thay vì đập bừa:
- **2 genuine-spec-conflict** (`Submit_AllFourMet_NoWorkflow_SetsChoDuyet` + `Submit_V1Phieu_…SubmitsOk`) = **cố ý** khẳng định V1-submit OK → **rewrite** assert-throws (V1-submit deprecated, an toàn vì data V1 đã wipe S59).
- **6 collateral** (Section-3 tests seed null-workflow để test Section-3) → **dời guard ra sau Section-3** giữ cả 6 nguyên vẹn (KHÔNG churn).
- **1 validator** (`Validator_WorkItemIdPresent_NoErrorOnWorkItemId` assert IsValid=true) → +param `approvalWorkflowId` BuildCreateCommand.
- Relocate 2 validator test → `PeWorkItemGuardTests` (nhà của validator); xóa file riêng tạm.
**Test 354→356** (+2 validator). Full slnx build sạch (gotcha #65).
**Deploy (commit `fc1f19d`, cicd-monitor Run #333 PASS):**
- Smoke api/admin/eoffice 200 · Mig **57** no-pending · test gate pass.
- **Bundle KHÔNG rotate** admin `CsJetgZH`/user `BVS0ApIm` (= #330) — **#69-REFINE:** 0 `fe-*/src` change → Vite deterministic same-hash; ship-signal THẬT = **Last-Modified in-window** (17:10/17:11), KHÔNG hash-delta. `deploy.yml` rebuild FE unconditional NHƯNG output byte-identical. (Canonical gotcha #69 cần fold refinement này — defer monthly 2026-07-01; recorded cicd-memory.)
**FE:** KHÔNG sửa — submit null-workflow → BE 409 → FE toast "Phiếu chưa chọn quy trình duyệt…". Phiếu A/040 kẹt sửa bằng Trả lại→Sửa→chọn quy trình→gửi lại.
---
## §L spawn-records (3 sub, Agent-tool spawn — KHÔNG Workflow fan-out → 0 run-trace folder)
| agent | task | nấc | evidence |
|---|---|---|---|
| 🟫 tooling-auditor (H1) | session-start 4-mặt freshness + diff | verified | roster 11/11 inherit no-`[1m]` · plugin 18/15/3 · 5 stale-cite (ef-core SKILL Mig56→57 + skills/README #69#71) carry monthly · docs canonical FRESH |
| ⬜ harvest-curator (H2) | session-start harvest-integrity scan | verified | 0 orphan-run · 0 un-appended delta · 0 corruption · all L1 <soft-cap |
| 🟩 cicd-monitor | verify deploy Run #333 (rich-prompt dogfood) | verified | PASS smoke 200×4 + Mig 57 no-pending + #69-REFINE; wrote own MEMORY (#333 + #69-REFINE) |
**§L.a AS-scan:** 0 hit. Test-before + full-suite bắt spec-conflict **pre-commit** (working-as-intended, KHÔNG broken commit). S82 self-shrink correction = guard-held (mark `RC-…01-58-01` + role_boundary), KHÔNG RCA mới.
---
## 🔴 NEXT SESSION
- **Anh:** restart CLI activate budget `token_governor` v3 (220/60/50) + `spawn_fill_directive` runtime (config JSON sống ngay; engine/command `.md` no hot-reload).
- **Em (carry):** frontend-designer 26.1KB + test-specialist 27.7KB WATCH strike-1 (<2, no-action). **Monthly audit 2026-07-01:** fold **#69-REFINE** vào gotcha canonical · ef-core SKILL Mig5657 + skills/README #69#71 stale-cite · STATUS/HANDOFF re-tier (bloat).
- **Pending product:** "Ngưỡng giá CEO" Mig 54 Designer UAT · "C" chuyển phiếudự án chờ spec. **FE proactive guard** (disable submit nút cho phiếu null-workflow) = offered, chờ anh.
- **Ops S58/S59:** tzutil VPS UTC+7 · anh Chương email typo · 5 real-staff pw · gán CNTT.