[CLAUDE] Docs: Chunk C — chốt Session 21 turn 3 fix gotcha #45 PE button "Trả lại" mismatch
Add gotcha #45 narrative đầy đủ ~120 dòng KEEP rule §6.5: - Triệu chứng UAT screenshot + user mô tả "Trả về nhưng hệ thống vẫn duyệt" - Root cause 3 chỗ inconsistency table + BE service path - Severity CRITICAL data integrity - Fix Chunk A BE code + 3 test list - Fix Chunk B FE code diff × 2 app - Pattern reusable (boundary guard semantic invariant) + phòng tránh tương lai - References 2 commit + Session 17 spec + gotchas.md checklist debug entry 22 quick lookup. Update STATUS.md Last updated header + count 81→84 test + 44→45 gotcha. Insert HANDOFF.md TL;DR S21 t3 đầy đủ Chunk A/B/C + state cumulative. New session log docs/changelog/sessions/2026-05-12-2100-s21-turn3-fix-tra-lai-bug45.md. Verify: - 84 test PASS (dotnet test SolutionErp.slnx — Chunk A persisted) - npm run build × 2 app pass (Chunk B persisted) - KHÔNG paraphrase / KHÔNG cắt narrative cũ S21 t1/t2/S20 (rule §6.5 KEEP) Pending: bro confirm push remote `0a3b747..HEAD` 3 commits ahead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
107
docs/HANDOFF.md
107
docs/HANDOFF.md
@ -1,8 +1,113 @@
|
||||
# HANDOFF — Brief 5 phút cho session tiếp theo
|
||||
|
||||
**Last updated:** 2026-05-12 (Session 21 turn 2 — **🎯 RAG Hybrid setup planning + Cách A validation deep dive. 2 commit (`1f8e9af` plan save 1223 LOC + this chốt). KHÔNG implement, plan only — defer chờ bro confirm 5 dự án future. Decision chốt: Cách A defensive (giữ blanket 120K em main + RAG retrieve) over Cách B aggressive (cắt 60-70% blanket). Industry-validated cross 4 Anthropic blog + 5 community tools (Cursor/Continue/Cline/Aider). Stack: Voyage-3-large + Qdrant + FastMCP + Streamlit dashboard. Multi-agent cost reality: 4 agents → ~520K cumulative blanket → heavy session ~560K (Cách A) vs ~700K (lazy). 3-layer pattern Phase 1-3 rollout (embeddings + BM25 + reranking, ~70% → ~92% recall). Stats: +1 memory entry (`feedback_rag_hybrid_pattern`) +1 plan file (`rag-setup-plan.md` 1500 LOC). Sub-agents vẫn 4 seeds-only, em main solo session.**)
|
||||
**Last updated:** 2026-05-12 2100 (Session 21 turn 3 — **🔴 BUG FIX CRITICAL "Trả về nhưng hệ thống vẫn duyệt" PE workflow (gotcha #45 mới). 3 chunk per-commit: `de00887` (BE Chunk A guard + 3 test) + `4b29d00` (FE Chunk B fix 2 app mirror) + this Chunk C Docs. Root: `PeWorkflowPanel.tsx` `isReject` payload (L64-66) thiếu nhánh TraLai → button "← Trả lại" gửi `decision: 1` (Approve) thay vì `2` (Reject) khi target=TraLai(98) → BE skip Reject branch → enter APPROVE STEP → `ApproveV2Async` UPSERT opinion "đã duyệt" + advance Cấp tiếp theo. Inconsistency phụ: dialog `isSendBack` (L247-248) cùng pattern thiếu TraLai → dialog title sai `'✓ Duyệt → Trả lại'` + KHÔNG amber warning. Severity CRITICAL — data integrity issue khó rollback (BE đã `SaveChangesAsync`). Test-before §7 BẮT BUỘC: viết test reproduce → confirm FAIL (BE đi sâu vào ApproveV2Async throw "Phiếu chưa pin workflow") → thêm BE guard early throw ConflictException khi `target ∈ {TraLai, TuChoi} && decision != Reject` → confirm PASS. 3 regression test (Throws TraLai+Approve, Throws TuChoi+Approve consistency, happy path Reject+TraLai). Tổng `dotnet test SolutionErp.slnx` 84 PASS (58 Domain + 26 Infra = +3 from 81 baseline). `npm run build` × 2 app pass. Stats: 27 mig (no change) · 59 tables · ~142 endpoints · 34 FE pages · **84 test (+3)** · **45 gotcha (+1 #45)** · 17 memory · 6 skills · 4 sub-agents seeds-only. Em main solo S21 t3 — bug fix reasoning chain cross BE/FE Implementer REFUSE per multi-agent rule (decision tree: tightly coupled BE+FE+test). CHƯA push remote — chờ bro confirm sau Chunk C wrap.**)
|
||||
**S21 turn 2:** 2026-05-12 1800 (Session 21 turn 2 — **🎯 RAG Hybrid setup planning + Cách A validation deep dive. 2 commit (`1f8e9af` plan save 1223 LOC + this chốt). KHÔNG implement, plan only — defer chờ bro confirm 5 dự án future. Decision chốt: Cách A defensive (giữ blanket 120K em main + RAG retrieve) over Cách B aggressive (cắt 60-70% blanket). Industry-validated cross 4 Anthropic blog + 5 community tools (Cursor/Continue/Cline/Aider). Stack: Voyage-3-large + Qdrant + FastMCP + Streamlit dashboard. Multi-agent cost reality: 4 agents → ~520K cumulative blanket → heavy session ~560K (Cách A) vs ~700K (lazy). 3-layer pattern Phase 1-3 rollout (embeddings + BM25 + reranking, ~70% → ~92% recall). Stats: +1 memory entry (`feedback_rag_hybrid_pattern`) +1 plan file (`rag-setup-plan.md` 1500 LOC). Sub-agents vẫn 4 seeds-only, em main solo session.**)
|
||||
**S21 turn 1:** 2026-05-12 0030 (Session 21 turn 1 — **🎯 Add con thứ 4 cicd-monitor (Path A — post-deploy verifier). 1 commit `f1c61c9` pushed `36e21c8..f1c61c9 main -> main`. CI skipped per path filter (3 file `.md`). Cost reality update: ~750K spawn (3 → 4 agents) · ~1.35M heavy / ~700K optimized. Stats: 4 sub-agents seeds-only · 16 memory · 27 mig · 59 tables · ~142 endpoints · 81 test · 44 gotcha · 6 skills unchanged. KHÔNG flush 3 agent MEMORY.md (chưa spawn work — em main solo). Trial Week 1 kick-off S21 turn 2+ Plan B Contract V2 wire mirror PE pattern.**)
|
||||
|
||||
## TL;DR Session 21 turn 3 — Bug fix CRITICAL "Trả về nhưng hệ thống vẫn duyệt" (gotcha #45)
|
||||
|
||||
User UAT 2026-05-12 21:00 screenshot button labeled `← Trả lại` trong PE Workflow Panel (menu "Duyệt"), mô tả hành vi: nhấn vào nhưng phiếu KHÔNG về phase TraLai — ngược lại tiến qua Cấp tiếp theo. User mô tả: "Trả về nhưng hệ thống vẫn duyệt".
|
||||
|
||||
### Diagnose (em main solo, no agent spawn)
|
||||
|
||||
3 chỗ inconsistency cùng pattern trong `PeWorkflowPanel.tsx` (× 2 app fe-admin + fe-user):
|
||||
|
||||
| # | Location | Logic | Bug? |
|
||||
|---|---|---|---|
|
||||
| 1 | L205-207 button `isSendBack` | include TraLai → label `← Trả lại` ĐÚNG | ✅ no bug |
|
||||
| 2 | L64-66 payload `isReject` | thiếu nhánh TraLai → gửi `decision: 1` (Approve) | 🔴 BUG ROOT |
|
||||
| 3 | L247-248 dialog `isSendBack` | thiếu nhánh TraLai → dialog title fallback `'✓ Duyệt → Trả lại'` + no amber warning | 🔴 BUG phụ |
|
||||
|
||||
BE `PurchaseEvaluationWorkflowService.TransitionAsync`:
|
||||
- L51 `if (decision == Reject)` branch → đúng cho decision=Reject.
|
||||
- L97 `APPROVE STEP` branch khi decision=Approve + fromPhase=ChoDuyet → ApproveV2Async UPSERT opinion + advance Cấp.
|
||||
- → FE gửi `decision=1` (do bug `isReject`) → BE đi vào nhánh APPROVE thay vì REJECT → phiếu approve mặc dù user định trả lại.
|
||||
|
||||
### Chunk A — BE defense-in-depth + 3 regression test (`de00887`)
|
||||
|
||||
**Test-before §7 BẮT BUỘC:** Viết test reproduce bug TRƯỚC fix.
|
||||
|
||||
```csharp
|
||||
// Sau line 48 (set isAdmin/isSystem), trước REJECT branch (L51)
|
||||
if ((targetPhase == PurchaseEvaluationPhase.TraLai
|
||||
|| targetPhase == PurchaseEvaluationPhase.TuChoi)
|
||||
&& decision != ApprovalDecision.Reject)
|
||||
{
|
||||
throw new ConflictException(
|
||||
$"Transition tới {targetPhase} BẮT BUỘC decision=Reject (nhận {decision}). " +
|
||||
"Báo lỗi caller — payload mismatch giữa target phase và decision.");
|
||||
}
|
||||
```
|
||||
|
||||
Boundary protection cho mọi caller tương lai (API client / mobile / cron retry). Guard KHÔNG xoá khi FE fix — defense-in-depth.
|
||||
|
||||
3 test file `tests/SolutionErp.Infrastructure.Tests/Services/PurchaseEvaluationWorkflowServiceGuardTests.cs`:
|
||||
- `TransitionAsync_TargetTraLai_WithApproveDecision_Throws_AndDoesNotMutateState` — reproduce bug, expect `ConflictException` "*TraLai*Reject*"
|
||||
- `TransitionAsync_TargetTuChoi_WithApproveDecision_Throws_AndDoesNotMutateState` — consistency cover TuChoi
|
||||
- `TransitionAsync_TargetTraLai_WithRejectDecision_SetsPhaseTraLai` — happy path control (Reject branch vẫn đúng)
|
||||
|
||||
+ `NoOpNotificationService` stub reusable cho future PE service tests (avoid `INotificationService` real DI complexity).
|
||||
|
||||
Run test → 2 FAIL (reproduce bug, BE đi sâu vào ApproveV2Async throw "Phiếu chưa pin workflow") + 1 PASS (happy path). Thêm BE guard → 3 PASS. Tổng `dotnet test SolutionErp.slnx` 84 PASS (+3 from 81 baseline).
|
||||
|
||||
### Chunk B — FE fix mirror 2 app (`4b29d00`)
|
||||
|
||||
3 chỗ × 2 app = 6 edits:
|
||||
|
||||
```typescript
|
||||
// Chỗ 1: isReject payload (L64-66)
|
||||
const isReject = target === PurchaseEvaluationPhase.TuChoi
|
||||
|| (target === PurchaseEvaluationPhase.DangSoanThao
|
||||
&& evaluation.phase !== PurchaseEvaluationPhase.DangSoanThao)
|
||||
|| (target === PurchaseEvaluationPhase.TraLai // ← THÊM
|
||||
&& evaluation.phase !== PurchaseEvaluationPhase.TraLai)
|
||||
|
||||
// Chỗ 3: dialog isSendBack (L247-248)
|
||||
const isSendBack = (target === PurchaseEvaluationPhase.DangSoanThao
|
||||
|| target === PurchaseEvaluationPhase.TraLai) // ← THÊM
|
||||
&& evaluation.phase !== PurchaseEvaluationPhase.DangSoanThao
|
||||
&& evaluation.phase !== PurchaseEvaluationPhase.TraLai // ← THÊM
|
||||
```
|
||||
|
||||
Chỗ 2 (button label `isSendBack` L205-207) đã đúng từ S17, KHÔNG đụng.
|
||||
|
||||
Verify: `npm run build` × 2 app pass (fe-user 17.91s + fe-admin 6.71s, 0 TS6 err).
|
||||
|
||||
### Chunk C — Docs (this commit)
|
||||
|
||||
- `docs/gotchas.md` +#45 PE button label vs decision payload mismatch (~120 dòng narrative + 2 commit cross-ref + pattern reusable + phòng tránh tương lai)
|
||||
- `docs/gotchas.md` checklist debug +entry 22 quick lookup
|
||||
- `docs/STATUS.md` Last updated S21 t3 + count 81→84 test + 44→45 gotcha
|
||||
- `docs/HANDOFF.md` TL;DR S21 t3 narrative đầy đủ (file này)
|
||||
- `docs/changelog/sessions/2026-05-12-2100-s21-turn3-fix-tra-lai-bug45.md` session log mới
|
||||
|
||||
### Pending (carry from S21 turn 2)
|
||||
|
||||
Plans A-I unchanged. Plan C1 (test regression gotcha #44 silent 403 S18) vẫn còn nợ — không bundle với S21 t3 fix (scope khác, ưu tiên unblock UAT bug critical trước).
|
||||
|
||||
### Audit cadence
|
||||
|
||||
- Lần gần nhất: 2026-05-04 manual trễ 4 ngày
|
||||
- Lần kế: **2026-06-01** combined audit
|
||||
- Drift sau S21 t3: 44→45 gotcha (+1) + 81→84 test (+3) + 17→17 memory (no new) + 6 skills unchanged
|
||||
|
||||
### State chốt S21 turn 3
|
||||
|
||||
| Metric | Trước (S21 t2) | Sau (S21 t3) | Δ |
|
||||
|---|---|---|---|
|
||||
| DB tables | 59 | 59 | 0 |
|
||||
| Migrations | 27 | 27 | 0 |
|
||||
| Endpoints | ~142 | ~142 | 0 |
|
||||
| FE pages | 34 | 34 | 0 |
|
||||
| **Unit tests** | 81 | **84** | **+3** (PE guard) |
|
||||
| **Gotchas** | 44 | **45** | **+1** (#45) |
|
||||
| Memory entries | 17 | 17 | 0 |
|
||||
| Skills | 6 | 6 | 0 |
|
||||
| Sub-agents | 4 seeds-only | 4 seeds-only | 0 |
|
||||
| **Commits S21 t3** | — | **3** | (`de00887` + `4b29d00` + this) |
|
||||
|
||||
---
|
||||
|
||||
## TL;DR Session 21 turn 2 — RAG Hybrid setup planning (Cách A chốt + 3-layer pattern)
|
||||
|
||||
User clarify 5 dự án future > 1M MD tokens → cuộc thảo luận deep ~15 turn về RAG infrastructure. Em main solo (no SOLUTION_ERP sub-agent spawn), delegate 2 lần claude-code-guide agent research Anthropic + community practice.
|
||||
|
||||
Reference in New Issue
Block a user