Files
solution-erp/.claude/agent-memory/investigator-codebase/MEMORY.md
pqhuy1987 33e7f68890
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled
[CLAUDE] Docs: S158 closeout - adap /day probe-first (nac agreed) + bookend-close 5 vong
Phien-LOGIC L7 window 5, vao bang /tiep. Governance/adap-only: 0 prod-code,
0 migration, 0 test moi. Test do tuoi 562 PASS (45D+517I). Counter 31->32.

VIEC
- /tiep recovery tron: San-3 5 tin-hieu MANH deu keu DUNG (corroborate WAL),
  verify: 5/5 PASS 0 lech, bien-nhan _tiep-4.md (window-ordinal 5).
- /check-email AI_INFRA: verify bang NOI DUNG - 22/22 file outbox/se co trong
  inbox, cmp 0 byte-drift => se=0 that + khong co stamp-then-edit (H18).
- /adap-apply day-wake-probe-first qua /fable-real investigator-codebase:
  nac AGREED (0 file co-che bi sua). Spec 3-muc + adap-report + 4 phan-bien
  gui nguoc hub + 1 datum dogfood (hub tu khai co 0).
  Engine BAC 2 tien-de cua lead: mo-coi 0/8 (khong phai "co squash => co mo-coi")
  va probe PHAI dung phep-2 - chung bang cua S158 noi 2 phep cho verdict NGUOC NHAU.
- Ra 6 HIGH lens-wave spec KHKK: 4 phu tron, 2 con ho (H5 W3 N chua pin =>
  N=0 van PASS; H6 §2.4:224 giu co-che IsVisible da bi chinh file do do-dia bac).
- Bookend-close 10 spawn / 5 vong. V4 nen-ngu KHONG-NHIP (shard 15/15 => IM).

VA TRONG PHIEN
- STATUS:459 RAG khai "alive" -> lat DOWN (3 phep do doc-lap: chunk_count=0
  cho ca 7 project + shared_global; canonical tu mau thuan voi :473 cach 14 dong,
  song 5 nhan phien).
- STATUS:461 bundle hash prod da chet -> 8-QYcMOg/DptYR4wL (control-am 900/876 B).
  Hai that: cicd-verify:58 dung chinh o nay lam baseline.
- STATUS:6 4->5 cua-so, counter 31->32; M-1 nhet lai nguyen van owner
  "da xong buoc thu 6 tuc CEO duyet" (ring2: grep = 0/STATUS + 0/HANDOFF).
- WAL:5 + WAL:21 tick; HANDOFF segment S155->S158 + slot (42)...(48).
- GATE 5-ANCHOR di-tru khoi WAL sang HANDOFF NEXT-em TRUOC khi §6.4 reset xoa no
  (lead-gap FLAG-4, han chot = cua ke).
- ef-core-migration SKILL: va CAU TRUC (frontmatter thoi khai bang la nguon
  "moi nhat") thay vi them row - ring1: day la lan 3 cung class.
- contract-workflow:371 "Contract V2 chua" SAI ~2,3 thang -> dinh chinh
  (ring1 thach-CLEAN thung H1).
- C12: +3 dong run= hoi-to S155/S156/S157. 2 orphan run-folder -> synthesis dang-1.
- M9 seed on-behalf 3 diary: ctx-verifier, investigator-codebase, ctx-audit.

#53 x8 - DOI-CHUNG NOI-PHIEN SACH DAU TIEN
Ep-ghi-dia KHONG giam garble (3/3 vai bi ep van garble) nhung dua thiet-hai ve 0
(2.818/5.354/7.957 B nam san); 4 vai khong ep MAT TRANG phai resume.
=> chong #53 = thiet-ke ARTIFACT, khong phai PROMPT (xac nhan lan 5).
So #53 ghi bu sau 5 nhan phien dung yen: 66 can-duoi qua S158.
+2 sub-class moi: skeleton-ruot-rong nac-2 (byte>0 ma ruot rong) va
engine-process-exit (0 delta dia).

BAY CHAN DUOC
Moi-ngam neo bang SO DONG trong file append-o-TREN da nen 3 lan. Dong 99 hom nay
la van-de MO THAT (luat nen ho) => spawn ctx-audit ma khong xu = hoac DAT-ao,
hoac dan nhan "bay cai san" len dung cau dang trinh owner. Lead khoi phuc tu git,
pin bang NOI DUNG. ring2 chung them: neo SAI NGAY TAI COMMIT SINH RA NO
(stale-at-birth), khong phai troi-do-nen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 20:50:58 +07:00

