① nút đính kèm 'Bảng so sánh' gate drafter+phase (cả 2 app) · ② gom 3 cặp dự án trùng dấu-cách trên PROD (5 phiếu+5 NS repoint, 3 ẩn mềm) + vá gốc chuẩn hóa Code +4 test. CI #407 PASS, bundle rotate ×2 verify 2-nguồn. Session log + merge script (docs/changelog/data-fixes) + STATUS/HANDOFF + garble tally ×3 + harvest investigator/reviewer/cicd. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9.3 KiB
Investigator-Codebase Agent — Persistent Memory
Persistent diary cross-session. Auto-injected first ~200 lines at spawn (L1 HOT). Update BEFORE every stop; keep entries to 1 line (gotcha #53 truncation — index hit 28KB @S148, hard-cap 24.4KB). Detail →
archive/2026-07.md+archive/_INDEX.md(sha-keyed substring, Ctrl-F) + gitd2f52ba+archive/2026-0{5,6}.md+runs/*/sub-*.md. Renamed S39: investigator → investigator-codebase (internal; external → investigator-api).
🎯 Role baseline
Read-only INTERNAL audit SOLUTION_ERP. Tools: Read/Grep/Glob/Bash + 5 RAG MCP. Output: concise <500w + file:line. Skills: contract-workflow + permission-matrix + ef-core-migration.
- ✅ MINE: sqlcmd schema scan, EF/grep, controller/authz audit, migration diff, count grounding
- ❌ NOT: external docs/CVE/lib → investigator-api · write → implementer · test → test-specialist · architecture decision → em main
📌 Recent invest (1-line digest; full detail → archive/runs/git)
- S148 (07-23) PE tree DUP project by-space:
FLOCK 01/FLOCK01= path-A TWO real Project rows diff-by-space. Tree groups onp.projectIdGUID (PurchaseEvaluationsListPage.tsx:192-197, display projectCode); PE→Project FKProjectId(PurchaseEvaluation.cs:15) JOIN-resolved (PeFeatures.cs:579/:647) — NO denorm string. CRUD zero-trim (ProjectFeatures.cs:80validator,:95/:138exactCode==dupe-check). Both seeds exact-Code key emit ONLY no-space:SeedRealMasterDataAsync:2776(UNGATED :128) +SeedDemoMasterDataAsync:2681(gated :117 OFF-prod). Space=legacy/manual. Blast=3 tables ProjectId (Contracts/PeWorkItemBudgets/PurchaseEvaluations); onlyPeWorkItemBudgetsUNIQUE(ProjectId,WorkItemId) filtered [IsDeleted]=0 (PeWorkItemBudgetConfiguration.cs:27). Direction: KEEP no-space (in seed→idempotent), RETIRE space (not-in-seed); soft-del survivor→seed RE-CREATES (#75/#76). Dev only FLOCK 01 pair (FLOCK03/CAL01 space-twins prod-only); prod UNVERIFIED (SSH dies on SQL-client, S134). Tag[s148, pe-tree-dup-project-by-space, path-A-two-rows, no-normalize-crud] - S147 (07-23) PE attach TraLai edit-block: FE-ONLY block, BE zero phase-guard (
PurchaseEvaluationsController.cs:15class[Authorize]only; handlers check exists onlyPurchaseEvaluationAttachmentFeatures.cs:66/:160). Gate = rawreadOnlyPROP not phase (GeneralAttachmentsSection:3555/:3577 hide-when-readOnly); List detail HARDCODEreadOnly=true(:574/:669) ⇒ TraLai loại khỏi SCREEN không khỏi editable-SET (workspacePeListPanel.tsx:88isEditablePhase GỒM TraLai). fe-admin MIRROR. BE no-guard CỐ Ý (S78). Fix FE:attachEditable=isDrafter&&isEditablePhase. Tag[s147, pe-attach-tralai, fe-only-screen-gate] - S141 (07-20) adap đợt-9/10 5-lane [fable-clone-ensemble, 5/5 clean]: (ii)-nới-có-vết đủ đóng dangling-head (3/3 squash-benign,
.session-counter.json); tick-head=wal-commit. byte-safe⟂tolerant-EXTRACTION 2-lỗ tách → pin regex\"?([0-9a-fA-F]{8,64})\"?. Roster-count 3-tầng (prose/glob/pointer). refine⟂lead-omission = discriminator WHOSE-memory. Detail →runs/…S141…. - S138 (07-17) adap 3-bản 17-07 [fable-real]: 3/3 FIT; delta hẹp hub PHẢI grep landing-site trong luật SỐNG (SE chép 4-nhãn lỗi vào
reviewer.md:46= adopt-verbatim kế-thừa lỗi nguồn). Detail →runs/…S138…. - S135/S134/S133 (07-17) PE budget invest [fable-real, #53→sub-file cứu trọn]: S134 lũy-kế lệch-tiền-đề row1 (
PeBudgetAccumulator.cs:42-48PrevSubmitted ĐÃ gồm ChoDuyet; DaDuyet-only chỉ row2 :50-60) predicate 1-bản helper Features:962+WorkflowService:1018. S133 freeze-at-DaDuyet 4-assignment (PurchaseEvaluationWorkflowService.cs:861/:899/:931/:1053, Mig67). S135 tick H24 single-entrysession-start:181-206. Detail → archive + runs. - S128 (07-16) adap-16-07 [fable-real, garble→on-behalf]: RAG config in-repo (
AI_INFRA\claude-rag\lib\projects.py:39owner-final,rag.json:26override); nhãn-đo "calibrated" chỉ C1; ghi-đĩa-trong-lúc-làm cứu draft khi garble. Detail → runs. - S126 (07-16) worker-pin + all-inherit sweep [opus×2]: 14/14 opus+max (no-tier lane resolve opus DÙ lead=Fable); B1 284→15 floor-sống; mega-line blow Read-cap → perl-window.
[s126, h23-precedence] - S125 (07-16) adap-review [fable-real]: auto-memory 50 tracked/0 porcelain; 14/14 opus+effort:max; residue all-inherit floor-sống 2 (
fable-real.md:37+fable-clone.md:43) vá; verifier-suspect-first. - S122 (07-15) retro-harvest [6/6 clean]: 🔴 0/7 mất 7/7 XONG synthesis-sai-chỗ (orphan đo TÊN không NỘI-DUNG); lane-RỖNG≠mất; lane tự truy git đừng tin brief.
- S116/S117 (07-13) PE negative-quote + giá-chốt RANGE [fable]: neg-quote FE-ONLY (BE/DB nhận âm; quote sống
details[].quotesKHÔNGsuppliers[].quotes). S117 ApprovedPrice WRITE 1-siteApplyApprovedPriceOnFinalize; HĐ-gen KHÔNG đọc ApprovedPrice (GiaTri=SUM IsSelected). endsBeforeCeo=config-lie #78 (detail :1152 / list :647). - [archived → archive/2026-07.md + git] S87-S114 PE recon (multi-winner IsSelected per-hạng-mục Mig65 · WinnerQuoteTotal DERIVED · budget gate PURE-ROLE · V2 routing=ApproverUserId LINEAR) · Supplier-import-v2 (ClosedXML, Mã NCC=Code, IsPublic fail-closed, import authz-mismatch) · S105 BVAAU auth RCA (relative-
/apiprod-404) · S104 30-field · S98-S101 harness · Office/HRM/Governance recon. Ctrl-F_INDEX.md.
📋 Patterns proven
Schema scan sqlcmd
sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Dev -Q "..." # runtime API (primary)
sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Design -Q "..." # ef tooling
Prod: ssh vietreport-vps powershell-wrapper sqlcmd -S '.\SQLEXPRESS' -d SolutionErp -E … — ⚠️ SSH session DIES whenever SQL-client loads (S134/S148 re-confirm); prod-DB effectively UNVERIFIABLE this path, flag + give query for implementer. 2 LocalDB distinct: _Dev=runtime · _Design=dotnet ef default. Queries: sys.columns/indexes/tables, __EFMigrationsHistory, dup-detector REPLACE(Code,' ','').
Controller / wire-claim audit
- Grep
\[Route\("api/[a-z]+"\)\]controllers ·\[Authorize(Policy="…"per-action (gotcha #44 silent-403; class-level[Authorize]trần = no phase-guard, S147) - Grep
// Mock/alert(/setEditing(null) // close UI— wire bugs
Memory cross-reference
30 user-memory C:\Users\pqhuy\.claude\projects\D--…\memory\MEMORY.md. Key: designtime_runtime_db · workflow_fanout_reliability · canonical_spec_over_broadcast · root_cause_over_symptom · cardinality_change_grep_consumers.
⚠️ Anti-patterns
❌ Skip MEMORY update · ❌ Vague "seems/probably" · ❌ Missing file:line · ❌ >500 words · ❌ Scope drift to architecture rec (em main decides) · ❌ Multi-line MEMORY entries (index truncates >24.4KB)
🧠 SOLUTION_ERP context (numbers canonical → docs/STATUS.md; re-ground don't trust)
- DB: Dev
SolutionErp_Dev· DesignSolutionErp_Design(distinct) · Prod.\SQLEXPRESS/SolutionErp/vrappvia SSHvietreport-vps - Migration path:
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/*.cs(NOT root). Last-schema Mig 67AddPeApprovedBudgetSnapshot(S133); ~67 mig. - Counts (docs/STATUS.md canonical): ~88 SQL tables (count
.ToTable()snapshot NOT DbSet) · ~253 endpoints · 68 FE pages · 54 menu keys (MenuKeys.cs) · ~354 test · ~71+ gotchas · 14 sub-agents (worker-tier-pin S124) - Tech: .NET 10 Clean Arch (Api→Application←Domain + Infra) + CQRS MediatR + EF Core 10 + 2 React Vite TS (fe-admin :8082 + fe-user :8080) + SQL Server + Gitea CI + IIS
- Prod: api/admin/eoffice.solutions.com.vn · Gitea
git.baocaogiaoduc.vn/…/solution-erp(Actions API/actions/tasksNOT/runs, cache stale ~2min #46) - Auth:
admin@solutions.com.vn/Admin@123456(full) /nv.test@solutions.com.vn/TestUser@123456(Drafter). Password ≥12.
🔄 Active workflow schemas (V1 + V2 coexist post-S17)
- V1 Mig 21 flat —
WorkflowDefinitionpin cũ, match Dept+PositionLevel. - V2 Mig 22-31 —
ApprovalWorkflowpin PE/Contract, matchApproverUserId1-1 OR-of-N cùng Cấp. Steps(Phòng)>Levels(Cấp). Proposal V2 Mig38, WorkflowApps Mig39. (Mig25 IsUserSelectable · 26 LevelOpinions UPSERT · 30 AllowApproverEditBudget · 31 SkipToFinal→ApproverLevel · 53 cờ-gấp+CeoThreshold · 54 giá-đề-xuất · 58 IsWinner multi + AllowApproverFinalize · 65 Quote.IsSelected per-hạng-mục · 66 ApprovedPrice Min-Max · 67 budget-freeze snapshot). - State PE 5: Nháp / Đã gửi duyệt / Trả lại (TraLai=98) / Từ chối (TuChoi, REMOVED-path S60) / Đã duyệt
- Mode Trả lại 4: OneLevel / OneStep / Assignee / Drafter (Phase=TraLai). 3 đầu giữ ChoDuyet lùi pointer. Admin bypass
level.Allow*. - Seeds gating:
SeedDemoMasterDataAsyncgatedDemoSeed:Disabled(OFF prod) ·SeedRealMasterDataAsyncUNGATED (62 dự án + 71 hạng mục Excel, per-code idempotent, exact-Code key #75/#76 resurrect risk).
🔄 Curate log
- S148 (07-23): hard-cap rewrite 28.2→~14KB — collapsed multi-line S133-S148 → 1-liner, dropped stale pointer-list (S87-S114 → grouped 1-line, verbatim in archive/git). Single-writer inv-cb (hook @28KB).
- Prev: S125 (23.9→~15KB, 14 lines→archive/2026-07.md) · S71/S70/S40. Verbatim byte-exact in
archive/.