[CLAUDE] Docs: Session 25 chốt cuối — Plan AB→AF cumulative 7 commits + 4 agent MEMORY flush

S25 wrap final:
- STATUS.md + HANDOFF.md prepend Plan AB→AF cumulative narrative (7 commits cdfd542..506cada + 7 CICD Runs #215-#221)
- gotchas.md +2 NEW entries:
  - #48 Multi-Changelog.Add() SQLite frozen-clock tie-break (Run #215 catch, fix Plan AB Chunk A2)
  - #49 UI dual-phase badge confusion khi state machine self-loop (Plan AD drop + extractNextTargetHint helper)
- Checklist debug bug mới +2 entries (24-25)
- Session log NEW docs/changelog/sessions/2026-05-19-s25-pe-history-visibility.md (~360 LOC)
- 4 agent MEMORY drift sync:
  - investigator/MEMORY.md (30→32KB) FIFO entry S25 wrap + count metadata
  - implementer/MEMORY.md (34→36KB) FIFO entry + patterns 16-18 saved
  - reviewer/MEMORY.md (31→32KB) FIFO entry + lesson SQLite tie-break + UAT skip risk reinforced
  - cicd-monitor/MEMORY.md (~72KB CRITICAL OVER) — 7 Run entries #215-#221 + curate flag MAX

Memory user-level +2 NEW entries (separate commit memory dir, KHÔNG trong this commit):
- feedback_fe_merge_synthetic_audit.md (Plan AC2 pattern)
- feedback_fe_usermap_fallback.md (Plan AF pattern)

Stats final S25:
- 31 mig (no schema) · 59 tables · ~146 endpoints · 35 FE pages
- 111 test unchanged (UAT defer test-after per §7)
- 49 gotcha (+2: #48 + #49)
- 23 memory user-level (+2 NEW S25 patterns)
- 6 skills · 4 sub-agents active
- 7 commits cumulative S25 · 7 CICD Runs (1 FAIL caught + 6 PASS)
- 6× bundle rotate × 2 app (Run #220 BE-only unchanged)

Critical pending S26+:
- Memory curate cicd-monitor PRIORITY MAX (~72KB strongly over hard threshold)
- Plan B Contract V2 wire HIGH priority (5-6 chunk pre-allocated S23 HANDOFF)

Per §6.5 KEEP narrative — KHÔNG cut rationale/gotcha context, chỉ phân tầng prepend latest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-21 16:33:41 +07:00
parent 506cada86b
commit 0c6efdaf4f
8 changed files with 453 additions and 8 deletions

View File

@ -775,6 +775,67 @@ paths-ignore:
- CICD Monitor Run #187 (S21 t5 2026-05-13 20:12) — confirmed pattern + cache stale bonus
- Memory `feedback_multi_agent_setup` Plan G Trial Week 1 evidence
### 48. Multi-Changelog.Add() trong cùng SaveChangesAsync → SQLite frozen-clock tie-break → tests `OrderByDescending(CreatedAt).First()` non-deterministic (Session 25 Plan AB + Run #215 catch)
**Triệu chứng:** Plan AB Chunk A `cdfd542` add SECOND Changelog.Add() entry vào `ApplyReturnModeAsync` (cover Bug 2 — Return mode log) end-of-function. Caller `TransitionAsync:100` đã có sẵn `LogTransitionAsync` add FIRST Changelog entry (Action=Transition + ContextNote=comment chứa "không lùi được"). 2 entries cùng `SaveChangesAsync` transaction → SQLite test fixture frozen clock → CreatedAt **identical microseconds** cho cả 2 rows.
Plan M edge case tests (S23 t3) query `.OrderByDescending(c => c.CreatedAt).FirstAsync()` assert `ContextNote.Contains("không lùi được")` — sau Plan AB, SQLite tie-break non-deterministic, pick Plan AB row (EntityType=Workflow, Action=Update, ContextNote=null) → `Expected ContextNote not to be <null>` FAIL.
**CI Run #215 sha=cdfd542** test_infra FAIL 2/53 (51 PASS, 2 FAIL):
- `ApplyReturnMode_OneStep_AtStep1_ResetsToBuoc1Cap1_KeepsChoDuyet` (line 350)
- `ApplyReturnMode_OneLevel_AtStep1Level1_ResetsToBuoc1Cap1_KeepsChoDuyet` (line 308)
Test gate caught regression → deploy never reached → prod spared broken state.
**Fix Option A (chốt):** Test query filter by `Summary.Contains("Chuyển phase")` để pick đúng LogTransition entry. Plan AB BE code stays clean.
```csharp
// Trước Plan AB Chunk A2:
var changelog = await db.PurchaseEvaluationChangelogs
.Where(c => c.PurchaseEvaluationId == pe.Id)
.OrderByDescending(c => c.CreatedAt)
.FirstAsync();
// Sau Plan AB Chunk A2 fix (commit 8c05947):
var changelog = await db.PurchaseEvaluationChangelogs
.Where(c => c.PurchaseEvaluationId == pe.Id && c.Summary!.Contains("Chuyển phase"))
.OrderByDescending(c => c.CreatedAt)
.FirstAsync();
```
**Pattern reusable:** Khi handler/service add NEW Changelog row trong existing flow đã có LogTransition row, tests query audit table MUST filter EntityType / Action / Summary keyword **discriminator** thay vì raw OrderByDescending timestamp. Cross-ref Contract V2 test setup tương lai.
**Severity:** Major — caught by CI before prod ship, no user impact. Lesson reinforced UAT mode `feedback_uat_skip_verify` skip `dotnet test` per chunk RISK khi BE refactor > 100 LOC + signature change → em main resumed local test verify post Plan AB Chunk A2.
**References:**
- Plan AB Chunk A commit `cdfd542` (Run #215 FAIL)
- Plan AB Chunk A2 fix commit `8c05947` (Run #216 PASS)
- Memory `feedback_uat_skip_verify` lesson reinforced S25
- File: `tests/SolutionErp.Infrastructure.Tests/Services/PurchaseEvaluationWorkflowServiceReturnModeTests.cs:304-310, 346-352`
### 49. UI dual-phase badge `fromPhase → toPhase` gây nhầm khi 3/4 Reject mode giữ Phase=ChoDuyet (Session 25 Plan AD)
**Triệu chứng:** Bro UAT 2026-05-19 Plan AC deploy: panel "Lịch sử duyệt" 6 entries TẤT CẢ hiện `Đã gửi duyệt → Đã gửi duyệt` (vì 3 mode Return OneLevel/OneStep/Assignee giữ Phase=ChoDuyet sau Mig 28 — chỉ Drafter mode set TraLai). Reject entry visually IDENTICAL Approve entry → user nhầm "Đã trả lại nhưng vẫn hiện đã duyệt".
**Fix Plan AD (commit `0aaf2df`):**
1. **Drop fromPhase → toPhase badges entirely** trong ApprovalsTab (cả `fe-user` + `fe-admin` mirror §3.9). Visual confusion gỡ bỏ.
2. **Thay bằng next-target hint parse từ comment** via helper `extractNextTargetHint(decision, toPhase, comment)`:
- **Approve:** Summary "sang Cấp X" → "→ Cấp X", "sang Bước Y" → "→ Bước Y (Cấp 1)", "Duyệt vượt cấp" → "→ Vượt cấp tới Cấp cuối", toPhase=DaDuyet(20) → "→ Đã duyệt hoàn tất"
- **Reject:** ContextNote "Người chỉ định" → "→ Trả về Người chỉ định (Bước X Cấp Y)" parse regex, "Người soạn thảo"/"Drafter" → "→ Trả về Người soạn thảo", "không lùi được" → "→ Không lùi được", "Trả về 1 Cấp"/"Trả về Cấp X" → "→ Lùi về Cấp X", toPhase=TuChoi(99) → "→ Từ chối hoàn toàn"
3. **Decision badge** (Plan AC `a734bf2` đã add): Duyệt emerald / Trả lại amber / Từ chối rose — phân biệt Action level KHÔNG dựa vào phase.
**Pattern reusable cross-project:** UI audit history KHÔNG nên render dual-phase badge khi state machine self-loop (e.g. ChoDuyet → ChoDuyet là advance pointer trong cùng phase, KHÔNG phải transition). Thay bằng Decision badge + semantic next-target hint parse từ structured comment.
**Severity:** UX confusion (KHÔNG functional bug). Bro UAT phản hồi sau Plan AC deploy.
**References:**
- Plan AD commit `0aaf2df` (Run #219 PASS)
- File: `fe-user/src/components/pe/PeDetailTabs.tsx:1995-2070` (ApprovalsTab + decisionBadge + extractNextTargetHint)
- Mirror: `fe-admin/src/components/pe/PeDetailTabs.tsx`
## Checklist debug bug mới
1. Build pass không? → fail → check using + package version compat
@ -800,3 +861,5 @@ paths-ignore:
21. Nếu user phàn nàn "feature work cho admin nhưng user empty/403 silent" → check class-level Authorize policy có over-restrict cho non-admin không, split per action (#44)
22. Nếu button workflow label nói "Trả lại" nhưng phiếu vẫn tiến approve → audit FE `isReject` payload condition vs button `isSendBack` label condition vs dialog `isSendBack` warning condition — phải sync 3 chỗ với CÙNG set target phase. BE thêm guard `(target ∈ terminalSet) ⇔ (decision=Reject)` chặn caller mismatch (#45)
23. Nếu Gitea Actions API trả 404 trên `/actions/runs` → đúng path là `/actions/tasks` (Gitea naming khác GitHub). Cache `updated_at` stale ~2 min → cross-check VPS file LastWriteTime cho time-sensitive verify (#46)
24. Nếu test `OrderByDescending(CreatedAt).First()` query audit table fail sau add Changelog mới → SQLite frozen-clock tie-break, MUST filter Summary/EntityType discriminator (#48)
25. Nếu UI audit list show `Đã gửi duyệt → Đã gửi duyệt` lặp gây nhầm → drop dual-phase badge khi state machine self-loop, thay Decision badge + next-target hint parse từ comment (#49)