# Implementer Agent — Persistent Memory > **Persistent diary cross-session.** Auto-injected first 200 lines / 25KB at spawn. > Update BEFORE every stop. Curate when > 25KB. --- ## 🎯 Role baseline Code execution specialist for SOLUTION_ERP. Conditional WRITE (Case 1+2+3+5 ONLY). Tools: Read, Edit, Write, Bash, Skill, Grep, Glob. Output: commits + verification report. ## 🚨 STRICT scope auto-refuse criteria REFUSE if ANY: 1. Schema design decisions needed (FK strategy / nullable / discriminator) 2. UX flow decisions needed (drawer vs tab vs modal) 3. Cross-stack > 2 layers tight coupling 4. Bug fix involving reasoning chain 5. Integration testing involving multiple components 6. < 30 min trivial task 7. First time pattern (no prior precedent) 8. Spec ambiguity > 20% --- ## 📋 Patterns proven (cross-session) — apply confidently ### Pattern 1: Per-chunk discipline 5-chunk A-E (Anthropic Case 2 orchestrator-workers) Memory `feedback_per_chunk_commit` chốt: - **Chunk A:** Domain entities + Migration (3-file rule) - **Chunk B:** Application handlers (CQRS Commands + Queries + Validators) - **Chunk C:** Service layer (workflow logic, business rules) - **Chunk D:** API controllers + endpoints - **Chunk E:** FE update (cả 2 app mirror) + Tests + Docs + commit final Build + test pass mỗi chunk. Commit message format: ``` [CLAUDE] : Chunk Verify: - Build pass (X warning, 0 error) - N test pass (...) Pending Chunk : Co-Authored-By: Claude Opus 4.7 (1M context) ``` ### Pattern 2: 3-file rule EF migration (BẮT BUỘC commit đủ) Memory + gotcha #17: - `Migrations/{TS}_{Name}.cs` (Up + Down) - `Migrations/{TS}_{Name}.Designer.cs` (snapshot at migration time) - `Migrations/ApplicationDbContextModelSnapshot.cs` (current snapshot) ```bash dotnet ef migrations add \ --project src/Backend/SolutionErp.Infrastructure \ --startup-project src/Backend/SolutionErp.Api # Apply lên DB Dev: dotnet ef database update --project src/Backend/SolutionErp.Infrastructure \ --startup-project src/Backend/SolutionErp.Api \ --connection "Server=(localdb)\MSSQLLocalDB;Database=SolutionErp_Dev;Trusted_Connection=True;TrustServerCertificate=true" # Apply lên DB Design (catchup nếu thiếu): dotnet ef database update --project src/Backend/SolutionErp.Infrastructure \ --startup-project src/Backend/SolutionErp.Api ``` ### Pattern 3: Audit reuse trước khi clone (memory `feedback_audit_reuse_before_clone`) Khi user nói "clone X sang Y": 1. **Grep discriminator field** (`ApplicableType`, `Type`, `Kind` enum) 2. **Check Service / Handler / Controller** có hardcode type cụ thể không 3. **Check FE pages** có route dynamic typeCode hay hardcode 4. **Check menu key** (BE const + FE menuKeys.ts) — thường thiếu chính ở đây 5. Default reuse 80%, chỉ thêm menu key + sample seed (3 file ~60 LOC) Bài học S17+ Clone B: 1 commit `937eb24`, deploy 1 phát chạy. ### Pattern 4: Service hook vs CRUD endpoint cho derived state (memory `feedback_service_hook_vs_endpoint`) State X = derived của action Y → UPSERT trong handler Y, KHÔNG endpoint /X riêng. Bài học S19 Mig 26 PE LevelOpinions: Service `ApproveV2Async` UPSERT row qua match `ApproverUserId == actorUserId` (fallback first khi Admin override). 0 endpoint mới. ### Pattern 5: FE mirror 2 app rule §3.9 Duplicate `fe-admin/` + `fe-user/` CÓ CHỦ ĐÍCH: - Sửa fe-admin xong → mirror fe-user (tay) - Khi breaking change rename prop → BẮT BUỘC `npm run build` × 2 app (memory `feedback_uat_skip_verify` exception) ### Pattern 6: VND format helpers + Phone/Email validate (S20 turn 4) Inline mỗi file FE PE: ```ts const parseVnd = (s: string): number => Number(s.replace(/[^\d]/g, '')) || 0 const formatVndInput = (n: number): string => (n > 0 ? n.toLocaleString('vi-VN') : '') const PHONE_RE = /^0\d{9,10}$/ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ const isValidPhone = (s: string) => !s || PHONE_RE.test(s.replace(/[\s\-.]/g, '')) const isValidEmail = (s: string) => !s || EMAIL_RE.test(s) ``` ### Pattern 7: Per-NV admin opt-in flag (S21 t5 Mig 29 + S22 Mig 30) ApprovalWorkflowLevel +1 column `bool` DEFAULT 0 (opt-in admin set explicit). EF config `HasDefaultValue(false)`. DTO extend field. FE Designer checkbox inline mỗi Level row. Reusable cho future flag F5/F6 (vd `AllowEarlyApprove`, `AllowDelegate`): admin per-NV opt-in qua Level table thay vì global flag. Decision tree: flag scope role-context → table mapping natural (Approver → Level table carry ApproverUserId FK, Drafter → User table direct — memory `feedback_per_nv_permission_scope`). Bài học S22: AllowApproverEditSection1 (Mig 30) follow same pattern Mig 29. 0 schema redesign cần. ### Pattern 8: Tách endpoint riêng cho narrow scope (S22 AdjustBudget vs UpdatePeDraft) Khi 1 action có 2 scope khác nhau theo role: - **Drafter scope (rộng):** `UpdatePeDraft` cover Section 1 (Tên/Địa điểm/Mô tả/Payment + Budget) — chỉ phase Nháp / Trả lại - **Approver scope (hẹp):** `AdjustBudget` chỉ Budget rows — phase Đang duyệt với per-NV flag KHÔNG default expand Drafter scope cho Approver — tránh accidental edit Section 1. Endpoint tách riêng = guard tự nhiên + audit trail rõ. Bài học S22: AllowApproverEditSection1 flag opt-in cụ thể PATCH /budget rows, KHÔNG /full-update. ### Pattern 9: Defense-in-depth FE + BE guard pair (S22+1) UI button `disabled={!canReject}` + BE helper `EnsureCanRejectV2Async(peId, userId)` throw 403 nếu non-approver. Tránh request forge non-approver gọi PATCH direct qua DevTools. Pattern reusable: bất kỳ action sensitive (approve/reject/adjust) → FE disable + BE guard helper riêng (NOT inline trong handler). Bài học S22+1: 3 button (Duyệt / Trả lại / Từ chối) — UI disable + BE helper. Tránh leak action qua API direct. ### Pattern 10: Reflection-based regression test cho Authorize policy (S22 Plan C task 4 #44) 5 test lightweight ~50 LOC catch class-level `[Authorize(Policy = "...")]` regression: ```csharp var attr = typeof(ControllerXxx).GetCustomAttribute(); attr.Policy.Should().Be("CanDoSomething"); ``` KHÔNG cần WebApplicationFactory heavy (slow + complex setup). Reflection catch ai accidentally remove `[Authorize]` hoặc đổi policy name. Pattern reusable cho future controller sensitive (Approve / Reject / Adjust / Reset). ### Pattern 11: Test infra helper cookie-cutter (S22) Trong `PurchaseEvaluationWorkflowServiceReturnModeTests` + `PurchaseEvaluationDraftGuardTests`: ```csharp private async Task SeedWorkflowAsync(...) { // 1 Step (DepartmentId=null skip Dept FK) + 2 Levels } private async Task SeedApproversAsync(Guid levelId, ...) { // Multi user via fix.CreateUserAsync } ``` Pattern reusable: test PE workflow → 1 Step + 2 Levels + N approvers per Level. `DepartmentId=null` skip Dept FK ràng buộc. Token cost ~80 LOC repeated cross 2 test class S22. ### Pattern 12: InternalsVisibleTo csproj expose helper cho test (S22) `PurchaseEvaluationDraftGuard` static helper internal — expose qua `` trong `SolutionErp.Application.csproj` thay vì rewrite public API. Tránh API surface bloat. Reusable cho future guard / helper internal cần test. ### Pattern 16-bis: 4-place mirror checklist khi cookie-cutter copy page CROSS-APP (S29 Plan CA Hotfix 1 — gotcha #50, reinforced 5× cumulative qua S33+S34) Khi spec yêu cầu "move page X từ fe-admin → fe-user" hoặc ngược lại (Implementer Case 2 cookie-cutter mirror page), MUST mirror 4 places (NOT just 3): 1. ✅ **Page file** (`pages//*.tsx`) — copy nguyên content, verify import path `@/...` resolves 2. ✅ **`App.tsx` Routes** — add `` 3. ✅ **`lib/menuKeys.ts` constants** — mirror BE `MenuKeys.cs` thêm key mới 4. ⚠️ **`components/Layout.tsx` `resolvePath` staticMap** — KEY mapping → route path. **DỄ MISS** vì khác file scope với pages directory. **Bug latency observed:** Plan CA Hotfix 1 commit `06a441c` (Implementer Case 2 move 4 master pages) MISSED point 4 → silent sidebar drop 3 leaf Suppliers/Projects/Departments. Bro UAT catch screenshot post-deploy. Em main solo fix Hotfix 1 commit `e55d96b` +12 LOC. Lesson: REFUSE criteria #4 "bug fix involving reasoning chain" KHÔNG apply ở đây vì cookie-cutter mirror miss 1/4 places là routine. Phòng tránh: task prompt MUST list 4 places explicit. **Verification post-fix:** Reviewer Cat 1 "Wire claim verify" SHOULD add to checklist: "Sidebar menu visible end-to-end test post-build" — curl `/api/menus/me` + grep MenuLeaf render output. Smart Friend prevent silent drop. **S34 G-O1 Task 3 reinforcement (2026-05-27, Plan B Internal Directory):** Pattern 16-bis applied clean lần thứ 5 cumulative. Mirror 4 places × 2 app (8 modification + 4 new file) cho `Off_DanhBa → /directory`: - 4 new file: `types/directory.ts` × 2 (SHA256 `7349d9f64e78`) + `pages/office/InternalDirectoryPage.tsx` × 2 (SHA256 `2aa7e0eed2c8`) — both MATCH identical hash - 6 modified: App.tsx × 2 (+route), menuKeys.ts × 2 (+Off/OffDanhBa const), Layout.tsx × 2 (+staticMap Off_DanhBa) - npm build × 2 app: fe-admin 21.99s clean (bundle 1436.71 kB / gzip 364.54 kB), fe-user 9.37s clean (bundle 1350.28 kB / gzip 349.01 kB) — 0 TS error - Token cost ~20k (under budget 25k). Card grid + avatar gradient palette inline helpers (Pattern 14 reuse) — không tách component riêng vì single-use scope. - LESSON pattern repeat trust: S33 Task 5 spec "Task 5 cookie-cutter mirror EmployeesListPage" used 4-place checklist explicit. S34 G-O1 Task 3 spec follow same template → execute 0 ambiguity. Pattern 16-bis xứng đáng "BLESSED Foundation" cho future cookie-cutter cross-app mirror. ### Pattern 12-ter: 5× satellite CRUD scaffold cookie-cutter same parent (S34 G-H1 Phase 1.5 Item 3) Khi spec yêu cầu "5 satellite entity CRUD same parent" (vd Employee → WorkHistory/Education/FamilyRelation/Skill/Document): - **1 file Application layer** `SatelliteFeatures.cs` chứa 5 region cookie-cutter Create/Update/Delete cho mỗi satellite (~600 LOC) - **1 file Controller** extend với 15 endpoint (3 verb × 5 satellite) - **Pattern per region:** - `Create{X}Command(EmployeeProfileId, ...)` → `IRequest` + Validator + Handler (verify parent exists trước → `AnyAsync` parent + throw NotFoundException → save → return Id) - `Update{X}Command(Id, ...)` → `IRequest` + Validator + Handler (FirstOrDefaultAsync `!IsDeleted` + throw NotFoundException + assign + save) - `Delete{X}Command(Id)` → `IRequest` + Handler (soft delete IsDeleted=true + DeletedAt + DeletedBy từ ICurrentUser + save) - **Controller endpoints:** - `POST /{parentId:guid}/{satellite}` — verify `parentId == cmd.EmployeeProfileId` (BadRequest "ID không khớp" mismatch) → return `{ id: newId }` - `PUT /{parentId:guid}/{satellite}/{satId:guid}` — verify `satId == cmd.Id` → NoContent - `DELETE /{parentId:guid}/{satellite}/{satId:guid}` — direct `DeleteCommand(satId)` → NoContent - **Per-action policy override class-level Read** (`Hrm_HoSo.Create/Update/Delete`) - **Verify parent exists pattern**: `AnyAsync(x => x.Id == ... && !x.IsDeleted, ct)` — không cần Include nav - **Soft delete pattern**: AuditableEntity `IsDeleted` + `DeletedAt = DateTime.UtcNow` + `DeletedBy = currentUser.UserId` (inject ICurrentUser) Bài học S34 Plan 3 Phase 1.5 Item 3: 2 file modification (1 new ~621 LOC + 1 extend +160 LOC) — build clean 0 error 2 warn (pre-existing DocxRenderer), 130/130 test PASS, endpoint count 5→20. Reusable cho future bất kỳ parent entity có N satellite cookie-cutter (Project → milestones/risks/deliverables, Department → roles/budgets/headcounts...). Polymorphic discriminator field (vd EmployeeSkill.Kind) treat as regular required field — không cần special handling. ### Pattern 12-bis: Cross-module entity cookie-cutter mirror (S29 Plan B Chunk C — Mig 33) Khi spec yêu cầu "mirror entity X từ PE module sang Contract module" (vd LevelOpinions / DepartmentApproval / ManualBudgetFields): - **Sub-task 6 file MAX** — không hơn vì entity cookie-cutter rất narrow: 1. New entity class `Domain//.cs` (rename FK field + nav) 2. Modify parent entity: add `List Children` nav collection 3. Modify `IApplicationDbContext`: add `DbSet Xs { get; }` 4. Modify `ApplicationDbContext`: add `public DbSet Xs => Set();` 5. New `Configuration.cs` (separate file, mirror PE pattern — NOT inline ContractConfiguration multi-class) 6. `dotnet ef migrations add ` → 3 file scaffold (mig + Designer + Snapshot updated) - **AuditableEntity inherit** match PE pattern (13 column scaffold = 4 BaseEntity + 6 Audit + 4 own field) - **FK pattern mirror PE EXACT:** - Parent FK Cascade (xoá HĐ/PE → wipe children) - 3rd-party FK Restrict (admin xoá Level/Dept chặn nếu còn child reference) - User FK skip nav (denorm `ByFullName` để tránh cascade xoá user) - **Mig scaffold verify:** column structure + 2 FK + 2 index (UNIQUE composite + supporting non-unique) khớp 100% PE counterpart - **Apply 2 DB:** Dev (`SolutionErp_Dev` explicit connection) + Design (default factory) per `feedback_designtime_runtime_db` - **Test baseline preserve:** 111 PASS no regression (Mig table-add KHÔNG đụng existing entity) Token cost ~15k tokens (Mig add + Mig file Read verify + Apply 2 DB + Build + Test). Bài học S29 Plan B Chunk C commit `26c98d3`: 8 file +4265 LOC (Mig Designer.cs ~4033 LOC autogen chiếm 95%), implementer code ~232 LOC handcraft only. Em main spec deterministic 100% — 0 spec ambiguity → ACCEPT clean. Pattern reusable cho future Contract↔PE mirror: ContractDepartmentOpinions, ContractCodeSequences-like sub-table, hoặc bất kỳ sub-entity cần 1:1 mirror PE module sang Contract module. ### Pattern 13: Read-only admin Designer mirror page (S24 Plan AA Chunk B) Khi spec yêu cầu "user xem read-only data admin đã config" (vd workflow matrix ghim, permission summary, dept tree readonly): - **Drop edit mutations** — useMutation / PATCH / POST / DELETE KHÔNG cần - **Reuse DTO types subset** — copy `AwAdminOverviewDto` từ admin sang user types/ (KHÔNG re-export, KHÔNG share package — duplicate có chủ đích §3.9) - **Filter via query param BE-side** — `?isUserSelectable=true` thay vì FE filter client (network payload nhẹ hơn + security tự nhiên) - **Implementer Case 2 single file ~180-215 LOC** ACCEPT đúng scope (page mới + types mới + route 3-line App.tsx) - **Verify shadcn library availability trước** — fe-user thường thiếu Card/Badge (chỉ có Button/Dialog/Input/Label/Select/Textarea). Fallback inline `
` mirror admin Designer DefinitionCard Bài học S24 Plan AA Chunk B: 3 file ~305 LOC, useQuery readonly, no mutation, ACCEPTED ~14k tokens. Pattern reusable cho future user-side read-only page (vd permission summary, dept hierarchy view). ### Pattern 14: Tailwind JIT palette array (S24 Plan AA) Tailwind v3 JIT KHÔNG resolve dynamic class interpolation (`bg-${color}-50` → purge xoá khi production build). Solution: PALETTE array với full class strings literal. ```ts const PALETTE = [ { bg: 'bg-blue-50/40', border: 'border-blue-200', text: 'text-blue-900', accent: 'bg-blue-100' }, { bg: 'bg-emerald-50/40', border: 'border-emerald-200', text: 'text-emerald-900', accent: 'bg-emerald-100' }, { bg: 'bg-amber-50/40', border: 'border-amber-200', text: 'text-amber-900', accent: 'bg-amber-100' }, // ... 6-8 colors total ] as const // Apply cycle qua index: const colorClasses = PALETTE[index % PALETTE.length]
...
``` Lý do array (vs object): cycle natural qua `index % length` cho dynamic NV/Step/Cap count. Lý do `as const`: TypeScript narrow literal type tránh `string`. Bài học S24 Plan AA redesign v1 (commit 4d60598): panel-per-NV color theo NV index — 6 NV cycle 6 màu blue/emerald/amber/violet/rose/cyan. ### Pattern 15: HTML table rowSpan iteration helper (S24 Plan AA redesign v2) Khi render table với nested rowSpan (vd Bước rowSpan N cấp × Cấp rowSpan M NV), nested loop + conditional cells gây nhầm key + hard maintain. Solution: flat row builder helper với metadata flags. ```ts type FlatRow = { stepIndex: number capIndex: number nvIndex: number isFirstInStep: boolean // render Bước cell rowSpanStep: number // cap count × nv count isFirstInCap: boolean // render Cấp cell rowSpanCap: number // nv count // ... level data } function buildFlatRows(definition: AwDefinitionDto): FlatRow[] { const rows: FlatRow[] = [] definition.steps.forEach((step, si) => { const stepNvCount = step.levels.reduce((sum, lv) => sum + lv.users.length, 0) step.levels.forEach((cap, ci) => { cap.users.forEach((nv, ni) => { rows.push({ stepIndex: si, capIndex: ci, nvIndex: ni, isFirstInStep: ci === 0 && ni === 0, rowSpanStep: stepNvCount, isFirstInCap: ni === 0, rowSpanCap: cap.users.length, // ... }) }) }) }) return rows } // Render flat: {rows.map(row => ( {row.isFirstInStep && {step.name}} {row.isFirstInCap && {cap.name}} {nv.fullName} {/* 7 flag cells */} ))} ``` Cleaner than nested `forEach` + render-time `if (ni === 0) `. Easier debug (console.log rows array thấy structure rõ). Bài học S24 Plan AA redesign v2 (commit fbbd361): table 3 cột meta (Bước/Cấp/NV) + 7 cột flag với rowSpan natural. --- ## ⚠️ Anti-patterns observed (DO NOT) 1. ❌ Skip MEMORY.md update — knowledge tài sản 2. ❌ Bypass pre-commit hooks `--no-verify` (forbidden absolute) 3. ❌ `git add -A` hoặc `git add .` — specific files only 4. ❌ Touch files outside spec scope — anti-fiddle rule 5. ❌ Push remote autonomously cho heavy change — em main pushes (UAT iteration: confirm với em trước push) 6. ❌ Modify `SolutionErp.slnx` autonomously — em main updates khi thêm `.cs/.csproj` 7. ❌ Lower bar to match em main quality — Smart Friend Cognition anti-pattern 8. ❌ Proceed when spec ambiguous > 20% — return REFUSE với reason --- ## 🧠 SOLUTION_ERP conventions (auto-load via skills) - **BE .NET 10:** PascalCase tiếng Anh entities + DTO records + command names. CQRS + MediatR + FluentValidation + AutoMapper. Repository qua `IApplicationDbContext`. `GlobalExceptionMiddleware` map exception → ProblemDetails (NO try-catch trong controllers). - **FE React 19 + Vite 8 + TS 6:** Named export only (trừ App). TanStack Query. shadcn/ui copy-paste. TS6 `erasableSyntaxOnly` cấm `enum` → const-object pattern. UI 100% tiếng Việt. Mirror 2 app rule §3.9. - **Test:** baseline 104/104 PASS (58 Domain + 46 Infra: 23 baseline + 3 PE WF guard regression S21 t3 gotcha #45 + 20 mới S22 — gồm PE WF ReturnMode + Draft guard + Reflection-based Authorize policy). Phase 9 UAT skip per chunk theo memory `feedback_uat_skip_verify`. Stack xUnit + FluentAssertions 7.2 + EF SQLite 10 `TestApplicationDbContext` override `nvarchar(max) → TEXT`. - **Build:** `dotnet build SolutionErp.slnx` clean 0 err + `npm run build` × 2 app pass. - **Commit:** `[CLAUDE] : ` + Co-Authored-By Claude Opus 4.7 (1M context). ## Scopes (pick 1) `Contract` · `PurchaseEvaluation` · `Budget` · `Form` · `Workflow` · `Supplier` · `Auth` · `Admin` · `Api` · `App` · `Domain` · `Infra` · `FE-Admin` · `FE-User` · `Tests` · `Docs` · `CICD` · `Scripts` · `Skill` --- ## 🔑 Pin versions (package pinning §2.8) KHÔNG `*` / `latest`. Critical pins: - MediatR `12.4.1` (14 fail DI) - Swashbuckle `6.9.0` (10 conflict OpenApi 2) - Node engines `>= 20` + CI pin `20.x` (bài học NamGroup, memory `feedback_node_cicd`) - LibreOffice `25.8.6` - @microsoft/signalr `8.0.7` --- ## 📅 Recent activity (last 10 FIFO) - **2026-05-26 (S33 Plan B G-H1 Task 5 — Phase 10.1 FE 2 app HRM scaffold Case 2 cookie-cutter cross-app mirror):** Em main spec deterministic 100% ULTRA-MINIMAL scope (Phase 1 read-only, no separate DetailTabs component, inline 6-section `
` collapsible, no satellite CRUD). Implementer Case 2 cross-app mirror 4-place ACCEPT clean. Tổng 14 file (3 NEW page × 2 app SHA256 IDENTICAL + 4 modified file: menuKeys+Layout+App × 2). **3 NEW file SHA256 verified IDENTICAL:** `types/employee.ts` CCFC70666568 + `pages/hrm/EmployeesListPage.tsx` DC859C897C5C + `pages/hrm/EmployeeCreatePage.tsx` C796F25D01AC. Pattern 16-bis 4-place mirror cross-app reinforced **4th time cumulative** (S29 Plan CA HF1 + S29 Plan B Chunk D + S33 Task 5). Pattern 12-bis cross-module FE port PE → Hrm reinforced **4th time** (Plan B Chunk C Mig 33 + Plan B G-H1 Task 4 BE + Task 5 FE). **Verify all clean:** fe-admin build PASS (21.4s 0 TS err 1429KB bundle warn expected), fe-user build PASS (9.2s 0 TS err 1345KB bundle warn expected), dotnet build PASS (1.59s 0 warn 0 err), dotnet test PASS **120/120 baseline preserve** (58 Domain + 62 Infra). **Ambiguities encountered:** 0 — spec deterministic 100%. **Files touched:** fe-admin/src/types/employee.ts (NEW, ~283 LOC), fe-admin/src/pages/hrm/EmployeesListPage.tsx (NEW, ~417 LOC), fe-admin/src/pages/hrm/EmployeeCreatePage.tsx (NEW, ~178 LOC), fe-admin/src/lib/menuKeys.ts (+3 LOC Hrm+HrmHoSo), fe-admin/src/components/Layout.tsx (+4 LOC staticMap Hrm_HoSo), fe-admin/src/App.tsx (+5 LOC imports+routes), 6 fe-user files mirror identical (3 SHA256 + 3 edit mirror Hrm_HoSo). **Out-of-scope respected:** KHÔNG satellite CRUD form, KHÔNG inline edit Header, KHÔNG PermissionGuard wire (em main Task 6 Hrm_HoSo policy registration). KHÔNG add Bg_*/Catalog* to fe-admin menuKeys.ts (em main defer optional). **Token cost estimate:** ~25k tokens (Read 8 reference + Write 3 file + Edit 6 + 3 Bash verify). KHÔNG commit (em main commits). Tag: `[mirror-page, phase-10.1, frontend]`. - **2026-05-26 (S32 wrap — em main proxy curate + Plan G 11 module future scope):** Session 32 đóng clean. Em chủ trì spawn em 1 lần S32 startup verify (ab23cc322b5d495c0 alive, MEMORY size FLAG 36.2KB > 25KB). **Em main proxy curate Plan A3:** archived 5 verbose entries q2 (S25 Plan AB Chunk A + S25 wrap + S26 t1 Plan AG + S27 Plan CA Chunk B + S29 Plan B Chunk D detail) → 36.2→27.5KB. Patterns 1-19 + 12-bis + 16-bis foundation **preserved untouched**. **Plan G 11 module backlog DOCUMENTED migration-todos** với 10 Plan G-* atomic sprint. **Pending tasks em main S33 spawn em Case 2 cookie-cutter mirror:** (a) **Plan G-H1 Hồ sơ NS scaffold** — BE 6 entity (EmployeeProfile main + 5 satellite WorkHistory/Education/FamilyRelation/Skill/Document) + EF Config + DbInitializer seed 30 demo profile mirror 30 users + CQRS Create/Update/GetDetail/List + 6 endpoint controller + FE 2 app types/employee.ts + EmployeesPage 3-panel + EmployeeDetailTabs (6 section); (b) **Plan B-Wrap test bundle BW1-BW7 codegen** — Case 2 cookie-cutter mirror PE WorkflowService test pattern (PurchaseEvaluationWorkflowServiceReturnModeTests.cs structure) cho ContractWorkflowServiceApproveV2Tests.cs (7 test scenario spec deterministic migration-todos D-Bis); (c) **Plan G-O2 Phòng họp BookingCalendar** — Case 2 FE 2 app FullCalendar lib new dep; (d) **Plan G-O3..G-O6 Workflow Apps** — cookie-cutter mirror PE Mig 22-26 Plan B pattern 12-bis cross-module entity scaffold cho 4 module (Proposal/LeaveRequest/OtRequest/VehicleBooking/ItTicket). **REFUSE forward:** S33+ start Phase 10.1 G-H1 entity scaffold đúng spec deterministic, KHÔNG schema design (em main solo Mig 34 design). Token cost wrap ~5K. Tag: `[wrap, phase-9-to-phase-10, frontend+backend]`. - **2026-05-26 (S32 startup — context verify + RAG live confirm + size FLAG > 25KB):** Em chủ trì spawn em verify Session 32 context. **Verify done:** (1) MEMORY size 36.2KB (Get-Item Length=36207 bytes) — **OVER 25KB threshold ~45% bigger** → FLAG cho em main schedule dedicated curate session per Pattern curate trigger rule line 364. KHÔNG self-curate vì em chủ trì preference reserve cho em main solo judgment call §6.5 KEEP vs CUT (S27 retrospective C1-C4 task lesson). (2) Patterns saved 1-12 foundation + 12-bis NEW S29 + 13-15 + 16-bis NEW S29 + 17-19 — total **17 numbered patterns** (Pattern 16 baseline implied trong recent activity S27 chưa numbered explicit). Pattern 12-bis (cross-module entity cookie-cutter mirror PE→Contract Mig 33) **SAVED line 178-200** confirmed present. Pattern 16-bis (4-place mirror cross-app S29 Plan CA Hotfix 1) **SAVED line 165-176** confirmed present. (3) MCP RAG tools **PRESENT** — `mcp__rag-unified__search_memory` + `mcp__rag-unified__cross_project_search` both visible trong tools list. Test query "Pattern 12-bis cross-module entity cookie-cutter mirror PE Contract V2" top_k=3 returned 3 results với rerank scores **0.824/0.801/0.793** — all healthy > 0.7 threshold. S31 RAG v1.3 baseline PASS confirmed live post CLI restart. **Pending tasks em main có thể gọi em lại spawn S32+:** (a) Plan B-Wrap BW1-BW7 test bundle codegen Case 2 cookie-cutter mirror PE WorkflowService test pattern (regression ApproveV2Async + UPSERT LevelOpinions test) — 7 file new test class mirror PE test bundle structure; (b) ContractWorkflowMatrixView mirror PE WorkflowMatrixView Plan AA S24 (1 page mirror cross-module — Case 2 fits Pattern 13 read-only admin Designer mirror + Pattern 14 Tailwind JIT palette + Pattern 15 HTML table rowSpan iteration helper). **Decision tree forward:** Em chủ trì gọi em với task code edit → em ACCEPT case (a)/(b) khi spec deterministic, REFUSE nếu first-time pattern. Em chủ trì confirm Layer A governance still active scope SOLUTION_ERP. Token cost spawn này ~5k (3 Read + 1 RAG query + 1 Edit + final report). KHÔNG curate — defer em main full curate session. Tag: `[verify, phase-9, infra]`. - **S34 G-H1 Phase 1.5 Test Bundle (2026-05-27, ACCEPT Case 3 test generation):** 3 test class mới ~310 LOC, baseline 120 → **130 PASS** (+10 [Fact] = 3 codeGen + 4 Create handler + 3 List query). 0 regression cũ. Duration 16s Infra (added 1s codeGen + 2s Create + 17s List heavy seed via IdentityFixture). - **EmployeeCodeGeneratorTests** (3 [Fact]): mirror PE codeGen pattern, format `NV/{YYYY}/{Seq:D4}` 4-digit pad, year boundary reset preserves prior-year row. - **CreateEmployeeProfileCommandTests** (4 [Fact]): IdentityFixture + direct `handler.Handle()`. Mirror BW5 ConflictException + NotFoundException. **SPEC MISMATCH discovered Fact 3:** Spec say "AfterSoftDelete allows new profile" BUT code (EmployeeFeatures.cs:158-163) check existing KHÔNG filter `!IsDeleted` → soft-deleted vẫn block, throw discriminator message khác ("đã xoá mềm. Cần khôi phục thay vì tạo mới." vs active "mỗi user chỉ được 1 hồ sơ"). Test theo CODE (single source truth), document mismatch trong header comment + final report cho em main review. - **ListEmployeesQueryTests** (3 [Fact]): filter Status + DepartmentId + Search. Search `"0001"` (not `"000"`) cho unique match avoid `Contains("000")` ambiguity bắt cả `0010`. - Token cost ~30k (slightly over 25k budget — heavy reference reading 4 fixture files first spawn). - Pattern 11 (test infra helper cookie-cutter) reinforced. Pattern 12 (InternalsVisibleTo) KHÔNG cần — public CQRS Command/Handler. - LESSON: Spec drift detection BEFORE writing test = saved bug. Em main spec write Fact 3 từ memory generic "soft-delete UNIQUE compat" — code thực tế chặn opt-out. KIỂU drift điển hình khi spec viết offline trước khi handler implement chốt. - **Archived to `archive/2026-05-q3.md` 2026-05-27 S34 curate (em main proxy):** S29 wrap (5-spawn Plan CA + Plan B 4 chunks + E3 stopped + Pattern 12-bis NEW) + S28 wrap (Layer A governance perspective Implementer) + S27 wrap retrospective REFUSE analysis (8 task ACCEPT/REFUSE table + Pattern 20 5 PS scripts mirror) + 2026-05-22 curate session note + 2026-05-11 setup baseline. KEY takeaways absorbed in current entries S33+S32 + Patterns 1-15+12-bis+16-bis foundation section line 26-283. - **5 verbose entries S25-S29 archived to `archive/2026-05-q2.md` 2026-05-26 S32 curate:** S29 Plan B Chunk D detail + S27 Plan CA Chunk B detail + S26 t1 Plan AG Phase 1 detail + S25 wrap + S25 Plan AB Chunk A. KEY takeaways preserved trong S33+S32 wrap entries. Patterns 16-19 NEW S25-S26 reference foundation section line 165-283. --- ## 🔄 Curate trigger - Memory size > 25KB → archive recent entries to `archive/.md` - Duplicate entries detected → merge - Stale > 3 months → remove **Last curate: 2026-05-27 S34 em main proxy curate** (post-S33 wrap, sequence 1/4) — archived 5 verbose entries (S29 wrap + S28 wrap + S27 wrap REFUSE analysis + S22 curate session note + S11 setup) → `archive/2026-05-q3.md`. KEEP: S33 Task 5 (latest cookie-cutter cross-app mirror Plan B G-H1), S32 wrap (Plan G 11 module backlog), S32 startup (size FLAG + RAG verify). Patterns 1-15 + 12-bis + 16-bis foundation section line 26-283 preserved untouched. MEMORY size before: 30.5 KB → after: target ~18-20 KB. Per `feedback_md_compact_narrative.md` §6.5 — archive preserves full verbose entries cho cross-session audit retrieve. **Previous curate: 2026-05-26 S32** — 5 verbose S25-S29 → `archive/2026-05-q2.md`. **Previous curate: 2026-05-22** — 12 verbose S21 t3 → S24 Plan AA → `archive/2026-05-q1.md`. Next trigger: > 25KB OR Plan G-O1 Danh bạ kick off.