Files
solution-erp/.claude/agent-memory/investigator-codebase/archive/2026-06.gist.md
pqhuy1987 f36aab8934
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m52s
[CLAUDE] Docs: adopt Harness-9 — L2 archive dark-matter recovery (4 sub) + adap 2-workflow mandate (S70)
3-stage Workflow run-id evidence: investigate wf_be952f3c-97f / implement wf_a58e0d15-beb / audit wf_9520d8cd-4fe.

PART 1 (L2 recovery): 4 over-cap sub (cicd-monitor/investigator-codebase/reviewer/implementer-backend)
curated L1->L2 byte-exact + archive/_INDEX.md (substring sha-keyed pointers, no line-hints)
+ <period>.gist.md (4-field distill, distill-gen:1, verbatim frozen). All 4 MEMORY.md now < 25KB
auto-inject cap (closes P1 curate-debt). ~240KB archive no longer RAG-dark. 0-byte-loss git+sha
verified (Stage C audit + em-main self-gate on 2 reviewer StructuredOutput no-returns). Read-side
gap fixed (MEMORY.md L5 header -> _INDEX). + memory-budget.json (seed-by-measure) +
scripts/measure-agent-memory.ps1 + .ragignore guard.

PART 2/3 (process mandate): every adap = 2 separate workflows (implement + review) + report with
run-id; short-but-needs-confirm still requires review. Codified in .claude/commands/adap-apply.md
+ agents/README.md (Upgrade S70) + session-start.md (§2.1.2 budget-audit, pending-restart).

adap-report + email-back to AI_INFRA (body-hash 7c07b716e775).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:52:51 +07:00

13 KiB
Raw Blame History

Gist 2026-06 — investigator-codebase (2026-06.md distilled)

distill-gen: 1 (already-distilled — do NOT re-compress). 4-field per record: VIỆC · KẾT-LUẬN (+file:line) · BÀI-HỌC · BẤT-NGỜ. Same-topic merged. Confidence cao/vừa/thấp. Each line ends with a back-resolve substring:"…" (unique Ctrl-F) into 2026-06.md. Covers all 15 records (3 S57bis-era + 12 moved here by Harness-9 curate 2026-06-17). 22-marker coverage gate satisfied across this + 2026-05.gist.md.


gotcha #57 family — soft-delete + bare unique index (reachable 500)

  • [cao] gotcha #57 EXTENSION reachability audit · VIỆC: 6 candidates for soft-delete + bare .IsUnique() on Code → recreate-after-delete throws DbUpdateException 500. KẾT-LUẬN: FIX 3 Master = Department/Supplier/Project (Department/Supplier/ProjectConfiguration.cs:18/24/19 bare unique), all CONFIRMED-reachable (DepartmentFeatures.cs:76+125, ProjectFeatures.cs:87+147, CreateSupplierCommand.cs:45+DeleteSupplierCommand.cs:20). SKIP 3 = ContractClause (no Create/Update/Delete handler anywhere — not CRUD-reachable), MeetingRoom (Delete sets IsActive=false NOT IsDeleted, MeetingFeatures.cs:178; Create also && !IsDeleted), EmployeeProfile (Create BLOCKS reuse by design — UserId check sees soft-deleted → throws "Cần khôi phục" :160-163; EmployeeCode auto-gen atomic). Mig 46 = exactly 3 indexes. BÀI-HỌC: every OTHER bare-unique is safe (composite junction, nullable-code already filtered, or no-soft-delete). BẤT-NGỜ: Master's GLOBAL HasQueryFilter(!IsDeleted) MAKES the bug — auto-hides soft-deleted from the Create dup-check so it passes, then the unfiltered index throws 500 — opposite of HRM where the bug needs a manual !IsDeleted; either way the unfiltered index is the fault. · 2026-06.md · substring:"S51 gotcha #57 EXTENSION reachability audit"
  • [cao] add-kind 11-spot stack + bare-unique confirm · VIỆC: add a HrmConfigs kind (Vehicle/Driver). KẾT-LUẬN: HrmConfigs has NO kind-enum/registry backend — 4 separate entities (LeaveType/Holiday/ShiftPattern/OtPolicy), "kind" is FE-only union+route param; adding 1 kind = mirror full entity stack across 11 spots (Domain/Configuration/DbContext×2/Features-region/Controller-4-routes/DbInitializer/MenuKeys+All/Page-KIND_CONFIG/App-route/menuKeys+staticMap). gotcha #57 CONFIRMED still bare: LeaveTypeConfiguration.cs:19 + ShiftPatternConfiguration.cs:19 + OtPolicyConfiguration.cs:22 .IsUnique() lack .HasFilter("[IsDeleted]=0") — only HolidayConfiguration.cs:18 fixed (Mig43) → Vehicle/Driver Code UNIQUE must add the filter from day one. BÀI-HỌC: each kind = its own table (NOT discriminated) → Mig 44 must CREATE TABLE. · 2026-06.md · substring:"S50 P11-C Vehicle+Driver — HrmConfigs add-kind pattern VERIFIED"
  • [vừa] P11-C Vehicle/Driver catalog pre-flight · VIỆC: where to home the catalog. KẾT-LUẬN: extend HrmConfigs (NOT new module) — add Region 5/6 (kind vehicles/drivers); FE = +2 KIND_CONFIG entries; VehicleBooking stays free-text (Office/VehicleBooking.cs:13-19, no VehicleId/DriverId FK). BÀI-HỌC: HRM entities have NO global HasQueryFilter → manual .Where(!IsDeleted) + UNIQUE soft-delete needs .HasFilter("[IsDeleted]=0") (Holiday Mig43 lesson). · 2026-06.md · substring:"P11-C Vehicle+Driver catalog pre-flight"