81 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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)
- **S157 (07-28) KH-ký-kết-HĐ b.712 AB đĩa, §CD PENDING lượt sau, `runs/2026-07-28-S157-ke-hoach-ky-ket-hd/sub-invest-kehoach-1.md`]:** Owner chốt O-1 *"cấu trúc trình ký GIỐNG, khác nội dung"* tái dùng khung V2, dựng 7 bảng NỘI-DUNG `ContractSigningPlan*` (Mig 69 thuần CreateTable; mig cuối=68 verify ls) + `ApplicableType=10` (slot trống `ApprovalWorkflow.cs:53-67`). 🔴 Bẫy twin MỚI: **Proposal-lite ApproveV2 PHÁ OR-of-N** `ProposalFeatures.cs:427-439` flatten global-level + `ElementAtOrDefault` match 1-user, entity không StepIndex (`Proposal.cs:27`) 2-row-cùng-Order thành AND tuần tự; KH service PHẢI copy `ContractWorkflowService.ApproveV2Async:217-394`, Proposal chỉ làm khuôn CRUD/menu/FE. Twin đo thật: Proposal BE 849 · FE 1.956 LOC · 4 bảng (Mig 38 grep CreateTable) · PE 6.5K/14.9K cận trên. `ConflictException :115-116` tự xác minh đĩa (skill contract-workflow stale fallback V1 chỉ sống đường display). ISO doc 9 bước `ContractPhase` 1-9 khớp 1:1 (7 LEGACY = ISO mã-hoá cứng); khúc b.7-12 thiếu CẢ ISO-doc lẫn code; FO-002.01 luật auto-pass-quá-01-ngày (mâu thuẫn V2 no-auto-approve; O-2 SLA=tham-khảo). #53: coordinator chặn skeleton-rỗng @202K-token cắt còn §AB, Edit-liền-tay từng mục. Tag `[s157, ke-hoach-ky-ket, proposal-lite-breaks-or-of-n, iso-9-steps-eq-contractphase]`
- **S156 (07-27) BCH post-CEO flow bước 721 0-§36 đĩa, §4-§5 PENDING lượt sau, `runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md`]:** Verdict **LAI** 1321 TÁI DÙNG Contract (7 dòng `[LEGACY]` `ContractPhase.cs:11-13` chính trạm 13-21 đã gỡ CỐ Ý Mig21/S17; V2 `ContractWorkflowService.cs:217-394` cookie-cutter sẵn, terminal gen-mã+DaPhatHanh) · 7-12 DỰNG MỚI (0-hit shopdrawing/TVGS, khuôn 12-bis + `ApplicableType=10` append-only). 🔴 Chuỗi "cơ-chế đúng, thứ đi qua KHÔNG " phía HĐ: cầu PE pin V1 (`CreateContractFromEvaluationFeatures.cs:68-71,108`) không nhận V2 + UpdateDraft không re-pin · `GetEligiblePhases` (`ContractFeatures.cs:334-351`) + inbox `PhaseActorRoles` (`:363-372`) 100% LEGACY-phase approver V2/BCH KHÔNG xem/inbox được ChoDuyet · `CeoApprovalThreshold` 0-consumer (bước-18 ">5 tỷ" chưa có máy) · SLA V2 hardcode `AddDays(7)` 3 site, Step không có SlaDays · notify chỉ Drafter (`:407`) · `AttachmentPurpose` thiếu ký-nháy (enum-extend 0-mig tiền lệ PE=4) · HĐ TraLai reset-toàn-phần không 4-mode. Mig 68 `AddPeAllowApproverDelete` ĐÃ land 07-27 ⇒ mig kế = 69. Bắt lead sai grounding: 12 enum/7 LEGACY (lead ghi 9/6) — lead nhận. #53 strike-1 (return bốc hơi, đĩa nguyên → lead đọc từ đĩa, không redo). Tag `[s156, bch-post-ceo, verdict-lai, eligible-phases-legacy-only, bridge-pins-v1]`
- **S155 (07-27) PE xóa-phiếu màn DUYỆT [24 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-be-1.md`]:** DELETE `/api/purchase-evaluations/{id}` ĐÃ CÓ (`PurchaseEvaluationsController.cs:146`, authz = class `[Authorize]` TRẦN) nhưng allow-list `{DangSoanThao,TuChoi}` (`PurchaseEvaluationFeatures.cs:1404`) chặn ChoDuyet. `Remove()`=**SOFT** gián tiếp qua `AuditingInterceptor.cs:56-62` — lớp #81-EXT indirect. Lũy kế: `PeBudgetAccumulator.cs` 2 hàm/4 call-site DUY NHẤT; ChoDuyet ăn số **2 chỗ** (`ComputeAsync:54` PrevSubmitted + `ComputePendingAsync:114` PendingSelected); `TraLai` KHÔNG triệt tiêu; `TuChoi` rơi khỏi 100% phép cộng. Query 0 dòng `IsDeleted` → dựa global `HasQueryFilter` (`PurchaseEvaluationConfiguration.cs:84`) ⇒ soft-del TỰ rớt, không sửa accumulator. Snapshot Mig67 KHÔNG re-compute. 🔴 Cascade 6 FK (`:75-80`) **không bao giờ chạy** vì soft ⇒ con `BaseEntity` ở lại = rác ẩn. **Git khảo cổ TRÚNG:** "chỗ cho hủy" = nút Từ chối, gỡ `6db195d` 12-06 S60; guard `PurchaseEvaluationWorkflowService.cs:101-106` còn sống tự trỏ "Xóa phiếu khi còn Bản nháp" = chính cái lỗ. 0 tiền lệ hủy chứng-từ in-flight; khuôn gần nhất `CancelMeetingBookingHandler` (`MeetingFeatures.cs:457`, Status=Cancelled NOT IsDeleted). Tag `[s155, pe-delete-approver, s60-tuchoi-removal-hole, soft-delete-no-cascade]`
- **S155 (07-27) PE xóa-phiếu FE/authz-slice [18 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-fe-2.md`]:** Khối HÀNH ĐỘNG = `components/pe/PeWorkflowPanel.tsx:458-506` **byte-identical 2 app** (md5 `02671be6…`, cùng PeDetailTabs/PeListPanel/ListPage) ⇒ sửa-1-bên-là-sót. Gate 3 tầng: `?pendingMe=1``readOnly={!pendingMe}` (`ListPage:590`/`:676`) · `next=workflow.nextPhases` BE-source (`:257`) · `blockedByV2Level` (`:99-103` isAdmin ∥ actor∈currentApproval.approvers). 🔴 Plumbing xóa ĐÃ NỐI SẴN vào màn duyệt: `onDelete={del.mutate}` truyền ở `ListPage:573`+`:668` (`api.delete('/purchase-evaluations/:id')` `:90`) nhưng nút chết vì `PeDetailTabs:445` đòi `mode==='workspace' && canEditPhase && !readOnly`; nút hiện chỉ ở `:460` `phase===DangSoanThao`. **Authz 2 tầng:** PE vùng FE = **0-hit** `usePermission|PermissionGuard` (guard chỉ sống ở Master+Users, khuôn `DepartmentsPage:101 action="Delete"`); `menuKeys.ts` KHÔNG có const `Pe_*` (chỉ root `:23`) — `Pe_*` sinh BE `MenuKeys.cs:134-141`, seed `DbInitializer:1870-1877`, FE khớp bằng regex `Layout.tsx:120` (fe-admin `:107` **LỆCH**, thiếu WfView). 🔴 `Pe_*` **KHÔNG ∈ `MenuKeys.All`**`Program.cs:82-89` không đăng-ký policy `Pe_*.{action}` (0 dynamic provider) ⇒ dùng `[Authorize(Policy="Pe_…")]` = policy-chưa-tồn-tại; **dùng được ngay = `PurchaseEvaluations.Delete`** (root ∈ All, + `GetMyMenuTreeQuery:66-72` cho `Pe_*` KẾ THỪA cờ CRUD từ root ⇒ 0 key mới, 0 migration). Ma trận enumerate `db.MenuItems` (`PermissionFeatures.cs:20`) nên ô Delete đã hiện sẵn. Q6: thêm-nút KHÔNG kích 4-place (0 route/page/staticMap `Layout.tsx:56-106`); `Pe_*` resolve nhánh regex `:119-134` KHÔNG qua staticMap. Tag `[s155, pe-delete-fe-authz, two-app-byte-identical, pe-keys-not-in-All]`
- **S155 (07-27) PE menu/trash/dept-head [21 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-menu-3.md`]:** 🔴 Menu = **SEED DB** không hard-code FE — `Pe_<Code>` khai `DbInitializer.cs:1874-1877`; thêm mục = restart API, 0 migration (upsert `:1888-1914` chỉ sửa `Order`, **KHÔNG đụng Label** ⇒ rename qua `labelBackfill:1918-1924`; `DisplayLabel` **CHỈ ăn fe-user** `MenuDtos.cs:14`). 6-chỗ-mirror: +2 seed permission SONG SONG `:2092-2096`/`:2492-2496` + regex `Layout.tsx:120` (fe-admin `:107` thiếu `WfView`). Đổi KEY = mồ côi 13 row/key × 10 key ⇒ giữ key chỉ đổi label. **`Đã duyệt` chạy được HÔM NAY**: `phase=` đủ 3 tầng (`Controller:23``Features:565``:620`), DaDuyet=7 ⇒ `?type=1&phase=7`, 0 route mới. `pendingMe` KHÔNG phải param BE (FE rẽ `/inbox` `ListPage:61-68` + lọc client `:182`). `IgnoreQueryFilters` 0 src/Backend / 15 hit tests; `HasQueryFilter(`=12. An-toàn accumulator = **cấu trúc** (`PeBudgetAccumulator.cs:42`/`:100` dựng `peers` FRESH). 🎁 Changelog `: BaseEntity` + lọc CHỈ `PurchaseEvaluationId` (`:1424`) ⇒ lịch sử phiếu-xóa đọc MIỄN PHÍ; cái chôn = DETAIL bundle. 0 tiền lệ thùng-rác (hit "khôi phục" duy nhất = STRING `EmployeeFeatures.cs:162` ghost-wire). 🔴 **"Trưởng phòng" CÓ TÊN CHƯA CÓ ĐỜI**: `Department.ManagerUserId` **0/10 Dev** + 2 FE hardcode `managerUserId: null` payload SỬA (`DepartmentsPage.tsx:43`/`:57`) ⇒ tự-xoá mỗi lần sửa phòng. `PositionLevel.TruongPhong` 33/33 NULL (V1-legacy). Tag `[s155, menu-seed-db, phase-param-exists, changelog-survives-softdelete, dept-head-name-only]`
- **S155 (07-27) WF-V2 sửa-tại-chỗ vs version-mới [25 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-wfver-4.md`]:** 🔴 **0 lệnh Update**`ApprovalWorkflowsV2Controller.cs` (54d TOÀN BỘ) chỉ GET/POST/PATCH-user-selectable/DELETE ⇒ sửa 1 cờ = buộc POST = `MAX(Version per Code)+1` (`ApprovalWorkflowV2AdminFeatures.cs:325-328`) + hạ MỌI active cùng type (`:330-334`). Chặn THẬT bằng mã. 🔴 **F17:** POST tạo entity mới ⇒ **Id mới** (`:336`+`BaseEntity.cs:5`) mà phiếu đọc workflow theo **Id đã pin** (`PurchaseEvaluationWorkflowService.cs:674`) ⇒ **cờ mới KHÔNG tới phiếu đang chạy**; re-pin chỉ `PurchaseEvaluationFeatures.cs:149`/`:291``:249-251` chặn chỉ Nháp/TraLai ⇒ ChoDuyet kẹt bản cũ vĩnh viễn; 0 backfill re-pin. ⇒ cờ `AllowApproverDelete` **HỎNG nếu không có lệnh Update**. Pin = **tham chiếu SỐNG** (chỉ NS có snapshot Mig67). Con trỏ **LAI**: Bước=INDEX `steps[currentIdx]` (`:686` vỡ ÂM THẦM/`:683` kẹt) · Cấp=ORDER-VALUE (`:694``:695` kẹt) ⇒ ranh AN-TOÀN = **không đổi tập `{Step.Order}``{Level.Order}`**. 13 thao tác: 3 an-toàn (thêm-người-cùng-Order · cờ `Allow*` · đổi tên) · 2 nửa (bớt/đổi `ApproverUserId` → 403 GUID-trần `:705`, FK Restrict `PeLevelOpinionConfiguration:25-28`) · 6 phá-vỡ · 2 hỏi-owner (`CeoApprovalThreshold`·`Step.DepartmentId`). OR-of-N XÁC NHẬN (`:689` GroupBy Order) ⇒ owner không tự mâu thuẫn; ⚠️ comment `ApprovalWorkflow.cs:81-82` SAI *"KHÔNG OR-of-many"*. Blast 6+ module (198 hit/23 file). Designer **fe-admin ONLY** (`ApprovalWorkflowsV2Page.tsx`), "Nhân bản"→*"Tạo quy trình mới"*; **0 cảnh báo đang-dùng/0 disable IsActive**. F6 tick `:999-1007` +dây `:54/:110/:159/:177/:605` + fe-user `WorkflowMatrixViewPage.tsx:282` + BE `:41/:230/:188/:368`. CẤM delete-then-insert Levels → diff theo `Level.Id`. Tag `[s155, wf-v2-no-update-cmd, new-version-new-id-unreachable, pointer-index-vs-order]`
- **S153 (07-26) ctx soft-memory spec [fable-real, detail → `runs/2026-07-26-S153-ctx-adopt/sub-fable-invest-S153.md`]:** SE **0 content-ts-reader sống** (session_ctx.py = git-ts+mtime) ⇒ rào-2 canonical `_TS_KEY_RE` đặt session_ctx.py, máy-7-phép = EXTEND python (tái dụng `_SECRET_RES` 1-nguồn) KHÔNG .ps1 mới; `secrets_sweep` rglob TRỌN session-dir ⇒ `_mind` tự vào lưới; `_mind` mới-nhất-ở-TRÊN ⟂ `_context` FLOW ở-CUỐI (bẫy chép-khuôn); C11(b) filter `^sub-<role>[-.]` ⇒ tên `sub-ctx-audit-*` lọt lưới ngay. Tag `[s153, ctx-mind-spec, ts-reader-absent, one-source-regex]`
- **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); PE→Project 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 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: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]`
- **S133-S141 (07-16→20) gộp [detail → archive/2026-07.md + `runs/…S1{28,33,34,35,38,41}…`]:** S141 adap 5-lane (byte-safe⟂tolerant-EXTRACTION → pin regex `\"?([0-9a-fA-F]{8,64})\"?`; roster-count 3-tầng) · S138 delta-hẹp PHẢI grep landing-site trong luật SỐNG · S134 lũy-kế lệch-tiền-đề row1 (`PeBudgetAccumulator.cs:42-48` PrevSubmitted ĐÃ gồm ChoDuyet) · S133 freeze-at-DaDuyet 4-assignment (`PurchaseEvaluationWorkflowService.cs:861/:899/:931/:1053` Mig67) · S128 RAG config in-repo (`projects.py:39` owner-final) · S126 worker-pin 14/14 opus+max, no-tier→opus DÙ lead=Fable · S125 verifier-suspect-first · S122 orphan đo TÊN không NỘI-DUNG, lane-RỖNG≠mất.
- **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, Mã 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
- **S155 (07-27):** hook @19.5KB → compact 20.7→~17.1KB: gộp S122-S141 thành 1 dòng, trim 3 entry S155 (detail nguyên vẹn ở `runs/2026-07-27-S155-pe-delete-approver/sub-*.md`) + S153.
- **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).
- **Prev:** S125 (23.9→~15KB) · S71/S70/S40. Verbatim byte-exact in `archive/`.
## S149 (2026-07-24→25) — 10 invocation gộp 1 entry [LEAD GHI ON-BEHALF @S150 — M9/B3 theo H2-F3 Coverage-miss (10 lượt → 0 delta sổ, ngoài lưới C11(b) by-design); nguồn: sub-file trong `runs/2026-07-24-S149-{dong-du-5-vong,hoi-tu-bookend,owner-gated-3-khoan}/` + `runs/2026-07-25-S149-adap-backlog/sub-invest-backlog.md`]
- 10 lượt invest @S149: chẩn-đoán **"SE = rules-đủ, máy-thiếu"** (0 script GHI `.session-counter.json` → chuỗi "đo rồi như chưa đo": backfill S146 · tally-rơi S148 · ×27≠33) — ĐỨNG qua gate reviewer-Fable, thành spec hội-tụ-bookend M1-M9. Backlog adap phân-loại **A-12/B-6/C-1/D-3** ("nợ REPORT không phải nợ ADOPT") → wave 6-lane land 23/23. O-2 nguồn thật = depth-axis → **posture-A**.
- #53 trong 10 lượt (ghi sổ garble @S150): L1 **ngược-#53** (return OK, ĐĨA không — vớt journal) · L5 kinh-điển (đĩa cứu) · L7 mất-cả-hai (bù deep-pass). Sub-class mới: ghi-đĩa-trong-lúc-làm = CẦN, KHÔNG ĐỦ.
## S152 (2026-07-25) — R1 retention-note không-fabricate [M9 on-behalf lead]
- **KHÔNG fabricate — uncertain thì nói "uncertain" + reason:** finding không chứng được từ đĩa/DB phải khai uncertain kèm lý-do thiếu-chứng, KHÔNG lấp bằng suy-đoán (tiền lệ tốt: A/018 S117 — verify prod-DB `Phase=ChoDuyet` trước khi phán "lũy kế đúng", thay vì đoán theo lời UAT). Claim ≠ chứng: mọi số kèm lệnh. Tag `[s152, r1-retention, no-fabricate-uncertain-reason]`
## S158 (2026-07-28) — `/fable-real` adap `day-wake-probe-first` [LEAD SEED ON-BEHALF @closeout M9 — mày chạy THẬT (Fable, 222K tok, 20 tool-use) nhưng KHÔNG tự ghi; nguồn = `runs/2026-07-28-S158-day-wake-probe-first/sub-invest-day-1.md` 25.440 B + adap-synthesis]
- **Return CLEAN 0-garble** giữa một closeout mà **7/8 lane khác đều `#53`**. Khác biệt DUY NHẤT: prompt ép **ghi đĩa từng phần trong lúc làm** + **verify RUỘT có chữ trước khi return**. ⇒ datum củng cố: chống `#53` = **thiết-kế artifact**, không phải prompt.
- 🔴 **BÁC 2 tiền-đề của LEAD — đây là giá trị chính của lượt này, không phải bản đề-xuất:**
(a) *"SE có squash ⇒ có sha mồ-côi"* → đo `cat-file -e` + `is-ancestor` trên 8 marker = **sống 8 / mồ-côi 0**; squash `session-end` chỉ gọt trailing-`wal:` **chưa push**, 6/8 sha đã push. **Vẫn giữ guard** vì tiền lệ S127 dangling có thật + chính feature `/day` tự đẻ điều kiện orphan.
(b) *"probe nên tái dùng Sàn-3"***BÁC bằng bằng-chứng CÙNG CỬA**: Sàn-3 ② HIT ⟂ anchor-delta 0 CLEAN, verdict **NGƯỢC NHAU** vì hỏi **2 câu khác nhau** (*"tồn-tại việc dở"* neo `origin/main`*"đổi so điểm dừng"* neo marker pause) ⇒ dựng phép-2 KHÔNG vi phạm B1.
**Nghề rút ra:** khi lead nêu sẵn một hướng nghiêng, cách bác mạnh nhất là **tìm một cửa mà 2 phép cho verdict ngược nhau** — mạnh hơn mọi lập luận về nguyên tắc.
- **Nghề đo đáng giữ:** anchor = **carrier-commit** `git log --diff-filter=A -1 -- <marker>` (commit ĐẦU TIÊN thêm chính file đó) — 8/8 resolve, **sống-sau-squash by construction**, và **nuốt luôn bẫy-anchor-lệch-1-nhịp** mà hub phải xử bằng bước resolve riêng. Mạnh hơn form của hub.
- **Đo BYTE, CẤM quy token** (chính lỗi làm thư hub trượt vòng r1: dán nhãn "token tự đo" lên proxy ký-tự). `tiep_reload` SE = **122.115 B / 5 nguồn**; nền SE **nhẹ hơn hub 3,6×** ⇒ đừng mượn số hub bán lợi ích.
- **2 phát hiện ngoài đề-bài, cả 2 lead xác nhận:** `docs/HANDOFF.md` segment mới nhất còn **S153** ⇒ nguồn-2 của `tiep_reload` nạp brief cũ **3 nhãn phiên** (vá @S158) · `_tiep-1.md` ghi head-sha **7 ký tự** trong khi 7 marker kia ghi đủ 40 = form drift trong cùng một loại marker.
- Tag `[s158, fable-adap, ghi-dia-cuu-return, bac-tien-de-lead-bang-cua-verdict-nguoc, carrier-commit-anchor, byte-khong-token, seed-on-behalf]`