Migrate .claude/workflows/wave-*/ (gitignored) -> runs/<run-id>/ git-TRACKED (run.md+sub-md/+harvest/) + _ledger.md 2-beat + 3-layer anti-miss + containment model shift (B6 'any tracked-change=violation' -> 'tracked-change outside run-folder+code-disjoint=violation'). hmw.js wave->run-trace (accept args.run + alias). Review (R2+R3) caught C5 L1 over-claim -> fixed (em-main convention, engine no-fs). 3 run-id: wf_9c2cd2cd-2e7 / wf_e4e46725-231 / wf_636bc95b-939. 0 production code, state unchanged (Mig 53/88 tables/306 test/68 gotcha). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
33 KiB
Reviewer 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 RAGsearch_memoryjust-in-time. Keep entry ≤ 1.5K chars (gotcha #53). Full verbatim history pre-S40 → gitd2f52ba+archive/2026-05-q1..q2.md; S51→S57 detail →archive/2026-06.md(S69 curate). Archive map:archive/_INDEX.md+ per-period.gist.md.
📁 Area memory (L2 on-demand — Read khi review vùng tương ứng)
- S62 PE budget soft-warning — PASS: hard-block→soft-warning; submit-guard intact + validator giữ
BudgetPeriodAmount>0, row8 negative-safe (additive-only). Validator classPurchaseEvaluationFeatures.cs:317(reconcile S63: stray cwd-misland → canonical, anchor verified). - Wire/mirror claim verification anchors — sha256 twin-file ·
git diff -U0isolate true-adds ·allowNegativebleed check · guard-still-intact grep.
🎯 Role baseline
Adversarial pre-commit reviewer SOLUTION_ERP. Read-only verify + live curl prod UAT (*.solutions.com.vn). Tools: Read, Grep, Glob, Bash (curl + git diff + sqlcmd read) + 5 RAG MCP. Skills: dependency-audit-erp + contract-workflow + permission-matrix. Output: PASS/FAIL + concrete issues file:line. NEVER write code.
🚨 Recurring bug patterns (catch priority)
- #44 Silent 403 class-level Authorize quá strict — Drafter dropdown empty silent (TanStack catch silent → UI empty). Grep
\[Authorize\(Policy=.*\)\]class-level + curl non-admin expect 200. Fix: class-level[Authorize]only (any authenticated); POST/PUT/DELETE giữ[Authorize(Policy="X.Create")]. - #43 Step.Order ≠ index 0-based —
Where(s=>s.Order==i)wrong row. Fix: EF query → in-memoryOrderBy(Order).ToList()→ index. - #42 Dual schema V1/V2 — Service phải branch —
if (entity.ApprovalWorkflowId is Guid awId) ApproveV2Async else V1Legacy. - Wire BE claim — grep diff
// Mock/alert(/no POST-PUT-DELETE call + live curl expect 2XX. Severity CRITICAL block. - Cross-module security mirror (S29 Smart Friend) — khi mirror entity/Command cross-module (PE→Contract→Budget V2), em main solo focus data shape MISS security guard. Pattern:
aw.ApplicableType == ExpectedTypevalidate ON Create BEFORE instantiation (mirrorPurchaseEvaluationFeatures.cs:62-77). Attack: Drafter forge POST/api/contractsvớiapprovalWorkflowIdcủa PE/Budget → FK Restrict chỉ check Id existence NOT ApplicableType → wrong-scope pin. Also re-verifyIsActive+IsUserSelectableserver-side. Password ≥12 chars (Identity reject 11-char legacy). Severity MAJOR block push. - #17 EF migration 3-file —
git diff --name-only | grep Migrations/expect 3 (target + Designer + Snapshot). - #47
.claude/agent-memory/**NOT in paths-ignore (PENDING bro decide) — MEMORY flush commit triggers CI ~3.5min waste. paths-ignore hiện['docs/**','**/*.md','.claude/skills/**']missing agent-memory. Severity minor (CI waste). ⚠️ S40 note: agent-memory commits đang trigger — recommend bro add.
📋 5-category checklist (EVERY review)
- Cat 1 Wire BE/feature claim: grep mock markers diff +
await api\.(post|put|delete|patch)\(+ live curl POST/PUT/DELETE if deploy claim + status matrix. - Cat 2 Schema integrity: 3-file rule Mig + column types vs entity def. Reference
docs/gotchas.md(55 active). - Cat 3 Security:
[Authorize]class-level ALL new controllers + per-action policy admin-scoped (gotcha #44) + FE PermissionGuard + menuKeys.ts mirror BE MenuKeys.cs + FluentValidation + EF parameterized. - Cat 4 Code quality:
dotnet build SolutionErp.slnx0 err +npm run build× 2 app (TS6 strict) + tests baseline 130 PASS (Phase 9 UAT exception OK) + no--no-verify+ anti-fiddle (scope drift >20% LOC = FAIL) + mirror 2 FE app §3.9. - Cat 5 Test coverage: new helper → xUnit · new endpoint → integration · bug → regression test-before-fix. Phase 9 UAT test-after default OK (
feedback_uat_skip_verify). Baseline 130. - Cat 6 Authority boundary: describe issue + acceptance criteria, NOT code edits. Escalate disagreement explicit.
⚠️ Anti-patterns + 🛡️ Smart Friend guard
- ❌ Recommend code edits (only describe issue+criteria) · 2. ❌ Skip live curl if deploy claim · 3. ❌ Accept "wire" without grep proof · 4. ❌ Defer to em main authority (escalate explicit) · 5. ❌ Skip MEMORY · 6. ❌ Lower bar match em main (Smart Friend Cognition anti-pattern).
Smart Friend (Cognition): NEVER lower bar. Em main code fine → PASS. Em main issues → FAIL with specifics regardless social pressure. "Quality ceiling set by primary, not escalation." Value = raise quality through catch.
🧠 SOLUTION_ERP review essentials (S40 verified)
- Tests baseline: 130 PASS (58 Domain + 72 Infra). Must increase khi feature added (§7); Phase 9 UAT exception (
feedback_uat_skip_verify). - Gotchas: 55 active (
docs/gotchas.md, format### N.highest #55). Latest #53 truncation · #54 529-fallback · #55 truncation-mid-exploration. - Migrations: 40 latest
AddAttendances(pathsrc/Backend/SolutionErp.Infrastructure/Persistence/Migrations/). Per-NV Allow* (Mig 29 F1/F3 5 flag + Mig 30 F4 onApprovalWorkflowLevelsper slot + F2Users.AllowDrafterSkipToFinalper Drafter; Mig 31 SkipToFinal→ApproverLevel). - Endpoints: ~211 · 84 SQL tables.
- Identity password ≥12 chars (reject 11-char). Test creds: admin
admin@solutions.com.vn/Admin@123456(full) · UATnv.test@solutions.com.vn/TestUser@123456(Drafter CCM). - Prod: api/admin/eoffice.solutions.com.vn. Pin: MediatR
12.4.1(flagVersion="14) · Swashbuckle6.9.0· Node CI20.x. - Conventions:
docs/rules.md(§3.9 mirror 2 FE, §5.2 commit, §6.5 docs narrative, §7 test timing, §2.8 pin).
📅 Recent activity (FIFO — older → archive/git)
-
2026-06-18 (S71 Harness-10 adap run-trace convention — Stage-3 REVIEW lens R1 frozen-evidence+containment, PASS, 0 blocker): Governance/infra-only (wave-folder→run-trace
.claude/workflows/runs/<run-id>/TRACKED). 10 modified (8 H10 + investigator MEMORY residual + CLAUDE.md pre-existing) + 1 untrackedruns/. NO product/test/csproj/package.json/migration → test baseline 306 untouched, deps N/A. Spec path trap: spec saidruns/...but actual.claude/workflows/runs/...(verify disk, không tin claim path). R1 verify ALL PASS: (1) Frozen-evidence 0-touch —git status --porcelainon broadcasts/** · adap-reports/2026-06-07-harness-2 · error-ledger · sessions/* · STATUS · HANDOFF ·*/archive/*ALL empty = none touched. (2) Containment wording đồng-bộ 4 chỗ —_ledger.md:4↔hmw.js:89/113↔workflows/README:38↔runs/README:78ALL = "tracked-change NGOÀI run-folder + code-disjoint = vi-phạm" (model thay Harness-2 B6 "mọi tracked = vi-phạm"). (3) gitignore exit-code-trap —check-ignore runs/.../run.md && echo IGNORED || echo NOT=NOT (re-included via:83 !.claude/**);wave-x/wave.md=IGNORED (legacy:93kept); trap-note PRESENT gitignore:96-98. No new ignore rule shadows runs/. residuals verified as-claimed: investigator MEMORY +6 (3 S71 diary, 29819B≈29.8KB over-cap, race artifact closeout); CLAUDE.md pure test-count 263→306 flush. hmw.jsnode --check=PARSE-OK,args.runw/ legacyargs.wavefallback:91,sub-md/subdir:103. harvest-curator DEDUP axis (sha/substring before APPEND); session-end idempotent VERIFY-not-re-APPEND; session-start orphan-scan. 6×.gitkeeppresent. 1 MINOR (non-block, actionable): runs/ currently UNTRACKED (git ls-filesempty,?? runs/) = tracked-ELIGIBLE not-yet-committed; docs say "TRACKED" = post-commit steady-state — em main MUSTgit add runs/in SAME commit else run-trace invisible to git-diff audit model depends on. Learned: "TRACKED" containment = 2-level — check-ignore NOT-IGNORED (eligible) vsgit ls-files(committed); model only works aftergit add. surprise: internal varconst wave = (A.run&&A.run.dir)?A.run:...keeps namewavebut readsA.runfirst — cosmetic-only, downstream identical (not bug). Verdict PASS — safe commit (git-add-runs/ caveat). Tag [s71, harness-10-runtrace, frozen-evidence-clean, containment-wording-4file-sync, gitignore-exit-trap, tracked-eligible-vs-committed]. -
2026-06-17 (S69 GOLIVE Văn phòng số public-all-roles authz — PASS, 0 blocker, gotcha #44-family CLEAN): 1-file BE-only DbInitializer.cs (+81, new
SeedAllRolesOfficeModulePermissionsAsync:2261 + call :2055 AFTER S65 HRM grant → AFTER revoke :2042). NOT deployed (static + Dev-DB review, build PASS). Near-exact mirror of S65 HRM method, ONLY delta =+CanCreate=true(HRM was read-only). 8 verify ALL PASS: (1) Ordering — grant call sits afterRevokeTemporarilyHiddenModulesAsync(:2042) + after S65 (:2048) → grant wins revoke. (2) Allow-list EXACTLY 16 Off keys — Off/Dashboard/DanhBa/PhongHop(+View+Book)/DeXuat(+List+Create+Inbox)/DonTu(+Leave+Ot+Travel)/DatXe/ItTicket; const names map correct values per MenuKeys.cs:99-120; NO PhongHopManage/AttendanceReport/ChamCong; array contains ZERO Hrm*/Personal/Pe*/Master key → no leak. (3) Upgrade-only correct — row exists→only flips CanRead/CanCreate false→true (if(!row.CanRead)+if(!row.CanCreate)), NEVER touches CanUpdate/CanDelete, never lowers; new row→read+create=true, update/delete=false (Permission.cs defaults false anyway). (4) 3 excluded keys STAY HIDDEN — decisive cascade check:Offis NOT one of the 4 inherit-roots in GetMyMenuTreeQuery (:56-59,:70-73,:80-83 = Contracts/Workflows/PE/PeWorkflows ONLY) → granting Off does NOT cascade to children; each Off child reads its OWNresolvedflags (:65, falls to false-tuple if no row); PhongHop_Manage(parent=Off_PhongHop:1830)/AttendanceReport(parent=Off:1845) not-in-list→revoke-false→filtered by HasAccess(:96); ChamCong re-parented to Personal(:1850/:1962) under hidden Personal root, not under Off, not granted→hidden. (5) Admin unharmed — MenuPermissionHandler:27 Admin bypass; Dev DB: all 18 Off rows belong to Admin already read+create=true → upgrade branch no-op. (6) No real write-path opened — KEY for golive: grep Controllers for Off menu keys = 0 matches; Office controllers gate writes by class-level[Authorize](any-auth, self-service create) + per-action[Authorize(Roles="Admin")]for true admin writes (MeetingRoomsController Create/Update/Delete=Manage-rooms :26/34/43, Attendances :37/42, LeaveBalances :23/28) — NOT by Off_*.Create policy. So broad CanCreate grant only drives FE menu+button (usePermission/PermissionGuard); API write-auth untouched, admin CRUD stays Admin-only regardless. (7) No migration — seed-logic only; all 16 keys in MenuKeys.All:157-161 (seeded). (8) Idempotent — 2nd run: rows already true→0 change; SaveChanges gatedif(added>0||upgraded>0). Dev DB baseline (307 perms,13 roles): 0 non-admin Off rows exist→method takes add-branch for 12 non-admin roles (creates 16 read+create rows each, 3 excluded never added). build Infrastructure 0err/0warn. 0 rogue write (only cicd-monitor/MEMORY.md noise, read-only respected). Learned: for a public-grant golive the load-bearing security proof is TWO-fold — (a) cascade-safety = confirm the granted root is NOT an inherit-root (else siblings leak, gotcha #44-family) AND trace excluded keys' ParentKey to a non-granted/hidden parent; (b) write-path-safety = grep that the broadly-granted menu key is NOT used as a controller[Authorize(Policy=)](here Office uses class[Authorize]+per-action Roles=Admin, so CanCreate is FE-only — granting it cannot escalate API writes). surprise: the "Manage rooms" admin function is double-protected — excluded from allow-list (menu hidden) AND its API is[Authorize(Roles=Admin)]; menu-hide alone would've been insufficient but the controller gate makes the broad grant safe even if a key had slipped. Verdict PASS — safe commit+deploy. Tag [s69, office-golive-authz, public-all-roles, inherit-root-no-cascade, off-not-policy-key-fe-only-grant, gotcha44-family-clean, admin-write-double-protected]. -
2026-06-17 (S69 Văn phòng số RE-SKIN static logic-preservation — PASS, 0 blocker): 10 pages presentation-only re-skin → PURO PageHeader/KpiCard + Hồ sơ-NS idiom (9 fe-user office + 1 fe-admin AttendanceReport). NOT built yet, fe-admin not mirrored (em main next). Strongest proof = exact API/queryKey diff OLD-vs-NEW byte-identical ALL 8 fe-user pages (grep
api\.(get|post|put|delete)+queryKey:[...]sorted -u, zero delta): proposals POST /submit + /{kind} · workflow-apps POST /{k}+/submit+PUT /workflow · meeting-bookings POST/DELETE+invalidate · it-tickets PUT /{id}/assign · directory/departments/attendance-report/excel-blob all UNCHANGED. Mutation side-effects (onSuccess/onError/invalidateQueries/setActionDialog/setComment/navigate) 1:1 (line-shift only). ProposalCreate validation!title.trim()throw + required + submit-disabled intact. AttendanceReport exportExcel blob (createObjectURL→a.download→click→revoke) intact. Cat2 orphans CLEAN: 0 unused import — flagged Users(=UsersIcon alias) + FormEvent/ReactNode (React.* namespace not named-import) + Accent(comment word) all FALSE-alarm verified. Cat3 shared-comp contract: PageHeader{eyebrow,title,subtitle,icon,accent,actions} + KpiCard{label,value,icon,accent,active,onClick} props all match real sig; KpiCard onClick wired to REAL filter state (ItTicketssetFilter/WorkflowAppsListsetStatusFilter/ProposalsList — driving actual client.filter()), InternalDirectory 2 KpiCards INTENTIONALLY inert (no onClick=presentational counts, matches comp design — NOT dummy). Shared comps + index.css NOT modified (git status -- ui/ + *.css EMPTY; sha256 identical fe-user==fe-admin per ls). Cat4 color-trap CLEAN: grep added lines for(teal|violet|amberx|greenx)-(200|300|400|800|900)= ZERO; index.css confirms accents ship only 50/100/500/600/700 (brand has full 50-900 so brand-800 valid); gotcha #66 — 0 gradient/dark-bg headings added (all headers on light surface use accent-ink text-brand-800/{accent}-700 via PageHeader). Cat1 mock-markers: 0 //Mock/alert/TODO-wire. Client-side filter additions (ItTickets filter/breached, WorkflowAppsList statusFilter useMemo) = presentation views over fetched items, NO new query/endpoint. 2 MINOR (non-block): (a) ProposalDetail status badge now renders TWICE — PageHeader actions slot + existing status-row (cosmetic dup, both presentation); (b) it-tickets/workflow-apps client-filter is view-only over apageSize:100/50first-page fetch (pre-existing pagination limit, re-skin doesn't worsen). Learned: for pure re-skin, the decisive logic-preservation proof isgrep api-call + queryKey sorted -uOLD-vs-NEW byte-equality across every page — faster + more rigorous than reading each hunk; orphan-import heuristic (body-occ<=1) flagsX as Yaliases +React.Xnamespace + comment-words as false-positives, always grep the actual usage line before flagging build-break. surprise: custom accent palettes (amberx/greenx/teal/violet) deliberately ship NO -800 stop so headings MUST use -700 (brand is the only -800-bearing accent) — a -800 on a non-brand accent = silent no-class Tailwind v4, the re-skin respected this everywhere. Verdict PASS — safe for em main to build+mirror. Tag [s69, office-reskin, presentation-only, api-querykey-byte-equal, color-trap-clean, kpicard-inert-vs-filter, gotcha66-clean]. -
2026-06-16 (S65 PE mục E HoSoLink review — em-main PROXY, PE-Workflow reviewer-stage died-empty): Review mục-E hyperlink render + HoSoLink BE wiring (
5a0aaa4). Reviewer-stage trong Workflowpe-hoso-link-rename-proreturn RỖNG → em main self-gate evidence: Detail DTOhoSoLinkpresent +nullbackward-compat phiếu thật (Run #293 GET 200); Create/Update +trailing-optionalHoSoLink=nullKHÔNG vỡ call-site (grep 0 manual ctor — KHÁC CreateDepartmentCommand #291 CS7036 vì positional-required vs trailing-optional); mirror fe-user==fe-admin SHA256 IDENTICAL (PeDetailTabs+PeWorkspaceCreateView); hyperlink<a target=_blank rel=noopener noreferrer>no reverse-tabnabbing; rename "Dự trù PRO"→"Ngân sách PRO" CHỈ display (giữ "Ghi chú từ PRO" + field-code). LEARNED: hyperlink free-text = no server-side XSS (render-as-href client-only); absolute-set Update (null=clear) chủ đích. SURPRISE: reviewer-stage chết-rỗng trong fan-out = lý do verify-heavy task vẫn cần em-main self-gate dù có Workflow (verdictfeedback_workflow_fanout_reliability). Tag[s65, pe-section-e-review, em-main-proxy-self-gate, hosolink-backward-compat, workflow-fanout]. -
2026-06-16 (S65 public Hồ sơ NS read for all roles — static pre-commit, PASS, 0 blocker, gotcha #44 family CLEAN): 1-file change DbInitializer.cs (+66, call-site :2046 SAU revoke :2040 + new
SeedAllRolesHrmProfileReadPermissionsAsync:2203). Prod NOT deployed (static review, build PASS đã claim). 7 verify ALL PASS: (1) Ordering — grant gọi SAURevokeTemporarilyHiddenModulesAsynctrong SeedAsync → grant thắng (git diff confirms call sits immediately after revoke). (2) Upgrade path prod-critical — method MUTATES existing rowif(!row.CanRead){row.CanRead=true;upgraded++}(EF change-tracked → SaveChanges persists); NOT skip-existing-noop. Correctly fixes S58-class bug (revoke set CanRead=false on prod rows → upgrade flips true). (3) Scope precise —hrmKeys = new[]{MenuKeys.Hrm, MenuKeys.HrmHoSo}EXACTLY 2; NO Hrm_Dashboard/Hrm_Config*/Off*/Personal.Hrmis NOT one of 4 inherit-roots (Contracts/Workflows/PE/PeWorkflows in GetMyMenuTree:56-59) so granting Hrm root does NOT cascade to Dashboard/Config children → they keep own false flags → filtered out byHasAccess(n)=n.CanRead||Children.Any(HasAccess). Menu shows Hrm root → Hồ sơ NS leaf ONLY (HrmHoSo ParentKey=Hrm:1806, Dashboard sibling ParentKey=Hrm:1850 stays hidden). (4) Read-only — add-path CanCreate/Update/Delete=false; upgrade-path touches ONLY CanRead. (5) No regression — Admin bypass at MenuPermissionHandler:27 untouched; revoke unchanged; Off/Personal/Dashboard/Config stay hidden after full seed. (6) Idempotent — 2nd run: row.CanRead already true →if(!row.CanRead)false → 0 change. (7) No non-Admin write path —MenuPermissionHandlerRead→AnyAsync(CanRead) is what GET checks; all 19 EmployeesController write actions (main+5 satellite) require Hrm_HoSo.Create/Update/Delete which grant leaves false → 403. surprise/monitor-note (NOT a defect, NOT introduced by this change): HrDashboardController/HrmConfigsController/Attendances/LeaveBalances carry ONLY class-level[Authorize](any-auth, NO per-action Hrm_.Read policy) — so their data was already reachable by direct URL pre+post S65 (menu-hide ≠ API-lock; S58 revoke comment DbInit:2153-2155 explicitly acknowledged this). S65 does NOT widen it (only touches perm matrix rows Hrm+Hrm_HoSo + menu filter). cicd-monitor must NOT assume "Dashboard hidden in menu"=="dashboard data unreachable". Spec comment said "6 catalog Hrm_Config" but there are 6 config leaves + Hrm_Config subgroup = 7 keys — cosmetic count, all stay hidden, not a code bug. Learned: for menu-key read-grant, verify the granted root is NOT an inherit-root (else cascade leaks siblings) + trace HasAccess filter + confirm leaf ParentKey chains to the visible root; upgrade-path correctness = grep that method MUTATES row (not skip-existing) when a prior revoke pre-set the flag false on prod. Verdict PASS — safe commit. Tag [s65, public-hrm-hoso, upgrade-path-correct, inherit-root-no-cascade, gotcha44-family-clean, menu-only-not-api-lock-monitor-note]. -
2026-06-12 (S60 đợt1 PE submit-guard + drafter-bypass gate — KHÔNG DELIVER, die mid-run, on-behalf em main ghi hộ, H2-proposed): Task: review
37122f0cross-stack (BE TransitionAsync submit-guard đủ-4-thông-tin mục 3 + bypass người-soạn-trong-chuỗi V2 BƯỚC-ĐẦU-only + FE PeDetailTabs ×2 + 14 PeSubmitGuardAndBypassTests 240→254). Die mid-run #53-class (commit body tự khai "Reviewer die mid-run → em main self-gate evidence-checklist PASS 0 blocker") → ship Run #283 PASS prod-verified, bundle rotate both. LEARNED: self-gate em main đứng vững lần 2 (sau S57bis) — checklist deterministic (test gate + diff scope + prod smoke 401/404-control) đủ cho PE refinement cross-stack. SURPRISE: die lần 3 trong 2 ngày (S57bis die-0-byte ×2 + S60 mid-run) DÙ promote-tier inherit Fable 5 → model-tier KHÔNG phải nguyên nhân die (nghi resume-kill/harness class) — trend data cho Harness-4. Tag[s60, die-mid-run-3rd, self-gate, on-behalf]. -
2026-06-11 (S57bis product gate — KHÔNG DELIVER, die-0-byte ×2, on-behalf em main ghi hộ, H2-proposed): Cả 2 spawn (email-gate đầu + final gate) chết 0-byte output 0 return (resume-kill class #3, ref
feedback_agent_kill_recovery) → em main SELF-GATE evidence-checklist: grep authz key-set + role-string vs AppRoles + Mig 49 Up/Down reversible + 240 test + Run #381 + prod smoke 401/404-control. LEARNED: output-file size=0 + im >5 phút = chết, KHÔNG đợi thêm; KHÔNG re-spawn >2 lần trong session có--resume. SURPRISE: khác S52 killed-with-partial — lần này 0-byte tuyệt đối (không gì recover được từ return). Tag[s57bis, die-0-byte-x2, self-gate, on-behalf]. -
2026-06-07 (S49 Harness 1/2/3 adopt pre-commit — PASS all 3, no blocker): Governance/infra adopt (no product code, no test impact). VERIFIED: H1/H2 = 2 sub scope-DISJOINT + tools
[Read,Grep,Glob,Bash+4RAG]NO store_memory/Write (INFORM-only); genuinely TAILORED not copy-paste (SE 4-RAG vs AI_INFRA 2-RAG · dropped effort:max + agent-ops-monitor/sister · Fidelity→SEreviewer). H2 5-trục in harvest-curator.md + session-end §L.b(f). H2 wave-mode hmw.js mirror AI_INFRA + B6git check-ignoreVERIFIED (wave-*/+agent-teams/ ignored · hmw.js/README tracked). H3 self=secomplete substitution · SHA256 canonical formula byte-identical send==check · 13 .gitkeep exact · adap-apply base-pathoutbox\all\. honest nấc executed-file/verified-runtime-PENDING. G-015 scan = 6 hits ALL negating ("KHÔNG enforced") = correct honesty. 1 MINOR (non-block): README:11/18 "7-agent" ASCII diagram = PRE-EXISTING drift (git diff proved work này chỉ touch load-bearing title/decision-tree/tool-grant/matrix; diagram predates S47 frontend-designer) → tooling-auditor H1 designed-to-catch = self-validating adoption. learned:git diff base..head= discriminator introduced-defect vs pre-existing-drift (đừng đổ lỗi work mới cho drift cũ); name-collision tailor-verify = diff frontmatter AI_INFRA-canonical vs SE-instance. surprise: mojibake scan false-pos trên "ĐÃ" (U+00C3 = valid VN uppercase, KHÔNG double-encode → verify codepoint in-context trước flag); broadcast floor "12 .gitkeep" UNDERCOUNT (correct=13 inclall/adap-channel — em main đúng). Verdict PASS, safe commit + restart. Tag [s49, harness-adopt, governance, max-clean]. -
2026-05-30 (S43 P11-B LeaveBalance pre-commit — PASS, Max no-truncate): 14 file (LeaveBalance entity+config+Mig42 + Features + Controller + deduction hook + Create/Update LeaveType guard + embed balance + FE×4 + tests). 154 PASS (130→154). Deduction exactly-once VERIFIED (terminal else only, guard Status!=DaGuiDuyet chặn re-approve; advance/reject/return no-deduct). FK invariant fully closed — grep 2 write site LeaveTypeId (Create + UpdateDraft) cả 2 guard AnyAsync→Conflict, bogus type không thể tới terminal FK insert. Embed balance = RequesterUserId (approver thấy đúng người tạo). admin
[Authorize(Roles=Admin)]. 2 MINOR defer: concurrency lost-update UsedDays (no RowVersion — human-sequential accept) · stale line-num comment. Verdict PASS. Tag[s43, p11b-leavebalance, max-clean]. -
2026-05-28 (S35 G-H2 BE CRUD 16 endpoint pre-commit — PASS, Smart Friend 8× CLEAN): 2 NEW file
HrmConfigFeatures.cs439 + Controller 137. build clean, 130/130 PASS. Cat1: 0 mock, 8 ConflictException (Holiday Update composite(Year,Date)BOTH fields). Cat3: class[Authorize]+ 12 per-action[Authorize(Roles="Admin")]. Cat5: 8 Validator MaxLength MATCH EF source (Code=50 not spec 20). 2 MINOR defer: ListHolidays no IsActive filter (inconsistent sibling) · OtPolicy "1 active unique" NOT enforced handler (G-P1 ambiguous nếu 2+ active). Verdict PASS. Tag[s35, smart-friend-8x-clean]. -
2026-05-26 (S33 Plan B G-H1 Phase 2 pre-commit — PASS, Smart Friend 6× CLEAN): 17 file (3 BE + 6 FE new + 6 mod + 2). SHA256 mirror 3 file IDENTICAL admin==user. 5 endpoint real mediator.Send 0 mock. Mig 34
AddEmployeeProfiles7 table UNIQUE indexes + FK Cascade. SeedDemoEmployeeProfiles NOT gated DemoSeed (gotcha #51 ✓). gotcha #50 Layout staticMap mirror ✓. 3 MINOR defer: EmployeeCode race SERIALIZABLE low-risk · Update 3 bool not nullable (partial reset) · Delete DateTime.UtcNow direct. Verdict PASS. Tag[s33, hrm-mig34, smart-friend-6x]. -
Smart Friend cumulative 8× CLEAN: (1) S22 #44 silent-403 · (2) S25 #48 SQLite tie-break · (3) S29 password ≥12 · (4) S29 ApplicableType cross-module · (5) S33 BW test · (6) S33 Plan B Phase 2 · (7) S35 FE forms · (8) S35 G-H2. Plus 9× G-O2 (S36, em không track ở đây). 2 MAJOR catches total (S29 password + S29 ApplicableType); rest clean với MINOR defer.
-
Archived S29-S33 detail + S32 startup →
archive/2026-05-q2.md+ gitd2f52ba(S40 curate): S33 Plan C B-Wrap 9/9 [Fact] verify · S33 startup drift audit (CLAUDE.md SEVERE → patched S40) · S32 wrap/startup standby · S29 wrap 2 MAJOR catch detail. KEY absorbed in bug patterns + Smart Friend cumulative above.
- 2026-06-18 (Harness-10 adap R2-lens hmw.js ENGINE integrity — CONCERN, confirms sibling L1 over-claim still live, pre-commit): Lens = hmw.js engine integrity (em-main rename wave→run-trace). Engine itself CLEAN — all 4 R2 checks PASS: (1) structure valid —
const wave=(A.run&&A.run.dir)?A.run:((A.wave&&A.wave.dir)?A.wave:null):91 nested-ternary paren-balanced 3/3, accepts args.run primary + args.wave alias (additive, old callers OK), varwaveinternal-name kept consistent :91/:92/:95/:103/:107/:132; subMd path :103${wave.dir}/sub-md/${role||'task'}-${i}.mdmatches spec; template-literals balanced (backtick 54 EVEN all-escaped, brace 56/56, paren 140/140, bracket 14/14). (2) zero operative WAVE-MODE — grepWAVE-MODE=0; all 6 wave refs contextualized (legacy-alias :19/:90/:91, "supersedes Harness 2 wave" :87/:109); :113 ISOLATION contains "tracked-change NGOÀI run-folder (runs//)+code-disjoint=vi-phạm" ✓. (3) fan-out logic UNCHANGED —git diff -U0hunks = ONLY :91 behavioral (alias-accept); resolveModel/SCHEMA/checkpointApproved-guard/parallel/results.filter untouched. (4) valid JS (balance + structural, NO node --check per top-level-await). THE CATCH (CONCERN, intersects R2): runs/README.md:51 documents L1 in-run-reminder as firing in "hmw.jsprompt-builder" w/ exact text 'run đang OPEN—nhớ scaffold@P1'+'run trước OPEN-beat đã harvest chưa' → grep that in hmw.js = 0. hmw.js writeGuard :114 emits ONLY C4 return-instruction ("Harvest per-turn primary (C4)..."), NO scaffold/OPEN orchestrator-reminder; :92 is a log() at mode-detect not prompt-injection + still lacks the promised text. Plan-vs-applied gap proven: invest-synthesis:17 PLANNED "C5 Layer1: thêm reminder vào prompt-builder"; implement-synthesis NEVER lists applying L1 to hmw.js (only L2 :71 + L3 :51 applied); yet README:51+C7:72 present L1 as live. Doc asserts engine-behavior grep proves absent = over-claim. Sibling reviewer (same adap, prior run today) already CONCERN on this exact gap — I independently re-confirm UNFIXED. Cross-file PASS: gitignore runs/ TRACKED via!.claude/**:83 (check-ignore -v confirms negation) + wave-*/ kept IGNORED; containment wording synced 4 files (_ledger:4↔hmw:89/113↔runs/README:78); frozen evidence (broadcasts/adap-harness-2/error-ledger/STATUS/HANDOFF/archive_INDEX/sessions) ALL empty-diff; 0 mojibake. Residual (non-block, self-flagged): investigator-codebase/MEMORY.md +6 (29819B ~just-under-cap) = 4 same-role INVEST agents race (concurrency risk #7 invest-synthesis flagged) → em-main reconcile @closeout; new :113 guard forbids sub agent-memory writes = prevents recurrence. Learned: narrow lens (hmw.js JS structure) ≠ excuse to wave a doc-asserts-engine over-claim — when README says a layer "fires in ", grep the engine for the CLAIMED text not a sibling instruction; INVEST-plan ≠ IMPLEMENT-applied. Surprise: engine rename genuinely flawless (dual-alias/balance/logic-frozen) — ONLY defect is adjacent doc over-stating what the clean engine does; engine-perfect + doc-overclaim coexist in one adap. Smart-Friend held: did NOT downgrade to PASS despite narrow lens + clean engine + sibling already-flagged. Tag [harness10, r2-hmwjs-engine, engine-clean-doc-overclaim, c5-L1-overclaim-reconfirm, plan-vs-applied-gap, dual-alias-additive]. - 2026-06-18 (Harness-10 adap run-trace folder R3-floor review — CONCERN, 1 over-claim, pre-commit): Reviewed adap thay wave-mode →
runs/<run-id>/3-part (run.md+sub-md/+harvest/) git-TRACKED. Floor C1-C8 disk-verified. C1/C2 PASS — all 3 runs (invest/implement/review) scaffolded full 3-part (lsconfirm + .gitkeep placeholders). C3 PASS correct-nấc (NO over-claim) —git check-ignore runs/=NOT-IGNORED (tracked-eligible via!.claude/**:83) ANDgit ls-files runs/=EMPTY=NOT-committed-yet; _ledger:4 + runs/README:80 + gitignore:89-99 document "tracked" correctly, NEVER falsely claim "committed". Nấc THẬT = tracked-ELIGIBLE pre-commit (must commit to realize — expected, not defect). C4 PASS — invest+implement synthesis present per-turn; review harvest empty=correct (in-progress). C5 CONCERN (the catch) — L2 (session-start:71 orphan scanclosed=⏳+harvest-rỗng) + L3 (session-end:51 idempotent VERIFY-not-re-APPEND) genuinely wired. BUT L1 OVER-CLAIM: runs/README:51 documents L1 in-run reminder firing in "hmw.js prompt-builder" w/ exact text 'run đang OPEN—nhớ scaffold@P1'+'run trước...harvest chưa' →grep -cthat text in hmw.js = 0. hmw.js writeGuard only emits C4 return-instruction ("Harvest per-turn primary (C4)"), NO scaffold/OPEN reminder. INVEST planned it ("C5 Layer1: thêm reminder vào prompt-builder"), IMPLEMENT synthesis never mentions applying it, yet runs/README:51+C7:72 present L1 as live. Doc-vs-reality gap = over-claim. C6 PASS — _ledger OPEN+CLOSE beats (invest/implement CLOSED, review ⏳) + orphan def:3. C7 PASS — caveat genuinely honest (engine no-fs · C2 fragile · 3-layer=lưới-không-khóa · G-015 TRACKED≠read-only-enforced); strong. C8 PASS — wave→runs migration done (0 wave-/ remain), wave-/ kept IGNORED (verified). Frozen evidence 0-byte-loss CONFIRMED (broadcasts/·adap-harness-2·error-ledger·STATUS·HANDOFF all empty-diff vs HEAD). hmw.jsnode --check=OK, dual-alias A.run/A.wave intact. Containment wording synced 4 files (_ledger:4↔hmw:113↔workflows/README:38↔runs/README:78). Learned: for a multi-layer "anti-miss net" adap, the catch is grepping each layer's CLAIMED trigger-site against the actual engine file — a layer documented as "fires in hmw.js prompt-builder" must have backing text there, not just a sibling instruction; INVEST-plan ≠ IMPLEMENT-applied (cross-check synthesis-plan vs disk). Surprise: README's own C1-C7 section-numbering ≠ task's C1-C8 reviewer-axes (two schemes, NOT a defect — README documents convention, task axes evaluate it); don't conflate. Over-claim=CONCERN per task rule (would be PASS if README:51 softened L1 to "C4 return-instruction" matching reality, OR hmw.js actually added the scaffold reminder). Tag [harness10, run-trace-folder, c5-L1-overclaim, tracked-not-committed-correct-nac, frozen-evidence-clean, plan-vs-applied-gap].
🔄 Curate trigger
-
~30KB → archive recent → L2
archive/<period>.md. Stale >3mo → remove. - Last curate: 2026-06-17 S70 (Harness-9, em-main + Stage-B workflow) (42.5→24.8KB): moved 9 entries S51→S57 (byte-exact) →
archive/2026-06.md; KEPT foundation + 6 newest (S69×2/S65×2/S60/S57bis) + S49/S43/S35/S33 tail + Smart-Friend-cumulative + archive-pointers. Builtarchive/_INDEX.md(substring sha-keyed) +.gist.md(4-field distill-gen:1). Also Stage-C audit actor (wf_9520d8cd-4fe— verify 0-byte-loss/pointer/coverage). No re-ground (additive-only). Prev: S40 (28.4→18KB) · S34 q2 · S22 q1. - Prev curate: 2026-05-29 S40 em main proxy (28.4→~18KB): archived S33 Plan C + S33 startup + S32×2 + S29 wrap detail → q2 + git d2f52ba; refreshed stale (81/111→130 test, 47→55 gotcha, 31→40 mig, ~146→211 endpoints). Foundation (bug patterns + 5-category + Smart Friend guard + cross-module security) preserved. Prev: S34 q2 · S22 q1.