Permission / authz / seed model

  • [cao] BE authz split — Master write-open · VIỆC: assess making modules visible to all roles (blocks A/B/E/F). KẾT-LUẬN: config controllers gate WRITE behind [Authorize(Roles="Admin")], READ open (HrmConfigs/Catalogs/MeetingRooms) → FE-grant is pure UI-visibility there. BUT Master 3 controllers = class [Authorize] ONLY, no per-action role: SuppliersController.cs:17, ProjectsController.cs:11, DepartmentsController.cs:11 — ANY authed user can POST/PUT/DELETE via API (FE menu is the only gate). S55 prod data lives in SeedRealMasterDataAsync :2267-2460 → Projects(62 :2270), WorkItems(71 :2430-2438), Suppliers(3 :2440-2456), all ungated idempotent. BÀI-HỌC: making Suppliers/Projects/Departments visible-to-all needs [Authorize(Roles="Admin,CatalogManager")] or the staff can overwrite S55 master data. 10 departments now (9 + IT); 31 demo users, none zero-role. · 2026-06.md · substring:"S57 perm-broaden blocks A/B/E/F"
  • [cao] seed model — no per-employee default Read · VIỆC: blocks C/D recon. KẾT-LUẬN: SeedAdminPermissionsAsync DbInitializer.cs:1939-1977 loops MenuKeys.All CRUD=true (skip-existing); 2 sub-seeders give 7 roles Read+Update on PE keys and CatalogManager full-CRUD 9 master keys. NO generic per-employee Read seed → a plain Drafter sees ONLY PE keys; most non-admin staff see ~nothing but PE. 4 inherit-roots (Contracts/Workflows/PurchaseEvaluations/PeWorkflows) cascade root→child; Hrm/Off/Master NOT inherit (each leaf needs own row). BÀI-HỌC: grant-all pattern = mirror CatalogManager seeder but loop ALL 13 roles × key-set, CanRead-only, inserted AFTER the catalog seeder. · 2026-06.md · substring:"S57 perm-broaden RECON blocks C/D"
  • [cao] menu seed = UPSERT that re-sets Order · VIỆC: menu reorder cross-repo SE↔NAMGROUP. KẾT-LUẬN: SE menu = SeedMenusAsync DbInitializer.cs tuple-list; seed UPSERT re-sets Order (:1845-1871) → reordering in code propagates to Dev/prod next deploy, NO migration; but Label/ParentKey/Icon are NOT touched on existing rows → rename needs a separate labelBackfill dict. Order = BE-only (GetMyMenuTreeQuery.cs:35 OrderBy); both FE render menu as-is → no FE edit for pure reorder. BÀI-HỌC: HR is SCATTERED across 2 rootsHrm (Hồ sơ+Config+Dashboard) and transactional HR under Off (DonTu/DatXe/ChamCong/AttendanceReport). BẤT-NGỜ: NAMGROUP "Puro" = hardcoded FE array (NOT DB seed), index=order, flat single links vs SE deep-nested. · 2026-06.md · substring:"menu-order cross-repo recon SE↔NAMGROUP"

