From e939fab50ab24c2cb772049bc46619251a2bfe14 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Thu, 25 Jun 2026 08:35:26 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Memory:=20sleep-compress=20L2=20test?= =?UTF-8?q?-specialist=20=E2=80=94=20activity-s51-s52.gist.md=20additive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /sleep-recovery-memory-l2 all (S88). Phase 0 scan: 18/19 L2 verbatim SKIP (14x 2026-05-qN.md already in aggregate 2026-05.gist.md gen:1, verified by reading source-decl; 4x 2026-06.md double-distill guard gen 1-2; 5 subs empty archive). 1 distilled: test-specialist activity-s51-s52.md (gen-0 orphan, no gist) -> activity-s51-s52.gist.md (distill-gen:1), 4 records -> 3 clusters (C-A merges the 2 gotcha#57 episodes). reviewer Fidelity-gate FAIL v1 -> re-distill: C-A merge had mis-attributed the whole fix to "Mig 45"; verbatim ties Mig 45 to HRM-only (LeaveTypes/ ShiftPatterns), Master (Dept/Project/Supplier) = Mig 47 per canonical CLAUDE.md. Split per-episode -> PASS. coverage-diff 26/26, G-009 clean, ratio 97% (signal-dense, report-not-target). last_sleep_at -> 2026-06-25. +reviewer self-harvest: merge-distill false-specificity anti-pattern (presence-gate blind to cross-episode shared-token mis-attribution). Co-Authored-By: Claude Opus 4.8 --- .claude/agent-memory/memory-budget.json | 2 +- .claude/agent-memory/reviewer/MEMORY.md | 1 + .../archive/activity-s51-s52.gist.md | 44 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .claude/agent-memory/test-specialist/archive/activity-s51-s52.gist.md diff --git a/.claude/agent-memory/memory-budget.json b/.claude/agent-memory/memory-budget.json index a113003..562b3d2 100644 --- a/.claude/agent-memory/memory-budget.json +++ b/.claude/agent-memory/memory-budget.json @@ -1,7 +1,7 @@ { "_note": "Harness-9 (S70, 2026-06-17) memory budget. Caps SEEDED BY MEASUREMENT (scripts/measure-agent-memory.ps1), NOT imagined headroom. Budget-audit @session-start (session-start.md §2.1.2): if curate-to-fit is dropping important markers, BUMP the relevant cap rather than cut markers. Re-measure with the script; never hand-edit measured_bytes.", "seeded_date": "2026-06-18 (S71 re-measure after G1 curate — reviewer 36.7KB + investigator 29.8KB over-cap from S71 same-role race, curated L1->L2 back under auto-inject cap)", - "last_sleep_at": "2026-06-18", + "last_sleep_at": "2026-06-25", "_last_sleep_at_note": "Harness-10b sleep-recovery (S72): timestamp lan cuoi chay /sleep-recovery-memory-l2. null = chua tung. session-start §2.1.2 + session-end §L.b(c) doc field nay -> INFORM goi-y nen L2 neu null hoac today-last_sleep_at>=7 ngay. Lead=single-writer (chi command sleep set field nay).", "tiers": { "l1_hot": { diff --git a/.claude/agent-memory/reviewer/MEMORY.md b/.claude/agent-memory/reviewer/MEMORY.md index 9469ec7..0783b94 100644 --- a/.claude/agent-memory/reviewer/MEMORY.md +++ b/.claude/agent-memory/reviewer/MEMORY.md @@ -69,6 +69,7 @@ Adversarial pre-commit reviewer SOLUTION_ERP. Read-only verify + live curl prod - **S71 (2026-06-18) Harness-10 run-trace + finalize double-check — PASS/GAPS:** "TRACKED" containment 2-level = check-ignore(eligible) vs `git ls-files`(committed) — model chỉ work post `git add`. "Hoàn chỉnh toàn bộ" audit phải check `budget.json` measured-bytes vs DISK (over-cap re-accumulate mỗi session). → _INDEX S71*. - **S69 (2026-06-17) Office re-skin + golive authz — PASS:** re-skin logic-preservation proof = `grep api-call + queryKey sorted -u` byte-equal OLD-vs-NEW (nhanh+rigorous hơn đọc từng hunk); public-grant security = granted root NOT inherit-root (no sibling cascade gotcha#44-family) + menu-key KHÔNG dùng làm controller `[Authorize(Policy=)]` (Office=class-`[Authorize]`+Roles=Admin → CanCreate FE-only, không escalate API write). color-trap: accent thiếu -800 stop = silent no-class Tailwind v4. → _INDEX S69*. - **S65 (2026-06-16) public HRM Hồ sơ + PE mục E — PASS:** upgrade-path phải MUTATE row (`if(!row.CanRead){...}`) KHÔNG skip-existing khi prior revoke pre-set flag false (fix S58-class); menu-hide ≠ API-lock (class-`[Authorize]` controller data reachable direct-URL bất kể menu). hyperlink free-text = no server-side XSS. → _INDEX S65*. +- **S88 (2026-06-25) Fidelity-gate `/sleep-recovery-memory-l2` gist distill (test-specialist L2) — FAIL (1 fabrication-by-merge):** gist MERGE 2 episode gotcha#57 (S51-HRM + S52-Master) vào C-A cluster, KẾT-LUẬN span cả 2 Code-list `{Departments|Projects|Suppliers|LeaveTypes|ShiftPatterns}.Code` NHƯNG gán **"in Mig 45"** cho TOÀN cluster. Verbatim chỉ tie Mig 45→2 HRM config; S52-Master record CỐ Ý ghi "migration" KHÔNG số (vì fix ở mig riêng sau). Canonical CLAUDE.md xác nhận Master filtered-unique = **Mig 47** không phải 45 → gán SAI affirmatively cho Master half. **Anti-pattern: merge-distill fabricates false specificity — gán 1 token dùng-chung (`Mig 45`) cho cluster span N episode khi chỉ 1 episode mang số đó.** Phase-3a deterministic token-PRESENCE pass (ratio 92%, 30 token present, mojibake-clean) BLIND tới cross-episode mis-attribution — đúng lý do QUALITY gate đứng SAU presence gate. Mọi thứ khác faithful: 2 episode-distinct fact (S51 2-GREEN-Vehicle/Driver-Mig44 + S52 3-ALL-RED) giữ riêng, HRM-ref correction `active-count plain DbSet / all-count IgnoreQueryFilters()` không embellish, FIFO caveat (185/191/200 flag episode-local), 4 back-resolve substring count=1 unique, OtWeighted=12.0m + SLA 4/8/24/72h + Serializable-SQLite-NON-ISSUE khớp. Fix hẹp = đừng gán Mig-number cho Master half (giữ vagueness verbatim hoặc split per-episode). --- diff --git a/.claude/agent-memory/test-specialist/archive/activity-s51-s52.gist.md b/.claude/agent-memory/test-specialist/archive/activity-s51-s52.gist.md new file mode 100644 index 0000000..1991a06 --- /dev/null +++ b/.claude/agent-memory/test-specialist/archive/activity-s51-s52.gist.md @@ -0,0 +1,44 @@ +distill-gen: 1 +# Gist — activity-s51-s52 (test-specialist · S51-S52) · 4-field distillation + +> **distill-gen: 1** — already-distilled; do NOT re-compress (Phase 0.3 double-distill guard). Each block = VIỆC · KẾT-LUẬN(+file:line) · BÀI-HỌC · BẤT-NGỜ, ending `→ substring:"…"` that grep-resolves UNIQUE in the verbatim file. Pointer-style = substring (Ctrl-F), file/phrase keyed. value tag: cao/vừa/thấp. +> source-verbatim: `activity-s51-s52.md` (4 records → 3 clusters; C-A MERGES the two gotcha#57 episodes S51-HRM + S52-Master). Distilled S88 (2026-06-25) via /sleep-recovery-memory-l2, harvest-curator Phase-1 propose + reviewer Fidelity-gate. +> ⚠️ Counts (185 / 191 / 200 PASS) are EPISODE-LOCAL FIFO-snapshots (S51-S52-era), NOT current state — canonical current → `docs/STATUS.md`. + +--- + +## C-A · gotcha #57 filtered-unique soft-delete (MERGED S51-HRM + S52-Master) [cao] + +**VIỆC:** Test-before reproduce **gotcha #57** across 2 episodes — S51 HRM (`HrmConfigFilteredUniqueTests.cs`, +4: 2 GREEN Vehicle/Driver Mig 44-already-filtered + 2 RED LeaveType/Shift) → S52 Master (`MasterCatalogFilteredUniqueTests.cs`, +3 ALL RED Dept/Project/Supplier). test-before. + +**KẾT-LUẬN:** Bare `.IsUnique()` (Master configs `Dept cfg:18` / `Proj:19` / `Supp:24`) counts soft-deleted rows → `SQLite Error 19 UNIQUE constraint failed` on `{Departments|Projects|Suppliers|LeaveTypes|ShiftPatterns}.Code`. ROOT-CAUSE: app-check `AnyAsync(Code==X)` passes THROUGH `HasQueryFilter` (excludes soft-deleted → PASS) → `Add+SaveChanges` → DB UNIQUE counts the dead row → throw. **Fix = `.HasFilter("[IsDeleted]=0")`** (disk-true form `[IsDeleted] = 0`, with spaces) → flip GREEN — PER-EPISODE (do NOT cross-attribute): HRM `LeaveTypes`/`ShiftPatterns` in **Mig 45** (S51); Master `Departments`/`Projects`/`Suppliers` in **Mig 47** (S53, gotcha #57 EXT — per canonical `CLAUDE.md`; the verbatim Master record left the migration number bare). Handlers 1-dep `Create{Dept|Project|Supplier}CommandHandler(db)` / `new CreateXxxHandler(db)`. Verdict: S52 `3 RED` (Failed 3/Passed 0); S51 `2 RED INTENTIONAL + 2 GREEN`. RED ≠ test bug → REPORTED em main fix migration. + +**BÀI-HỌC:** all-count assertion MUST use `IgnoreQueryFilters()` (verified 3× on disk in Master test) — **CORRECTED** the HRM-ref's wrong `Count(Code==X)`-on-filtered-DbSet (returns 1 not 2 because DbSet already carries HasQueryFilter). Reusable pattern = **active-count = plain DbSet · all-count = `IgnoreQueryFilters()`**. Mirror = `HrmConfigFilteredUniqueTests` GROUP B / `HolidayTests Case 7` (seed-soft-deleted-slot origin). + +**BẤT-NGỜ:** `AuditingInterceptor` (prod soft-delete Deleted→Modified+IsDeleted=true) NOT wired in `SqliteDbFixture` → `Remove+SaveChanges = HARD delete` (can't test soft-delete via Remove) → must seed row `IsDeleted=true` manually to simulate the occupied Code-slot. + +→ substring:"all-count PHẢI" (IgnoreQueryFilters nuance, S52-Master record) + substring:"AuditingInterceptor (prod soft-delete" (soft-delete-in-test surprise, S51-HRM record) + +## C-B · round-robin assign + SLA-due [vừa · S52] + +**VIỆC:** +9 test `ItTicketAssignSlaTests.cs` (Infra 133→142, baseline 191→**200**); proxy by em main (agent killed session-limit before MEMORY step). + +**KẾT-LUẬN:** Round-robin assigns lowest-load `IsActive` user in Dept `Code="IT"` (A=1-open ticket vs B=0 → assign **B**, load 0<1); tie `A=B → ThenBy(Id)`; edge no-dept-IT / no-user-IT / user-outside-IT / `IsActive=false` → unassigned. SLA-due `Urgent→+4h / High→+8h / Medium→+24h / Low→+72h`, assert `SlaDueAt == CreatedAt + SlaWindow[priority]`. Regression P11-F: code-gen still `^IT/\d{4}/\d{3}$`. + +**BÀI-HỌC:** assign + per-priority SLA-window unit-testable via direct handler; window = flat lookup table. + +**BẤT-NGỜ:** `ItTicketSlaJob` BackgroundService SKIP unit-test — breach-query inline, hard to test directly (REPORTED, not covered). + +→ substring:"load 0<1" + +## C-C · codegen day-type + Serializable-SQLite-OK [vừa · S52] + +**VIỆC:** +5 test (Infra 128→133, 191 PASS): `ItTicketCodeGenTests` (3) + `AttendanceReportTests` (2), P11-E/F test-after. Handler `CreateItTicketHandler(db, cu, clock)` 3-dep MediatR. + +**KẾT-LUẬN:** Codegen `^IT/\d{4}/\d{3}$` sequential `001→002` per-prefix `IT/{year}` LastSeq++, `2027 reset 001`. Day-type: holiday check runs BEFORE weekend/weekday → seed `2026-06-01 (thứ Hai)` into holidaySet → asserts **Holiday** despite weekday (override day-of-week); `Holiday.Date=DateOnly` → `BuildHoliday` uses `DateOnly.FromDateTime`. `OtWeighted = 2×1.5+3×2.0+1×3.0 = 12.0m`. DepartmentId filter joins Users `u.DepartmentId==deptId` with `DefaultIfEmpty` (dept row optional). + +**BÀI-HỌC:** holiday-precedence-over-day-of-week = core day-type rule. MSBuild-OOM on full parallel → `-maxcpucount:1 -p:BuildInParallel=false` (env resource, NOT test fail). + +**BẤT-NGỜ:** **Serializable-on-SQLite GOTCHA = NON-ISSUE (confirmed)** — `BeginTransactionAsync(IsolationLevel.Serializable)` in `WorkflowAppCodeGen.GenerateMaDonTuAsync` runs CLEAN on SQLite (provider maps isolation gracefully, no throw); format+seq+per-year hold without try/skip. Also proven by `WorkflowAppApproveV2Tests` (DT/LR path). + +→ substring:"Serializable-on-SQLite GOTCHA = NON-ISSUE"