[CLAUDE] Docs: Chunk N4 — S23 t4 Plan N HOTFIX wrap: docs + session log + 2 agent MEMORY drift
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m25s
Plan N 2 commits:
- N1+N2 atomic (commit 0326458) BE fix line 765 ApproverUserId discriminator + 2 regression test
- N4 (this) docs + memory update
Docs update:
- docs/STATUS.md — Last updated S23 t4 + stats 108 test (+2 từ 106)
- docs/HANDOFF.md — TL;DR S23 t4 với Investigator pre-flight catch root cause
- docs/changelog/sessions/2026-05-15-s23-turn4-plan-n-per-nv-lookup-bug.md — Session log Plan N
Memory user-level update (1 entry CRITICAL HOTFIX section):
- feedback_per_nv_permission_scope.md — Wire checklist 9 surface points (NOT 8)
+ Point 9 mới: Handler lookup site `currentLevelOptions` MUST discriminate
ApproverUserId. 3× cumulative gap analysis Mig 29 + 30 + 31.
Agent MEMORY drift (auto-flush):
- Investigator (.claude/agent-memory/investigator/MEMORY.md) — S23 t4 spawn N0
audit Hypothesis B verdict + sqlcmd verify + API curl verify
- CICD Monitor (.claude/agent-memory/cicd-monitor/MEMORY.md) — S23 t3 Plan M
Run #200 anomaly note (docs-only trigger CI mặc dù paths-ignore)
Stats final S23 t4:
- 31 mig · 59 tables · ~145 endpoints · 34 FE pages
- **108 test PASS (+2: per-NV lookup discrimination regression)**
- 47 gotcha · 20 memory (1 entry reinforced CRITICAL section)
- 6 skills · 4 sub-agents (1 Investigator spawn ~80K)
- 2 commits Plan N `0326458..HEAD` ready push
Pending: CICD Monitor post-deploy verify Plan N
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -0,0 +1,166 @@
|
||||
# Session 23 turn 4 — 2026-05-15 — Plan N HOTFIX per-NV lookup site discrimination
|
||||
|
||||
**Dev:** Claude Opus 4.7 1M (4 sub-agents active + em main coordinator)
|
||||
**Duration:** ~1h
|
||||
**Base commit:** `f4055a1` (S23 t3 Plan M wrap)
|
||||
**Final HEAD:** `<pending>` (Plan N batch + docs)
|
||||
**Total commits Plan N:** **2** (atomic N1+N2 BE+test + N4 docs)
|
||||
|
||||
## 🎯 Trigger session
|
||||
|
||||
Bro UAT screenshot post-Plan M deploy phát hiện disconnect cực nghiêm trọng:
|
||||
|
||||
> "Hiện User UAT test v2 vẫn chưa thấy cho chuyển tiếp đến người cuối hoặc các option trả lại trong menu Duyệt NCC → Duyệt → Chưa thấy xuất hiện option duyệt thẳng, trả lại theo option và cho Edit"
|
||||
|
||||
4 screenshots evidence:
|
||||
- **Workflow Designer:** Admin tick TRUE 7 flag cho NV Test (UAT V2) slot Bước 2 Cấp 1, 3 NV khác CHỈ Drafter flag
|
||||
- **Dialog ✓ Duyệt:** Chỉ có "Ghi chú (tùy chọn)" + Xác nhận — KHÔNG có checkbox F2 skipToFinal
|
||||
- **Dialog ← Trả lại:** Chỉ có 1 radio "Trả về Người soạn thảo (mặc định)" — KHÔNG có 3 mode F1 khác (OneLevel/OneStep/Assignee)
|
||||
- **PE detail UI:** KHÔNG có F3 Edit Section 2 + F4 Edit ngân sách
|
||||
|
||||
## 🔍 Investigator pre-flight audit (~80K spawn, Hypothesis B verify)
|
||||
|
||||
🟦 Investigator spawn audit DB + API + FE wire cross-stack:
|
||||
|
||||
**API curl verify (admin token):**
|
||||
- GET `/api/purchase-evaluations/<id>` → `currentLevelOptions = {allowReturnToDrafter: true, 6 flag khác: false}` — KHÔNG match flag admin tick cho NV Test
|
||||
- GET `/api/approval-workflows-v2/<wfId>` → 4 Level cùng Order=1, NV Test slot có 7 flag TRUE, 3 NV khác CHỈ AllowReturnToDrafter=true
|
||||
|
||||
**sqlcmd prod verify:**
|
||||
- Schema `ApprovalWorkflowLevels` 4 rows cùng (ApprovalWorkflowStepId, Order=1) trong Step 2 — đúng OR-of-N Mig 29 pattern
|
||||
- NV Test (UAT V2) row có 7 flag TRUE: AllowReturnOneLevel + OneStep + ToAssignee + ToDrafter + EditDetails + EditBudget + SkipToFinal
|
||||
- 3 NV khác chỉ AllowReturnToDrafter=true
|
||||
|
||||
**FE wire grep verify:**
|
||||
- `fe-user/src/components/pe/PeWorkflowPanel.tsx:51,335-425` đọc `evaluation.currentLevelOptions.allow*` đúng tên field, conditional render đủ
|
||||
- `fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx:889-946` Designer wire 7 checkbox per slot đúng
|
||||
|
||||
**Verdict: HYPOTHESIS B confirm — BE handler bug line 765:**
|
||||
|
||||
```csharp
|
||||
// BUG ([PurchaseEvaluationFeatures.cs:765])
|
||||
var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);
|
||||
```
|
||||
|
||||
Schema Mig 29 (S21 t5 2026-05-13) refactor: 1 `ApprovalWorkflowLevel` row per `ApproverUserId` (OR-of-N cùng Order). 4 NV cùng Cấp = 4 row có `Order=1`. `FirstOrDefault(Order==X)` không có discriminator → **luôn lấy row đầu DB** (Trần Xuân Lưu / Lê Văn Bính / etc. tuỳ ordering EF nội bộ, đều chỉ Drafter flag) → bỏ qua admin tick per-NV của NV Test.
|
||||
|
||||
**Bug present từ Mig 29 deploy 2026-05-13** (2 ngày prod) nhưng chỉ bộc lộ khi lần đầu admin tick selectively per-NV. Trước đây tất cả slot FALSE → behavior giống nhau (mọi actor đều thấy "không có options"), không lộ.
|
||||
|
||||
## 🌳 Plan N 2 chunk execution
|
||||
|
||||
### Chunk N1 + N2 — BE fix + regression test (atomic commit)
|
||||
|
||||
👤 Chủ trì Solo (bug fix reasoning chain cross-stack — Implementer auto-refuse criteria #4).
|
||||
|
||||
**N1 BE fix ([PurchaseEvaluationFeatures.cs:765-781](src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs:765)):**
|
||||
|
||||
```diff
|
||||
- var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);
|
||||
+ // Match actor.UserId trong slot (per-NV admin opt-in flag).
|
||||
+ // Admin / non-approver fallback row đầu (giữ behavior view detail).
|
||||
+ var curLevel = curStep?.Levels.FirstOrDefault(l =>
|
||||
+ l.Order == curLevelOrder && l.ApproverUserId == currentUser.UserId)
|
||||
+ ?? curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);
|
||||
```
|
||||
|
||||
5 LOC delta. `ICurrentUser currentUser` đã có DI sẵn line 652.
|
||||
|
||||
**N2 Regression test (`tests/SolutionErp.Infrastructure.Tests/Application/GetPurchaseEvaluationCurrentLevelOptionsTests.cs`):**
|
||||
|
||||
2 test method (~210 LOC test new file):
|
||||
- `GetPe_PerNvLookup_ActorMatchesSlot_ReturnsActorSpecificFlags`:
|
||||
- Seed 1 Workflow + 1 Step + 4 Level cùng Order=1, mỗi Level distinct flag profile (A=Drafter / B=OneLevel / C=SkipToFinal / D=EditBudget)
|
||||
- 4 actor scenarios → assert mỗi actor nhận flag-set RIÊNG (KHÔNG profile khác)
|
||||
- Critical assertion: Actor C → `AllowApproverSkipToFinal=true` (regression bug bro UAT)
|
||||
- `GetPe_PerNvLookup_AdminNonApprover_FallsBackToFirstRow`:
|
||||
- Admin actor (KHÔNG match) → fallback FirstOrDefault EF SQLite non-deterministic ordering
|
||||
- Weak assertion: NOT null + match 1 trong 4 distinct profile (mỗi Level distinct flag → fallback pick exactly 1)
|
||||
|
||||
**Verify:**
|
||||
- `dotnet build src/Backend/SolutionErp.Application` clean (0 warning, 0 error)
|
||||
- `dotnet test SolutionErp.slnx` **108/108 PASS** (+2 từ 106: 58 Domain + 50 Infra)
|
||||
- 2 test scenario N2 PASS individually + full suite no regression
|
||||
|
||||
### Chunk N4 — Docs + memory update + commit (this commit)
|
||||
|
||||
- `docs/STATUS.md` Last updated S23 t4 entry
|
||||
- `docs/HANDOFF.md` TL;DR S23 t4 đầy đủ
|
||||
- Session log file này
|
||||
- Memory user-level `feedback_per_nv_permission_scope.md` reinforcement S23 t4 wire checklist 9 surface points (NOT 8)
|
||||
|
||||
## 📊 Stats Plan N chốt
|
||||
|
||||
| Metric | Trước (S23 t3) | Sau (S23 t4) | Δ |
|
||||
|---|---|---|---|
|
||||
| DB tables | 59 | 59 | 0 |
|
||||
| Migrations | 31 | 31 | 0 |
|
||||
| Endpoints | ~145 | ~145 | 0 |
|
||||
| FE pages | 34 | 34 | 0 |
|
||||
| **Unit tests** | 106 | **108** | **+2** (per-NV lookup discrimination regression) |
|
||||
| Gotchas | 47 | 47 | 0 |
|
||||
| Memory entries | 20 | 20 | 0 (1 entry `feedback_per_nv_permission_scope.md` reinforced — wire 9 points checklist) |
|
||||
| Skills | 6 | 6 | 0 |
|
||||
| Sub-agents | 4 | 4 (1 Investigator spawn ~80K) | active |
|
||||
| Commits Plan N | — | **2** (atomic N1+N2 + N4 docs) | pending push |
|
||||
|
||||
## 🎯 Multi-agent ROI evidence Plan N
|
||||
|
||||
| Spawn | Agent | Cost (tokens) | Output | Catch |
|
||||
|---|---|---|---|---|
|
||||
| Pre-flight | 🟦 Investigator | ~80K | Hypothesis B verdict + file:line + DB sqlcmd verify + API curl verify + FE wire grep verify | **Critical root cause** — em main lần đầu hypothesize 3 candidates (A: admin chưa tick + B: BE handler bug + C: FE wire bug), Investigator confirm B với evidence-based file:line, avoid em main spam fix WRONG |
|
||||
| N1 fix | 👤 Chủ trì | ~self | 5 LOC BE Service handler line 765 | — |
|
||||
| N2 test | 👤 Chủ trì | ~self | 210 LOC test new file 2 scenario | First iteration EF SQLite ordering non-deterministic → fix weak assert fallback test |
|
||||
| Reviewer | (skip) | 0 | — | LOW effort 5 LOC BE + isolated test, em main solo per criteria small scope < 30 min |
|
||||
| Post-deploy | 🟩 CICD Monitor | TBD (pending) | Bundle hash + smoke + sqlcmd | Spawn sau push |
|
||||
|
||||
**Total Plan N spawn cost (excl CICD):** ~80K tokens — Investigator chính, em main solo execute.
|
||||
|
||||
**Multi-agent value caught:**
|
||||
1. **Investigator catch root cause precisely** — file:line + sqlcmd + API + FE evidence-based. Em main solo có thể đã spawn fix sai (vd suspect admin chưa tick → ask bro re-tick → vô ích vì admin đã tick đúng).
|
||||
2. **3-spawn cumulative pattern caught** — Mig 29 + 30 + 31 + Plan N reveal: 3× refactor wire 8 surface points đúng nhưng MISS point 9 lookup discrimination. Pattern reinforced cho future flag F5+.
|
||||
|
||||
## ⚠️ Pattern reinforced — Per-NV admin opt-in wire 9 surface points (KHÔNG 8)
|
||||
|
||||
**Old (S23 t1 K9 catch — 8 points):** Mig 29 + 30 + 31 wire checklist 8 points (Domain + EF config + Mig 3-file + Service guard + PE bundle DTO + Admin AwLevelDto + CreateAwLevelInput + FE Designer).
|
||||
|
||||
**NEW S23 t4 Plan N catch:** Thêm point 9:
|
||||
|
||||
> **9. Handler lookup site `currentLevelOptions` MUST discriminate `ApproverUserId == currentUser.UserId`** (fallback row đầu cho admin/non-approver). Áp dụng cho TẤT CẢ handler đọc Allow* flag từ Level slot khi schema OR-of-N approvers cùng Cấp.
|
||||
|
||||
**Audit checklist trước commit cho future flag F5+:**
|
||||
- [ ] Grep `FirstOrDefault.*Order ==` trong codebase → enumerate all lookup sites
|
||||
- [ ] Verify mỗi site có discriminator role-context (ApproverUserId hoặc role-specific column)
|
||||
- [ ] Test regression: seed N rows cùng Order × N actor distinct → assert actor-specific flag returned
|
||||
|
||||
**3× cumulative gap analysis (Mig 29 + 30 + 31):**
|
||||
|
||||
| Migration | Wire 9 points | Bug surface | Caught when |
|
||||
|---|---|---|---|
|
||||
| Mig 29 F1+F3 | 1-8 OK, **9 GAP** | Lookup row đầu DB | Plan N S23 t4 (2 ngày prod) |
|
||||
| Mig 30 F4 | 1-8 OK, **9 GAP** | Same | Same (cumulative) |
|
||||
| Mig 31 F2 | 1-8 OK, **9 GAP** | Same | Same |
|
||||
|
||||
→ 3× cumulative refactor wire SAME bug — point 9 lookup discrimination chưa có precedent → em main + Reviewer + Implementer all MISS xuyên 3 plan.
|
||||
|
||||
## ⏭ Pending S23 t5+
|
||||
|
||||
- 🟩 **CICD Monitor post-deploy verify** — spawn sau push remote
|
||||
- 🟦 **Investigator follow-up gotcha #41/#48 candidate** controlled test paths-ignore (carry from Plan M)
|
||||
- 🟡 **Plan B Contract V2 wire (Mig 32+33)** — HIGH priority next
|
||||
- ⛔ **Plan F drop V1** — defer sau Plan B + UAT 2-3 tuần
|
||||
- 🟢 **Plan H PE PDF Export** — LOW priority carry
|
||||
- 🟡 **Plan I RAG Hybrid setup** — defer chờ bro confirm
|
||||
- 🔧 **Gotcha #47 paths-ignore agent-memory** — PENDING bro confirm
|
||||
|
||||
## 📋 Pattern reinforced Plan N
|
||||
|
||||
1. **Per-NV admin opt-in flag wire 9 surface points (NOT 8)** — point 9 handler lookup discrimination added. Memory user-level `feedback_per_nv_permission_scope.md` updated CRITICAL HOTFIX S23 t4 section.
|
||||
2. **Investigator pre-flight audit BẮT BUỘC cho bug fix cross-stack** — em main solo có thể spam fix WRONG hypothesis. Investigator file:line + sqlcmd + API + FE grep evidence base.
|
||||
3. **Atomic commit BE fix + regression test cùng commit** (per `feedback_uat_skip_verify` updated rule Plan L lesson) — Service semantic refactor BẮT BUỘC test cùng commit.
|
||||
4. **EF SQLite non-deterministic ordering** test gotcha — weak assertion cho fallback path (NOT null + match 1 distinct profile), KHÔNG assume "row đầu" deterministic.
|
||||
|
||||
## References
|
||||
|
||||
- Memory user-level updated: `feedback_per_nv_permission_scope.md` CRITICAL HOTFIX S23 t4 section
|
||||
- Files: [PurchaseEvaluationFeatures.cs:765-781](src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs:765) (N1) + [GetPurchaseEvaluationCurrentLevelOptionsTests.cs](tests/SolutionErp.Infrastructure.Tests/Application/GetPurchaseEvaluationCurrentLevelOptionsTests.cs) (N2)
|
||||
- Rules: §3.9 mirror 2 FE, §7 test timing test-before (regression bug), `feedback_per_nv_permission_scope` (S23 t4 wire 9 points), `feedback_uat_skip_verify` (Plan L Service refactor + test atomic)
|
||||
Reference in New Issue
Block a user