Prod facts / census / wipe

  • [cao] prod test-data wipe + FK + PE tree · VIỆC: wipe prod test PE + retree by Hạng mục. KẾT-LUẬN: prod PE=10 active (MaPhieu A/031-040, all WorkItemId NULL) + Contracts=7 all [DEMO] V1; FK: PE children CASCADE except Quotes→PE NO_ACTION (multi-path) — Plan R proved a single DELETE FROM PurchaseEvaluations works (NO_ACTION checked end-of-statement after Details→Quotes cascade); PE.ApprovalWorkflowId Restrict → wipe PE before deleting AW. Demo gate OK (SeedDemoContracts/PE inside DemoSeed:Disabled). FE tree = pe/PurchaseEvaluationsListPage.tsx:138-179 Project>Year>Supplier, PeListItem already has workItemId/Name → FE-only change. BÀI-HỌC: ~10 orphan upload folders from S23 (files not deleted on wipe). BẤT-NGỜ: 20 REAL users batched 2026-06-11 06:01 (S58 seed-fix landed; thanh.lethanh now exists, correcting stale S57bis memory). · 2026-06.md · substring:"S59 recon — prod test-data wipe + PE tree"
  • [cao] prod user census + pwd-policy env divergence · VIỆC: why is the demo-user lock a no-op. KẾT-LUẬN: LockDemoSampleUsersAsync DbInitializer.cs:1552 hardcodes 14 named-person emails = a population that exists ONLY on Dev; prod has 34 all-active users (20 UAT-matrix placeholders hand-created 2026-05-13, 9 real staff, binh.lethanh, a typo-domain chuong.phan@solution.com.vn dup, admin/catalog.manager/nv.test). ROOT CAUSE seed-users-never-on-prod = prod Identity:Password:RequiredLength=12 vs DemoUserPassword="User@123456"=11 chars → CreateAsync silent-fails every prod startup since 04-21; Dev fallback length 8 → Dev gets the 33 named users. BÀI-HỌC: fix needs 20 real prod emails; keep nv.test (breaking it breaks CI smoke). BẤT-NGỜ: bod.1@ never appears in git pickaxe → created by hand via admin UI, not seed. · 2026-06.md · substring:"S57bis lock no-op — prod user census"
  • [cao] PE entity recon — 4 đầu việc · VIỆC: PE Year/WorkItem/create-UI/perm. KẾT-LUẬN: PE has NO Year, NO WorkItem link (free-text detail); MaPhieu gen-AT-CREATE PurchaseEvaluationCodeGenerator.cs:23 format PE/{YYYY}/{A|B}/{Seq:D3}; PE controller class-[Authorize] only (no policy → opening the menu is enough, no silent-403); Pe_* leaves NOT in MenuKeys.All. BÀI-HỌC: extending InReviewScope must match key == MenuKeys.PurchaseEvaluations EXACT — the prefix "Pe" would also catch PeWorkflows (admin); root inherit cascades. BẤT-NGỜ: WorkItem write is Admin-only (CatalogsController:113-130) so CatalogManager has the menu but the API write is blocked. · 2026-06.md · substring:"S57bis PE recon — 4 đầu việc sếp"

