[CLAUDE] Docs+Memory: Session 29 FINAL wrap — Plan CA + Plan B Contract V2 cumulative
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m31s

20 commits S29 push 4 CI Runs PASS (#229+#230 Plan CA, #231+#232 Plan B).
2 big plans END-TO-END deployed prod.

Changes (docs + memory + scripts — CI skip per paths-ignore):

docs/:
- STATUS.md: S29 FINAL wrap header với cumulative summary 20 commits +
  multi-agent ROI ~565K + 8 patterns NEW + state stats (33 mig, 60 tables,
  51 gotcha, 14 AppRoles, 34 active users, 4× bundle rotate)
- HANDOFF.md: S29 FINAL wrap header với end-to-end V2 capability + pending S30+
  follow-up (anh restart CLI MCP RAG hot-reload, UAT verify V2, test bundle
  Plan B, curate dedicated session)
- gotchas.md: +gotcha #51 INFRASTRUCTURE vs DEMO seed phân biệt (Plan B
  Hotfix CICD lesson) với decision tree + seed classification table
- changelog/sessions/2026-05-22-s29-plan-ca-plan-b-contract-v2-wire.md:
  Session log đầy đủ 20 commits + 4× Smart Friend pattern proven + 8
  patterns NEW + file-touched list + NEW capability end-to-end test plan

.claude/agent-memory/:
- 4 MEMORY.md flush S29 wrap entry FIFO each agent perspective:
  - Investigator (25.2 KB just over threshold) — Plan CA + Plan B pre-flight
    2 spawn + 3 patterns NEW (terrain map, V1+V2 coexist, reference templates)
  - Implementer (35.4 KB over hard threshold, defer curate S30) — 5 spawn
    cookie-cutter + E3 stopped + Pattern 12-bis NEW (cross-module entity mirror)
  - Reviewer (23.0 KB compacted) — 4 spawn 2 MAJOR catches + Cat 3 security
    cross-module validation foundation reinforced
  - CICD Monitor (24.9 KB) — 4 Runs verify + CRITICAL DemoSeed gate catch +
    Stage 4.6 sqlcmd seed verify foundation + Discovery #6 gotcha #51 cross-ref
- implementer/pattern_master_page_mirror.md (NEW Plan CA Chunk B Pattern 16-bis)

scripts/:
- plan-ca-{verify-menu,verify-perms,run-perms}.{sql,ps1} (5 verify scripts)
- plan-b-{verify-prod,run-verify}.{sql,ps1} (2 verify scripts)

Smart Friend pattern proven 4× cumulative S22 #44 + S25 #48 + S29 Reviewer
#ApplicableType + S29 CICD #DemoSeed.

Pending S30+:
- Anh restart CLI hot-reload MCP RAG cho 4 sub-agents (commit b51fc94)
- Anh UAT verify V2 contract end-to-end (Drafter → CCM approve → DaPhatHanh)
- Test bundle Plan B (regression ApproveV2Async + ApplicableType validation)
- Curate dedicated session 4 MEMORY (Implementer 35.4 KB priority)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-22 13:29:49 +07:00
parent 38f1c4d2d9
commit e199603420
22 changed files with 2216 additions and 153 deletions

View File

