# Reviewer Agent — Gist 2026-06 (S51→S57, moved from L1 @S69 curate) > **distill-gen: 1** (đã nén — KHÔNG nén lại bản này). > 4-field/record: **VIỆC · KẾT-LUẬN(+file:line/commit) · BÀI-HỌC · BẤT-NGỜ**. Mỗi dòng kết bằng back-resolve `substring:"..."` về verbatim. Nhãn cao/vừa/thấp. > Verbatim: `2026-06.md` (entry-bullets, chronological earliest-first). Mục lục: `_INDEX.md`. **Archive FROZEN.** > 9 record = các entry vừa dời từ MEMORY.md L1 lúc S69 curate (giữ verdict + file:line + bài-học). --- - [cao] VIỆC: S51 P11-C Vehicle+Driver catalog (Mig 44/45 + FE KIND_CONFIG +2 + 5 test) — **spawn, em-main proxy (reviewer return truncated gotcha #53)**. KẾT-LUẬN: **PASS post-fix, 1 MAJOR caught** = Driver FE↔BE required-field mismatch (FE render phoneNumber/licenseNumber/licenseClass OPTIONAL nhưng BE validator `NotEmpty()`+EF `.IsRequired()` → empty submit 400/500); fix FE +`required:true` align Vehicle. Mig 45 = filter 3 HRM unique (gotcha #57). BÀI-HỌC: **parallel fan-out BE∥FE file-disjoint → inconsistency trong SHARED em-main contract chỉ lộ lúc integration; green tests ≠ correct contract (no test chạm empty-optional path); reviewer = the net**. BẤT-NGỜ: transient mid-deploy bundle hash + reviewer self-truncate trước ghi MEMORY → em-main proxy. substring:"S51 P11-C Vehicle+Driver + gotcha #57" → 2026-06.md - [cao] VIỆC: S52 P11-E AttendanceReport + P11-F MaTicket codegen pre-commit (migration-free) — spawn. KẾT-LUẬN: PASS 0-blocker, 191 PASS — **gotcha #44 attack DISARMED: `[Authorize(Roles="Admin")]` ×2 report endpoints, verify `AppRoles.Admin="Admin"` LITERAL (AppRoles.cs:5) == attribute == FE includes('Admin'); "QTV" (DbInit:1454) = display-code DECOY**; camelCase contract field-for-field; handler `.Year/.Month` IQueryable-translatable, holiday-check in-memory AFTER ToListAsync. MaTicket codegen-on-Create (kanban no-workflow). BÀI-HỌC: **khi spec NAMES attack vector (gotcha #44 role-string), verify LITERAL const value không chỉ attribute-presence**. BẤT-NGỜ: Bash tool = bash không phải PowerShell (Select-String exit 127 → dùng grep). substring:"S52 P11-E AttendanceReport + P11-F MaTicket" → 2026-06.md - [cao] VIỆC: S52-late Task C ItTicket admin-reassign + Task D AttendanceReport menu-key pre-commit (migration-free, 5 prod file) — spawn. KẾT-LUẬN: PASS 0-blocker — **menu-key `"Off_AttendanceReport"` byte-identical 4 chỗ (MenuKeys.cs:125 == menuKeys.ts:68 == seed parent == Layout staticMap:87)**; FE PUT `/it-tickets/{id}/assign` body MATCH BE record; admin auto-perm via SeedAdminPermissions iterate MenuKeys.All. BÀI-HỌC: **menu-key wiring = verify byte-identity FULL mirror set (BE const + All[] + seed parent + FE menuKeys + staticMap) + confirm target route THỰC SỰ tồn tại (grep App.tsx) — staticMap→non-existent route silently drops leaf (gotcha #50)**. BẤT-NGỜ: lucide `FileBarChart` = deprecated-alias re-export FileChartColumn nhưng vẫn valid (d.ts grep confirm trước flag). substring:"S52-late Task C ItTicket admin reassign" → 2026-06.md - [cao] VIỆC: S53 Mig 47 Master catalog (Department/Project/Supplier) Code filtered-unique `+.HasFilter("[IsDeleted] = 0")` (4th/5th/6th cumulative gotcha #57 EXT) + 3 test — spawn. KẾT-LUẬN: PASS 0-blocker, **203 PASS** — **filter string byte-identical HolidayConfiguration:18 (xxd `5b 49 73 ... 30`, spaces quanh `=`); index STAYS unique:true (filter NARROW scope KHÔNG drop uniqueness)**; test seeds IsDeleted=true row → real handler `AnyAsync(Code)` thru HasQueryFilter → NotThrow (RED-before SqliteException confirmed). BÀI-HỌC: **cookie-cutter EXT = byte-compare filter string (xxd) vs canonical sibling + verify index still unique; app-level dup-check = test premise, verify handler có `AnyAsync(Code)` else premise false**. BẤT-NGỜ: implementer claim "2 pre-existing DocxRenderer warn" nhưng clean incremental rebuild = 0 warn. substring:"S53 gotcha #57 EXT Mig 47" → 2026-06.md - [cao] VIỆC: S54 ItTicket reassign authz Admin-OR-dept-IT cross-stack — controller `[Authorize(Roles="Admin")]`→`[Authorize]` any-auth, authz moved INTO `AssignItTicketHandler` + new capability query — spawn. KẾT-LUẬN: PASS 0-blocker, 216 PASS — **role-string "Admin" chain traced FULL: `AppRoles.Admin="Admin"`(AppRoles.cs:5)→SeedRoles `Name=roleName`(DbInit:1485)→GetRolesAsync returns NAMES→JwtTokenService:32 `Claim(ClaimTypes.Role)`→CurrentUserService:30-31 `Roles.Contains("Admin")`; "QTV"(DbInit:1458 RoleLabels)=ShortName DECOY; Program.cs no RoleClaimType override**; guard fail-CLOSED khi itDeptId null; capability 0-leak `{canReassign:false,staff:[]}`. BÀI-HỌC: **authz role-string review = trace const→seed Name→GetRolesAsync(names not codes)→Claim→reader AND grep JWT cfg `RoleClaimType` override (none=symmetric); display-code (QTV) = classic decoy**. BẤT-NGỜ: moving authz controller→handler = CORRECT gotcha #44 fix (không phải smell) khi paired BE-computed capability flag. substring:"S54 ItTicket reassign authz Admin-OR-dept-IT" → 2026-06.md - [vừa] VIỆC: S55 master-data import — Mig 48 `AddProjectMasterFields` (Project +4 nullable Year/Investor/Location/Package) + `SeedRealMasterDataAsync` (62 Project+71 WorkItem+3 Supplier per-code idempotent ungated) + FE ×2 — **spawn, em-main proxy (reviewer truncated gotcha #53 trước verdict)**. KẾT-LUẬN: PASS — em-main completed pending-check `dotnet test` = clean rebuild **216 PASS** (giải tỏa cached-binary 2.76s concern); Mig Up=4 AddColumn/Down=4 DropColumn reversible; per-code idempotent ungated line 118 (reaches prod); FLOCK01 collision skip-demo-wins; runtime Dev proof Investor populates. BÀI-HỌC: **long adversarial review return truncates (gotcha #53) → reviewer emit PASS/FAIL verdict SỚM trước deep re-verify để sống sót; em-main complete được pending-check deterministic (clean dotnet test = fresh build)**. BẤT-NGỜ: cached-binary fast-build nghi → clean test = fresh build giải tỏa. substring:"S55 master-data import pre-commit" → 2026-06.md - [cao] VIỆC: S55 Phase-1 FE visual redesign pre-commit — 14 fe-admin file VISUAL/CSS-only (NAMGROUP density + SOLUTION brand) — spawn. KẾT-LUẬN: PASS 0-blocker, **verdict-first survived** — npm build fe-admin ✓ 0 TS err; **Button cva variant keys + size STABLE chỉ class VALUES swap (51 call-site safe); Input/Select/Dialog forwardRef+passthrough unchanged; DataTable `Column` type UNCHANGED**; **Be-Vietnam-Pro KEPT (grep @import:3 + --font-sans:22 + font-family:34 unchanged — initial font-drop blocker RETRACTED sau grep)**; Tailwind v4 `shadow-xs`/slash-opacity valid. 2 MINOR: text-slate-400 hint ≈3.5-4:1 borderline-AA (defer). BÀI-HỌC: **font-drop scare = grep 3 load-bearing lines (@import/--font-sans token/font-family) TRƯỚC khi flag — diff hunk lower in file ≠ font removed; emit PASS/FAIL line-1 FIRST (gotcha #53 survival)**. BẤT-NGỜ: Tailwind v4 `shadow-xs` real (v3 shadow-sm renamed) — đừng flag typo. substring:"S55 Phase-1 FE visual redesign pre-commit" → 2026-06.md - [cao] VIỆC: S56 pre-golive authz **live prod curl** 8 new endpoints — spawn. KẾT-LUẬN: PASS 0-blocker — **8/8 return 401 unauth; admin-authed hrm-configs/vehicles/drivers/leave-balances/attendances all 200 (xlsx 6797B); non-admin Drafter correctly 403 on 2 Admin-only**; **gotcha #44 silent-403 sweep CLEAN: GET /it-tickets/assignable-staff returns HTTP 200 `{canReassign:false,staff:[]}` for non-IT (NOT swallowed 403), handler returns flag không throw (`WorkflowAppsFeatures.cs:466`)**. 1 MINOR: PUT /it-tickets/{id}/assign checks NotFound BEFORE Forbidden (`:496-508`) = existence-oracle leak (mutation fail-closed, post-golive hardening). BÀI-HỌC: capability endpoint = flag-return không throw = đúng gotcha #44 fix. BẤT-NGỜ: NotFound-before-Forbidden ordering = minor info-leak defense-in-depth defer. substring:"S56 pre-golive authz live-curl" → 2026-06.md - [cao] VIỆC: S57-resume Harness-4 two-tier adopt gate (governance pre-send + pre-commit, no product code) — spawn (self-report `claude-fable-5[1m]` = promote-list direct evidence). KẾT-LUẬN: **PASS-with-fixes 0-blocker** — re-verify ALL GREEN: frontmatter **7 pin `claude-opus-4-8` + 4 `inherit` + 0 `[1m]`-in-frontmatter** + 0 project-pin settings; **evidence track-record 8/8 REAL** vs HANDOFF/STATUS; **nấc G-011 đúng mọi chỗ load-bearing (demote=executed-file·pending-restart, 0 overclaim runtime)**. Fixes: hash PLACEHOLDER trước send + "SENT ✓" premature status-verb + count "(13)"vs"11" + invalid-role typo→rơi 'opus'. BÀI-HỌC: **gate adopt-governance = re-run MỌI grep claim + cross-check evidence vs HANDOFF nguyên văn; n=2 demoted spawn-test double-duty làm inherit-chain proof HỢP LỆ (registry cached=chạy config cũ) nhưng cần phrase rõ**. BẤT-NGỜ: CCD harness cache agent frontmatter → đổi agent .md phải restart CLI mới ăn. substring:"S57-resume Harness-4 two-tier adopt gate" → 2026-06.md