# Gist 2026-05 — investigator-codebase (q1+q2+q3+q4 distilled)

> `distill-gen: 1` (already-distilled — do NOT re-compress).
> 4-field per record: **VIỆC** · **KẾT-LUẬN** (+file:line/commit) · **BÀI-HỌC** · **BẤT-NGỜ**. Same-topic records merged. Confidence tag cao/vừa/thấp.
> Each line ends with a back-resolve `substring:"…"` (unique Ctrl-F) into the named verbatim file. Files: q1=2026-05-q1.md · q2=2026-05-q2.md · q3=2026-05-q3.md · q4=2026-05-q4.md.
> This is the lossy lens; the verbatim files hold the full text. The 22-marker coverage gate is satisfied here.

---

## Bug RCAs (PE workflow, F-features)

- **[cao] F4 budget-edit broken at readOnly short-circuit** · VIỆC: UAT admin tick F3+F4 for Approver slot, menu Duyệt → Section2 + budget-adjust stay read-only. KẾT-LUẬN: F3 wire OK (`PeDetailTabs.tsx:118 itemsReadOnly = readOnly && !approverEditMode`); **F4 BUG `BudgetAdjustSection :973 canAdjust = !readOnly && (…isApproverChoDuyet)` — `!readOnly` short-circuits to false BEFORE isApproverChoDuyet evaluates** (asymmetric vs F3 :113-118); BE handler `:281-329` correct. BÀI-HỌC: mirror the approverEditMode bypass into the budget gate; ~3-5 LOC 1 file. BẤT-NGỜ: only desktop `?pendingMe=1` 3-panel hard-codes readOnly=true; mobile `/inbox`→DetailPage default false. · q1 · substring:"S23 t2 spawn L2 — F3+F4 edit menu Duyệt audit"
- **[cao] Allow* flags invisible to non-row-1 actor — wrong-slot lookup** · VIỆC: admin tick 7 Allow*=TRUE on one specific NV slot, that NV logs in, Duyệt dialog shows no SkipToFinal/Return/Edit. KẾT-LUẬN: HYPOTHESIS B — **BE `PurchaseEvaluationFeatures.cs:765 curLevel = Levels.FirstOrDefault(l => l.Order == curLevelOrder)` picks FIRST row of the Cấp, not the actor's**; post-Mig29 every NV in a Cấp shares the same `Order` (4 rows Order=1). Fix = add `&& l.ApproverUserId == currentUser.UserId` (admin fallback `?? FirstOrDefault(Order==)`); ~2-3 LOC. BÀI-HỌC: Mig29 OR-of-N split (1 row per ApproverUser) silently broke every `FirstOrDefault(Order==)` lookup. BẤT-NGỜ: **bug PRESENT since Mig29 deploy 2026-05-13, NOT an S23 regression** — hidden because default users sat in row-1 with all-FALSE flags so behavior looked identical. · q1 · substring:"S23 t3 spawn — UAT bug Allow* flags không hiện cho actor non-row1"
- **[cao] Return-mode + budget changelog gaps** · VIỆC: 2 UAT bugs — Budget-adjust 2×click shows no history; Return-Assignee shows no history. KẾT-LUẬN: Budget handler DOES log (Header/Update) → FE HistoryTab filter (TraLai-only) hides it; **`PurchaseEvaluationWorkflowService.cs:215-378 ApplyReturnModeAsync` has ZERO changelog writes** (4 mode branches mutate pointers only; caller LogTransition logs phase only). Schema `EntityType.Workflow=5` exists but **design-only, unused 4+ migrations**. BÀI-HỌC: fix B2 first (add `Changelogs.Add()` per mode, 1 BE file) then relax FE filter. BẤT-NGỜ: Header.Update collision — budget-adjust vs section-2 edit share the same EntityType/Action (needs a Kind subtype). · q2 · substring:"S25 t1 spawn audit 2 bug critical UAT"

## Semantic / phase audits (no code bug)

- **[cao] F1-F4 all preserve Phase=ChoDuyet except F1.Drafter** · VIỆC: bro thought "return/skip/edit forces draft". KẾT-LUẬN: code already correct — `PurchaseEvaluationWorkflowService.cs:268-275` F1.Drafter is the ONLY path setting Phase=TraLai=98; `:285-360` OneLevel/OneStep/Assignee keep ChoDuyet (move pointer only); `:483-524` F2 skipToFinal keeps ChoDuyet (jumps to last step+level, final NV approves → DaDuyet). BÀI-HỌC: this was a mental-model disconnect not a defect; LOW effort = confirm + optional FE label. BẤT-NGỜ: "Trả lại" gets called "draft" colloquially → conflates Phase=TraLai=98 vs Phase=DangSoanThao=1. · q1 · substring:"S23 t2 spawn M0 — Plan M F1+F2+F3+F4 ChoDuyet semantic audit"

