Files
solution-erp/.claude/agent-memory/investigator-codebase/MEMORY.md
pqhuy1987 5f6c3becfb [CLAUDE] Docs: S147 closeout — PE attach-fix (Trả lại) + project-dedup ship-prod
① 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>
2026-07-23 17:37:59 +07:00

59 lines
9.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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) + git `d2f52ba` + `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 on `p.projectId` GUID (`PurchaseEvaluationsListPage.tsx:192-197`, display projectCode); PEProject FK `ProjectId` (`PurchaseEvaluation.cs:15`) JOIN-resolved (`PeFeatures.cs:579/:647`) NO denorm string. CRUD zero-trim (`ProjectFeatures.cs:80` validator, `:95/:138` exact `Code==` 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); only `PeWorkItemBudgets` UNIQUE(ProjectId,WorkItemId) filtered [IsDeleted]=0 (`PeWorkItemBudgetConfiguration.cs:27`). Direction: KEEP no-space (in seedidempotent), RETIRE space (not-in-seed); soft-del survivorseed 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:15` class `[Authorize]` only; handlers check exists only `PurchaseEvaluationAttachmentFeatures.cs:66/:160`). Gate = raw `readOnly` PROP not phase (`GeneralAttachmentsSection` :3555/:3577 hide-when-readOnly); List detail HARDCODE `readOnly=true` (:574/:669) TraLai loại khỏi SCREEN không khỏi editable-SET (workspace `PeListPanel.tsx:88` isEditablePhase 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-safetolerant-EXTRACTION 2-lỗ tách pin regex `\"?([0-9a-fA-F]{8,64})\"?`. Roster-count 3-tầng (prose/glob/pointer). refinelead-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, #53sub-file cứu trọn]:** S134 lũy-kế lệch-tiền-đề row1 (`PeBudgetAccumulator.cs:42-48` PrevSubmitted ĐÃ 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-entry `session-start:181-206`. Detail archive + runs.
- **S128 (07-16) adap-16-07 [fable-real, garbleon-behalf]:** RAG config in-repo (`AI_INFRA\claude-rag\lib\projects.py:39` owner-final, `rag.json:26` override); 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 lead=Fable); B1 28415 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`) ; 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ỖNGmấ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[].quotes` KHÔNG `suppliers[].quotes`). S117 ApprovedPrice WRITE 1-site `ApplyApprovedPriceOnFinalize`; 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, NCC=Code, IsPublic fail-closed, import authz-mismatch) · S105 BVAAU auth RCA (relative-`/api` prod-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` · Design `SolutionErp_Design` (distinct) · Prod `.\SQLEXPRESS`/`SolutionErp`/`vrapp` via SSH `vietreport-vps`
- **Migration path:** `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/*.cs` (NOT root). Last-schema Mig 67 `AddPeApprovedBudgetSnapshot` (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/tasks` NOT `/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** — `WorkflowDefinition` pin cũ, match Dept+PositionLevel.
- **V2 Mig 22-31** — `ApprovalWorkflow` pin PE/Contract, match `ApproverUserId` 1-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:** `SeedDemoMasterDataAsync` gated `DemoSeed:Disabled` (OFF prod) · `SeedRealMasterDataAsync` UNGATED (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/`.