Files
solution-erp/.claude/agent-memory/investigator-codebase/MEMORY.md
pqhuy1987 18fced6695
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m16s
[CLAUDE] Workflow: adopt Harness-10 flat-refine + checklist-v2 + sleep-recovery-cmd (re-audit 3-workflow)
Re-audit Harness-8/9/10/10-refine + checklist v1/v2 + hmw vs canonical AI_INFRA
(mandate Harness-9 B1+B2): audit wf_13868efb-ea7 -> implement wf_ac43b5ff-7d1 ->
review wf_d482e10d-5dd. SE was BEHIND Harness-10 flat.

- run-trace SUBFOLDER->FLAT: hmw.js (:103 subMd + :52 schema + H4.5->H8 drift) +
  workflows/README full-rewrite + runs/README + session-start/end + agents/README
  Upgrade S72 + _ledger; 5 old S71 runs KEEP subfolder (C8 dual-accept). node --check OK.
- adopt 2 pending broadcasts (checklist-v2 + h10-flat-detector-refine).
- port /sleep-recovery-memory-l2 (A8, J2-tailored SE-only, floor intact, live skill).
- detector refine-b TAILORED-OUT (SE Workflow-tool no-CLI-bypass; containment
  git-diff+tracked+orphan-scan G-015).
- REVIEW (B2) caught 2 IMPLEMENT-self-assess missed (hmw.js:52 schema-stale +
  sleep-cmd auto-check un-wired overclaim) -> fixed (auto-check WIRED: budget.json
  +last_sleep_at + session-start/end INFORM). +3 minor fixed.