## Pre-flight audits (schema/migration/cleanup)

- **[cao] Plan K F2 refactor state** · VIỆC: move `Users.AllowDrafterSkipToFinal` → Level slot. KẾT-LUẬN: Mig30 latest; F2 Drafter branch in SUBMIT path `:119-161`, advance branch `~:393-525`; prod 33 users / 4 flagged (Dev only 2). BÀI-HỌC: flagged users lose value on DROP — acceptable under new semantic. BẤT-NGỜ: Dev DB drifted to 2 users, not matching 33-user prod seed. · q1 · substring:"S23 t1 spawn K0 — Plan K F2 refactor pre-flight"
- **[cao] Plan R destructive-cleanup pre-flight + DECISION** · VIỆC: wipe prod test PE. KẾT-LUẬN: **PE.ApprovalWorkflowId = Restrict + ApprovalWorkflow extends BaseEntity (NO soft-delete) → hard-DELETE required**; cascade ~620 rows; filtered indexes need `SET QUOTED_IDENTIFIER ON`. **DECISION: bro chose Option A = hard-DELETE PE + V2-unghim + V1-inactive, KEEP V2-ghim + V1-active.** BÀI-HỌC: Plan F precedent — never drop a V1 that still has PE pinned (BE crash). BẤT-NGỜ: SQL Express has no COMPRESSION and RESTORE VERIFYONLY needs sysadmin. · q1 · substring:"S23 t8 spawn Plan R pre-flight cleanup audit"
- **[cao] Plan B Contract V2 wire pre-flight** · VIỆC: mirror PE V2 onto Contract. KẾT-LUẬN: **`ApproveV2Async` PurchaseEvaluationWorkflowService.cs:446-634 = 189-LOC clone template** (load AW.Steps.Levels + actor match :484-495 + UPSERT opinion :522-546 + advance :605-633 + skipToFinal F2 :561-602); **Mig22 = 3 CREATE TABLE shared PE+Contract; Mig23/24 = 15-LOC / 3-LOC cookie-cutter rename Pe→Contract**; prod 7 Contracts 100% V1, ApprovalWorkflows ZERO ApplicableType=3. BÀI-HỌC: coexist V1+V2, 6-chunk split. BẤT-NGỜ: ContractType has 7 variants vs one generic ApplicableType=3 → may need per-type filter later. · q2 · substring:"Plan B Contract V2 wire pre-flight audit"
- **[vừa] Plan AG PE-list tree-view** · VIỆC: flat list "đám rừng". KẾT-LUẬN: shadcn fe-user MISSING Accordion/Collapsible/Tree → Phase1 native `<details>` group view ~160 LOC ×2 app; Phase2 ProjectPackage schema defer. BÀI-HỌC: hybrid FE-first cookie-cutter. · q2 · substring:"S26 spawn Plan AG 5Q audit"
- **[vừa] Plan AA matrix-view + sidebar** · VIỆC: workflow matrix page + widen sidebar. KẾT-LUẬN: `ApprovalWorkflowsV2Controller.cs:16-19` **class-level [Authorize] bare since S18 2026-05-08 (gotcha #44 fixed permanent)**; ApplicableType enum {DuyetNcc=1,DuyetNccPhuongAn=2,Contract=3}. BÀI-HỌC: order-strategy must UPDATE existing Order (not just INSERT-if-absent); wrap commits `da218f1..ee0902a` see Tailwind-JIT record below. · q1 · substring:"S24 t1 spawn Pre-A — Plan AA User Workflow Matrix view"

## Patterns / gotchas / state

- **[cao] Identity rename atomic + pwd policy + PS discipline** · VIỆC: seed 20 role-based users on prod. KẾT-LUẬN: **gotcha #38 = rename atomic 4 fields (Email+NormalizedEmail+UserName+NormalizedUserName+FullName) + sqlcmd needs `SET QUOTED_IDENTIFIER ON` for filtered unique index**; **Identity pwd policy ≥12 chars (`User@123456`=11 FAILs 400, `TestUser@2026`=13 passes)**; login response = `accessToken`+`refreshToken`+`user` (no `token`). BÀI-HỌC: **gotcha #30 = PS 5.1 ASCII-only script discipline (Vietnamese names without diacritics or parser error)**. · q1 · substring:"S22, no spawn — em main solo throughout"
- **[cao] bug #45 + per-NV scope + EF reorder** · VIỆC: S21 dev log. KẾT-LUẬN: **gotcha #45 bug-fix** + F1/F2/F3 workflow-level Mig28/29; reusable = per-NV permission scope split + EF migration ADD→BACKFILL→DROP reorder. · q1 · substring:"S21 t3-t5, no spawn"
- **[cao] Tailwind JIT full-class-strings** · VIỆC: Plan AA color-coded menu hierarchy. KẾT-LUẬN: **Tailwind JIT requires full class strings array — dynamic `bg-${color}-100` gets purged**; STEP/LEVEL 5-palette each; v2 table rowSpan layout. BÀI-HỌC: reusable for hierarchy color coding cross-project; plus hanging-indent reverse-wrap = `inline-block icon + inline text + absolute ChevronDown`. · q1 · substring:"S24 t1-t4 post-spawn, em main solo 4 polish chunks"
- **[cao] S40 state grounding** · VIỆC: re-ground 7 metrics. KẾT-LUẬN: mig=40 / gotcha=55 / git clean / **SQL tables=84 = count `.ToTable()` in ModelSnapshot NOT DbSet (DbSet=77 undercounts by 7 Identity)** / endpoints=211 / FE 65 pages / menu 53 keys. BÀI-HỌC: tables must be counted via ToTable, never DbSet. · q4 · substring:"S40 STATE GROUNDING"
- **[vừa] BVAAU 7-agent port** · VIỆC: split roster 4→7. KẾT-LUẬN: research(2)/implement(2)/quality(3); boundary repo-interface=domain, EF-config=infra, test=specialist; all 7 get 5 RAG MCP. BÀI-HỌC: BVAAU template aspirational (Phase-0 empty codebase), not battle-tested; SE keeps 6 skill + backend/frontend split. · q4 · substring:"S39 BVAAU 7-agent extract"
- **[vừa] P11-A WorkflowApps pre-flight** · VIỆC: wire Leave/OT/Travel/Vehicle. KẾT-LUẬN: schema pinned Mig39 (ApprovalWorkflowId?+CurrentApprovalLevelOrder?+WorkflowAppStatus); Proposal = perfect mirror (`ProposalFeatures.cs:403-486` flatten Steps→Levels). BÀI-HỌC: gap = 4 LevelOpinion tables + 3 controllers + 4 seed WF. BẤT-NGỜ: **`ApprovalWorkflow.cs:72` says Level is NOT OR-of-N (1 ApproverUserId/Level) — contradicts older "OR-of-N" memory, verify**; `ExtendApplicableTypeForWorkflowApps` mig has empty Up/Down (enum-only). · q4 · substring:"P11-A WorkflowApps wire pre-flight"

## RAG research

- **[vừa] RAG distribution research** · VIỆC: setup RAG for 5 colocated projects. KẾT-LUẬN: 4 study cases (Cursor Merkle+Turbopuffer / Cline markdown JIT / Continue.dev hub / Sourcegraph Cody dropped-embeddings); winner for single-dev = Pattern C user-global MCP (1 localhost server serves 5). BÀI-HỌC: **Voyage AI 200M tokens/month free covers 5 devs** → only $15 VPS. · q2 · substring:"S26 spawn Plan AI RAG distribution research"

## [meta] bookkeeping (low signal)

- **[thấp] spawn-attribution FLAG** · The S20-S26 memory entries claiming "spawn Investigator" may be misattributed `general-purpose` (the `investigator` agent type was NOT found / registry not loaded in S27); trust-but-flag for future audit. · q3 · substring:"S27 wrap-up retrospective em main proxy"
- **[thấp] gotcha #48 SQLite tie-break** · Plan AB wrap: CICD runs #215 FAIL on Plan-M tests SQLite tie-break re-emerge → #216-#221 PASS; **gotcha #48 SQLite tie-break pending docs**. · q3 · substring:"S25 wrap Plan AB Bug 1+2 audit"
- **[thấp] curate note (S29-era)** · archived 10 verbose S21→S24 entries to q1; KEEP-list recorded. · q3 · substring:"Curate session em main S29 era"
- **[thấp] agent setup baseline** · init load 44 gotcha / 27 mig / 81 test, no investigation yet. · q1 · substring:"2026-05-11 (setup)"
- **[thấp] agent setup baseline (re-archived dup)** · same baseline note, kept in q3 by S34 curate. · q3 · substring:"2026-05-11 — Setup baseline"