@ -129,16 +129,26 @@ State machine 5 trạng thái phiếu PE: Nháp / Đã gửi duyệt / **Trả l
## 📅 Recent activity (last 10 FIFO)
- **2026-05-15 (S24 t1 spawn Pre-A Plan AA User Workflow Matrix view + sidebar widen):** 5Q audit. Q1 endpoint: `ApprovalWorkflowsV2Controller.cs:16-19` đã class-level `[Authorize]` bare từ S18 2026-05-08 (gotcha #44 fixed permanent), per-method admin Workflows.Create. Handler `GetAwAdminOverviewQuery` KHÔNG có IsUserSelectable filter — cần ADD param + Where conditional. Q2 menu seed: `DbInitializer.cs:1429-1437` peOrder global increment (Group=1, leaves 2/3/4 cycle per type). Permission seed `line 1541-1547` cho 7 role (Drafter/DeptManager/Procurement/CostControl/ProjectManager/Director/AuthorizedSigner). Accounting NOT trong list — admin manual grant nếu cần. Q3 Admin Designer: `ApprovalWorkflowsV2Page.tsx` 975 lines, AwLevelDto 13 fields (7 Allow*), VI labels line 892-948 ("Trả về 1 Cấp trước"/"Trả về 1 Bước trước"/"Trả về Người chỉ định"/"Trả về Drafter (mặc định)"/"Cho phép chỉnh sửa Section 2 (Hạng mục/NCC/Báo giá) lúc đang duyệt"/"Cho phép chỉnh sửa Section ngân sách lúc đang duyệt"/"Cho phép duyệt thẳng Cấp cuối khi đang duyệt"). KHÔNG có usePermission/PermissionGuard wrap (class-level [Authorize] route guard sufficient). Q4 sidebar widen: fe-user `Layout.tsx:325` + fe-admin `Layout.tsx:218` `w-60 xl:w-72` (240/288px). PE Workspace 2-panel `[260px_1fr] xl:[320px_1fr]` (NOT 3-panel như memory `feedback_responsive_laptop_breakpoint` stale claim). After widen `w-72 xl:w-80` (288/320px) SAFE (sidebar 288 + main 992 → workspace 260+732 fit @ 1280px). `w-80 xl:w-96` THRESHOLD RISKY (sát 700px remaining). Q5 ApplicableType enum `ApprovalWorkflow.cs:45-50` {DuyetNcc=1, DuyetNccPhuongAn=2, Contract=3}. Surprises: (1) memory responsive breakpoint stale "3-panel" → cần update sau Plan AA. (2) Order strategy "Luồng duyệt" Order=2 first → shift existing leaves +1 → cần DbInitializer UPDATE Order existing (KHÔNG chỉ INSERT-if-not-exists). (3) Contract=3 chưa wire FE (chỉ DuyetNcc + DuyetNccPhuongAn). Recommendation: Proceed Plan AA — chỉ ADD param filter + 1 menu key + page mới + sidebar widen. Token cost ~32k.
- **2026-05-15 (S24 t1-t4 post-spawn, em main solo 4 polish chunks — Plan AA wrap):** 7 commits total `a1a910f..ee0902a`: BE+Layout (`ee776d5`) + FE Page (`c667802`) + Docs (`ac2c859`) + 4 polish iter UAT (`da218f1` px-2 + `4d60598` v1 panel-per-NV + `fbbd361` v2 table rowSpan + `ee0902a` sidebar label wrap). **Pattern reusable**: `inline-block icon + inline text + absolute ChevronDown` cho hanging-indent reverse wrap (label dài về đầu hàng). Mirror admin Designer style cho user view read-only. **Sidebar widen tradeoff**: `w-72 xl:w-80` + remove `truncate` FAIL fit 44+ chars label custom Mig 27 — cần combine với `text-[12px] + leading-snug` + restructure flex → block + inline. Sole `truncate` removal không đủ — phải full layout restructure NavLink. **Memory drift confirmed**: `feedback_responsive_laptop_breakpoint.md` claim "PE Workspace 3-panel" → S24 verify ACTUAL **2-panel** (260+1fr only, KHÔNG có panel thứ 3). Cross-ref update needed memory user-level (admin trigger curate sau). **Plan AA color palette success**: STEP_PALETTE 5 màu (blue/purple/emerald/amber/pink) + LEVEL_PALETTE 5 màu (violet/sky/teal/orange/rose) — **Tailwind JIT yêu cầu full class strings array, KHÔNG dynamic interpolation** (`bg-${color}-100` FAIL — class purged). Reusable cross-project cho menu hierarchy color coding (step parent + level child distinct palette). Final layout v2 table rowSpan: Step column merge per-Phòng + Level column rowSpan per-Cấp + NV column 1-row-per-approver, đẹp hơn v1 panel-per-NV stacked. Token cost iteration negligible (em main solo, no spawn).
- **2026-05-15 (S23 t8 spawn Plan R pre-flight cleanup audit):** Bro chốt cleanup destructive prod. 4 sqlcmd queries audit: 35 PE total (28 active + 7 soft) + 17 V2 (15 IsUserSelectable=false + 2 ghim) + 4 V1 (2 active + 2 inactive). FK gotcha catch: PE.ApprovalWorkflowId Restrict + ApprovalWorkflow extends `BaseEntity` NO soft-delete → hard-DELETE required; LevelOpinion → ApprovalWorkflowLevel Restrict cascade block. SQL Express limit: NO COMPRESSION + RESTORE VERIFYONLY require sysadmin. Filtered indexes (Mig 29+) require `SET QUOTED_IDENTIFIER ON`. Cascade child estimate: 446 PE children + ~140 V2 + ~37 V1 = ~620 rows. 3 Option compare → bro chốt A (Hard-DELETE PE + V2 unghim + V1 inactive, GIỮ V2 ghim + V1 active). Plan F precedent: KHÔNG drop V1 active (PE pin → BE crash).
- **2026-05-15 (S23 t6 spawn Plan P FE wire audit — confirm BE-only scope):** Em main hypothesize Plan P scope BE Controller body record drop. Investigator audit FE × 2 confirm: `PeWorkflowPanel.tsx:113-124` `api.post(/transitions, body)` SEND ĐÚNG 7 fields (TargetPhase + Decision + Comment + ReturnMode + ReturnTargetUserId + SkipToFinal). No service file (untyped object literal). BE `PurchaseEvaluationsController.cs:267` `TransitionPeBody` record CHỈ 3 fields → ASP.NET silent DROP 3 missing fields. Verdict: Plan P BE Controller ONLY ~6 LOC + no test (Mig 28/31 Domain test cover handler). Saved em main blind fix cross-stack.
- **2026-05-15 (S23 t3 spawn — UAT bug Allow* flags không hiện cho actor non-row1):** Bro UAT login `nv.test@solutions.com.vn` vào menu eoffice "Duyệt NCC → Duyệt" phiếu PE/2026/A/026 (Phase=ChoDuyet, WF=QT-DN-V2-001 v12, ở Bước 2 Cấp 1 4 NV: Trần Xuân Lưu/NV Test UAT V2/Hồ Thị Nữ Nguyên/Lê Văn Bính). Admin ĐÃ tick 7 Allow*=TRUE riêng cho slot NV Test UAT V2. Nhưng FE dialog Duyệt KHÔNG hiện checkbox SkipToFinal + Trả lại 4 mode + Edit. **Verdict: HYPOTHESIS B — BE handler picks wrong slot row.** Evidence: (1) `PurchaseEvaluationFeatures.cs:765` `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);` — match FIRST row có `Level.Order == curLevelOrder`, NOT actor's row. Post-Mig 29 refactor, Level.Order trùng nhau cho mọi NV cùng Cấp (4 row có `Order=1` ở Step 2). EF returns Trần Xuân Lưu trước (PK order) → `FirstOrDefault` lấy row đó (all-false except Drafter=true). (2) API curl admin token + nv.test token return CÙNG `currentLevelOptions={ allowReturnOneLevel=false, OneStep=false, Assignee=false, Drafter=true, EditDetails=false, EditBudget=false, SkipToFinal=false }` — handler currentUser-agnostic confirm. (3) Workflow detail GET `/approval-workflows-v2?applicableType=1` `.types[0].active.steps[1].levels` enumerate 4 slot Bước 2 Cấp 1: NV Test (UAT V2) = ALL 7 TRUE; 3 NV còn lại = ALL FALSE (trừ Drafter=true mặc định). Admin Designer wire ĐÚNG (`fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx:889-946` 7 checkbox per-slot). FE consumer wire ĐÚNG (`fe-user/src/components/pe/PeWorkflowPanel.tsx:51 levelOptions = evaluation.currentLevelOptions` + line 343/357/371/397 conditional render mode picker + line 425 SkipToFinal checkbox). **Root cause:** BE line 765 lookup semantic broken sau Mig 29 (S21 t5). Trước Mig 29, 1 Level row per Cấp + `ApproverUsers` join table → `FirstOrDefault(Order==X)` đúng. Sau Mig 29 split 1 Level row PER ApproverUser → `Order` field collide → cần match thêm `ApproverUserId == currentUser.UserId`. **Fix BE 1 dòng:** `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder && l.ApproverUserId == currentUser.UserId);` (admin bypass: fallback `?? curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder)` để admin xem detail không lỗi). Edge case: Phase=DaDuyet/TraLai/TuChoi pointer null → existing guard line 760-762 skip block OK. **LOC ~2-3 LOC 1 file.** Surprise: bug PRESENT từ deploy Mig 29 (S21 t5 2026-05-13) — không phải regression S23. Lý do trước đây không bắt: UAT test users (default 13 cũ) đa số là row đầu của slot Cấp (Admin tick toàn FALSE → behavior giống nhau, không lộ); chỉ bộc lộ khi admin tick CHỌN LỌC per-NV (UAT V2 S22+2 thêm 20 user role-based + bro tick chỉ NV Test UAT V2). Cross-reference memory `feedback_per_nv_permission_scope.md` cumulative S21 t5 → S22+5 → S23 t1 — KHÔNG có entry nào nhắc bug lookup BE post-refactor.
- **2026-05-15 (S23 t2 spawn M0 — Plan M F1+F2+F3+F4 ChoDuyet semantic audit):** Bro UAT post-Plan L deploy 2026-05-15 ~02:00: "Hiện logic cũ là khi trả lại 1 cấp hoặc chỉ định hoặc edit là trạng thái draft -> cái này thay đổi lại nhé, các tính năng duyệt thẳng, trả lại 1 cấp hoặc người chỉ định hoặc cho edit thì cho xử lý đc ở trạng thái đang gửi duyệt luôn." Audit 4 BE file + 4 FE file × 2 app cho F1+F2+F3+F4 phase semantic ChoDuyet preservation. **Verdict: CODE ĐÃ ĐÚNG semantic mới — đây là DISCONNECT bro mental model vs code reality post-Mig 28/29/30/31.** Evidence per feature: **F1.OneLevel** `PurchaseEvaluationWorkflowService.cs:285-312` SWITCH branch lùi 1 Cấp cùng Step (`curLevel-1`) ELSE lùi Step trước Cấp cuối; **Phase KHÔNG đổi** (giữ ChoDuyet, line 364 reset SLA only); fallback Drafter `:303-310` CHỈ KHI đang Bước 1 Cấp 1 no further back (clear pointer + Phase=TraLai). **F1.Assignee** `:335-360` foreach Steps find ApproverUserId match → set pointer; Phase giữ ChoDuyet; ConflictException nếu không tìm thấy NV trong workflow. **F1.OneStep** `:314-333` lùi prev Step Cấp max; Phase giữ ChoDuyet; fallback Drafter nếu đang Bước 1. **F1.Drafter** `:268-275` SET `Phase=TraLai=98` + clear cả 2 pointer + SLA null — đây là CASE DUY NHẤT về "draft". **F2 skipToFinal** `:483-524` Plan K L1 ĐÃ FIX advance pointer tới Bước cuối Cấp cuối (max), **Phase giữ ChoDuyet** (NV cuối duyệt thật để DaDuyet); guard line 485 ConflictException non-admin + flag off; opinion UPSERT trước line 441-468 ensure actor's signature lưu trước. **F3 EnsureEditableForDetailsAsync** `PurchaseEvaluationDetailFeatures.cs:42-99` 2 trường hợp accepted: Drafter scope (DangSoanThao/TraLai return pe sớm line 49-51) **OR Approver scope ChoDuyet line 54-94** (V2 schema + actor match level.ApproverUserId + level.AllowApproverEditDetails flag). **F4 AdjustPurchaseEvaluationBudgetCommandHandler** `PurchaseEvaluationFeatures.cs:272-329` Drafter scope `:283-290` (DangSoanThao/TraLai + isDrafter) ELSE Approver scope ChoDuyet `:291-323` (V2 + pointer init + actor match + level.AllowApproverEditBudget flag) — Phase ChoDuyet đã handle full. **Validation Allow* flag location** `PurchaseEvaluationWorkflowService.cs:252-265` ApplyReturnModeAsync gate per slot per mode: throw ConflictException nếu disabled (Admin bypass line 252). **FE PeWorkflowPanel.tsx**: TraLai dialog `:331-422` 4 radio button (OneLevel/OneStep/Assignee/Drafter) gated bằng `levelOptions?.allowReturnXxx` flag per current Approver Cấp (line 343-396); useEffect `:60-68` S23 t2 fix default first available mode KHÔNG Drafter khi admin tick F1 modes. Skip Final checkbox `:425-442` chỉ visible khi `levelOptions?.allowApproverSkipToFinal` + Approve forward direction (line 425). **FE PeDetailTabs.tsx F3+F4 wire**: `itemsReadOnly = readOnly && !approverEditMode` line 118 bypass readOnly khi F3 enabled (Mig 28 pattern); `canAdjust = isAdmin || (!readOnly && isDrafter && isDrafterPhase) || isApproverChoDuyet` line 977 bypass readOnly khi F4 enabled (L2 fix). Mirror fe-admin/fe-user line 109-115 + 967-979 ĐỒNG BỘ rule §3.9. **Surprise**: "Trả lại" trong UI memory docs đôi khi gọi "draft" colloquial — bro confuse 2 khái niệm `Phase=TraLai=98` (Drafter sửa rồi gửi LẠI từ Step 0) vs `Phase=DangSoanThao=1` (chưa từng gửi duyệt). KHÔNG code path nào trong F1 OneLevel/OneStep/Assignee/F2/F3/F4 set targetPhase=DangSoanThao mà không nên. **Recommendation: LOW effort** (0-20 LOC): chỉ cần communication clarification em main confirm với bro 4 mode F1 + F2 + F3 + F4 đã giữ Phase=ChoDuyet trừ F1.Drafter; mở DB SELECT phiếu UAT confirm `Phase` column number sau click test; OPTIONAL touch up FE label nếu user thấy "Đã gửi duyệt" nhầm "Bản nháp". KHÔNG cần Service refactor hay handler change. Nếu bro thấy phiếu cụ thể về Phase=1 SAU click F1.OneLevel hoặc F2 → spawn lại Investigator audit DB state + log Changelog cho phiếu đó cụ thể (data debug, not code bug).
- **2026-05-15 (S23 t2 spawn L2 — F3+F4 edit menu Duyệt audit):** Bug UAT prod 409a967: admin tick F3+F4 cho slot Approver, login actor user, vào menu "Duyệt" (`?pendingMe=1` cùng `PurchaseEvaluationsListPage` 3-panel), click PE Phase=ChoDuyet → Section 2 Hạng mục/NCC/Báo giá + Section 5 Điều chỉnh ngân sách vẫn read-only. **Root cause F3 = OK / F4 = BROKEN at readOnly short-circuit:** F3 wire ĐÚNG (`PeDetailTabs.tsx:118 itemsReadOnly = readOnly && !approverEditMode` override readOnly per Mig 28 S21 t4 → ItemsTab read prop OK). F4 wire SAI (`PeDetailTabs.tsx:245` passes `readOnly={readOnly}` (=true từ menu Duyệt) xuống BudgetAdjustSection, line 973 compute `canAdjust = !readOnly && (isAdmin || (isDrafter && isDrafterPhase) || isApproverChoDuyet)``!readOnly` short-circuits to false BEFORE F4 isApproverChoDuyet evaluate. Edit pencil button hidden line 1030 `{canAdjust && <Button>Điều chỉnh</Button>}`. Asymmetric vs F3 pattern Section 2 (PeDetailTabs.tsx:113-118). **Evidence:** FE F3 OK `fe-user/src/components/pe/PeDetailTabs.tsx:113-118` + `:224 ItemsTab ev={evaluation} readOnly={itemsReadOnly}`; FE F4 BUG `:957-973 BudgetAdjustSection !readOnly gate` + `:245 readOnly={readOnly}`; menu Duyệt route `fe-user/src/pages/pe/PurchaseEvaluationsListPage.tsx:256-261 PeDetailTabs readOnly={true}` (cùng route Danh sách); BE GetPe `PurchaseEvaluationFeatures.cs:735-770 currentLevelOptions populate 7 fields` OK; BE budget-adjust handler `:281-329` Phase ChoDuyet F4 branch + actor match + flag check ĐẦY ĐỦ + return ConflictException nếu Allow=false; BE PurchaseEvaluationDraftGuard.EnsureEditableForDetailsAsync ở `PurchaseEvaluationDetailFeatures.cs:42` (8 callsites Detail+Supplier handlers). **Recommendation:** Fix `BudgetAdjustSection` line 973 mirror approverEditMode pattern Section 2: thay `canAdjust = !readOnly && (isAdmin || ...)` thành `canAdjust = isAdmin || (!readOnly && isDrafter && isDrafterPhase) || isApproverChoDuyet` — Approver bypass readOnly khi F4 conditions met. **LOC ~3-5 LOC 1 file.** Surprise: Inbox `/inbox` route (InboxPage.tsx) navigate sang `/purchase-evaluations/:id` (mobile DetailPage route, default readOnly=false) — chỉ Danh sách `?pendingMe=1` desktop 3-panel mới hard readOnly=true.
- **2026-05-14 (S23 t1 spawn K0 — Plan K F2 refactor pre-flight):** Audit F2 state cho Plan K Mig 31 (move `Users.AllowDrafterSkipToFinal``ApprovalWorkflowLevels.AllowApproverSkipToFinal` + change semantic Drafter Nháp → Approver ChoDuyet skip thẳng Cấp cuối). **Confirmed state Mig 30:** Migrations path = `Persistence/Migrations/` (not direct `Migrations`); 30 mig latest = `20260513160703_AddAllowApproverEditBudgetToLevels`; `User.cs:38` AllowDrafterSkipToFinal prop; `ApprovalWorkflow.cs:86-105` 6 Allow* props (4 ReturnMode + EditDetails + EditBudget) per Level slot; F2 Drafter branch ở `PurchaseEvaluationWorkflowService.cs:119-161` trong SUBMIT branch (line 125 `if (skipToFinal && evaluation.ApprovalWorkflowId is Guid skipAwId)` check user.AllowDrafterSkipToFinal); APPROVE STEP branch ở `~line 393-525` (advance pointer). TransitionAsync signature: `skipToFinal` là param thứ 8 (position 47:47), default=false. `TransitionPurchaseEvaluationCommand``PurchaseEvaluationFeatures.cs:393-402` với param `SkipToFinal=false` default. `ApprovalWorkflowOptionsDto``PurchaseEvaluationDtos.cs:86-92` (6 field). `PurchaseEvaluationDetailBundleDto.DrafterAllowSkipToFinal` ở line 217 + `CurrentLevelOptions` ở line 214. UsersController `PATCH /users/{id}/allow-skip-final` ở line 91-98 + `SetAllowDrafterSkipToFinalBody` ở line 105. `SetUserAllowDrafterSkipToFinalCommand``UserFeatures.cs:332`. **FE state:** fe-admin Designer `system/ApprovalWorkflowsV2Page.tsx` slot label "NV #{ei + 1}" ở line 873 (KHÔNG phải "#NV {order}" theo prompt) — inline checkbox panel 5+1=6 checkbox ở line 853-933 (4 ReturnMode + EditDetails + EditBudget). fe-admin `system/UsersPage.tsx` "Skip cuối" column line 306-318 + FastForward button toggle line 365-372 + allowSkipMut hook line 181-186. fe-admin/fe-user PeDetailTabs Drafter Workspace checkbox "Gửi thẳng Cấp cuối (skip trung gian)" ở line 287-297 (admin) / 294-304 (user). **GAP fe-user**: KHÔNG có UsersPage + ApprovalWorkflowsV2Page (admin-only mgmt) → Plan K UI changes localized fe-admin chỉ; fe-user side chỉ touch PeDetailTabs (remove old Drafter checkbox + thêm Approver toggle near Duyệt button). **Drift Dev DB**: Total=2 user (admin + test.drafter), Flagged=0 — NOT match 33-user prod seed. **Prod actual**: Total=33 / Flagged=4 (NOT 2 per S22+2 spec). 4 user flagged sẽ lose value when DROP column — acceptable per new semantic (Drafter pre-submit moot).
- **2026-05-13 (S22, no spawn — em main solo throughout):** S22 18:00→~21:00 em main solo. Cumulative state: 30 mig (+1 Mig 30 `AddAllowApproverEditBudgetToLevels` F4 per-Level slot), 104 test PASS (+20: 5 reg #44 Authorize policy + 7 ReturnMode + 7 Guard + 1 V2 actor scope reject), ~146 endpoints (+3: PATCH /users/{id}/allow-skip-final + PATCH /pe/{id}/budget-adjust + GET /pe/{id}/attachments/{attId}/view), 46 gotcha unchanged, 19 memory unchanged (recommend +1 entry — see below). Prod active users 13→33 (+20 role-based: act.nv/pp/tp, bod.1/2, equ/fin/hra/pm/qs.nv/pp/tp). **Discoveries S22:** (1) **Per-NV admin opt-in flag pattern reinforced 2×** — Mig 30 F4 cùng pattern Mig 29 F1+F3 (S21 t5). Bro corrected em main lần đầu: "phải tick checkbox như Section 2", default = admin opt-in per slot, KHÔNG = mở rộng default. Cross-ref memory `feedback_per_nv_permission_scope.md` proven 2×. (2) **Plan F drop V1 ABORTED** — pre-flight sqlcmd reveal Contract entity HOÀN TOÀN V1 chưa wire V2 (chưa có ApprovalWorkflowId column) + 4 PE V1-only + 19 PE V1+V2 mix. Lesson: drop migration cần verify entity scope toàn bộ (Contract liên đới — không chỉ PE). (3) **Identity password policy ≥12 chars** — seed 20 user FAIL 400 với "User@123456" (11 chars), `TestUser@2026` (13 chars) pass. (4) **Identity rename atomic 4 fields** confirm gotcha #38: Email + NormalizedEmail + UserName + NormalizedUserName + FullName; sqlcmd cần `SET QUOTED_IDENTIFIER ON` cho filtered unique index. (5) **API login response field name `accessToken` + `refreshToken` + `user`** — KHÔNG có field `token` (correct prior Bash example trong spec dùng `.token` sẽ fail). (6) **PS 5.1 ASCII-only script discipline** reinforced gotcha #30: `seed-test-users-prod.ps1` viết Vietnamese names without diacritics tránh parser error. Recommend bro add 1 memory entry "Admin opt-in flag pattern proven 2×" cumulative Mig 29 + Mig 30.
- **2026-05-13 (S21 t3-t5, no spawn):** Em main solo 3 turns (bug fix gotcha #45 + F1+F2+F3 workflow-level Mig 28 + refactor per-NV Mig 29). Implementer REFUSE per cross-stack reasoning chain rule. Investigator KHÔNG spawn — em main đã có context cumulative S20 t12 setup + active dev throughout. No findings to flush. Cumulative state update: 84 test, 29 mig, 45 gotcha, 19 memory entries (+2 S21 t5 pending), 6 skills unchanged. Pattern reusable saved cho future spawn: per-NV permission scope split + EF migration ADD→BACKFILL→DROP reorder.
- **2026-05-22 (S29 wrap — Plan CA + Plan B pre-flight 2 spawns + 3 patterns NEW):** S29 close 2 big plans cumulative. **Plan CA (Move Cấu hình danh mục admin → eoffice)** 7 commits `06a441c..6eec8d7` push deployed Run #229+#230 PASS. **Plan B (Contract V2 wire mirror PE V2 pattern Mig 22-26)** 11 commits `58898e8..38f1c4d` push deployed Run #231+#232 PASS. **Investigator role 2 spawn:** (1) **Plan CA pre-flight audit** (agentId a7ab5576c77ee3730, ~15K token): map 9 menu danh mục terrain + GOTCHA tree-inherit Catalogs↔Master + recommend chunk structure A/B/C/D. fe-user component parity verified (DataTable + PageHeader + PermissionGuard + 6 shadcn ui). DbInitializer SeedAdminPermissionsAsync admin role grant CRUD 27 menu key. Permission Matrix dynamic load /api/menus → tự reflect post-move. (2) **Plan B pre-flight audit Contract V1 state** (agentId abf91b30391fb0cdb, ~25K token): map `Contract.cs` 25 fields (V1 only) + `ContractPhase` enum 12 values (TraLai=98 + TuChoi=99 ready) + `ContractWorkflowService.cs` 220 LOC V1 only + sqlcmd prod 7 V1 contract (Phase 2-8 active workflow) + PE Mig 22-26 reference templates + impact assessment (COEXIST V1+V2, KHÔNG drop V1) + re-chunk 6 chunks (split A → A1 entity + A2 mig). 3 surprise: ApprovalWorkflows Prod ZERO ApplicableType=3 (Chunk A2 must seed sample) + `RejectedAtStepIndex` drift deprecated + ContractType 7 variants generic ApplicableType=3. **Patterns proven NEW Investigator perspective S29:** (a) **9-menu permission terrain map pattern** (Plan CA) — Investigator inventory file paths + line ranges + component parity check + recommend chunk before delegate Implementer. ROI cao. (b) **V1+V2 coexist boundary** (Plan B) — KHÔNG drop V1 vì 7 prod contract pinned. Mirror PE Mig 22-24 spec. (c) **Reference template paths cross-module mirror** (PE → Contract V2): Investigator cite EXACT line ranges (PE Mig 23:14-31, Mig 24:14-17, Mig 26 UNIQUE composite, Service ApproveV2Async 446-634, 519-546 UPSERT, 774-783 ResolveActor) → em main + Implementer chỉ cần mirror rename entity. ROI rất cao saving 30%+ time. **Anti-patterns observed:** (a) Investigator KHÔNG verify endpoint exists end-to-end qua live curl — defer to CICD Monitor stage 4. (b) Investigator output sometimes verbose >700 words → em main hỏi cô đọng <500 next time.
- **2026-05-22 (Plan B Contract V2 wire pre-flight audit Q1-Q5 + Bonus re-chunk):** Em main spawn Investigator pre-flight Plan B priority HIGH. 5Q audit + Bonus chunk refinement. Tag schema: `[audit, phase-9, contract]`. **Findings:** (Q1) `Contract.cs:8-58` 25 fields, V1 ready (WorkflowDefinitionId line 22 + CurrentWorkflowStepIndex line 39 + Phase line 12 + RejectedAtStepIndex line 40) MISSING `ApprovalWorkflowId Guid?` + `CurrentApprovalLevelOrder int?` need Mig 32 add. (Q2) `ContractPhase.cs:14-28` 12 values ready ChoDuyet=10 + TraLai=98 + TuChoi=99 mirror PE. `ContractWorkflowService.cs:23-219` 220 LOC V1 ONLY. NO V2 branch. Match Dept+PositionLevel line 113-126. Gen line 148-155 trigger last step Phase=DaPhatHanh (terminal khác PE DaDuyet). (Q3) Prod: 7 Contracts 100% V1Pinned (Mig 21 flat WorkflowDefinitionId), 6 in-workflow Phase 2-8 MUST coexist V1+V2, KHÔNG drop V1. ApprovalWorkflows Prod: 2 rows `ApplicableType=1 (DuyetNcc)` ZERO `ApplicableType=3 (Contract)` chưa seed. (Q4) Mig 22 `20260508053749_AddApprovalWorkflowsV2.cs:14-127` 3 CREATE TABLE shared cho cả PE+Contract, Mig 32 chỉ cần ADD COLUMN tại `Contracts`. Mig 23 `20260508072821_AddApprovalWorkflowIdToPurchaseEvaluation.cs:14-31` template 15 LOC cookie-cutter rename PeContract. Mig 24 `20260508074937_AddCurrentApprovalLevelOrderToPe.cs:14-17` 3 LOC. `ApproveV2Async` `PurchaseEvaluationWorkflowService.cs:446-634` 189 LOC clone mẫu load AW.Steps.Levels + match actorId pendingLevelGroup.ApproverUserId (line 484-495) + UPSERT opinion (line 522-546) + advance level/step (line 605-633) + skipToFinal F2 (line 561-602). Branch entry pattern line 167-171 ternary `if (evaluation.ApprovalWorkflowId is Guid awId) ApproveV2Async else ApproveV1Legacy`. (Q5) Risk LOW schema 80% shared. F1-F4 7 flags Mig 29+30+31 trên `ApprovalWorkflowLevels` (entity line 86-114) inherits FREE Contract. **Risk MEDIUM:** ContractType discriminator 1 workflow serve ALL 7 ContractType vs per-type? PE chỉ 2 type. Defer Q em main. **Bonus re-chunk 6 chunks:** A1 entity 5 LOC (em main) + A2 Mig 32 cookie-cutter (Implementer) + B Service ternary 189 LOC clone adapt gen terminal (em main critical cross-stack) + C Mig 33 ContractLevelOpinions cookie-cutter (Implementer) + D FE-User Workspace Select V2 (Implementer mirror) + E FE Section 5 LevelOpinionsV2 dynamic (Implementer mirror). **Surprises:** (a) ApprovalWorkflows Prod ZERO ApplicableType=3 recommend Chunk A2 include DbInitializer seed sample. (b) `RejectedAtStepIndex` Contract line 40 DEPRECATED chưa marked obsolete drift với PE line 50. (c) ContractType 7 variants vs ApprovalWorkflow generic ApplicableType=3 future Mig 34 thể cần `ContractTypes int[]` filter nếu Solutions cần per-type workflow. **Recommendation: PROCEED coexist V1+V2 pattern, 6 chunk re-chunk.** Token ~25K. source_path: `solution_erp/audit/investigator-plan-b-contract-v2-preflight-2026-05-22`.
- **2026-05-22 (S28 wrap Layer A governance internalized + tag schema mandatory forward):** S28 5-turn arc t1 RAG ROI verdict t2 over-reach mistake t4 bro caught t5 Layer A active. Investigator agent absorb 3 rules forward: (1) **Tag schema mandatory** every RAG ingest `[<type>, phase-<N>, <bc-or-module>]` type {bug, plan, audit, schema, ui-pattern, decision, retrospective, gotcha-doc}; phase enum 11 (`phase-9` UAT current); bc/module 8 domain {contract, pe, budget, master, identity, forms, notifications, audit-log} + 5 cross-cutting {cicd, infra, rag, governance, deploy}. (2) **4-category default + skip list** skip ephemeral state ("S28 t3 startup ngày 22"), pure file paths không context, single-file < 5-line edit confirmation. Investigator output report tags MUST include all 3. (3) **NO self-authorize cross-project rule** lesson S28 t4: stay scope-down SOLUTION_ERP self-discipline, don't generalize policy without bro consent. **Pre-flight audit query patterns Layer A §6.2** internalized: Pattern A `lookup_gotcha_<id>` (top_k=3, narrow), Pattern B `verify_precedent_pattern_X` (top_k=3 thay default 10 broad similarity rerank surface 3 best matches), Pattern C `find_code_symbol_<class.method>` (top_k=5, symbol-anchor). **Weekly Friday eval ritual:** Investigator support Plan B Contract V2 wire pre-flight audit kick-off khi bro launch. Cumulative audit checklist (foundation cicd-monitor MEMORY S22+5S23 t6 10-surface-point per-NV): (a) Contract entity V1 state inspect `Domain/Contracts/Contract.cs` + `WorkflowDefinitionId`, (b) Mig 22-23/26 PE V2 mirror reference confirm pattern reusable, (c) 4 PE V1-only audit migrate gap (per memory S22+4 Plan F ABORT), (d) 7 V1 contract scope drop boundary, (e) verify 10-surface-point per-NV checklist S22+5 cumulative reusable Contract V2 wire trước Mig 32 schema design. **source_path convention output:** `solution_erp/audit/investigator-<topic>-<date>` standardized cho tag schema BC=`pe` or `contract` switch per task. **Lesson abandoned:** S28 t2 "ghi RAG mọi tương tác" rule ABANDONED Investigator KHÔNG mass-ingest, only specific findings with full tag schema. Audit retroactive S20-S26 "Investigator spawn" claims (memory log discrepancy registry NOT loaded vs token cost ghi 28-40K) defer S28+ priority #4 uncertainty preserve cross-session, không retract memory unverified.
- **2026-05-22 (S27 wrap-up em main proxy - retrospective Investigator):** Investigator pre-flight CRITICAL miss: nếu spawn pre-Plan A.3 (RAG manual control build) would have catch Qdrant Web UI static missing PRE-em main write rag-dashboard.ps1 link `localhost:6333/dashboard`. Pattern reinforced: **pre-flight infrastructure audit MUST spawn Investigator** trước khi em main claim "X work" trong docs. Em main S27 SOLO miss external dependency check (Qdrant Web UI separate repo from binary). Anh pqhuy catch via UAT browser escalate.
**Audit cumulative S20-S26 memory log entries claiming "Investigator spawn" - re-verify retroactive:** Per pitfall confirm spawn `investigator` agent type NOT FOUND trong session S27, nghĩa registry chưa bao giờ load trong session này. Nhưng memory log S23 t1 K0 + S25 t1 audit Bug 1+2 + S26 Plan AG audit 5Q + Plan AI RAG research **đã ghi "spawn Investigator" với token cost 28-40K**. Possibility: (a) Previous sessions registry load thành công (Claude Code version hơn / file format khác / hot-reload sau /agents UI invoke), hoặc (b) Em main misattribute - actually spawn `general-purpose` agent default. Cần audit history Claude Code logs để xác minh - ngoài scope S27. **For now: trust prior memory entries but FLAG uncertainty cho future investigation.**
- **2026-05-22 (Curate session em main):** Archived 10 verbose Recent activity entries S21 S24 Plan AA `archive/2026-05-q1.md`. KEEP: S25 Bug audit + wrap, S26 Plan AG + Plan AI RAG, 2026-05-11 setup. Patterns proven section + Active workflow schemas section preserved. Memory size before: 34.9 KB after: target ~20-22 KB.
- **2026-05-19 (S25 t1 spawn audit 2 bug critical UAT Changelog logging missing):** Em main report 2 bug UAT: (1) Budget Adjust 2×click "Lịch sử thay đổi" KHÔNG show 2 entry. (2) Return Assignee mode F1 click "Lịch sử thay đổi" KHÔNG show return action. Audit 5Q: Q1-DB state Prod SSH fail (auth), fallback code inspect. Q2-Budget handler: `PurchaseEvaluationFeatures.cs:379-387` **ĐÃ log changelog** EntityType=Header + Action=Update + summary diff **code ĐÚNG, likelihood FE filter bug or UAT DB stale**. Q3-Return handler: `PurchaseEvaluationWorkflowService.cs:215-378 ApplyReturnModeAsync` **ZERO changelog log** 4 mode branches (OneLevel/OneStep/Assignee/Drafter) mutate pointers only, return summary, caller `TransitionAsync:100 LogTransitionAsync` only logs phase transition KHÔNG log mode side-effect. Q4-Schema: `PurchaseEvaluationChangelog.cs` support EntityType=Workflow(5) enum but **ZERO code populate** schema incomplete missing Kind/ChangeType subtype enum to disambiguate "budget adjust" vs "detail edit" vs "return mode" (all Header/Workflow entity cùng Action.Update). Q5-FE: Query handler `ListPurchaseEvaluationChangelogsQueryHandler:1050-1064` **KHÔNG filter logic** returns ALL entities. FE query component unknown (fe-user source not easily searchable) but **likely filter EntityType == (Supplier|Detail|Quote)** omit Header+Workflow Bug 1 Budget (Header type) hidden, Bug 2 Return (Workflow type unlogged vậy). Root cause B1: FE filter skip Header updates OR Schema gap (Header.Update collision: budget vs section 2 edit). Root cause B2: Handler **intentionally skip logging** (no companion audit table like PurchaseEvaluationApprovals for return history). Fix path B1: Option A (add Kind enum 30 LOC schema+handlers) vs B (extend EntityType 20 LOC) vs C (FE filter conditional show Budget 10 LOC FE). Fix path B2: Add `db.PurchaseEvaluationChangelogs.Add()` per mode (15-25 LOC 1 file). Cross-ref pattern memory: S23 t3 lookup bug (Level.Order collision per-NV Mig 29) schema Mig 29 OR-of-N refactor created similar subtype ambiguity. Surprise: `EntityType.Workflow=5` enum value design-only, unused 4+ mig history. Recommendation: B2 fix first (clear win, 1 file BE), then B1 design (schema + cross-module pattern audit Contracts). Token ~28k.
- **2026-05-19 (S25 wrap Plan AB Bug 1+2 audit + 6 follow-up plans em main solo):** Pre-Plan AB audit ~28K confirm root cause: Bug 1 Budget Adjust Handler ĐÃ log Changelog (Header+Update) nhưng FE HistoryTab filter strict TraLai-only loại. Bug 2 ApplyReturnModeAsync 4 mode KHÔNG add Changelog.Add() chỉ caller LogTransitionAsync log phase transition. Recommended fix path: BE add log return mode + FE filter relax + Decision badge differentiation. **Subsequent em main solo follow-ups** (Plan AC..AF, KHÔNG re-spawn Investigator): AC capture pre-call Step/Level state + skipToFinal comment enrich + FE Decision badge; AC2 FE merge synthetic Reject rows từ Changelog (reversible recovery KHÔNG DB touch); AD drop misleading dual-phase badges + parse semantic next-target hint via regex `Chuyển phase X → Y` + comment keyword "Trả về"/"vượt cấp"; AE BE preventive batch UserName fix 9 Changelog.Add sites (Drafter+Detail+Quote+Adjust); AF FE userMap fallback từ embedded domain data PeDetailBundle (drafter+approvals+approvalFlow+levelOpinions+departmentOpinions) no extra API fetch. **Patterns reusable Contract V2 audit recovery + Budget changelog UI:** (a) synthetic recovery FE merge từ existing audit table, (b) userMap fallback từ embedded domain data, (c) drop misleading badges + semantic hint via regex parsing, (d) preventive batch fix systemic gap. Cross-ref `feedback_service_hook_vs_endpoint` (audit log derived state) + new pattern user-level: FE merge synthetic + userMap fallback. **Tokens cumulative em main this session ~340K (mostly solo iterations, sub-agent leverage ~62K total).** **CICD result:** 7 commits `e23f51c..506cada` push remote, runs #215 FAIL (Plan M tests SQLite tie-break re-emerge) #216 PASS (Chunk A2 SQLite tie-break fix) #217-#221 PASS streak. Gotcha #48 SQLite tie-break pending docs.
- **2026-05-21 (S26 spawn Plan AG 5Q audit PE List tree view feedback Tra Sol):** Bro UAT 2026-05-21 screenshot phàn nàn UI Duyệt NCC flat list "đám rừng" + propose Outlook-style folder template. Em main spawn Investigator audit 5Q: Q1 prod data scale (SSH auth fail, fallback code inspect ~50-200 projects × 5-15 PE typical). Q2 Project entity `Master/Project.cs:5-14` extends AuditableEntity với Code+Name+dates+Budget+PM+Note, **MISSING MaxLength + navigation tới PE** ready for Phase 2 ProjectPackage table mở rộng. Q3 PE List structure `PurchaseEvaluationsListPage.tsx:133` 3-panel grid `lg:grid-cols-[340px_1fr_360px]` flat `<ul><li>` line 199-252 + pageSize 50 + filter type/phase/awId/search. Q4 shadcn fe-user component GAP **THIẾU Accordion/Collapsible/Tree/Card/Badge** (chỉ Button/Dialog/Input/Label/Select/Textarea) Phase 1 fallback HTML `<details>/<summary>` native + inline badge `<div>` (verified S24 Plan AA pattern). Q5 Mig 32 prep naming `AddProjectPackageTable` follow cumulative pattern. **Recommend Approach C Hybrid: Phase 1 FE-only group view ~160 LOC × 2 app (1-2 ngày) + Phase 2 ProjectPackage schema (3-5 ngày defer post-UAT). Implementer Case 2 cookie-cutter mirror 2 app ACCEPT.** Token ~30k.
- **2026-05-21 (S26 spawn Plan AI RAG distribution research 4 study cases industry-validated):** Bro plan setup RAG cho 5 dự án cùng máy localhost share infrastructure. Investigator deep research 7Q: Anthropic patterns + community tools + multi-tenant architecture + distribution mechanism + auth + cost + sync. **Findings 4 study cases:** (1) **Cursor** Merkle tree + Turbopuffer + 92% similarity reuse pattern, secret key derived Git commit hash, per-team index sharing cut indexing hoursseconds. (2) **Cline Memory Bank** markdown + JIT retrieval + git-native sync. (3) **Continue.dev Hub** slug-based YAML config sharing centralized. (4) **Sourcegraph Cody** interesting anti-pattern, BỎ embeddings sang Search API + graph IR scale 100K+ repos enterprise (alternative if good search infra sẵn). **Multi-tenant 3 patterns:** Single index (pool, cheap), Per-tenant isolated (silo, expensive), Hybrid base+delta (Cursor pattern). **Distribution combo winner cho 5-dev team:** FastMCP HTTP server VPS Hetzner $15/tháng + git-sync embeddings snapshots committed to private repo. Auth JWT RS256 + role scopes + document-level ACL. Cost reality 5 dev ~$20/month vs cloud Qdrant $50/month. Sync git-based weekly cron (real-time chỉ cần khi team > 10 dev). **Surprise:** Voyage AI **200M tokens/month free tier cover 5 devs** comfortably — coi như chỉ tốn $15 VPS. **Anthropic standards 9/9 matched** + community best practices 6/7 matched (Sourcegraph alternative N/A cho memory-heavy). Plan AI architecture chốt với em main: User-level Global MCP (Pattern C — 1 server localhost serve 5 project) thay vì team VPS pattern (anh single dev 5 dự án). Token ~40k.
- **2026-05-11 (setup):** Investigator agent initialized. Baseline knowledge load complete (44 gotchas + 14 memory entries + 6 skills + 27 mig + 81 test pass cumulative). No investigations performed yet. Awaiting first SendMessage from em main.
---
@ -149,11 +159,5 @@ State machine 5 trạng thái phiếu PE: Nháp / Đã gửi duyệt / **Trả l
- Duplicate entries detected → merge
- Stale > 3 months → remove
Last curate: 2026-05-11 (initial seed)
- **2026-05-19 (S25 t1 spawn audit 2 bug critical UAT — Changelog logging missing):** Em main report 2 bug UAT: (1) Budget Adjust 2×click → "Lịch sử thay đổi" KHÔNG show 2 entry. (2) Return Assignee mode F1 click → "Lịch sử thay đổi" KHÔNG show return action. Audit 5Q: Q1-DB state Prod SSH fail (auth), fallback code inspect. Q2-Budget handler: `PurchaseEvaluationFeatures.cs:379-387` **ĐÃ log changelog** EntityType=Header + Action=Update + summary diff → **code ĐÚNG, likelihood FE filter bug or UAT DB stale**. Q3-Return handler: `PurchaseEvaluationWorkflowService.cs:215-378 ApplyReturnModeAsync` **ZERO changelog log** — 4 mode branches (OneLevel/OneStep/Assignee/Drafter) mutate pointers only, return summary, caller `TransitionAsync:100 LogTransitionAsync` only logs phase transition KHÔNG log mode side-effect. Q4-Schema: `PurchaseEvaluationChangelog.cs` support EntityType=Workflow(5) enum but **ZERO code populate** — schema incomplete missing Kind/ChangeType subtype enum to disambiguate "budget adjust" vs "detail edit" vs "return mode" (all Header/Workflow entity cùng Action.Update). Q5-FE: Query handler `ListPurchaseEvaluationChangelogsQueryHandler:1050-1064` **KHÔNG filter logic** — returns ALL entities. FE query component unknown (fe-user source not easily searchable) but **likely filter EntityType == (Supplier|Detail|Quote)** omit Header+Workflow → Bug 1 Budget (Header type) hidden, Bug 2 Return (Workflow type unlogged vậy). Root cause B1: FE filter skip Header updates OR Schema gap (Header.Update collision: budget vs section 2 edit). Root cause B2: Handler **intentionally skip logging** (no companion audit table like PurchaseEvaluationApprovals for return history). Fix path B1: Option A (add Kind enum — 30 LOC schema+handlers) vs B (extend EntityType — 20 LOC) vs C (FE filter conditional show Budget — 10 LOC FE). Fix path B2: Add `db.PurchaseEvaluationChangelogs.Add()` per mode (15-25 LOC 1 file). Cross-ref pattern memory: S23 t3 lookup bug (Level.Order collision per-NV Mig 29) — schema Mig 29 OR-of-N refactor created similar subtype ambiguity. Surprise: `EntityType.Workflow=5` enum value design-only, unused 4+ mig history. Recommendation: B2 fix first (clear win, 1 file BE), then B1 design (schema + cross-module pattern audit Contracts). Token ~28k.
- **2026-05-19 (S25 wrap — Plan AB Bug 1+2 audit + 6 follow-up plans em main solo):** Pre-Plan AB audit ~28K confirm root cause: Bug 1 Budget Adjust Handler ĐÃ log Changelog (Header+Update) nhưng FE HistoryTab filter strict TraLai-only loại. Bug 2 ApplyReturnModeAsync 4 mode KHÔNG add Changelog.Add() — chỉ caller LogTransitionAsync log phase transition. Recommended fix path: BE add log return mode + FE filter relax + Decision badge differentiation. **Subsequent em main solo follow-ups** (Plan AC..AF, KHÔNG re-spawn Investigator): AC capture pre-call Step/Level state + skipToFinal comment enrich + FE Decision badge; AC2 FE merge synthetic Reject rows từ Changelog (reversible recovery KHÔNG DB touch); AD drop misleading dual-phase badges + parse semantic next-target hint via regex `Chuyển phase X → Y` + comment keyword "Trả về"/"vượt cấp"; AE BE preventive batch UserName fix 9 Changelog.Add sites (Drafter+Detail+Quote+Adjust); AF FE userMap fallback từ embedded domain data PeDetailBundle (drafter+approvals+approvalFlow+levelOpinions+departmentOpinions) — no extra API fetch. **Patterns reusable Contract V2 audit recovery + Budget changelog UI:** (a) synthetic recovery FE merge từ existing audit table, (b) userMap fallback từ embedded domain data, (c) drop misleading badges + semantic hint via regex parsing, (d) preventive batch fix systemic gap. Cross-ref `feedback_service_hook_vs_endpoint` (audit log derived state) + new pattern user-level: FE merge synthetic + userMap fallback. **Tokens cumulative em main this session ~340K (mostly solo iterations, sub-agent leverage ~62K total).** **CICD result:** 7 commits `e23f51c..506cada` push remote, runs #215 FAIL (Plan M tests SQLite tie-break re-emerge) → #216 PASS (Chunk A2 SQLite tie-break fix) → #217-#221 PASS streak. Gotcha #48 SQLite tie-break pending docs.
- **2026-05-21 (S26 spawn Plan AG 5Q audit — PE List tree view feedback Tra Sol):** Bro UAT 2026-05-21 screenshot phàn nàn UI Duyệt NCC flat list "đám rừng" + propose Outlook-style folder template. Em main spawn Investigator audit 5Q: Q1 prod data scale (SSH auth fail, fallback code inspect — ~50-200 projects × 5-15 PE typical). Q2 Project entity `Master/Project.cs:5-14` extends AuditableEntity với Code+Name+dates+Budget+PM+Note, **MISSING MaxLength + navigation tới PE** → ready for Phase 2 ProjectPackage table mở rộng. Q3 PE List structure `PurchaseEvaluationsListPage.tsx:133` 3-panel grid `lg:grid-cols-[340px_1fr_360px]` flat `<ul><li>` line 199-252 + pageSize 50 + filter type/phase/awId/search. Q4 shadcn fe-user component GAP **THIẾU Accordion/Collapsible/Tree/Card/Badge** (chỉ Button/Dialog/Input/Label/Select/Textarea) → Phase 1 fallback HTML `<details>/<summary>` native + inline badge `<div>` (verified S24 Plan AA pattern). Q5 Mig 32 prep naming `AddProjectPackageTable` follow cumulative pattern. **Recommend Approach C Hybrid: Phase 1 FE-only group view ~160 LOC × 2 app (1-2 ngày) + Phase 2 ProjectPackage schema (3-5 ngày defer post-UAT). Implementer Case 2 cookie-cutter mirror 2 app ACCEPT.** Token ~30k.
- **2026-05-21 (S26 spawn Plan AI RAG distribution research — 4 study cases industry-validated):** Bro plan setup RAG cho 5 dự án cùng máy localhost share infrastructure. Investigator deep research 7Q: Anthropic patterns + community tools + multi-tenant architecture + distribution mechanism + auth + cost + sync. **Findings 4 study cases:** (1) **Cursor** — Merkle tree + Turbopuffer + 92% similarity reuse pattern, secret key derived Git commit hash, per-team index sharing cut indexing hours→seconds. (2) **Cline Memory Bank** — markdown + JIT retrieval + git-native sync. (3) **Continue.dev Hub** — slug-based YAML config sharing centralized. (4) **Sourcegraph Cody** — interesting anti-pattern, BỎ embeddings sang Search API + graph IR scale 100K+ repos enterprise (alternative if good search infra sẵn). **Multi-tenant 3 patterns:** Single index (pool, cheap), Per-tenant isolated (silo, expensive), Hybrid base+delta (Cursor pattern). **Distribution combo winner cho 5-dev team:** FastMCP HTTP server VPS Hetzner $15/tháng + git-sync embeddings snapshots committed to private repo. Auth JWT RS256 + role scopes + document-level ACL. Cost reality 5 dev ~$20/month vs cloud Qdrant $50/month. Sync git-based weekly cron (real-time chỉ cần khi team > 10 dev). **Surprise:** Voyage AI **200M tokens/month free tier cover 5 devs** comfortably — coi như chỉ tốn $15 VPS. **Anthropic standards 9/9 matched** + community best practices 6/7 matched (Sourcegraph alternative N/A cho memory-heavy). Plan AI architecture chốt với em main: User-level Global MCP (Pattern C — 1 server localhost serve 5 project) thay vì team VPS pattern (anh single dev 5 dự án). Token ~40k.
**Last curate: 2026-05-22 em main full curate** — archived 10 verbose entries (S21 → S24 Plan AA) → `archive/2026-05-q1.md`. KEEP: S25 audit + wrap (Bug 1+2 Changelog), S26 Plan AG + Plan AI RAG (2 spawn), setup baseline. Patterns + Active workflow schemas foundation preserved. Per `feedback_md_compact_narrative.md` §6.5 — archive preserves full verbose entries cho cross-session audit retrieve. Next curate trigger: > 25KB OR Plan B Contract V2 wire complete.

View File

@ -0,0 +1,63 @@
# Investigator Agent — Archive Recent Activity Q1 2026-05 (S21-S24)
> **Archived:** 2026-05-22 by em main SOLUTION_ERP curate session.
> **Scope:** Recent activity FIFO entries S21 → S24 Plan AA (10 verbose entries) — moved from MEMORY.md để giữ slim < 25KB threshold.
> **Rule §6.5 compliance:** KHÔNG cắt narrative — full verbose entries preserved cho cross-session audit.
> **Source MEMORY.md before archive:** 34.9 KB.
> **KEEP in MEMORY:** S26 Plan AG + Plan AI RAG (2 spawn), S25 Bug audit + wrap, 2026-05-11 setup baseline. Patterns proven section preserved.
---
## Archive entries (FIFO chronological — earliest first)
### 2026-05-11 (setup)
Investigator agent initialized. Baseline knowledge load complete (44 gotchas + 14 memory entries + 6 skills + 27 mig + 81 test pass cumulative). No investigations performed yet. Awaiting first SendMessage from em main.
### 2026-05-13 (S21 t3-t5, no spawn)
Em main solo 3 turns (bug fix gotcha #45 + F1+F2+F3 workflow-level Mig 28 + refactor per-NV Mig 29). Implementer REFUSE per cross-stack reasoning chain rule. Investigator KHÔNG spawn — em main đã có context cumulative S20 t12 setup + active dev throughout. No findings to flush. Cumulative state update: 84 test, 29 mig, 45 gotcha, 19 memory entries (+2 S21 t5 pending), 6 skills unchanged. Pattern reusable saved cho future spawn: per-NV permission scope split + EF migration ADD→BACKFILL→DROP reorder.
### 2026-05-13 (S22, no spawn — em main solo throughout)
S22 18:00→~21:00 em main solo. Cumulative state: 30 mig (+1 Mig 30 `AddAllowApproverEditBudgetToLevels` F4 per-Level slot), 104 test PASS (+20: 5 reg #44 Authorize policy + 7 ReturnMode + 7 Guard + 1 V2 actor scope reject), ~146 endpoints (+3: PATCH /users/{id}/allow-skip-final + PATCH /pe/{id}/budget-adjust + GET /pe/{id}/attachments/{attId}/view), 46 gotcha unchanged, 19 memory unchanged (recommend +1 entry — see below). Prod active users 13→33 (+20 role-based: act.nv/pp/tp, bod.1/2, equ/fin/hra/pm/qs.nv/pp/tp).
**Discoveries S22:**
1. **Per-NV admin opt-in flag pattern reinforced 2×** — Mig 30 F4 cùng pattern Mig 29 F1+F3 (S21 t5). Bro corrected em main lần đầu: "phải tick checkbox như Section 2", default = admin opt-in per slot, KHÔNG = mở rộng default. Cross-ref memory `feedback_per_nv_permission_scope.md` proven 2×.
2. **Plan F drop V1 ABORTED** — pre-flight sqlcmd reveal Contract entity HOÀN TOÀN V1 chưa wire V2 (chưa có ApprovalWorkflowId column) + 4 PE V1-only + 19 PE V1+V2 mix. Lesson: drop migration cần verify entity scope toàn bộ (Contract liên đới — không chỉ PE).
3. **Identity password policy ≥12 chars** — seed 20 user FAIL 400 với "User@123456" (11 chars), `TestUser@2026` (13 chars) pass.
4. **Identity rename atomic 4 fields** confirm gotcha #38: Email + NormalizedEmail + UserName + NormalizedUserName + FullName; sqlcmd cần `SET QUOTED_IDENTIFIER ON` cho filtered unique index.
5. **API login response field name `accessToken` + `refreshToken` + `user`** — KHÔNG có field `token` (correct prior Bash example trong spec dùng `.token` sẽ fail).
6. **PS 5.1 ASCII-only script discipline** reinforced gotcha #30: `seed-test-users-prod.ps1` viết Vietnamese names without diacritics tránh parser error. Recommend bro add 1 memory entry "Admin opt-in flag pattern proven 2×" cumulative Mig 29 + Mig 30.
### 2026-05-14 (S23 t1 spawn K0 — Plan K F2 refactor pre-flight)
Audit F2 state cho Plan K Mig 31 (move `Users.AllowDrafterSkipToFinal``ApprovalWorkflowLevels.AllowApproverSkipToFinal` + change semantic Drafter Nháp → Approver ChoDuyet skip thẳng Cấp cuối). **Confirmed state Mig 30:** Migrations path = `Persistence/Migrations/` (not direct `Migrations`); 30 mig latest = `20260513160703_AddAllowApproverEditBudgetToLevels`; `User.cs:38` AllowDrafterSkipToFinal prop; `ApprovalWorkflow.cs:86-105` 6 Allow* props (4 ReturnMode + EditDetails + EditBudget) per Level slot; F2 Drafter branch ở `PurchaseEvaluationWorkflowService.cs:119-161` trong SUBMIT branch (line 125 `if (skipToFinal && evaluation.ApprovalWorkflowId is Guid skipAwId)` check user.AllowDrafterSkipToFinal); APPROVE STEP branch ở `~line 393-525` (advance pointer). TransitionAsync signature: `skipToFinal` là param thứ 8 (position 47:47), default=false. `TransitionPurchaseEvaluationCommand``PurchaseEvaluationFeatures.cs:393-402` với param `SkipToFinal=false` default. `ApprovalWorkflowOptionsDto``PurchaseEvaluationDtos.cs:86-92` (6 field). `PurchaseEvaluationDetailBundleDto.DrafterAllowSkipToFinal` ở line 217 + `CurrentLevelOptions` ở line 214. UsersController `PATCH /users/{id}/allow-skip-final` ở line 91-98 + `SetAllowDrafterSkipToFinalBody` ở line 105. `SetUserAllowDrafterSkipToFinalCommand``UserFeatures.cs:332`. **FE state:** fe-admin Designer `system/ApprovalWorkflowsV2Page.tsx` slot label "NV #{ei + 1}" ở line 873 (KHÔNG phải "#NV {order}" theo prompt) — inline checkbox panel 5+1=6 checkbox ở line 853-933 (4 ReturnMode + EditDetails + EditBudget). fe-admin `system/UsersPage.tsx` "Skip cuối" column line 306-318 + FastForward button toggle line 365-372 + allowSkipMut hook line 181-186. fe-admin/fe-user PeDetailTabs Drafter Workspace checkbox "Gửi thẳng Cấp cuối (skip trung gian)" ở line 287-297 (admin) / 294-304 (user). **GAP fe-user**: KHÔNG có UsersPage + ApprovalWorkflowsV2Page (admin-only mgmt) → Plan K UI changes localized fe-admin chỉ; fe-user side chỉ touch PeDetailTabs (remove old Drafter checkbox + thêm Approver toggle near Duyệt button). **Drift Dev DB**: Total=2 user (admin + test.drafter), Flagged=0 — NOT match 33-user prod seed. **Prod actual**: Total=33 / Flagged=4 (NOT 2 per S22+2 spec). 4 user flagged sẽ lose value when DROP column — acceptable per new semantic (Drafter pre-submit moot).
### 2026-05-15 (S23 t2 spawn L2 — F3+F4 edit menu Duyệt audit)
Bug UAT prod 409a967: admin tick F3+F4 cho slot Approver, login actor user, vào menu "Duyệt" (`?pendingMe=1` cùng `PurchaseEvaluationsListPage` 3-panel), click PE Phase=ChoDuyet → Section 2 Hạng mục/NCC/Báo giá + Section 5 Điều chỉnh ngân sách vẫn read-only. **Root cause F3 = OK / F4 = BROKEN at readOnly short-circuit:** F3 wire ĐÚNG (`PeDetailTabs.tsx:118 itemsReadOnly = readOnly && !approverEditMode` override readOnly per Mig 28 S21 t4 → ItemsTab read prop OK). F4 wire SAI (`PeDetailTabs.tsx:245` passes `readOnly={readOnly}` (=true từ menu Duyệt) xuống BudgetAdjustSection, line 973 compute `canAdjust = !readOnly && (isAdmin || (isDrafter && isDrafterPhase) || isApproverChoDuyet)``!readOnly` short-circuits to false BEFORE F4 isApproverChoDuyet evaluate. Edit pencil button hidden line 1030 `{canAdjust && <Button>Điều chỉnh</Button>}`. Asymmetric vs F3 pattern Section 2 (PeDetailTabs.tsx:113-118). **Evidence:** FE F3 OK `fe-user/src/components/pe/PeDetailTabs.tsx:113-118` + `:224 ItemsTab ev={evaluation} readOnly={itemsReadOnly}`; FE F4 BUG `:957-973 BudgetAdjustSection !readOnly gate` + `:245 readOnly={readOnly}`; menu Duyệt route `fe-user/src/pages/pe/PurchaseEvaluationsListPage.tsx:256-261 PeDetailTabs readOnly={true}` (cùng route Danh sách); BE GetPe `PurchaseEvaluationFeatures.cs:735-770 currentLevelOptions populate 7 fields` OK; BE budget-adjust handler `:281-329` Phase ChoDuyet F4 branch + actor match + flag check ĐẦY ĐỦ + return ConflictException nếu Allow=false; BE PurchaseEvaluationDraftGuard.EnsureEditableForDetailsAsync ở `PurchaseEvaluationDetailFeatures.cs:42` (8 callsites Detail+Supplier handlers). **Recommendation:** Fix `BudgetAdjustSection` line 973 mirror approverEditMode pattern Section 2: thay `canAdjust = !readOnly && (isAdmin || ...)` thành `canAdjust = isAdmin || (!readOnly && isDrafter && isDrafterPhase) || isApproverChoDuyet` — Approver bypass readOnly khi F4 conditions met. **LOC ~3-5 LOC 1 file.** Surprise: Inbox `/inbox` route (InboxPage.tsx) navigate sang `/purchase-evaluations/:id` (mobile DetailPage route, default readOnly=false) — chỉ Danh sách `?pendingMe=1` desktop 3-panel mới hard readOnly=true.
### 2026-05-15 (S23 t2 spawn M0 — Plan M F1+F2+F3+F4 ChoDuyet semantic audit)
Bro UAT post-Plan L deploy 2026-05-15 ~02:00: "Hiện logic cũ là khi trả lại 1 cấp hoặc chỉ định hoặc edit là trạng thái draft -> cái này thay đổi lại nhé, các tính năng duyệt thẳng, trả lại 1 cấp hoặc người chỉ định hoặc cho edit thì cho xử lý đc ở trạng thái đang gửi duyệt luôn." Audit 4 BE file + 4 FE file × 2 app cho F1+F2+F3+F4 phase semantic ChoDuyet preservation. **Verdict: CODE ĐÃ ĐÚNG semantic mới — đây là DISCONNECT bro mental model vs code reality post-Mig 28/29/30/31.** Evidence per feature: **F1.OneLevel** `PurchaseEvaluationWorkflowService.cs:285-312` SWITCH branch lùi 1 Cấp cùng Step (`curLevel-1`) ELSE lùi Step trước Cấp cuối; **Phase KHÔNG đổi** (giữ ChoDuyet, line 364 reset SLA only); fallback Drafter `:303-310` CHỈ KHI đang Bước 1 Cấp 1 no further back (clear pointer + Phase=TraLai). **F1.Assignee** `:335-360` foreach Steps find ApproverUserId match → set pointer; Phase giữ ChoDuyet; ConflictException nếu không tìm thấy NV trong workflow. **F1.OneStep** `:314-333` lùi prev Step Cấp max; Phase giữ ChoDuyet; fallback Drafter nếu đang Bước 1. **F1.Drafter** `:268-275` SET `Phase=TraLai=98` + clear cả 2 pointer + SLA null — đây là CASE DUY NHẤT về "draft". **F2 skipToFinal** `:483-524` Plan K L1 ĐÃ FIX advance pointer tới Bước cuối Cấp cuối (max), **Phase giữ ChoDuyet** (NV cuối duyệt thật để DaDuyet); guard line 485 ConflictException non-admin + flag off; opinion UPSERT trước line 441-468 ensure actor's signature lưu trước. **F3 EnsureEditableForDetailsAsync** `PurchaseEvaluationDetailFeatures.cs:42-99` 2 trường hợp accepted: Drafter scope (DangSoanThao/TraLai return pe sớm line 49-51) **OR Approver scope ChoDuyet line 54-94** (V2 schema + actor match level.ApproverUserId + level.AllowApproverEditDetails flag). **F4 AdjustPurchaseEvaluationBudgetCommandHandler** `PurchaseEvaluationFeatures.cs:272-329` Drafter scope `:283-290` (DangSoanThao/TraLai + isDrafter) ELSE Approver scope ChoDuyet `:291-323` (V2 + pointer init + actor match + level.AllowApproverEditBudget flag) — Phase ChoDuyet đã handle full. **Validation Allow* flag location** `PurchaseEvaluationWorkflowService.cs:252-265` ApplyReturnModeAsync gate per slot per mode: throw ConflictException nếu disabled (Admin bypass line 252). **FE PeWorkflowPanel.tsx**: TraLai dialog `:331-422` 4 radio button (OneLevel/OneStep/Assignee/Drafter) gated bằng `levelOptions?.allowReturnXxx` flag per current Approver Cấp (line 343-396); useEffect `:60-68` S23 t2 fix default first available mode KHÔNG Drafter khi admin tick F1 modes. Skip Final checkbox `:425-442` chỉ visible khi `levelOptions?.allowApproverSkipToFinal` + Approve forward direction (line 425). **FE PeDetailTabs.tsx F3+F4 wire**: `itemsReadOnly = readOnly && !approverEditMode` line 118 bypass readOnly khi F3 enabled (Mig 28 pattern); `canAdjust = isAdmin || (!readOnly && isDrafter && isDrafterPhase) || isApproverChoDuyet` line 977 bypass readOnly khi F4 enabled (L2 fix). Mirror fe-admin/fe-user line 109-115 + 967-979 ĐỒNG BỘ rule §3.9. **Surprise**: "Trả lại" trong UI memory docs đôi khi gọi "draft" colloquial — bro confuse 2 khái niệm `Phase=TraLai=98` (Drafter sửa rồi gửi LẠI từ Step 0) vs `Phase=DangSoanThao=1` (chưa từng gửi duyệt). KHÔNG code path nào trong F1 OneLevel/OneStep/Assignee/F2/F3/F4 set targetPhase=DangSoanThao mà không nên. **Recommendation: LOW effort** (0-20 LOC): chỉ cần communication clarification em main confirm với bro 4 mode F1 + F2 + F3 + F4 đã giữ Phase=ChoDuyet trừ F1.Drafter; mở DB SELECT phiếu UAT confirm `Phase` column number sau click test; OPTIONAL touch up FE label nếu user thấy "Đã gửi duyệt" nhầm "Bản nháp". KHÔNG cần Service refactor hay handler change. Nếu bro thấy phiếu cụ thể về Phase=1 SAU click F1.OneLevel hoặc F2 → spawn lại Investigator audit DB state + log Changelog cho phiếu đó cụ thể (data debug, not code bug).
### 2026-05-15 (S23 t3 spawn — UAT bug Allow* flags không hiện cho actor non-row1)
Bro UAT login `nv.test@solutions.com.vn` vào menu eoffice "Duyệt NCC → Duyệt" phiếu PE/2026/A/026 (Phase=ChoDuyet, WF=QT-DN-V2-001 v12, ở Bước 2 Cấp 1 4 NV: Trần Xuân Lưu/NV Test UAT V2/Hồ Thị Nữ Nguyên/Lê Văn Bính). Admin ĐÃ tick 7 Allow*=TRUE riêng cho slot NV Test UAT V2. Nhưng FE dialog Duyệt KHÔNG hiện checkbox SkipToFinal + Trả lại 4 mode + Edit. **Verdict: HYPOTHESIS B — BE handler picks wrong slot row.** Evidence: (1) `PurchaseEvaluationFeatures.cs:765` `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder);` — match FIRST row có `Level.Order == curLevelOrder`, NOT actor's row. Post-Mig 29 refactor, Level.Order trùng nhau cho mọi NV cùng Cấp (4 row có `Order=1` ở Step 2). EF returns Trần Xuân Lưu trước (PK order) → `FirstOrDefault` lấy row đó (all-false except Drafter=true). (2) API curl admin token + nv.test token return CÙNG `currentLevelOptions={ allowReturnOneLevel=false, OneStep=false, Assignee=false, Drafter=true, EditDetails=false, EditBudget=false, SkipToFinal=false }` — handler currentUser-agnostic confirm. (3) Workflow detail GET `/approval-workflows-v2?applicableType=1` `.types[0].active.steps[1].levels` enumerate 4 slot Bước 2 Cấp 1: NV Test (UAT V2) = ALL 7 TRUE; 3 NV còn lại = ALL FALSE (trừ Drafter=true mặc định). Admin Designer wire ĐÚNG (`fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx:889-946` 7 checkbox per-slot). FE consumer wire ĐÚNG (`fe-user/src/components/pe/PeWorkflowPanel.tsx:51 levelOptions = evaluation.currentLevelOptions` + line 343/357/371/397 conditional render mode picker + line 425 SkipToFinal checkbox). **Root cause:** BE line 765 lookup semantic broken sau Mig 29 (S21 t5). Trước Mig 29, 1 Level row per Cấp + `ApproverUsers` join table → `FirstOrDefault(Order==X)` đúng. Sau Mig 29 split 1 Level row PER ApproverUser → `Order` field collide → cần match thêm `ApproverUserId == currentUser.UserId`. **Fix BE 1 dòng:** `var curLevel = curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder && l.ApproverUserId == currentUser.UserId);` (admin bypass: fallback `?? curStep?.Levels.FirstOrDefault(l => l.Order == curLevelOrder)` để admin xem detail không lỗi). Edge case: Phase=DaDuyet/TraLai/TuChoi pointer null → existing guard line 760-762 skip block OK. **LOC ~2-3 LOC 1 file.** Surprise: bug PRESENT từ deploy Mig 29 (S21 t5 2026-05-13) — không phải regression S23. Lý do trước đây không bắt: UAT test users (default 13 cũ) đa số là row đầu của slot Cấp (Admin tick toàn FALSE → behavior giống nhau, không lộ); chỉ bộc lộ khi admin tick CHỌN LỌC per-NV (UAT V2 S22+2 thêm 20 user role-based + bro tick chỉ NV Test UAT V2). Cross-reference memory `feedback_per_nv_permission_scope.md` cumulative S21 t5 → S22+5 → S23 t1 — KHÔNG có entry nào nhắc bug lookup BE post-refactor.
### 2026-05-15 (S23 t6 spawn Plan P FE wire audit — confirm BE-only scope)
Em main hypothesize Plan P scope BE Controller body record drop. Investigator audit FE × 2 confirm: `PeWorkflowPanel.tsx:113-124` `api.post(/transitions, body)` SEND ĐÚNG 7 fields (TargetPhase + Decision + Comment + ReturnMode + ReturnTargetUserId + SkipToFinal). No service file (untyped object literal). BE `PurchaseEvaluationsController.cs:267` `TransitionPeBody` record CHỈ 3 fields → ASP.NET silent DROP 3 missing fields. Verdict: Plan P BE Controller ONLY ~6 LOC + no test (Mig 28/31 Domain test cover handler). Saved em main blind fix cross-stack.
### 2026-05-15 (S23 t8 spawn Plan R pre-flight cleanup audit)
Bro chốt cleanup destructive prod. 4 sqlcmd queries audit: 35 PE total (28 active + 7 soft) + 17 V2 (15 IsUserSelectable=false + 2 ghim) + 4 V1 (2 active + 2 inactive). FK gotcha catch: PE.ApprovalWorkflowId Restrict + ApprovalWorkflow extends `BaseEntity` NO soft-delete → hard-DELETE required; LevelOpinion → ApprovalWorkflowLevel Restrict cascade block. SQL Express limit: NO COMPRESSION + RESTORE VERIFYONLY require sysadmin. Filtered indexes (Mig 29+) require `SET QUOTED_IDENTIFIER ON`. Cascade child estimate: 446 PE children + ~140 V2 + ~37 V1 = ~620 rows. 3 Option compare → bro chốt A (Hard-DELETE PE + V2 unghim + V1 inactive, GIỮ V2 ghim + V1 active). Plan F precedent: KHÔNG drop V1 active (PE pin → BE crash).
### 2026-05-15 (S24 t1 spawn Pre-A — Plan AA User Workflow Matrix view + sidebar widen)
5Q audit. Q1 endpoint: `ApprovalWorkflowsV2Controller.cs:16-19` đã class-level `[Authorize]` bare từ S18 2026-05-08 (gotcha #44 fixed permanent), per-method admin Workflows.Create. Handler `GetAwAdminOverviewQuery` KHÔNG có IsUserSelectable filter — cần ADD param + Where conditional. Q2 menu seed: `DbInitializer.cs:1429-1437` peOrder global increment (Group=1, leaves 2/3/4 cycle per type). Permission seed `line 1541-1547` cho 7 role (Drafter/DeptManager/Procurement/CostControl/ProjectManager/Director/AuthorizedSigner). Accounting NOT trong list — admin manual grant nếu cần. Q3 Admin Designer: `ApprovalWorkflowsV2Page.tsx` 975 lines, AwLevelDto 13 fields (7 Allow*), VI labels line 892-948 ("Trả về 1 Cấp trước"/"Trả về 1 Bước trước"/"Trả về Người chỉ định"/"Trả về Drafter (mặc định)"/"Cho phép chỉnh sửa Section 2 (Hạng mục/NCC/Báo giá) lúc đang duyệt"/"Cho phép chỉnh sửa Section ngân sách lúc đang duyệt"/"Cho phép duyệt thẳng Cấp cuối khi đang duyệt"). KHÔNG có usePermission/PermissionGuard wrap (class-level [Authorize] route guard sufficient). Q4 sidebar widen: fe-user `Layout.tsx:325` + fe-admin `Layout.tsx:218` `w-60 xl:w-72` (240/288px). PE Workspace 2-panel `[260px_1fr] xl:[320px_1fr]` (NOT 3-panel như memory `feedback_responsive_laptop_breakpoint` stale claim). After widen `w-72 xl:w-80` (288/320px) SAFE (sidebar 288 + main 992 → workspace 260+732 fit @ 1280px). `w-80 xl:w-96` THRESHOLD RISKY (sát 700px remaining). Q5 ApplicableType enum `ApprovalWorkflow.cs:45-50` {DuyetNcc=1, DuyetNccPhuongAn=2, Contract=3}. Surprises: (1) memory responsive breakpoint stale "3-panel" → cần update sau Plan AA. (2) Order strategy "Luồng duyệt" Order=2 first → shift existing leaves +1 → cần DbInitializer UPDATE Order existing (KHÔNG chỉ INSERT-if-not-exists). (3) Contract=3 chưa wire FE (chỉ DuyetNcc + DuyetNccPhuongAn). Recommendation: Proceed Plan AA — chỉ ADD param filter + 1 menu key + page mới + sidebar widen. Token cost ~32k.
### 2026-05-15 (S24 t1-t4 post-spawn, em main solo 4 polish chunks — Plan AA wrap)
7 commits total `a1a910f..ee0902a`: BE+Layout (`ee776d5`) + FE Page (`c667802`) + Docs (`ac2c859`) + 4 polish iter UAT (`da218f1` px-2 + `4d60598` v1 panel-per-NV + `fbbd361` v2 table rowSpan + `ee0902a` sidebar label wrap). **Pattern reusable**: `inline-block icon + inline text + absolute ChevronDown` cho hanging-indent reverse wrap (label dài về đầu hàng). Mirror admin Designer style cho user view read-only. **Sidebar widen tradeoff**: `w-72 xl:w-80` + remove `truncate` FAIL fit 44+ chars label custom Mig 27 — cần combine với `text-[12px] + leading-snug` + restructure flex → block + inline. Sole `truncate` removal không đủ — phải full layout restructure NavLink. **Memory drift confirmed**: `feedback_responsive_laptop_breakpoint.md` claim "PE Workspace 3-panel" → S24 verify ACTUAL **2-panel** (260+1fr only, KHÔNG có panel thứ 3). Cross-ref update needed memory user-level (admin trigger curate sau). **Plan AA color palette success**: STEP_PALETTE 5 màu (blue/purple/emerald/amber/pink) + LEVEL_PALETTE 5 màu (violet/sky/teal/orange/rose) — **Tailwind JIT yêu cầu full class strings array, KHÔNG dynamic interpolation** (`bg-${color}-100` FAIL — class purged). Reusable cross-project cho menu hierarchy color coding (step parent + level child distinct palette). Final layout v2 table rowSpan: Step column merge per-Phòng + Level column rowSpan per-Cấp + NV column 1-row-per-approver, đẹp hơn v1 panel-per-NV stacked. Token cost iteration negligible (em main solo, no spawn).