Pre-golive verify / FE-redesign / master-import

  • [cao] pre-golive logic verify — 4 streams PASS · VIỆC: audit P11-B/D/E/F + ApproveV2 + catalogs + S55 wiring. KẾT-LUẬN: LeaveBalance deduction exactly-once (terminal DaDuyet, guard Status!=DaGuiDuyet :296); AttendanceReport classifies day-type in-memory; MaTicket gen-on-Create Serializable; ApproveV2 4-module flatten correct; master-data idempotency PROVEN (re-run → identical counts). BÀI-HỌC: Travel/Vehicle ApproveV2 = 0 tests (cookie-cutter of tested Leave/OT) — add 2 smoke post-golive. BẤT-NGỜ: dept "IT"/Phòng CNTT DOES exist on prod (Id 65CC6307…) but has 0 active users → ItTicket auto-assign no-ops, SLA job no target (corrects stale S52 "no IT dept"); ops fix = assign ≥1 user to dept IT (1 UPDATE). · 2026-06.md · substring:"S56 pre-golive verify — 4 logic streams"
  • [vừa] FE-redesign Phase-2 recon · VIỆC: 25-page redesign audit. KẾT-LUẬN: NOT a rewrite — S55 already redesigned ui-primitives+DataTable+shell so importers auto-inherit density; hover-hidden quick-win ~absent (only 1 real opacity-0×group-hover site, excluded); only 5/25 use <DataTable> (12 roll raw <table>); 3 Drawer candidates (Suppliers/Projects/Users-create); no Drawer.tsx exists yet; bậc-thang inline-edit reference already exists (EmployeesListPage.tsx). BÀI-HỌC: effort mostly S (auto-inherit) + a few M (Drawer/bậc-thang). · 2026-06.md · substring:"S56 Phase 2 FE-redesign RECON — 25 page audit"
  • [cao] master-data Excel-import recon · VIỆC: import 3 masters from Excel. KẾT-LUẬN: WorkItem/"Hạng mục" master EXISTS (Domain/Master/Catalogs/WorkItem.cs, full CRUD) — no new table needed; PE detail is pure free-text (no FK→WorkItem); Project MISSING Year/Investor/Location/Package (only Note free-text); Supplier MISSING Status/bank-acct/legal-rep + "Cả hai" unmappable (Type single-valued); seed = idempotent existingCodes.Contains→skip; no bulk import (Master is single-CRUD, POST one-at-a-time). BÀI-HỌC: nạp via idempotent DbInitializer mirror (NOT API loop) → reaches prod by design. BẤT-NGỜ: SeedDemoMasterData + SeedCatalogs run REGARDLESS of DemoSeed:Disabled (outside the if-block) → real+demo data mix on prod unless gated. · 2026-06.md · substring:"S55 master-data Excel-import recon"

Governance / wave / harness

  • [vừa] Harness 1/2/3 adap-apply recon · VIỆC: apply AI_INFRA broadcast. KẾT-LUẬN: roster 8→10 (+tooling-auditor H1, +harvest-curator H2); SE hmw.js is pre-wave (AI_INFRA = canonical); email id authoritative = se; git check-ignore -v = ground-truth B6 (wave patterns must sit AFTER !.claude/** last-match-wins). BÀI-HỌC: git-diff + chunk-count = defense-in-depth (caught 1 self-MEMORY write, 0 RAG-write). · 2026-06.md · substring:"Harness 1/2/3 adap-apply recon — 3 slice"
  • [cao] wave h2-verify — B6 isolation + Bash surprise · VIỆC: audit wave write-isolation. KẾT-LUẬN: B6 = 2 rules — transient wave-*/+agent-teams/ gitignored (audit-noise=0) AND canonical agent-memory/**/MEMORY.md TRACKED (rogue writes surface in git status); all 10 MEMORY.md tracked. BÀI-HỌC: ordering gotcha — wave/team patterns MUST sit after !.claude/** or it un-ignores everything. BẤT-NGỜ: Bash tool = /usr/bin/bash NOT PowerShell despite env=PowerShell → Get-ChildItem/Select-String/Test-Path fail (exit 2/127); read-only Bash-only subs MUST use POSIX. · 2026-06.md · substring:"S50 wave h2-verify — B6 guardrail audit"

Monthly drift audit

  • [vừa] 2026-06 monthly drift audit · VIỆC: ground-truth counts vs docs. KẾT-LUẬN: migrations=42 (last AddLeaveBalances) / gotchas highest=#56 (file header has no self-count) / tests=154 / tables≈91; biggest drift = ef-core-migration SKILL (says 31 mig / 59 bảng / 111 test). BÀI-HỌC: schema-diagram migration table stops at Mig 16 → missing §§ for Mig 27-42. BẤT-NGỜ: STATUS backlog "Curate 4 agent MEMORY 35.7/…" is STALE (already curated S40) → remove. · 2026-06.md · substring:"MONTHLY DRIFT AUDIT"