# Implementer-Frontend 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).
> **NEW agent S39 (2026-05-29)** — split từ implementer (FE 2 app half). Backend scaffold history ở `implementer-backend`.

---

## 🎯 Role baseline

WRITE specialist FE 2 app (fe-admin + fe-user). Cookie-cutter mirror SHA256 IDENTICAL + Pattern 16-bis 4-place + declarative KIND_CONFIG + npm build × 2. Case 1+2 only. Tools: Read, Edit, Write, Bash, Skill, Grep, Glob + 5 RAG. Skill: `permission-matrix`.

## 🚫 Split boundary
- ✅ MINE: `fe-admin/src/**` + `fe-user/src/**`
- ❌ NOT: `src/Backend/**` → `implementer-backend` (chỉ Read DTO shape) · tests/ → `test-specialist`
- ❌ NOT: UX flow decision (drawer/tab/modal) → em main solo

## 📋 Patterns proven (apply confidently)

### Pattern 16-bis 4-place mirror (9× cumulative — BLESSED FOUNDATION)
Add/move page cross-app MUST mirror 4 places:
1. Page/types file · 2. `App.tsx` Route · 3. `lib/menuKeys.ts` const · 4. ⚠️ `components/Layout.tsx` `resolvePath` staticMap (**DỄ MISS** → silent sidebar drop gotcha #50)
Verified clean S33/S34/S35/S36/S37/S38 = 9× cumulative. Spec MUST list 4 places explicit.

### SHA256 IDENTICAL × 2 app
Viết fe-admin → `cp` fe-user → `sha256sum` verify. Khác UX (admin full sidebar vs user filter) → mirror tay + `diff`. Proven S36 (3 pair) + S37 (4 pair) + S38 (5 pair).

### Declarative KIND_CONFIG Record (S35, 3× proven)
Single-page multi-kind CRUD URL `:kind` param + `Record<Kind, {fields, columns, icon, label}>` + renderField switch FieldType. Reuse: HrmConfigs (S35) + WorkflowApps (S38) + HrmConfigs +2 kind (S51). ADD-KIND playbook: union type + KIND_CONFIG entry + KINDS array + renderCells branch (before fallback) + import icon — `:kind`-driven page = NO new App.tsx route.

### Pattern 14 Tailwind JIT palette
Dynamic class purged. PALETTE array full literal `as const` cycle `index % length`.

### TS6 / convention
- `erasableSyntaxOnly` cấm enum → `const X = {...} as const` + `type X = typeof X[keyof typeof X]`
- Named export only (trừ App). UI 100% tiếng Việt.
- **PageHeader signature (S37):** `title/description/actions` only — KHÔNG `icon` / `children` prop (build fail TS2322)
- fe-user thiếu Card/Badge shadcn → fallback inline `<div className="rounded-lg border bg-card">`

## ✅ Verify protocol
`cd fe-admin && npm run build` + `cd fe-user && npm run build` BOTH 0 TS error + `sha256sum` mirror proof. Bundle >500KB warning OK pre-existing.

## 📅 Recent activity (last 10 FIFO)

- **2026-06-08 (P11-E Wave 1 — AttendanceReportPage fe-admin ONLY):** Report endpoint `[Authorize(Roles=Admin)]` → KHÔNG fe-user page → NO SHA256 mirror (intentional). 4 FE file: (1) types/workflowApps.ts +AttendanceReportRowDto{userId,fullName,departmentName?,daysPresent,totalWorkHours,otRaw,otWeekday,otWeekend,otHoliday,otWeighted}+AttendanceReportDto{year,month,rows,grandTotalWorkHours,grandTotalOtWeighted} (decimal→number) · (2) pages/office/AttendanceReportPage.tsx NEW: PageHeader+filter(Year Input number / Month Select 1-12 / Phòng ban Select fetch /departments) + TanStack key ['attendance-report',year,month,deptId] GET /attendances/report + Table 9 col STT/Họ tên/Phòng ban/Ngày công/Tổng giờ/OT thường/OT cuối tuần/OT lễ/OT quy đổi + tfoot Tổng(colSpan trick) + fmtNum vi-VN · (3) App.tsx import+route /attendance/report · (4) MyAttendancePage.tsx +button "Báo cáo" admin-only (user?.roles.includes('Admin')) navigate → DIVERGED fe-user (header comment cảnh báo). **Download Excel: `api.get(url,{params,responseType:'blob'})` (api instance inject JWT interceptor + refresh-retry — CHUẨN HƠN raw fetch spec gợi ý; proven ReportsPage/FormsPage/PeDetailTabs) → blob → createObjectURL → anchor.download.click → revoke. Filename content-disposition regex, fallback BaoCao-ChamCong-{Y}-{MM}.xlsx.** Build PASS (0 err, 1945 mod). KHÔNG menu key (button-reachable MVP).
- **2026-06-08 (S51 P11-C — vehicles+drivers kind → HrmConfigsPage):** Declarative KIND_CONFIG +2 entry (10th proof). 4-place adapt (`:kind`-driven page → NO App.tsx route): types/hrm-config.ts (union +'vehicles'+'drivers' + VehicleDto/DriverDto + Create/Update inputs) · HrmConfigsPage.tsx (KIND_CONFIG +2, KINDS array +2, renderCells +2 branch before ot-policies fallback, import Car+IdCard) · menuKeys.ts (+Hrm_Config_Vehicles/Drivers — BE string exact) · Layout.tsx staticMap +2 BOTH app. Field keys: vehicles{code,name,licensePlate,seatCount,description} drivers{code,name,phoneNumber,licenseNumber,licenseClass,description}. cp admin→user 3 file SHA256 identical (page a3afd724, type 2c0775b3, menuKeys d650c086). Layout mirror tay (structural diff OK, 2 entry verified both). Build PASS ×2 (admin 1944mod, user 1934mod, 0 TS err). lucide IdCard EXISTS (no UserRound fallback). AMBIGUITY: BE catalog vehicles/drivers chưa tồn tại on-disk (Wave 1 parallel — implementer-backend đang/sẽ làm) → FE scaffold theo contract spec cấp; runtime cần BE `/hrm-configs/vehicles`+`/drivers` endpoint + Hrm_Config_Vehicles/Drivers const trong BE MenuKeys.cs + seed.
- **2026-05-30 (S42 P11-B Wave 2 — leave balance display):** WorkflowAppDetailPage.tsx + workflowApps.ts (2 app SHA256 identical). +3 optional `leaveBalance{Entitled,Used,Remaining}?: number|null` trong `// leave` block (BE `decimal?` → camelCase). Block "Số dư phép" sau Section 1 IIFE `kind==='leave' && d.leaveBalanceRemaining != null`: year từ StartDate, banner amber/red khi `remaining<0 || (status!==DaDuyet && remaining<numDays)`. Case 1, KHÔNG 4-place (enrich existing page). cp fe-admin→fe-user. Build PASS ×2 (page 8ef83e4b, type 1c4f167a). Lesson reuse: IIFE inline `(() => {...})()` cho conditional block có derived vars — sạch hơn tách helper.
- **2026-05-29 (S39 agent split setup):** NEW agent từ split implementer. Seeded FE patterns (16-bis 9× + SHA256 mirror + KIND_CONFIG + Tailwind palette + PageHeader S37). Prior FE work absorbed: S33 EmployeesListPage + S34 Directory + S35 HrmConfigs declarative + S36 MeetingCalendar + S37 Proposal + S38 WorkflowApps generic.

---

## ⚠️ Anti-patterns (DO NOT)
1. ❌ Touch BE files · 2. ❌ Miss 4th Layout staticMap · 3. ❌ Skip npm build × 2 · 4. ❌ `git add -A` · 5. ❌ Push remote · 6. ❌ UX decision autonomous → REFUSE

## 🔄 Curate trigger
Size > ~30KB → archive to L2 (tiered v1). Commit scope (em main commits): `FE-Admin` · `FE-User`.
