Files
solution-erp/.claude/agent-memory/reviewer/MEMORY.md
pqhuy1987 0c6efdaf4f [CLAUDE] Docs: Session 25 chốt cuối — Plan AB→AF cumulative 7 commits + 4 agent MEMORY flush
S25 wrap final:
- STATUS.md + HANDOFF.md prepend Plan AB→AF cumulative narrative (7 commits cdfd542..506cada + 7 CICD Runs #215-#221)
- gotchas.md +2 NEW entries:
  - #48 Multi-Changelog.Add() SQLite frozen-clock tie-break (Run #215 catch, fix Plan AB Chunk A2)
  - #49 UI dual-phase badge confusion khi state machine self-loop (Plan AD drop + extractNextTargetHint helper)
- Checklist debug bug mới +2 entries (24-25)
- Session log NEW docs/changelog/sessions/2026-05-19-s25-pe-history-visibility.md (~360 LOC)
- 4 agent MEMORY drift sync:
  - investigator/MEMORY.md (30→32KB) FIFO entry S25 wrap + count metadata
  - implementer/MEMORY.md (34→36KB) FIFO entry + patterns 16-18 saved
  - reviewer/MEMORY.md (31→32KB) FIFO entry + lesson SQLite tie-break + UAT skip risk reinforced
  - cicd-monitor/MEMORY.md (~72KB CRITICAL OVER) — 7 Run entries #215-#221 + curate flag MAX

Memory user-level +2 NEW entries (separate commit memory dir, KHÔNG trong this commit):
- feedback_fe_merge_synthetic_audit.md (Plan AC2 pattern)
- feedback_fe_usermap_fallback.md (Plan AF pattern)

Stats final S25:
- 31 mig (no schema) · 59 tables · ~146 endpoints · 35 FE pages
- 111 test unchanged (UAT defer test-after per §7)
- 49 gotcha (+2: #48 + #49)
- 23 memory user-level (+2 NEW S25 patterns)
- 6 skills · 4 sub-agents active
- 7 commits cumulative S25 · 7 CICD Runs (1 FAIL caught + 6 PASS)
- 6× bundle rotate × 2 app (Run #220 BE-only unchanged)

Critical pending S26+:
- Memory curate cicd-monitor PRIORITY MAX (~72KB strongly over hard threshold)
- Plan B Contract V2 wire HIGH priority (5-6 chunk pre-allocated S23 HANDOFF)

Per §6.5 KEEP narrative — KHÔNG cut rationale/gotcha context, chỉ phân tầng prepend latest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:33:41 +07:00

32 KiB
Raw Blame History

Reviewer Agent — Persistent Memory

Persistent diary cross-session. Auto-injected first 200 lines / 25KB at spawn. Update BEFORE every stop. Curate when > 25KB.


🎯 Role baseline

Adversarial pre-commit reviewer for SOLUTION_ERP. Read-only verification + live curl on prod UAT environment (*.solutions.com.vn). Tools: Read, Grep, Glob, Bash (curl + git diff + sqlcmd read). Output: PASS/FAIL verdict + concrete issues file:line.


🚨 Recurring SOLUTION_ERP bug patterns (catch with priority)

Gotcha #44 — Silent 403 class-level Authorize quá strict (S18 lesson)

  • Symptom: Drafter dropdown V2 workflow empty silent (no error toast)
  • Root: [Authorize(Policy = "Workflows.Read")] class-level → non-admin 403, TanStack Query catch silent → UI empty
  • Verify: grep \[Authorize\(Policy = .*\)\] class-level vs action-level + curl với non-admin token expect 200
  • Fix pattern: class-level [Authorize] only (any authenticated). POST/PUT/DELETE giữ [Authorize(Policy = "X.Create")] admin-only

Gotcha #43 — Step.Order ≠ index 0-based

  • Symptom: EF query Where(s => s.Order == i) returns wrong row
  • Verify: grep step.Order arithmetic — array index 0-based vs Order field 1-based
  • Fix pattern: precompute candidates EF query → in-memory OrderBy(s => s.Order).ToList() → array index access

Gotcha #42 — Dual schema workflow V1 vs V2 — Service phải branch

  • Symptom: PE submit failed do Service không biết V1 hay V2 schema
  • Verify: grep evaluation.ApprovalWorkflowId is Guid awId — phải branch theo pin field
  • Fix pattern: if (evaluation.ApprovalWorkflowId is Guid awId) ApproveV2Async(...) else ApproveV1LegacyAsync(...)

Wire BE claim recurring bug pattern

  • Symptom: claim wire CRUD nhưng grep diff finds // Mock / alert(...) / no POST/PUT/DELETE call
  • Verify: grep diff mock markers + live curl POST/PUT/DELETE expect 2XX
  • Severity: CRITICAL — block commit

Gotcha #17 — EF migration 3-file rule

  • Symptom: commit migration nhưng thiếu .Designer.cs hoặc ApplicationDbContextModelSnapshot.cs → next migration fail
  • Verify: git diff --name-only | grep Migrations/ expect 3 files (target.cs + target.Designer.cs + Snapshot.cs)

Gotcha #47 — .claude/agent-memory/** NOT in paths-ignore filter (S22 discovery, PENDING bro decide)

  • Symptom: MEMORY.md drift patch commit (end-of-session flush) triggers full CI deploy ~3.5min waste
  • Verify: check .gitea/workflows/deploy.yml paths-ignore — currently ['docs/**', '**/*.md', '.claude/skills/**'] MISSING .claude/agent-memory/**
  • Discovery: S21 CICD Monitor Run #188 verify chốt initial — confirmed via path filter audit
  • Fix recommended: add .claude/agent-memory/** vào paths-ignore (em main KHÔNG tự edit — flag bro decide; pending add to docs/gotchas.md 47th entry)
  • Severity: minor (CI waste only, no functional impact)

📋 5-category checklist (apply EVERY review)

Category 1: Wire BE / feature claim verify

  • Grep mock markers in diff (// Mock, alert(, setEditing(null) // close UI, TODO.*wire)
  • Grep actual API call: await api\.(post|put|delete|patch)\( trong FE diff
  • Live curl POST/PUT/DELETE/PATCH if deploy claim (https://api.solutions.com.vn/...)
  • Status code matrix expected vs actual

Category 2: Schema integrity (44 active gotchas)

  • Reference docs/gotchas.md + skill dependency-audit-erp
  • Check 3-file rule Mig
  • Check column types vs entity definition (Mig 27 lesson: IsVisible bit NOT NULL DEFAULT 1 + DisplayLabel nvarchar(200) NULL)

Category 3: Security

  • [Authorize] class-level on ALL new controllers
  • Per-action [Authorize(Policy = "...")] cho admin-scoped (gotcha #44 lesson)
  • Permission guard wrap new admin pages (FE)
  • Route permission map populate (menuKeys.ts mirror BE MenuKeys.cs + All[])
  • Input validation FluentValidation Validator class
  • SQL parameterized (EF Core default OK) + XSS escape

Category 4: Code quality

  • dotnet build SolutionErp.slnx clean 0 err
  • npm run build × fe-admin + fe-user clean (TS6 strict)
  • Tests baseline 81 PASS (Phase 9 UAT exception OK)
  • No --no-verify bypass (forbidden absolute)
  • Anti-fiddle audit (scope drift > 20% LOC outside spec = FAIL)
  • Mirror 2 FE app khi feature FE (rule §3.9)

Category 5: Test coverage

  • New helper static → unit test (xUnit)
  • New Repository method → repo test
  • New endpoint API → integration test (WebApplicationFactory)
  • Bug recurring → regression test TDD-style (test BEFORE fix)
  • Phase 9 UAT exception: test-after default OK theo memory feedback_uat_skip_verify
  • Test count baseline 81 → tăng khi feature added theo §7

⚠️ Anti-patterns observed (DO NOT)

  1. Recommend code edits — only describe issue + acceptance criteria
  2. Skip live curl verify if deploy claim — recurring risk
  3. Accept "wire" claim without grep proof
  4. Defer to em main authority — escalate disagreement explicitly
  5. Skip MEMORY.md update với anti-patterns observed
  6. Lower bar to match em main quality — Smart Friend anti-pattern Cognition

🛡️ Smart Friend anti-pattern guard

Per Cognition documented research:

  • NEVER lower bar to match em main's apparent quality
  • If em main code fine → say PASS
  • If em main code has issues → FAIL with specifics regardless social pressure
  • "Quality ceiling was set by the primary, not the escalation." — Your value = raise quality through catch

🧠 SOLUTION_ERP review essentials

  • Tests baseline: 111/111 PASS (S25 unchanged from S23 t3 +7 Plan M edge case tests; pre-Plan AB Chunk A2 SQLite tie-break regression Run #215 caught by CICD test gate → em main fix EntityType + Summary discriminator filter restored 111 PASS). Must increase nếu feature added per §7; UAT iteration exception per memory feedback_uat_skip_verify
  • Gotchas: 47 active (docs/gotchas.md reference) — +#48 Multi-Changelog.Add() trong same SaveChangesAsync transaction → SQLite test frozen clock CreatedAt tie-break non-deterministic (S25 pending docs add). +#45 PE button TraLai payload mismatch + #46 Gitea API path/cache stale (S21 t3-t4). #47 paths-ignore agent-memory gap (S22 PENDING bro confirm add to docs)
  • Migrations: 31 latest AddPeLevelOpinionsForV2 (S19 — Mig 31 Plan K1 swap F2 Drafter→Approver scope per-Level slot S23 t1). Mig 30 AddAllowApproverEditBudgetToLevels (S22+5 per-slot F4 flag admin opt-in Approver scope edit budget ChoDuyet branch). Mig 29 prev RefactorAdvancedOptionsToPerLevelAndDrafterUser (S21 t5 per-NV split)
  • Per-NV Allow scope split* (Mig 29 + Mig 30) — F1+F3 5 flag + F4 AllowApproverEditBudget (S22) on ApprovalWorkflowLevels (per Approver slot), F2 1 flag on Users.AllowDrafterSkipToFinal (per Drafter). DTO: currentLevelOptions + drafterAllowSkipToFinal thay vì workflowOptions
  • Endpoints: ~146 (+3 S22: allow-skip-final / budget-adjust / attachments/view)
  • Identity password policy ≥12 chars (S22+2 enforced by ASP.NET Identity stack — reject User@123456 11 chars). Existing HANDOFF mention "User@123456" pattern S4 outdated, current test creds Admin@123456 + TestUser@123456 OK
  • Live deploys (Prod UAT): https://api.solutions.com.vn · https://admin.solutions.com.vn · https://eoffice.solutions.com.vn
  • Bearer token test:
    • Admin: admin@solutions.com.vn / Admin@123456 (full quyền)
    • UAT user: nv.test@solutions.com.vn / TestUser@123456 (Drafter Phòng CCM — verify non-admin access patterns)
  • Users active: 33 (rename role-based pattern act.nv / act.pp / act.tp etc.)
  • Conventions: docs/rules.md (§3.9 mirror 2 FE, §5.2 commit format, §6.5 docs KEEP narrative, §7 test timing, §2.8 package pinning)
  • 6 skills: contract-workflow · permission-matrix · form-engine · ef-core-migration · dependency-audit-erp · iis-deploy-runbook

🔑 Critical pin verify (gotcha #1-4)

  • MediatR 12.4.1 (14 fail DI)
  • Swashbuckle 6.9.0 (10 conflict OpenApi 2)
  • Microsoft.OpenApi 1.x (2 breaking)
  • Node engines >= 20 + CI 20.x (Node latest fail Windows IIS)

Flag commit nếu thấy <PackageReference Include="MediatR" Version="14... hoặc tương tự.


📅 Recent activity (last 10 FIFO)

  • 2026-05-19 (S25 wrap — Plan AB pre-commit verify + 6 follow-up plans em main solo self-review + 1 lesson catched by CICD): Plan AB Chunk A pre-commit verify spawn 1× ~22K with 5-category checklist + 8 adversarial deep checks PASS 0 blocker (1 minor V1 legacy fallback acceptable). Recommended PROCEED push cdfd542. MISSED gotcha #48: Multi-Changelog.Add() trong same SaveChangesAsync transaction → SQLite test frozen clock CreatedAt tie-break non-deterministic → Plan M existing tests .OrderByDescending(CreatedAt).FirstAsync() picked wrong entry → CI Run #215 FAIL. Lesson reinforced: UAT mode feedback_uat_skip_verify skip dotnet test per chunk risk recurring khi BE refactor > 100 LOC + signature change. Em main resumed local dotnet test post Plan AB Chunk A2 fix — caught by CICD test gate (no prod impact). Em main solo self-review Plan AC-AF (5 plans em main solo, Reviewer KHÔNG re-spawn — em main verify build+test+npm × 2 app mỗi chunk + CICD post-deploy verify thay vai pre-commit). Cumulative S25: 0 prod regression, 6 commits PASS CICD. Pattern caught: SQLite frozen clock multi-row tie-break — tests querying audit table cần discriminator beyond timestamp (EntityType + Summary keyword). Cross-ref future Contract V2 test setup. Smart Friend guard still active for future spawn — Reviewer should ADD test filter discriminator check vào Category 5 checklist post-S25.
  • 2026-05-19 (S25 Plan AB Chunk A pre-push verify, spawn): Adversarial verify commit cdfd542 Plan AB Chunk A — fix Changelog visibility 2 bug PE ID 3248f2f9 (Budget Adjust không hiện history + Trả lại Người chỉ định không log). Diff scope: 3 files +146/-95 LOC (BE PurchaseEvaluationWorkflowService.cs Service-only refactor + 2 FE PeDetailTabs.tsx mirror §3.9). Verdict: PASS — 0 critical / 0 major / 1 minor observation — proceed push OK. Wire BE: line 226-236 V1 legacy fallback return early UNCHANGED (giữ S17 behavior, KHÔNG log new Changelog — V1 phiếu read-only history per Mig 22-24 spec, acceptable). V2 ApplyReturnModeAsync refactor Drafter early return → if/else common path: Drafter mode line 285-292 set Phase=TraLai + clear pointer + SLA=null SEMANTIC IDENTICAL pre-refactor (only difference: removed return so fallthrough log block). OneLevel/OneStep/Assignee unchanged logic line 302-378 + SLA=AddDays(7) reset line 381. New db.PurchaseEvaluationChangelogs.Add() line 403-412 EntityType=Workflow(5) + Action=Update(2) + PhaseAtChange=evaluation.Phase (TraLai cho Drafter, ChoDuyet cho 3 mode khác) + UserId=actorUserId + UserName resolved via userManager.FindByIdAsync (mirror LogTransitionAsync line 700-704 pattern) + Summary "Trả lại ({modeName}): {summary}". KHÔNG SaveChangesAsync mới — TransitionAsync caller line 101 downstream save persists. Wire FE 2 file HistoryTab filter extend 3 rule: ADD summary.includes('Trả lại') Workflow entity + ADD entityType === Header(1) && summary.toLowerCase().includes('ngân sách') cover Budget Adjust + empty placeholder text update Vietnamese chuẩn "Chưa có lịch sử trả lại / điều chỉnh ngân sách / gửi duyệt lại." Schema integrity: 0 migration mới (verify git diff --name-only | grep Migrations/ empty); reuse PurchaseEvaluationChangelog Mig 12 + S21 t4 Mig 28 schema; PurchaseEvaluationEntityType enum line 25-33 + ChangelogAction enum ContractChangelog.cs:38-44 match BE values FE constant. Security: actorUserId param đã có từ caller TransitionAsync — non-admin user log đúng UserId không escalate permission; EF Core parameterized SQL default; FE substring filter trên BE-trusted Summary string không XSS risk. Code quality: dotnet build PASS 0 err 2 warn (DocxRenderer pre-existing); npm build fe-user PASS 394ms 0 TS err; npm build fe-admin PASS 421ms 0 TS err; anti-fiddle scope drift 0%; mirror 2 FE app §3.9 verify exact identical 17 lines (admin line 2033-2049 mirror user 2027-2043, chỉ shift 6 LOC do prior component lines khác). Test coverage: Phase 9 UAT exception ACCEPT per memory feedback_uat_skip_verify — test-after bundle defer (Bug fix Service refactor ideally test-before nhưng UAT mode skip OK). Cumulative state unchanged: 111 test baseline preserve. Adversarial deep checks all PASS: (1) Drafter mode refactor regression — line 285-292 set Phase=TraLai + clear pointer + SLA=null PRESERVED (S17 backward compat). V1 legacy 226-236 fallback return early no semantic change. (2) Drafter summary redundancy$"Trả lại (Người soạn thảo): Trả về Người soạn thảo" redundancy acceptable (audit clarity > terseness; consistent format 4 mode). (3) actorName resolve N+1 — single userManager.FindByIdAsync per ApplyReturnModeAsync invocation, mirror exact LogTransitionAsync line 700-704 pattern; KHÔNG N+1 (single call per transition). (4) FE filter substring case.includes('Trả lại') exact match BE format $"Trả lại ({modeName}): ..." — case-sensitive Vietnamese diacritics lowercase 'l' match. (5) FE placeholder Vietnamese — "Chưa có lịch sử trả lại / điều chỉnh ngân sách / gửi duyệt lại." chuẩn Vietnamese diacritics. (6) Comment update 5 bullet rule — clear narrative, KHÔNG noise, Plan AB S25 marker rõ. (7) Gotcha #45 regression — Plan AB Service-only refactor KHÔNG đụng PE button TraLai click logic (gotcha #45 đã fix S21 t3 BE guard decision != Reject throw line 64-72 defense), no regression. (8) Anti-fiddle scope — 3 file đúng spec, KHÔNG out-of-scope (no agent-memory commit, no docs/changelog touch). Minor observation (non-block, design choice): V1 legacy phiếu (line 226-236 fallback) return early TRƯỚC khi reach new Changelog.Add() block → V1 phiếu KHÔNG có new detailed "Trả lại (X): ..." log. FE filter phaseAtChange === TraLai(98) line 2042 vẫn catch V1 generic LogTransitionAsync log (V1 fallback set Phase=TraLai) → V1 history vẫn hiện (1 generic row "Chuyển phase X → TraLai" thay vì detailed mode breakdown). Acceptable per Mig 22-24 spec V1 = read-only history, không cần backfill audit detail. Recommendation: PASS proceed push remote. Smart Friend guard active.
  • 2026-05-15 (S24 Plan AA post-wrap cumulative finalize, no re-spawn): Post-Chunk C learning append — em main iterate 4 polish chunks back-to-back (da218f1 px-2 hotfix + 4d60598 redesign v1 panel-per-NV color + fbbd361 redesign v2 table layout rowSpan + ee0902a wrap fix sidebar label) UAT visual feedback bro, cumulative ~1.5h, KHÔNG Reviewer spawn. Anti-pattern observed S24 polish chunks: UI/UX iteration thuần CSS/layout KHÔNG cần Reviewer spawn mỗi chunk — cost overhead too high (~25K spawn × 4 = ~100K cumulative). Pattern reusable: chỉ self-verify build pass + bro visual confirm post-deploy là đủ. Smart Friend guard validation S24: Plan AA cumulative ~620 LOC qua 7 commits (a1a910f..ee0902a) — Reviewer spawn 1 lần (Chunk C cumulative A+B BE+FE wire) cost ~25K = ROI tốt. Multi-spawn polish chunks 4× sẽ ~100K = ROI thấp. Pattern saved: BUNDLE cumulative verify cho heavy chunk (wire BE / migration / cross-stack), SKIP cho < 30 min polish (CSS / layout / color). Discovery #3 anomaly re-tested S24: Plan AA Run #210 sha=ac2c859 push range mixed BE+FE+docs → CICD trigger normal 4/4 wire end-to-end + bundle hash 2 app rotate. KHÔNG reinforce docs-only anomaly hypothesis (S22 #47 gap pending separate). Defer Investigator follow-up. Low note S24: BE filter IsUserSelectable=false non-admin leak workflow chưa ghim — defer follow-up (severity Low, workflow data non-sensitive, NOTE only — Smart Friend guard didn't escalate to block commit). CICD Monitor Run #210 sha=ac2c859 PASS verify 4/4 wire end-to-end + bundle hash 2 app rotate. Cumulative state unchanged S24: 31 mig, 111 test, 47 gotcha.
  • 2026-05-15 (S24 Plan AA cumulative pre-commit verify, spawn): Adversarial verify Chunk A (BE + Layout, em main solo) + Chunk B (FE WorkflowMatrixViewPage, Implementer Case 2 PASS). Diff scope 8 file modified + 2 file CREATE — ~76 LOC BE + ~270 LOC FE, scope khớp Plan AA. Verdict: PASS with 0 critical / 0 major / 0 minor issues — proceed commit OK. Wire BE: Controller line 21-26 Overview(applicableType, isUserSelectable, ct) → new GetAwAdminOverviewQuery(applicableType, isUserSelectable) end-to-end. Handler line 114-117 request.IsUserSelectable is bool ius → query.Where(d => d.IsUserSelectable == ius) correct conditional. FE WorkflowMatrixViewPage line 29-33 actual api.get<AwAdminOverviewDto>('/approval-workflows-v2', { params: { applicableType: typeInt, isUserSelectable: true } }) — real call no mock/alert. Route /purchase-evaluations/workflow-matrix?type=N wired App.tsx:38 + Layout.tsx resolvePath:81-86. Schema integrity: 0 migration mới (column IsUserSelectable from Mig 25), DbInitializer INSERT-OR-UPDATE-Order idempotent verified (MenuItemConfiguration HasKey(Key) → PK unique, ToDictionary safe; existing rows UPDATE Order only nếu mismatch; new rows INSERT). 7 Allow* flag count match BE DTO ↔ FE type. ApplicableType enum {1,2,3} — FE chỉ wire 2 type PE matrix view correct. Security: class-level [Authorize] bare line 18 PRESERVED (gotcha #44 protect). GET any authenticated → non-admin Drafter OK access. Non-admin pass isUserSelectable=false BE không block → workflow chưa ghim leak risk — Low severity (workflow data non-sensitive, NOTE only). Permission seed 7 role × WfView leaf via SeedPurchaseEvaluationPermissionDefaultsAsync:1573 added — idempotent. Admin role qua SeedAdminPermissionsAsync chỉ cover MenuKeys.All[] static root keys (Pe_WfView dynamic NOT in All) — but admin uses fe-admin Designer, KHÔNG cần WfView access fe-user. Code quality: BE dotnet build PASS 0 err 2 warn (DocxRenderer pre-existing); FE fe-user npm build claim PASS (Implementer Case 2); FE fe-admin npm build VERIFY tự chạy PASS 1926 modules / 740ms / 0 TS err. Anti-fiddle 0% drift, scope khớp spec. Mirror 2 FE §3.9: Layout.tsx widen w-72 xl:w-80 cả 2 ✓; remove truncate 3 site fe-user (MenuGroup+MenuLeaf+StaticLeaf) + 2 site fe-admin (MenuGroup+MenuLeaf, no StaticLeaf component) — structural asymmetry acceptable (fe-user only có "Hộp thư" StaticLeaf); WorkflowMatrixViewPage fe-user only correct (admin có Designer riêng). Test coverage: Phase 9 UAT exception accept — test-after default OK. Adversarial deep checks: (1) DbInitializer ToDictionary duplicate key risk → PK constraint trên Key, tree.Add chỉ thêm Pe_DuyetNcc_WfView + Pe_DuyetNccPhuongAn_WfView (2 typeCode distinct) → no in-memory dup. (2) Sidebar widen 1280px responsive verified per task spec (288 sidebar + 992 main fit). (3) Plan U revert clean — 0 remaining truncate class outside Plan AA comments. (4) Mig drift schema: column existed Mig 25, no new mig needed. 2 SaveChangesAsync non-atomic giữa menu seed + label backfill (pre-existing, OUT scope Plan AA). Comment quality: Plan AA marker rõ ràng 8+ sites, no TODO/FIXME zombie. TypeScript: FlagCell indexed-access type clever từ Pick 7 keys union — TS happy compile clean. Recommendations defer: (a) enforce admin/non-admin policy filter (current GET cho phép user pass isUserSelectable=false — low risk, audit follow-up); (b) MenuKeys.All[] không cover dynamic Pe_WfView nên Admin role không auto grant — OK vì admin dùng fe-admin Designer, NOTE để future audit khi admin cần inspect user-side matrix view. Cumulative state unchanged: 31 mig, 111 test, 47 gotcha. Smart Friend guard active — KHÔNG lower bar (3 minor risk noted defer follow-up, không block commit).
  • 2026-05-15 (S23 t4-t11 cumulative em main self-review — Plan N+O+P+Q+R+S+T+U, no Reviewer spawn): 8 plan consecutive em main self-review per UAT mode (feedback_uat_skip_verify rule — em main verify build + test + npm build mỗi chunk). Key validations cumulative: Plan N GetPe handler PurchaseEvaluationFeatures.cs:765 per-NV ApproverUserId discriminator + admin fallback row đầu. Plan O 4 lookup sites cascade fix (EnsureCanRejectV2Async:201 + ApplyReturnModeAsync:248 + EnsureEditableForDetailsAsync:72 + AdjustBudgetCommandHandler:311) — pattern uniform Plan N, +3 regression test PurchaseEvaluationPerNvLookupRegressionTests.cs. Plan P Controller TransitionPeBody:267 record +3 fields mirror TransitionPurchaseEvaluationCommand schema — root cause 2 ngày prod bug F1+F2 wire fail. Plan Q FE banner mx-5 inset gap fix (CSS layout polish mirror 2 app). Plan R+S+T5 destructive sqlcmd cleanup prod ~720 rows wiped cumulative + Plan F precedent avoid được (V1 active workflow giữ nguyên → BE healthy startup). Plan T DbInitializer DemoSeed:Disabled flag config — disable 5 demo seed methods (Workflow V1 + PE V1 + Demo Contracts + Demo PE + Sample V2). Plan U FE sidebar truncate + tooltip 2 app mirror — handle long DisplayLabel (Mig 27 admin custom). Anti-patterns observed: (1) Plan N point 9 chỉ catch 1/5 sites — em main + Investigator spawn miss 4 sites khác → Plan O cascade fix. Lesson: grep ENUMERATE TẤT CẢ lookup sites cùng pattern (KHÔNG fix theo bug report mỗi lần). (2) Plan O caveat #1 surfaced Plan P pre-existing bug — CICD Monitor catch Controller body record drop trong Stage 4c verify wire — pattern "verify cross-stack body↔command count match". (3) DbInitializer auto re-seed loop — Plan R+S clean → IIS recycle → re-seed loop. Plan T flag fix root cause. Pattern reusable cross-project: refactor schema 1-row-per-role MUST grep enum lookup sites + Controller body record MUST mirror Command record fields. Cumulative state: 111 test (+7 vs 104 baseline pre-Plan M), 31 mig (no new), 47 gotcha unchanged, feedback_per_nv_permission_scope.md reinforced 5 lookup sites enum + 9 wire surface points + Plan P caveat → 10 surface points. Smart Friend guard still active for future spawn.
  • 2026-05-15 (S23 t3 Plan M cumulative review, spawn): Pre-push adversarial verify 3 commits local c2afef2..508b17a..4dd6f9c Plan M F1 edge case Bước 1 + Phase=TraLai display rename. Diff cumulative: 26 LOC BE (Service.cs:287-333) + 116 LOC test (1 file, +2 test Fact extend SeedWorkflowAsync helper +2 params optional) + 8 LOC FE (4 file × 2 LOC mirror admin+user). Verdict: PASS — wire BE M1 verified hot path 287-333 OneLevel+OneStep edge case replace Phase=TraLai+clear pointer+return with Set pointer (0,1) + summary "không lùi được" → fallthrough SLA reset line 364 → Phase=ChoDuyet preserved from pre-call state (entry guard 75-81 require ChoDuyet để Reject decision). ApplyReturnModeAsync caller line 94-100 truyền evaluation.Phase (now ChoDuyet) vào LogTransitionAsync → Summary="Chuyển phase ChoDuyet → ChoDuyet" + ContextNote contain "không lùi được" (matches test assert ContextNote.Contain). Drafter mode line 268-275 GIỮ Phase=TraLai semantic (unchanged). Assignee line 335-360 throw nếu không match unchanged. F2 ApproveV2Async + F3 EnsureEditableForDetailsAsync + F4 AdjustBudgetCommand handler — UNCHANGED. Schema integrity: 0 migration mới, Phase enum TraLai=98 còn dùng cho Drafter mode + display label rename only. Security: Admin bypass logic line 252-265 + Reject guard line 81 EnsureCanRejectV2Async + non-Approver block — preserved. Code quality: dotnet build PASS 0 err 2 warn (DocxRenderer pre-existing), dotnet test 106/106 PASS (58 Domain + 48 Infra, +2 từ 104 baseline), npm build admin+user PASS 0 TS err (chỉ chunk size warn pre-existing), no --no-verify. Test coverage: 2 Fact mới ApplyReturnMode_OneLevel_AtStep1Level1_ResetsToBuoc1Cap1_KeepsChoDuyet + ApplyReturnMode_OneStep_AtStep1_ResetsToBuoc1Cap1_KeepsChoDuyet cover OneLevel Step1Lv1 + OneStep Step1Lv2→reset. Assert đủ Phase=ChoDuyet + pointer (0,1) + SLA NotNull + ContextNote "không lùi được". Helper extend +2 params backward compat OK (default false). K7 cascade NO regression — 3 ApproveV2_SkipToFinal_* xanh (M1 chỉ đụng F1 ApplyReturnModeAsync, không động F2 ApproveV2Async). Mirror 2 FE app (§3.9): purchaseEvaluation.ts admin+user identical (98:'Cần chỉnh sửa lại' + PeDisplayStatus.TraLai:'Cần chỉnh sửa lại'), PeWorkflowPanel.tsx admin+user identical (2 inline literal "Phase → ..." + "Phiếu sẽ về ..." rename). Anti-fiddle: scope drift 0% — 8 LOC FE đúng spec rename Phase=TraLai display only. Anti-pattern guard: (1) Stale narrative comment Service.cs:288-289 + 327-328 UPDATED rõ "Plan M S23 t3 — KHÔNG fallback Drafter, phiếu giữ đang duyệt" — không zombie. (2) Audit log consistency test+code match "không lùi được" exact. (3) Backward compat phiếu UAT prod đang Phase=TraLai do logic cũ — Drafter resume từ TraLai vẫn work line 105-132 (entry point fromPhase==TraLai → targetPhase==ChoDuyet). Minor issues (non-block, recommend fix sau): (4) Inconsistent UX literal "Trả lại" còn ở 8 user-facing locations chưa rename (decision design): PeListPanel.tsx:112 "Bản nháp + Trả lại" filter label, PeWorkflowPanel.tsx:270 button "← Trả lại", 272 tooltip "(Duyệt / Trả lại / Từ chối)", 315 "← Trả lại Drafter sửa", 342 "Chọn cách Trả lại", PeDetailTabs.tsx:152 "chỉ Bản nháp / Trả lại mới sửa", 287 "(trừ khi approver Trả lại)", ApprovalWorkflowsV2Page.tsx:639 "(Trả lại / Edit Section 2 / ...)" — phân biệt action verb "Trả lại" (button approver click) vs phase result label "Cần chỉnh sửa lại" (Phase=TraLai display in dropdown/badge); spec M3 narrow scope chỉ rename phase result label OK. Em main quyết: giữ action verb hay rename hết. (5) Inconsistent across module contracts.ts:29 + budget.ts:20 vẫn 98:'Trả lại' — KHÔNG trong scope Plan M (PE-only) nhưng inconsistent giữa 3 module nếu Contract/Budget có Phase 98 — bro nếu deploy chung sẽ noticeable. Recommendation: SAFE to push 3 commit Plan M; consider follow-up chunk M4 (optional) rename 5 literal user-facing trong PeListPanel + PeWorkflowPanel + PeDetailTabs để consistent UX semantic mới. Smart Friend guard active.
  • 2026-05-14 (S23 t1 Plan K1+K2 cumulative review, spawn): Pre-K3 adversarial verify Mig 31 schema swap + Service Approver F2 branch. Diff scope: 11 BE files +4093/-83 LOC (Mig Designer 3938 lines dominate). 3 commits chuỗi eb106f2..56868bf..db66253..364aef6 — pre-A slot label refactor + K1 Domain/Mig/Snapshot/sentinel patches + K2 DTO+Service Approver branch. Verdict: PASS với 2 Major + 2 Minor issues — K3 OK proceed nhưng K5 endpoint cleanup nên ưu tiên trước K7 test fix. Wire claim verify: Approver F2 branch placed ĐÚNG vị trí (line 477 AFTER UPSERT opinion line 441-468 + BEFORE advance pointer line 502) — opinion sẽ ghi trước skip terminal, audit log đầy đủ context Bước/Cấp. ApproveV1LegacyAsync skipToFinal guard tại CALLER (line 147-149 trong TransitionAsync branch) thay vì callee — pattern OK, V1 method giữ nguyên signature legacy. Schema sqlcmd verify Dev: 7 Allow* columns ApprovalWorkflowLevels (AllowApproverEditBudget/EditDetails/SkipToFinal/ReturnOneLevel/OneStep/ToAssignee/ToDrafter) + Users.AllowDrafterSkipToFinal dropped (count=0). Snapshot regen clean. EF config HasDefaultValue(false) wire. Mig 31 Up() manual reorder ADD→DROP correct per memory feedback_ef_migration_backfill_reorder. Major issues caught (Smart Friend guard active — KHÔNG để pass): (1) Orphan UsersController endpoint zombie — K1 sentinel commented "K2 sẽ refactor DTO + drop field" nhưng K2 chỉ refactor PE side, KHÔNG động UsersController.SetAllowDrafterSkipToFinal + UserFeatures.SetUserAllowDrafterSkipToFinalCommand + UserDto field. Endpoint PATCH /api/users/{id}/allow-skip-final vẫn live nhưng silent NoOp (Task.CompletedTask), admin UI tick → BE swallow → confusion UX. Cần K5 endpoint cleanup chunk (per spec). (2) Stale Mig 28 comment ApprovalWorkflow.cs:78 — comment cũ "F2 (Drafter skip) đã move sang Users.AllowDrafterSkipToFinal" còn nguyên dù line 107-113 prop AllowApproverSkipToFinal mới. Confuse future dev. Minor issues: (3) Comment TransitionPurchaseEvaluationCommand DTO PurchaseEvaluationFeatures.cs:401 "F2 — Drafter skip thẳng Cấp cuối khi trình duyệt" still says Drafter (semantic outdated). (4) ApprovalWorkflowConfiguration.cs:22 stale Mig 28/29 narrative comment chưa note Mig 31. Anti-fiddle audit PASS: K1 18 LOC UserFeatures.cs sentinel patches valid compile-break workaround, K2 4 files within original spec. Anti-pattern reinforced 3×: admin opt-in per slot per-NV (Mig 29 F1+F3 + Mig 30 F4 + Mig 31 F2 — em main lần đầu sai Mig 30 default scope expansion → bro corrected). Production build PASS 0 err 2 warn (DocxRenderer unrelated). Test references K7-pending line 253. No --no-verify bypass. Pattern caught: "Transient sentinel pattern" — đặt sentinel + comment commit chunk khác cleanup nhưng chunk đó scope SHIFT → zombie state. Recommend explicit K5 cleanup chunk trước K7 test fix. Cumulative state: 31 mig (+1 Mig 31), 47 gotcha unchanged. Smart Friend guard active.
  • 2026-05-13 (S22 18:00→21:00, no spawn): Em main solo self-review S22 — Reviewer KHÔNG spawn per UAT mode feedback_uat_skip_verify. Em main verify build clean + test pass + npm build × 2 app mỗi chunk (11 commits cumulative). Key validations: (1) Plan E phân quyền strict V2 — actor.UserId scope in List + Detail, Inbox đã strict từ S17, loose UAT clause || ApprovalWorkflowId != null removed. (2) S22+1 V2 actor scope guard BE helper EnsureCanRejectV2Async chặn request forge non-approver PATCH /transitions decision=Reject (mirror FE button disable) — defense-in-depth FE+BE pattern. (3) S22+4 AdjustBudgetCommand handler 3-tier scope (Drafter Nháp/Trả lại + Approver ChoDuyet + Admin) — S22+5 refactor ChoDuyet branch dùng level.AllowApproverEditBudget flag (admin opt-in per slot) thay default Approver scope (security scope correction per bro feedback). (4) S22+2 Identity password policy enforced ≥12 chars (reject User@123456 11 chars outdated). Anti-patterns observed: (a) Default scope expansion mistake S22+4 → S22+5 fix — KHÔNG default expand permission scope without admin tick (per-NV opt-in pattern Mig 29 lesson reinforced); (b) History display field assumption BudgetAdjustSection initial — em assume PeDetailBundle.changelogs exists, FAIL TS2339 — pattern verify type fields trước render; (c) PS 5.1 Vietnamese diacritics gotcha #30 reinforced — script seed-test-users-prod.ps1 first attempt FAIL parser error, ASCII-only discipline. S22+4 attachment view endpoint + S22+4 budget-adjust endpoint chưa qua live curl verify (defer post-deploy — bro UAT direct). S22+5 Mig 30 applied LocalDB Dev + Design via dotnet ef database update. New gotcha discovered: #47 paths-ignore agent-memory gap (recommend add to docs/gotchas.md — pending bro decide). Cumulative state: 104 test (+20), 30 mig (+1 Mig 30), 46 gotcha unchanged (gotcha #47 pending), ~146 endpoints (+3), 33 active users. Smart Friend guard still active for future spawn.
  • 2026-05-13 (S21 t3-t5, no spawn): Em main solo verify via dotnet build + npm build × 2 app + dotnet test suite mỗi chunk. Reviewer KHÔNG spawn — em main self-review per UAT mode feedback_uat_skip_verify (skip dotnet test mỗi chunk, vẫn build verify). Gotcha #45 fix self-test 3 regression test (test-before §7). S21 t3-t5 push cumulative 12 commits — CICD Monitor verify post-deploy thay vai Reviewer (deploy ship + bundle hash + schema verify). Cumulative state: 84 test, 29 mig, 45 gotcha, 19 memory entries. Pattern saved cho future review focus: per-NV permission audit (Level table vs User table flag), EF migration backfill SQL injection between ADD-DROP order. Smart Friend guard still active for future spawn.
  • 2026-05-11 (setup): Reviewer agent initialized. Baseline knowledge load complete (44 gotchas + 5-category checklist + 6 skills cumulative). No reviews performed yet. Awaiting first SendMessage from em main. Smart Friend guard active.

🔄 Curate trigger

  • Memory size > 25KB → archive recent entries to archive/<period>.md
  • Duplicate entries detected → merge
  • Stale > 3 months → remove

Last curate: 2026-05-11 (initial seed)