19 KiB
Investigator-Codebase Agent — Persistent Memory
Persistent diary cross-session. Auto-injected first ~200 lines at spawn (L1 HOT). Update BEFORE every stop. Tiered Memory v1: L1 HOT soft-cap ~30KB · L2
archive/on-demand · L3 RAGsearch_memoryjust-in-time. Keep entry ≤ 1.5K chars (gotcha #53). Full verbatim history pre-S40 → gitd2f52ba+archive/2026-05-q1..q4.md+archive/2026-06.md. 🗺️ Lookup map:archive/_INDEX.md— 1 dòng/bản-ghi + con-trỏ substring (sha-keyed, Ctrl-F fallback); đọc verbatim +2026-0{5,6}.gist.mdtheo nhu cầu. S80 curate: moved 15 recon entries S65→S76 + 2× 06-20 → archive. Renamed S39: investigator → investigator-codebase (internal half; external → investigator-api).
🎯 Role baseline
Read-only INTERNAL audit SOLUTION_ERP codebase. Tools: Read, Grep, Glob, Bash + 5 RAG MCP. Output: concise findings <500 words + file:line refs. Skills: contract-workflow + permission-matrix + ef-core-migration.
🚫 Split boundary (S39)
- ✅ MINE: internal SQL/EF/grep/reference mirror, sqlcmd schema scan, controller audit, migration diff, count grounding
- ❌ NOT: external docs/CVE/lib →
investigator-api· write → implementer · test → test-specialist · architecture decision → em main
📋 Patterns proven (apply confidently)
Schema scan via sqlcmd
sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Dev -Q "..." # runtime API (primary)
sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Design -Q "..." # ef tooling
ssh vietreport-vps "sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P '...' -Q '...'" # prod
Queries: sys.columns, sys.triggers, __EFMigrationsHistory, COUNT(*), sys.indexes.
Gotcha 2 LocalDB distinct (feedback_designtime_runtime_db): _Dev=runtime (appsettings.Development), _Design=dotnet ef default. Prod password fallback C:\inetpub\solution-erp\api\appsettings.Production.json khi $env:PROD_DB_PASSWORD empty.
Controller / wire-claim audit
- Grep
\[Route\("api/[a-z]+"\)\]enumerate controllers ·\[Authorize(Policy = "..."per-action policy (gotcha #44 silent 403 class-level quá strict) - Grep
// Mock/alert(/setEditing(null) // close UI— wire claim bugs ·IActionResultvsActionResult<T>
Smoke verify catalog
Bearer từ POST api.solutions.com.vn/api/auth/login → status matrix expected vs actual + file:line evidence.
Memory cross-reference
30 user-memory tại C:\Users\pqhuy\.claude\projects\D--...\memory\MEMORY.md (index). Key: per_chunk_commit · uat_skip_verify · designtime_runtime_db · per_nv_permission_scope · ef_migration_backfill_reorder · workflow_fanout_reliability · canonical_spec_over_broadcast (S79).
External research → DEFER investigator-api (split S39)
⚠️ Anti-patterns
❌ Skip MEMORY update · ❌ Vague "seems like/probably" · ❌ Missing file:line · ❌ >500 words · ❌ Scope drift to architecture recommendation (em main decides)
🧠 SOLUTION_ERP context essentials (S80 verified — re-ground từ docs/STATUS.md canonical)
- DB: Dev
SolutionErp_Dev· DesignSolutionErp_Design(distinct) · Prod.\SQLEXPRESS/SolutionErp/vrappvia SSHvietreport-vps - Migration path:
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/*.cs(⚠️ NOT root/Migrations/). 57 mig, lastAddPeSuggestedPriceNotes. - Counts S80 (canonical docs/STATUS.md): 57 mig · 88 SQL tables (count
.ToTable()ModelSnapshot NOT DbSet) · ~253 endpoints · 68 FE pages · 54 menu keys (BEMenuKeysconst) · 354 test (45 Domain + 309 Infra) · 71 gotchas (format### N.) · 30 user-memory · 6 skills · 11 sub-agents (all-inherit H8) - Tech: .NET 10 Clean Arch (Api→Application←Domain + Infra) + CQRS MediatR + EF Core 10 + 2 React 19 Vite 8 TS 6 (fe-admin :8082 + fe-user :8080) + SQL Server + Gitea CI + IIS
- Prod: api/admin/eoffice.solutions.com.vn · Gitea
git.baocaogiaoduc.vn/vietreport-admin/solution-erp(Actions API/api/v1/repos/.../actions/tasksNOT/runs404, cache stale ~2min gotcha #46 — cross-check VPS mtime). Bundle live adminCsJetgZH/userBVS0ApIm(Run #330). - Auth:
admin@solutions.com.vn/Admin@123456(full) /nv.test@solutions.com.vn/TestUser@123456(Drafter). ResponseaccessToken+refreshToken+user. Password ≥12 chars.
🔄 Active workflow schemas (V1 + V2 coexist post-S17)
- V1 Mig 21 flat —
WorkflowDefinitionpin PE/Contract cũ. Match Dept+PositionLevel. - V2 Mig 22-31 —
ApprovalWorkflowpin PE/Contract mới, matchApproverUserId1-1 OR-of-N cùng Cấp. Steps (Phòng) > Levels (Cấp). PE + Contract đã wire V2 (Mig 32+33 S29). Proposal V2 (Mig 38). WorkflowApps skeleton (Mig 39).- Mig 25 IsUserSelectable · Mig 26 PE LevelOpinions UPSERT · Mig 29 Allow* per-NV · Mig 30 F4 AllowApproverEditBudget · Mig 31 SkipToFinal→ApproverLevel · Mig 53 cờ-gấp+CeoApprovalThreshold · Mig 54 giá-đề-xuất PRO/CCM+giá-chốt · Mig 56 ProInitial/ProAdjust · Mig 57 ghi-chú-giá.
- State machine PE 5 trạng thái: Nháp / Đã gửi duyệt / Trả lại (TraLai=98) / Từ chối (REMOVED-S60 hard-guard) / Đã duyệt
- Mode Trả lại 4 option per-Level: OneLevel (lùi 1 Cấp) / OneStep (lùi Bước trước) / Assignee (pick NV đã ký) / Drafter (Phase=TraLai). 3 mode đầu giữ ChoDuyet lùi pointer. Admin bypass
level.Allow*.
📅 Recent activity (compressed — full verbatim → archive/2026-06.md via archive/_INDEX.md)
-
2026-07-07 (S105 BVAAU cross-repo auth RCA — on-behalf em-main B3; #53-garble lần-7 → SendMessage-resume recover): Task: invest read-only repo BVAAU (Home Google login "đá ra ngoài" + CRM1 guard + Zalo User_ID). Verdict: Q1 root-cause = FE Home MÙ session — bundle prod cũ gọi relative
/apitrên site TĨNH (web.configloại^/api/khỏi SPA-fallback) →/api/auth/me404 → anonymous vĩnh viễn, TRONG KHI hub-side OK hết (state→callback→auto-provision→cookiebvaau.authDomain=.benhvienaau.comSameSite=Lax; 7 nghi vấn a-g đều KHÔNG); fix API_BASE-absolute = session-BVAAU commit51c69fb13:45 CÙNG-LÚC điều tra → em-main byte-verify bundle mới HomeCtTKjYz2+ CRM1Cr8wJMpnmarker PRESENT = LIVE. Q2 CRM1 trước đó hở 2 tầng (FE soft-gate + APIenforceCrmGate:false); FE-redirect-home live 51c69fb; kín API = flipAUTH_ENFORCE_CRM_GATE=truechờ anh. Q3 "User_ID" KHÔNG có trong UI 3 app (duyệt Zalo = StaffCode+Note);ProviderUserIdbackend = identity-map GIỮ (ApprovePendingLogin.cs:114,141). Nấc: verified (em-main first-hand git-show + curl byte + config live). Learned: class "hub tập-trung + site tĩnh: relative/apisống dev (Vite proxy), chết im prod" → auth-hub call luôn absolute-host; garble lần-7 = reasoning-lane, recover mới = SendMessage-resume khi diary trống (context sống trong-session). Tag[s105-bvaau-auth-rca, fe-blind-session, 53-garble-7-resume, cross-repo-readonly]. -
2026-07-06 Supplier 30-field invest+review WF
wf_5ac2cdb0(anh Kiệt FDC — 🅰️ schema go-live): ⭐ schema-domain lane #53-GARBLED (null, "no StructuredOutput") nhưng full design RECOVERED từ chính AS-10 memory-write của nó (reverted sau harvest —feedback_agent_return_garble_recover); em-main authored authoritative schema. 6 ground-truth correction vs brief: (1) ClosedXML 0.105.0 = project Excel-standard, KHÔNG phải OpenXml raw —csproj:8+ mọi path (XlsxRenderer.cs:18/ContractExcelExporter.cs:56/AttendanceReportExcelExporter.cs:14) dùngXLWorkbook;cell.GetString()auto-decode shared-string → "shared-string pitfall" MOOT (cả 2 pkg referenced, OpenXml KHÔNG dùng cho read). (2) reuse-existing-cols > parallel-new-cols — map TÊN CÔNG TY→Name(cũ), ĐỊA CHỈ XUẤT HĐ→Address, SĐT→Phone; thêm cột MỚI chỉ cho TYPE thật-mới (OfficeAddress/MailingAddress/ContactPhone); tạo companyName/invoiceAddress = ORPHAN cột seed live. (3)UpdateSupplierCommand.cs:49-57blind absolute-set cả 9 incl Note = latent #73 clobber → import (🅱️) PHẢI ghi entity direct + fill-where-non-empty, KHÔNG route qua Update cmd. (4) seed idempotent-by-Code (DbInitializer.cs:2781) SKIP existing → cột mới NULL → population = seed fill-nulls-if-exists (KHÔNG seed-insert-alone). (5)SupplierDtohand-projected 2 site (GetSupplierQuery.cs:21+ListSuppliersQuery.cs:48-50positional, no AutoMapper) → +6-file thread mỗi cột. (6) FE:Dialog.tsx:48đãmax-h-70vh overflow-auto→ form-expand cần 0 layout-code (go-live win lớn nhất); HoSoLinktoFileUrl/PathWithCopyLOCAL-không-export trongPeDetailTabs.tsx:2087/2098→ extract sharedui/PathLink.tsx. Design chốt: +18 nullable AddColumn (net 89),SupplierType +CaHai=6APPEND, newSupplierStatusenum nullable, Mig 62. Reviews 3× PASS_WITH_CONCERNS (2 goLiveSafe, import-robustness=false chờ 🅱️). Tag[supplier-30field, wf-invest, closedxml-not-openxml, reuse-cols, hand-dto-2site, update-blind-set-73, seed-fillnulls, dialog-autoscroll]. -
[→ git+session-log 07-03 + adap-reports] S101 H19-adopt Lane-2: map reviewer=review-gate / investigator=ground-truth-lane; 12-pt tier-checklist ALL✅ (11/11 inherit, C3 no-
[1m]-in-frontmatter); toggle-marker MUST copy.gitignore:87last-match placement; VACUOUS-MET all-inherit+Fable. (verbatim → archive/2026-07.md) -
[→ git+session-log 07-02 + adap-reports] S100 H18-adopt WF1: ⭐ ghost-wire-class config-key-defined-but-unread (
budget.json:54-55script re-hardcode same-value→no-flag; catch=grep-key-across-scripts); cron=ghost-wire (CronList=0);_ledgerorphan-catch 0/15-lifetime. (verbatim → archive/2026-07.md) -
[→ git+session-log 07-02] S98 verify-lane V2: detector 28→25, 8 derived-stale=100% FP count-token-soft-net vs canonical 61/89/440/79; grep-gotcha "Fable RESTORED" exact misses README variant ":3 Fable 5 1M RESTORED". (verbatim → archive/2026-07.md)
-
[→ git+session-log 07-01] S97 feedback-audit: #77/#78/#79 present
gotchas.md:1301/1317/1325; #53-garble ×6 = cicd MEMORY-self-target ~17.5KB structural-root-cause; Mig 60 wrong-table Approvals→Mig 61 Changelogs both present. (verbatim → archive/2026-07.md) -
[→ 07-06 entry above + session-log] 2026-07-01 Supplier GAP predecessor: SUPERSEDED by 07-06 schema-design entry above (same anchors: 9-prop lean, seed-cram→Note, HoSoLink NAS precedent, prod 20-NCC). (verbatim → archive/2026-07.md)
-
[→
scripts/mfe-eval.ps1§H + session-log 06-29] S93 MFE ground-truth: denominator=marks/AS/guards/gotcha dedup-by-AS-xref=29; per-role coverage denom=numbered-anti-pattern numer=diary-match exact-id OR ≥2-content-word (beats leading-verb-giả). (verbatim → archive/2026-07.md) -
PE FROZEN-Mig59 patchwork + go-live recon cluster (S87→S89, 8 entries →
archive/2026-06.md): AREA-2 budget-matrix (SetPeCcmBudgetPeriodCommandband-aid misplaced inPeSuggestedPriceFeatures.cs:153-199; PRO=drafter-flow vs CCM=role-flow authz asymmetry Section-B row3; "Dự án" col intentional FE-only "—") · AREA-3 finalize/price (AllowApproverFinalize AUTO Mig58 + finalizeByCcmDelegation OPT-IN Mig54 coexist, AUTO-first; ApplyApprovedPriceOnFinalize allow-list {Ncc,ProMin,ProMax,Ccm}; isSystem-branch DEAD via public ApproveV2Async) · AREA-4 UpdatePeDraft (LATENT #73-class BUG: HoSoLink absolute-setPurchaseEvaluationFeatures.cs:280but PeHeaderForm PUT OMITS → clears; 2 PUT call-sites mutually destructive; no HoSoLink-preserve test) · AREA-5 urgent/notify/TZ (SignalR push BYPASSES UtcDateTimeJsonConverter benign-Kind.Utc; urgent SET/UNSET symmetric fail-closed; possible double-notify-then-skip drafter=Cấp1) · AREA-6 FE-consumers (all 6 PE-comp+3 pages SHA-identical 2-app; residual single-winnerPeListPanel.tsx:168blank ≥2 joint; #70 stale-echo PRO row3/8 no-peFetching) · S89 AllowApproverFinalize-NOTE feasibility (GAP: BE field MỚI cần — flag chỉ ởcurrentLevelOptionscurrent-level; approvalFlow+list+dashboard DTO KHÔNG carry → exposeEndsBeforeCeo+FinalizeStep/LevelName; FE note đầuPeWorkflowPanel.tsxflow<ol>) · 06-24 3-change (winner=SINGLESelectedSupplierId, winnerQuoteTotal DERIVED 3-site; budget=0 blocked 2-layer; terminal=NEW per-Level bool mirror SkipToFinal) · 06-23 D2/D4/D5 UAT (urgent authz BẤT-ĐỐI-XỨNG gắn-role/gỡ-DeptMgr; PE-create dropdownPeWorkspaceCreateView.tsx:94; workflow-required 2-tầng). -
2026-06-20 governance-landing map (RC-sig + User-Mark H12/13 + objective-criteria): ⭐ WHERE-to-land 3 AI_INFRA gov broadcasts.
harness-11-engine.md= CANONICAL engine (D5/D6/D7 safety-tier + D8 one-direction-lock + D9 single-writer + D10 Bash-residual + CAVEAT no-OS-hook).error-ledger.md= §L.a AS-1..13 + §L.b 7-step. adap-report FORMAT richest =2026-06-18-Governance-harness-11.md. rules.md §6.6 = objective-criteria. report-before-stamp ⊂ D7 (extend, đừng duplicate → C3 vocab-fork). → _INDEX. -
2026-06-20 Harness-14 Eval/Budget/Outcome audit: ⭐ H-14 = time/age/recency-decay KHÔNG được làm căn-cứ cắt feature. (1) BUDGET aligned:
memory-budget.json0 decay/TTL/age hit;keep_floor=5=newest-protection (drains OLDEST), cap seed-by-MEASURE. (2) detectors = canonical-anchor-vs-STATUS + disk-cross-check, ZERO age-window. (3) EVAL genuine:eval/golden-set-solution_erp.jsonl(14q) +evaluator.mdrecall@5≥0.7 — weekly-manual no-automation. (4) anti-downgrade = Harness-8 "all-inherit chất-lượng>chi-phí" PARTIAL (no generic rule in rules.md, grep 0). → _INDEX. -
PE recon cluster (S69→S76, → _INDEX): "Giá chào thầu" mục-c =
WinnerQuoteTotal=SUM(Quote.ThanhTien WHERE supplier==Selected) DERIVED (3 nơi đồng-predicate) — PRO-Min/Max+CCM-proposed = Mig 54 NEW field. Budget gate = PURE ROLE no-phase (canEditPro=Admin||Procurement/canEditCcm=Admin||CostControlPurchaseEvaluationFeatures.cs:800-801; comment "bảng NS=tài-liệu-sống như Excel"); submission-count-lock NEXISTS (grep 0) → "khóa Initial sau lần-trình-đầu" = feature-MỚI. Value-threshold HOOK B =ApproveV2Asyncadvance:816-845(reuse skipToFinal mechanic); urgent flag = AddColumn mirrorItTicketPriority. Badge ✎NS = +2 bool DTO viaGetUsersInRoleAsyncbatch (no-N+1) both sites. PRO/CCM/CEO =Procurement/CostControl/Director(domain-shorthand NOT constants); V2 routing IGNORES roles (= specific ApproverUserId), 100% LINEAR no value/threshold config. -
Office/HRM recon cluster (S65→S69, → _INDEX): 21
Off_*keys, 10 office pages{fe-admin,fe-user}/src/pages/office/SHA256-mirror (except MyAttendance + AttendanceReport admin-only); golive-flip = removeRevokeTemporarilyHiddenModulesAsynccallDbInitializer.cs:2040. Employee master-detail EXISTS (not list-only), Dept FLAT no-tree (pre-Mig51), 5 satellite 15-endpoint full. NamGroup PURO = UI-skin (ref demo.purocorp.vn) hardcoded-navTree, KpiCard-not-tab, shared PageHeader/WidgetCard. gotcha #66:index.css h1-4{color:#0b1220}OUTSIDE @layer → TW-v4 unlayered wins → heading-in-gradient MUSTtext-white!. -
Governance/Harness recon cluster (S71, → _INDEX): H8 all-inherit FULLY adopted both layers (12/12 frontmatter + hmw.js resolveModel); run-trace "TRACKED" = 2-level (
git check-ignoreeligible vsgit ls-filescommitted — model works only postgit add); G-015 containment shift (Harness-2 "mọi tracked=vi-phạm" → H10 "tracked NGOÀI run-folder+code-disjoint=vi-phạm"). path-trap: bareruns/from repo-root = 0 → actual.claude/workflows/runs/(22 tracked). detector refine(b) =.claude/hooks/.claude/scriptsnot-exist (now S75 hasscripts/governance-detectors.ps1). -
[→ git pre-S60] S60 recon#2 V2-engine-map (ApproveV2Async:446-634 guard+UPSERT+advance; skipToFinal F2:561-602 precedent) · S60 PE Section-3 submit-guard ROLE-only. Full text git.
-
[→ archive/2026-06.md + git] S52 P11-D/E/F 6-gap recon · S50 HrmConfigs add-kind 11-spot · S51 gotcha #57 EXT reachability (curated S59).
-
[→ archive/2026-05-q4.md + git
d2f52ba] S29-S37: clean-room > NamGroup-port verified 4× · Pattern 12-bis cross-module mirror · FK+freetext dual-write. -
2026-07-10 (S108 first-real-run H19)
[engine: fable-real-single · Fable-S108](em-main harvest B3, GAP-2/3): Task cite-audit 3 artifact S108 (fable-real-runbook 610-line + adap-request hot-reload + email-draft), ~111 anchor. Verdict PARTIAL — 103/111 exact: 7 off-by-1/2 (cụm reviewer:37-56 + investigator:46/:77 — systematic quanh code-fence) + 1 drift-note-stale (runbook:123 “9 vai” trong khi engine :328 đã 10) + email-fact FALSE bắt trúng bẫy honesty (hmw.js:31 chưa-sửa lúc audit → em-main vá thật sau verdict). Learned: worker-draft cite lệch ±1-2 quanh fence → audit MỞ ĐÚNG DÒNG đừng tin range · drift-note về file khác re-check ngay-trước-commit (canonical có thể được patch song song). Surprise: meta-drift 2 tầng — đoạn cảnh-báo-drift tự drift vì engine update TRƯỚC khi note viết xong. Return dòng-1 VERDICT-header chuẩn, 0 garble. -
2026-07-11 (S110 H21+MTv3 deep-pass)
[engine: fable-real-single · Fable-S110]: Task ground-truth 2 broadcast (H21 spec-file+per-invocation · MTv3 owner-choice) + inventory TOKEN toàn repo + SPEC 3-mục. Verdict PASS: (1) 12 persona file SẠCH 0-hit fable/engine-token (grep 2 vòng cảengine-đắt|top-model|ensemble) — NGƯỢC hub vòng-1 bắt persona-phụ lỗi; (2) MTv3 self-check regex §5 chính-thức 0-hit nhưng extended "lead LUÔN top-model" bắt 5 ACTIVE (engine:332 K.D · runbook:140/:455 · fable-real.md:17 · mark ACTIVE-MARKS:19) = regex-heuristic-miss class — sister diễn-đạt khác cụm regex; (3) hmw.js:38 comment "tier:'fable' khi hệ-trọng" = xung-đột MTv3 §1.3/H21 §3 (đường nâng hạng-nhất DUY NHẤT = owner gõ; comment cho lead-discretion) — comment-only fix; (4) hmw-mode.on = HỆ KHÁC (consent fan-out T3ultracode-hmw-mem-governance, content tự khai /ultra-on) — ngoài scope H21; (5) mega-line "VẪN ON" class = standing-imperative-trong-history-blurb (S109-header + HANDOFF NEXT-anh = ACTIVE cần sửa; blurb-body = snapshot giữ). Bẫy fidelity lớn nhất: MTv3 §1.2/1.3 "sub gán cứng hạng-hai" đọc như floor → tưởng phá H8 all-inherit; triage-reply S2 CÙNG NGÀY waive đích-danh ("không đổi gì với form all-inherit"). ⚠️ #53 garble lượt return đầu (trả status-line giữa-chừng thay verdict) → coordinator SendMessage re-emit trong-session = recover OK, diary ghi trước re-emit.
🔄 Curate trigger
-
~30KB → archive recent → L2
archive/<period>.md(byte-exact append) +_INDEX.mdsubstring pointer. Stale >3mo → remove. - Last curate: 2026-07-06 (em-main single-writer, hook-triggered @21.4KB) — 6 stale governance/superseded entries (S93/S97/S98/S100/S101 + 07-01 Supplier-predecessor) verbatim →
archive/2026-07.md, replaced with pointer-stubs. L1 back under target. - Prev curate: 2026-06-18 S71 (29.8→23.2KB FIFO-trim 3 + gist gen:2). Prev S70 (47.0→24.1KB dark-matter recovery + built _INDEX/gist). Prev S40 (35.7→~20KB).