- em-main containment-check caught 1 reviewer residual-write (raw-Workflow no
  writeGuard) -> revert (reverse-finding #4). B3 self-correct: runs path 14->22.
- sleep-recovery-memory-l2 all = NO-OP (all periods already gisted). last_sleep_at set.

0 production code. State unchanged: Mig 53 / 88 tables / 306 test / 68 gotcha / menu 54
/ bundle BgNCjwsG/CBvh0vtf. adap-report + email ai_infra (5f511fe5c0f2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:04:03 +07:00

28 KiB
Raw Blame History

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 RAG search_memory just-in-time. Keep entry ≤ 1.5K chars (gotcha #53). Full verbatim history pre-S40 → git d2f52ba + archive/2026-05-q1..q4.md + archive/2026-06.md. 🗺️ Lookup map (Harness-9 S70): archive/_INDEX.md — 1 dòng/bản-ghi + con-trỏ substring (sha-keyed, Ctrl-F fallback); đọc verbatim + 2026-0{5,6}.gist.md (nén 4-field) theo nhu cầu. 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 · IActionResult vs ActionResult<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

27 user-memory tại C:\Users\pqhuy\.claude\projects\D--...\memory\MEMORY.md (index). Key: per_chunk_commit · uat_skip_verify · audit_reuse_before_clone · designtime_runtime_db · per_nv_permission_scope · ef_migration_backfill_reorder · status_handoff_tiering (S40) · 7agent_split_upgrade (S39).

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 (S40 verified — re-grounded)

  • 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 /Migrations/). 40 mig, last 20260528090839_AddAttendances.
  • Counts S40: 40 mig · 84 SQL tables (77 DbSet + 7 Identity, count .ToTable() ModelSnapshot NOT DbSet) · ~211 endpoints · 65 FE pages (36 admin + 29 user *Page.tsx) · ~53 menu keys (BE MenuKeys const) · 130 test (58 Domain + 72 Infra) · 55 gotchas (format ### N. highest #55) · 27 user-memory · 6 skills · 7 sub-agents
  • 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/tasks NOT /runs 404, cache stale ~2min gotcha #46 — cross-check VPS mtime)
  • Auth: admin@solutions.com.vn/Admin@123456 (full) / nv.test@solutions.com.vn/TestUser@123456 (Drafter). Response accessToken+refreshToken+user. Password ≥12 chars.

🔄 Active workflow schemas (V1 + V2 coexist post-S17)

  • V1 Mig 21 flatWorkflowDefinition pin PE/Contract cũ. Match Dept+PositionLevel.
  • V2 Mig 22-31ApprovalWorkflow pin PE/Contract mới, match ApproverUserId 1-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 S37 inline ApproveV2Async). WorkflowApps skeleton (Mig 39 S38 — ApproveV2 advance DEFER Phase 11).
    • Mig 25 IsUserSelectable · Mig 26 PE LevelOpinions UPSERT · Mig 29 Allow* per-NV (F1/F3 per Approver slot + F2 Users.AllowDrafterSkipToFinal) · Mig 30 F4 AllowApproverEditBudget · Mig 31 SkipToFinal→ApproverLevel
  • State machine PE 5 trạng thái: Nháp / Đã gửi duyệt / Trả lại (TraLai=98) / Từ chối / Đã 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 (FIFO — older → archive/git)

  • 2026-06-18 (S71 PART-C audit — run-trace vs checklist-v2 FLAT + detector-refine, on-disk): 2 GAP THẬT (trung-thực, không inflate): (1) C1/C2/C8 = SUBFOLDER, canonical-v2 = FLAT → migration NEEDED, chưa làm. find runs/ cho thấy MỖI run-folder có sub-md/+harvest/ SUBDIR (5 run: h10-{invest,implement,review}+h910-{finalize,curate}) — đúng cấu-trúc CŨ broadcast-delta phát-bỏ. ZERO flat-awareness: grep phẳng|flat|cùng cấp trong .claude/workflows/+.claude/commands/=0 hit. SE-adoption-commit 8c47bd0(06-18) TRƯỚC broadcast-flat cùng-ngày → SE chưa biết. README/hmw.js/session-end đều mô-tả subfolder. C8 dual-form-acceptance close-gate cũng chưa. (2) REFINE(b) detector = MISSING HOÀN-TOÀN. find .claude -name *.js/*.ps1=CHỈ hmw.js(=engine ≠ detector). .claude/hooks+.claude/scripts KHÔNG tồn-tại. Repo-wide grep bypass|scan.*runs script=0. SE KHÔNG có bộ-dò chống-lách-engine → 3-function (whitelist/path-variants/launch-key-anchor)+relation-acceptance = n-a. MET (đừng nhạ oan): C3 committed THẬT — git check-ignore runs=exit1(NOT-ignored)+git ls-files runs=22 file (cả hai nấc). C4 per-turn real (invest-synthesis.md 43-dòng). C5 3-layer wired: L1 README:51(convention em-main) · L2 session-start.md:71 orphan-scan runs/*/ closed=+harvest-rỗng · L3 session-end.md:51 close-gate idempotent 5-trục. C6 ledger 2-beat (_ledger.md:7, 5 run đều CLOSE-beat+wf_). C7 caveat present (README §69-73 no-overclaim/fragile/G-015 TRACKED≠enforced). ⚠️ sub-md/ chỉ .gitkeep (read-only sub→em-main scribe, design KHÔNG phải miss). Tag [s71, part-c-audit, subfolder-not-flat, detector-MISSING, c3-committed-real].

  • 2026-06-18 (S71 Harness-10 ref-sweep — wave-*/agent-teams/harvest migration map, on-disk): 2 RULE-MECHANISM (cơ-chế, sửa CẨN THẬN ≠ text-swap): (1) .gitignore:93-94 .claude/workflows/wave-*/ + .claude/agent-teams/ AFTER !.claude/**:83 (last-match-wins) — Harness-10 LẬT containment: runs/ TRACKED nên KHÔNG gitignore (đã có runs/_ledger.md:4 "tracked-change NGOÀI run-folder = vi-phạm" thay B6 "mọi tracked = vi-phạm"). agent-teams = n-a Windows in-process → giữ-hay-bỏ tùy. (2) hmw.js wave-mechanism: meta.description:9 (2-MODE) · args:19 wave:{name,dir} · SCHEMA subMdPath:52 · WAVE-MODE block:87-91 (const wave = A.wave&&A.wave.dir) · log:94 · subMd path:102 · writeGuard TOOL-AWARE 2-nhánh:106-120 (wave→sub-MD-isolated / default→return-delta) · prompt subMdPath:131. → run-trace = đổi waverun, dir wave-<tên>runs/<run-id>, +harvest/ path. TEXT-ONLY (đổi chữ, KHÔNG cơ-chế): .claude/workflows/README.md TOÀN BỘ (48 dòng, đầu-đề + table 2-MODE + structure + B1-B6 + agent-team §) · session-end.md:32,49,51 (§L.b(d)(f) GATE + B5 wave-gom) · session-start.md:71 (H2 báo wave-folder tồn-đọng) · agents/README.md:111 (decision-tree wave-gom B5) + :22-28,52 harvest-curator.md (B5 scan path wave-<tên>/sub-*.md + agent-team) · harvest-curator/MEMORY.md:20 (wave-folder gitignored). DOC/HISTORY (immutable evidence — KHÔNG sửa): broadcasts/** (handshake:17 + inbox/README:15 "khác wave-folder gitignored") · docs/governance/adap-reports/2026-06-07-Agent-harness-2.md (toàn bộ B1-B6 spec) · docs/changelog/sessions/* · error-ledger.md:86 (wave-folder-leak=0 evidence). ĐÃ SCAFFOLD Harness-10 (S71 đang chạy): runs/_ledger.md (2-beat OPEN/CLOSE) + runs/2026-06-18-h10-invest/run.md + harvest/. ⚠️ Note .gitignore:92 comment git check-ignore -v .claude/workflows/wave-x/wave.md = verify-cmd cũ, đổi theo. Tag [s71, harness-10-refsweep, wave-to-runtrace-migration, gitignore-mechanism, hmw-wave-mechanism].

  • 2026-06-18 (S71 Harness-10 STAGE-C harvest-flow recon — per-turn + 3-layer wire points, on-disk): CURRENT harvest = SINGLE-POINT @session-end (B5), KHÔNG per-turn. Driver = harvest-curator H2 (agents/harvest-curator.md:22 "sau workflow-dài/cuối-session quét wave-<tên>/sub-*.md→gom→APPEND agent-memory/"). Wired ONLY session-end.md §L.b(f):51 (5-trục GATE + wave-folder gom B5). session-start.md:71 = REPORT-only (báo wave tồn-đọng, KHÔNG gom). ZERO per-turn hook — hmw.js JS-sandbox no-fs (hmw.js:5), harvest deferred-to-close. C4 per-turn-primary wire (3 chỗ): (a) hmw.js:122-134 prompt-builder — sub return findings; (b) NEW em-main step: ghi runs/<id>/harvest/ SAU MỖI fan-out turn (KHÔNG đợi close); (c) session-end.md §L.b(f):51 đổi "gom @end" → "VERIFY per-turn harvest đủ". C5 3-layer anti-miss wire: L1 in-run-reminder = hmw.js prompt + run.md checklist (run trước chưa-harvest → flag); L2 post-exec-rescan = session-start.md:71 (mở rộng orphan-scan runs/*/ tìm ledger-OPEN-no-harvest, hiện chỉ báo wave); L3 close-gate = session-end.md §L.b(f):51 (GATE đã có, repoint wave→runs). EVIDENCE tracked: git check-ignore runs/.../run.md→matched !.claude/** (.gitignore:83 negation)=NOT-ignored ✓ vs wave-*/ still gitignored (:93). Run-folder ĐÃ scaffold S71: runs/2026-06-18-h10-invest/{run.md·sub-md/.gitkeep·harvest/.gitkeep}+runs/_ledger.md (2-beat OPEN/CLOSE :3, orphan=OPEN-no-CLOSE). G-015 shift: Harness-2 "mọi tracked=vi-phạm" (wave gitignored→diff mù) → Harness-10 "tracked NGOÀI run-folder+code-disjoint=vi-phạm" (_ledger.md:4) → containment MẠNH hơn (run-folder in git-diff thấy sub-MD writes). Tag [s71, h10-harvest-flow, per-turn-C4, 3-layer-C5, single-point-end-current].

  • 2026-06-18 (S71 Harness-10 task-A — hmw.js EXACT edit-list wave→run-trace, on-disk): Refines sibling ref-sweep with precise diffs. 3 LOGIC edits: (1) :90 const wave=(A.wave&&A.wave.dir)?A.wave:nullrun=(A.run&&A.run.dir)?A.run:null; (2) :102 subMd \${wave.dir}/sub-${role||'task'}-${i}.md``${run.dir}/sub-md/sub-${role||'task'}-${i}.md` (⚠️ +/sub-md/SUBDIR — matches scaffoldedruns//sub-md/, today FLAT); (3) :106-120writeGuard 2-branch keep TOOL-AWARE, reword. **CONTAINMENT-FLIP 2 strings:**:112"wave-folder gitignored nên KHÔNG hiện trong diff = sạch" → "run-folder TRACKED; tracked-change NGOÀI run-folder(+code-disjoint)=vi-phạm" (model =runs/_ledger.md:4); :114"file NGOÀI repo/wave-folder"→run-folder. **TEXT reword:**:5,9(+drop stale two-tier H4.5→H8),19(args wave→run),52,55,88-91,94,108,113,131. **VERDICT: pure mechanical** — fan-out/SCHEMA/resolveModel/parallel/checkpoint-gate ALL unchanged; only rename + path-subdir + 2 string-flips. **Read-only sub flow same** (:111subMdPath→em-main-scribe @P3, no Write tool). **C2/C4 stay em-main** (hmw.js no-fs:1-5). Tag [s71, h10-task-a, hmw-exact-difflist, subdir-sub-md, mechanical-rename]`.

  • 2026-06-17 (PE-workflow recon for FDC feature-plan — urgent flag + value-threshold routing, on-disk): PE VALUE: NO stored "giá trị gói thầu" column. Best-fit = winner-quote-total SUM(Quote.ThanhTien WHERE supplier==SelectedSupplierId) — COMPUTED (submit-guard PurchaseEvaluationWorkflowService.cs:188-190 + CurrentProposalTotal in PeBudgetSummaryDto). Other amounts: PE.BudgetPeriodAmount(:40 drafter NS kỳ này)/ExpectedRemainingAmount(:41)/PeWorkItemBudget.FullAmount=(Initial??0)+(Adjustment??0) (PeWorkItemBudget.cs:29-30) — all budgets, not deal-value. ROLES PRO/CCM/CEO = domain shorthand NOT constants (AppRoles.cs has Procurement/CostControl/Director; PRO=Procurement CCM=CostControl CEO=Director). V2 routing IGNORES roles — approvers = specific ApproverUserId (ApprovalWorkflow.cs:80), OR-of-N = N Level rows same Order (GroupBy :687). "Phòng CCM" = seed Step NAME + non-strict DeptId hint only (:67). CEO = positional (last level/last step), NOT conditional. ROUTING 100% LINEAR (level→step, DaDuyet when nextIdx>=steps.Count). ZERO value/threshold/conditional config anywhere (grep 0 on AW/Step/Level/PEType). HOOK B (value-threshold) = ApproveV2Async advance block lines 816-845 (:817 levelOrder++ / :828-837 terminal DaDuyet / :838-845 next step). Precedent: skipToFinal :773-814 already "jump pointer to last step+level" — reuse mechanic conditioned on value. HOOK A (urgent): add IsUrgent bit/PePriority enum (mirror ItTicketPriority{Low,Medium,High,Urgent} Office/Enums.cs:48-54) AddColumn no-new-table; notify INotificationService.NotifyAsync(userId,type,title,desc?,href?,refId?) (INotificationService.cs:10)+SignalR interceptor; LogTransition notifies DRAFTER-only on terminal (:960-980), NO approver-notify yet. Badge DTOs: PurchaseEvaluationListItemDto(PurchaseEvaluationDtos.cs:6)+DetailBundleDto(:201). Type A/B (PurchaseEvaluationType.cs:6-10) constrains pinnable ApplicableType only — ZERO type-conditional routing. ⚠️ "Từ chối" REMOVED S60 hard-guard :80-85 (throws even Admin; only Duyệt/Trả lại). ⚠️ drafter-in-chain bypass :543 auto-approves drafter's own step-1 levels on submit (interacts w/ value-finalize). Tag [pe-workflow-recon, value-threshold-hook, urgent-flag, fdc-feature-plan].

  • 2026-06-17 (S69 recon — Office-module inventory + Hồ sơ-NS CSS-contract, on-disk): PART A Office: 21 Off_* keys (MenuKeys.cs:99-121): root Off + DanhBa(card-grid), Off_PhongHop{View=cal/Manage=room-CRUD-admin/Book}, Off_DeXuat{List/Create/Inbox=Proposal-V2}, Off_DonTu{Leave/Ot/Travel}, Off_DatXe, Off_ItTicket, Off_ChamCong(re-parent→Personal S57), Off_AttendanceReport(admin). 10 office pages {fe-admin,fe-user}/src/pages/office/ ALL SHA256-MIRROR except MyAttendancePage DIFFERS + AttendanceReportPage ADMIN-ONLY. Routes App.tsx user:70-80/admin:88-100; staticMap Layout.tsx:87-103 (workflow-apps :kind /workflow-apps/{leave,ot,travel,vehicle}); menuKeys.ts:45-63. HIDE-FLAG RevokeTemporarilyHiddenModulesAsync (DbInitializer.cs:2157-2190 called :2040 LAST) wipes CRUD on MenuKey.StartsWith("Off")||"Hrm"||==Personal non-Admin, idempotent. Golive flip: remove :2040 call (+ re-add prefix InReviewScope grant). Office already S55-shell polished NOT bare. PART B Hồ sơ-NS CSS: layout=3-col flex (EmployeesListPage.tsx SHA256-identical x2, 1597 LOC): cây-tổ-chức TRÁI(:178) + NV-list MID(:244) + detail PHẢI = avatar-header app-gradient-brand(:643)+text-white!(:653)+initials chip bg-white/15 → 5-TAB(:507 Tổng quan/Thân nhân/Trình độ/Kinh nghiệm/Hợp đồng) → Card(:1526 left-rail+icon-chip) w/ Field(:1572 label uppercase accent-tint + value font-medium text-brand-800, empty=text-slate-300 —). ACCENT map :497-503 Record<5,{chipBg/chipFg/head/rail/labelText}> accent∈{brand,teal,violet,amberx,greenx}, palettes stops 50/100/500/600/700 only no-800→headings -700 (brand -800 OK). Tokens index.css: brand-600=#1f7dc1 brand-800=#175685 @theme:5-55, font Be-Vietnam-Pro:53; classes .app-gradient-brand(:105 120deg b600→700→800),.card-accent(:112),.icon-chip(:128 --chip-bg/--chip-fg),.stat-value(:140),.label-eyebrow(:89). ⚠️ GOTCHA #66 = index.css:79-83 h1,h2,h3,h4{color:#0b1220;font-weight:700} OUTSIDE @layer → TW-v4 unlayered wins → heading-tag inside gradient MUST text-white!. ⚠️ CROSS-APP DRIFT: fe-user=S68 (h1-4 #0b1220/700, label-eyebrow brand-600, 175L); fe-admin STILL OLD (h1-4 #0f172a/600, label-eyebrow #64748b slate, 167L) — fe-admin NOT synced S66-68 heading bump → mirror Office to fe-admin needs index.css sync. Tag [s69, office-inventory, hoso-css-contract, gotcha66, fe-admin-css-drift].

  • 2026-06-18 (S71 Harness-8/hmw/pending/sleep audit — fidelity ground-truth, on-disk): H8 all-inherit = FULLY ADOPTED both layers. (1) Frontmatter: ALL 12 .claude/agents/*.md = model: inherit (11 sub + README; grep-count 12/12, zero demoted). (2) hmw.js resolveModel:36-44 = all-inherit (:43 role-with-frontmatter→undefined=inherit; :41 invalid-role→fail-UP inherit; :42 role-less→inherit). Per-task escape-hatch PRESENT :37 if(tier==='fable'||'opus')return tier (H8.1 "ngoại lệ per-task" satisfied). hmw run-trace = args.run + legacy args.wave alias :91 (A.run&&A.run.dir)?A.run:((A.wave&&A.wave.dir)?A.wave:null) ✓. ⚠️ GAP-1 (the one real gap): hmw FLAT-vs-SUBFOLDER. hmw STILL emits SUBFOLDER: :103 subMd=${dir}/sub-md/${role}-${i}.md + desc/:113 reference run.md+sub-md/+harvest/. The 2026-06-18 h10-flat-detector-refine (supersedes-part-of checklist-9-10 §C1/C2/C8) mandates FLAT files-one-level distinguished BY FILENAME, no subdirs. Disk confirms subfolder: runs/2026-06-18-h10-invest/ has harvest/+sub-md/ dirs (not flat). GAP-2: SE adopted checklist v1 NOT v2 (broadcasts/outbox/ai_infra/2026-06-18-...checklist-adopted.md:16 cites 2026-06-16-Governance-checklist-harness-9-10 = v1, no -v2). UNADOPTED broadcasts (2 confirmed PENDING): 2026-06-18-h10-flat-detector-refine + 2026-06-18-checklist-harness-9-10-v2. NO other newer (last outbox/all = these two; SE outbox last report = 2026-06-18 v1). C3 two-level VERIFIED: git check-ignore runs/ exit=1 (NOT-ignored, neg !.claude/** :83) + git ls-files runs/ = 22 files committed. wave-x/wave.md check-ignore exit=0 (still gitignored :93). sleep-recovery-memory-l2 = AI_INFRA-internal (AI_INFRA/.claude/commands/sleep-recovery-memory-l2.md + docs/architecture/MEMORY-SLEEP-RECOVERY-L2-DESIGN-v3.md:scope "CHỈ L2, KHÔNG sister"; NOT in outbox/all — only its Harness-9 broadcast form is, already adopted S70). NOT a sister obligation. SE already does equivalent FULLY (not ad-hoc): memory-budget.json (caps seeded-by-measure scripts/measure-agent-memory.ps1) + 4× archive/_INDEX.md + 4× *.gist.md (distill-gen:2 counter) + .ragignore (exclude index/gist). Tag [s71, harness8-audit, hmw-flat-gap, checklist-v1-not-v2, sleep-recovery-ainfra-internal, gist-additive-done].

  • [→ git pre-S60] S60 recon#2 V2-engine-map (ApprovalWorkflow.cs Step/Level Order 1-based per-step; OR-of-N=N rows cùng Order service GroupBy:475; ApproveV2Async:446-634 guard+UPSERT+advance; notify DRAFTER-only:748; skipToFinal F2:561-602 = precedent advance-không-ghi-opinion) · S60 PE Section-3 submit-guard (submit path POST/pe/{id}/transitions→TransitionAsync:38 ROLE-only guard NO data-check; Section-3 mục a/b/c/d map — SUPERSEDED bởi S65ter post-Mig50 Budget-drop; test mirror PurchaseEvaluationWorkflowServiceGuardTests). Full text git.

  • 2026-06-16 (S65bis recon — Employee profile master-detail vs NamGroup, on-disk): STALE-PREMISE CORRECTION: fe-user /employees KHÔNG list-only — hrm/EmployeesListPage.tsx (1201 LOC) ĐÃ master-detail 2-panel (filter sidebar :117 + list table :197 + inline detail :234) với 6 collapsible section (<details> :1157, KHÔNG tab) + 5 satellite inline CRUD (WorkHistory/Education/FamilyRelation/Skill/Document, setEditing{X}Id+adding{X} mutex pattern 12-ter S35). fe-admin == fe-user diff -q IDENTICAL (SHA256 same). Entity gần đủ screenshot: Domain/Hrm/EmployeeProfile.cs (137 LOC) CÓ: DOB/Gender/Ethnicity/Religion/Nationality/Height/Weight(:98-99)/IdCard(số+ngàycấp+nơicấp :52-54)/permanent+temporary addr/phone/personalEmail/code/hireDate/qualification/salary(Base+Total)/bank/4×leave-days. THIẾU vs screenshot: (a) BloodType CÓ nhưng "sức khỏe loại" (health-grade A/B/C) KHÔNG; (b) thâm niên = DERIVED từ HireDate (no column); (c) chức danh = User.Position/PositionLevel (Identity, KHÔNG ở EmployeeProfile) — list/detail JOIN Users (EmployeeFeatures.cs:467); (d) "lương BHXH/phụ cấp" tách riêng KHÔNG có (chỉ Base+Total); đơn vị=DepartmentName JOIN. 5 satellite entity + 15 endpoint FULL (EmployeesController.cs:75-233 5 region×Create/Update/Delete; GET detail Include cả 5 :455-459). Skill polymorphic gộp 3 NamGroup table (Computer/Language/Other Kind :69). GAP THẬT: (1) NO org-treeDepartment.cs FLAT (Code/Name/ManagerUserId/Note, KHÔNG ParentId), DepartmentsController chỉ GET list+byId (NO /tree), KHÔNG endpoint count-per-dept → cây trái + badge phải build CLIENT-side group-by departmentId từ list; (2) 5-tab layout screenshot = 6-section <details> hiện tại (re-skin UI, data đủ); (3) "Hợp đồng lao động" tab = chỉ có EmployeeDocument type=LaborContract(5), KHÔNG entity HĐLĐ riêng (3 HĐLĐ table DEFER Plan H2 per EmployeeProfile.cs:10). NamGroup source: D:\...\NAMGROUP\SOURCECODE_CÔNG_TY\ find .tsx/.razor = 0 hit (KHÔNG phải React/archived) — RAG proj_namgroup_main 0 component; tham khảo layout = screenshot anh gửi, KHÔNG có code mirror trực tiếp. ⇒ Wire-lại-là-xong: data + API + satellite CRUD 100% sẵn. Build mới: Department.ParentId migration + /tree + count endpoint (nếu muốn org-tree thật thay client-group). Re-skin: 6-section→5-tab + avatar header. No new field bắt buộc trừ health-grade nếu anh cần. Tag [s65bis, employee-profile, master-detail-EXISTS, dept-flat-no-tree, stale-list-only-corrected].

  • 2026-06-17 (S69 recon — NamGroup "PURO" digital-office layout, CROSS-REPO D:\...\NAMGROUP\): PURO = UI design-language/skin (ref ERP demo.purocorp.vn), KHÔNG phải app riêng — NamGroup mirror sidebar/typography của nó (comments InternalLayout.tsx:33,74,109,200,332 "PURO exact spec"). Digital-office sống trong namgroup.client/ (app NV; admin = config-only). Shell = components/layout/InternalLayout.tsx (724L): sidebar trái fixed h-screen + <main flex-1 overflow-auto p-2.5..lg:p-4> :609 chứa <Outlet/>. Sidebar = navTree hardcoded array :76-122 (KHÔNG DB), flat 2-tier group→leaf, 4 group: "Văn phòng số" :90-100 = 6 leaf {Danh bạ /danhba · Phòng họp /phonghop · Đề xuất /dexuat · Đơn từ /dontu · Đặt xe công /xecong · Ticket CNTT /ticket}; + Nhân sự(3) + Cá nhân{Chấm công}(1) + Hệ thống(5). Routing = App.tsx:81-140 flat <Route element={InternalLayout}> > <RouteGuard> (perm) > index=HomePage. Landing / = internal/HomePage.tsx (296L): grid 2-col (LEFT 2/3 stack 4 WidgetCard: Đề xuất/Nghỉ phép/Bình luận/Truyền-thông · RIGHT 1/3 Công-việc-của-tôi); WidgetCard = gradient-blue header + inline stat-chips + body/EmptyState (shared comp tại :219). Layout pattern mỗi feature (KHÔNG dùng tab — dùng KpiCard-row + view-toggle): (a) <PageHeader> shared (icon-badge accent + breadcrumb + actions slot, components/shared/PageHeader.tsx); (b) KPI stat-cards clickable filter (DeXuat :1643 6-card / Ticket :197 5-card — "PURO KPI cards" comment); (c) body = list-table (DeXuat/Ticket: <table> master + right detail panel grid-cols-3) HOẶC list↔calendar ViewToggle (DonTu :683 + XeCong + PhongHop: custom month-grid Sun-Sat, NO FullCalendar — comment :PhongHop "saves install friction"); DanhBa = dept-tree trái + card-grid phải. Shared comp tái dùng: PageHeader · DataTable · KpiCard · CrudToolbar · ActionLogList · DatePickerVN · MasterDataPage · DonutChart/MiniBarChart (components/shared/ 16 file). Top files mirror: InternalLayout.tsx(shell+nav) · HomePage.tsx(dashboard) · PageHeader.tsx · DeXuatPage.tsx(1676 KPI+table+detail) · DonTuPage.tsx(1269 +DonTuCalendar.tsx toggle) · XeCongPage/PhongHopPage(month-grid) · TicketPage.tsx(595) · DanhBaPage.tsx(756 tree+grid) · ChamCongPage.tsx(809). ⚠️ Style/màu lấy chỗ khác per task — chỉ structure. SE đã có analog (fe-user InternalLayout/office pages) nhưng layout khác (deep-nested vs PURO flat). Tag [s69, namgroup-puro-recon, digital-office-layout, hardcoded-navtree, kpicard-not-tab, cross-repo].

  • [→ archive/2026-06.md + git] S52 P11-D/E/F 6-gap recon (IT-pool absent → S56 corrected: dept IT exists 0 user · SlaExpiryJob HostedService DI:46 pattern · OtPolicy 3-multiplier · ClosedXML exporter reuse · Attendance API cá nhân-only · FE skeleton state — full text git pre-S60) · S50 P11-C HrmConfigs add-kind 11-chỗ pattern · S50 wave h2-verify B6 gitignore ordering + POSIX-not-pwsh (curated S57bis) · S51 gotcha #57 EXT reachability 3-Master-fix/3-skip global-filter-makes-bug (curated S59).

  • Archived S29-S37 → archive/2026-05-q4.md + git d2f52ba (S40 curate): S36 G-O2 Phòng họp clean-room + FullCalendar v6 MIT eval · S36 startup MEMORY-size audit · S35 G-H2 HRM clean-room verdict · S33 G-H1 NamGroup TblNhanVien 10-bảng (105 cols main) · S33 startup RAG verify · S32 Plan G 11-module backlog · S29 Plan CA+B pre-flight (3 patterns: 9-menu terrain, V1+V2 coexist, reference-template-paths cite line-range ROI). KEY absorbed: clean-room > NamGroup port verified 4× · Pattern 12-bis cross-module mirror · FK+freetext dual-write.

  • 2026-06-18 (S71 audit — Harness-9 PART B adap-2workflow trung-thuc, on-disk): VERDICT B substantially-LANDED, ZERO nac-inflation (reports UNDER-state via honest hedge). B1/B2 ok-runtime: 2 adap cycle ran SEPARATE workflows distinct run-id — S70 impl wf_a58e0d15-beb≠audit wf_9520d8cd-4fe; S71 impl wf_e4e46725-231≠review wf_636bc95b-939 (review caught real C5-L1 over-claim impl-self-check missed). B2.5 ok: reverse-findings non-empty both reports (3+4 items)+both emails. B3 ok: 2 emails broadcasts/outbox/ai_infra/{2026-06-17,2026-06-18}-se-to-ai_infra-*.md carry true-nac+findings+BOTH run-ids. B4 partial/convention-met: rule codified adap-apply.md:38 (short-but-confirm→review) BUT no runtime instance (no short-decision task arose S70/S71) → pure-convention, lead-discipline. ⚠️ 3 PRECISION-flaws (not protocol-gap): (1) reviewer-agent StructuredOutput unreliable both sessions → em-main self-gate git/sha (disclosed, valid-branch per feedback memory). (2) PATH-TRAP: S71 report/email self-verify cited bare git ls-files runs/=14 — WRONG; actual = .claude/workflows/runs/ (22 tracked files, 5 runs: invest/implement/review + h910-finalize wf_73de399d-753 + h910-curate wf_f32987b8-03f). Auditor running bare runs/ from repo-root gets 0 → false "not-committed". Folder genuinely committed 8c47bd0 + NOT-ignored at correct path. (3) hmw.js RUN-TRACE runtime honest-flagged pending-restart. adap-apply.md:33-36 codify 2-workflow mandate (auto-loaded). Tag [s71-audit, harness-9-partB, adap-2workflow, path-trap-runs-folder, b4-convention-gap, no-nac-inflation].


🔄 Curate trigger

  • ~30KB → archive recent → L2 archive/<period>.md. Stale >3mo → remove.

  • Last curate: 2026-06-18 S71 Harness-9 L1→L2 (auto-inject 25600B cap) (29.8→23.2KB): FIFO-trimmed 3 oldest 2026-06-16 entries (S66/S65ter/S65) → archive/2026-06.md (additive +6 -0, md5 cedc21eb… byte-exact) + 3 rows _INDEX.md (unique substring) + 3 4-field gist 2026-06.gist.md (distill-gen:1→2, 15→18 records). 0-byte-loss verified (numstat additive + md5 match). Kept S65bis/S69/S71. Prev: S70 (47.0→24.1KB dark-matter recovery) · S40 (35.7→~20KB) · S34 q3 · S22 q1.