STATUS/HANDOFF S45 (154->181 test, Mig 43) + gotcha #57 (soft-delete UNIQUE must filter [IsDeleted]=0) + session log + root CLAUDE counts + ef-core skill Mig 43 row + flush 3 agent MEMORY (test-specialist proxy after #53 truncation + cicd Run #368 + investigator P11-C recon). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.9 KiB
Session 45 — HRM test-gap stabilization + Holiday drift fix (Mig 43)
Date: 2026-06-01
Scope: Tests + Infra (schema)
Commits: 051b62b (Tests) → 0c5a014 (Mig 43) → docs (this session-end)
CI: Gitea Run #368 (run_number 254) PASS ~4m20s — verified prod
Test: 154 → 181 PASS (58 Domain + 123 Infra, 0 fail / 0 skip)
Bối cảnh + quyết định
Anh giao quyền chọn thứ tự việc. Em main chọn "stabilize before extend": đóng 3 test-gap deferred từ S35-S38 TRƯỚC khi chồng schema Phase 11 mới (P11-C). Lý do: 1 gap CRITICAL-flagged, nhỏ + low-risk, deferred nhiều session; làm xong baseline vững rồi mới thêm Mig.
Việc done
1. Đóng 3 test-gap (commit 051b62b, +27 test)
🟪 test-specialist viết (em main chốt test plan sau recon 8 file):
- Gap1 (CRITICAL) —
HrmConfigHolidayTests.cs(7 test): Holiday composite UNIQUE (Year, Date). Create duplicate → Conflict; same-date-diff-year → OK; Update→occupied-slot → Conflict; ⭐ self-update giữ (Year,Date) đổi Name → KHÔNG false-positive (guard short-circuitentity.Year!=req.Year || entity.Date!=req.Date); Update→empty-slot OK; Update non-existent → NotFound; soft-delete exclusion. - Gap2 (MAJOR) —
EmployeeSatelliteTests.cs(10 test): 5× FK-invariant (mọi Create satellite guard parentAnyAsync(Id && !IsDeleted)→ NotFound); soft-deleted parent → NotFound; happy path FK đúng; Delete soft + DeletedBy + re-operate NotFound; DeleteEmployeeProfile soft KHÔNG cascade satellite (behavior hiện tại — handler chỉ soft-delete parent); EF modelDeleteBehavior.Cascadeconfig assertion (lock schema intent). - Gap3 (MAJOR) — extend
AuthorizePolicyRegressionTests.cs(10 test): 2 controller shape KHÁC nhau lock đúng intent —HrmConfigsController(class[Authorize]trần Policy/Roles null + writesRoles="Admin") vsEmployeesController(classPolicy="Hrm_HoSo.Read"+ per-action Create/Update/Delete + 1 satellite representative).
⚠️ gotcha #53 recurrence: test-specialist return truncated mid-MEMORY-update ("let me read it first"). → em main verify-on-disk (glob + git status + đọc 3 file line-by-line + dotnet test) thay vì tin output cụt. MEMORY proxy-updated bởi em main.
2. Holiday drift fix (commit 0c5a014, Mig 43)
👤 em main solo (bug-fix reasoning chain + schema decision tightly coupled → tránh spawn-truncation cho change nhỏ).
- Bug Gap1 lòi ra:
HolidayConfigurationDB UNIQUE(Year,Date)plain.IsUnique()KHÔNG filter, trong khi handler check!IsDeleted→ admin xoá (soft) 1 ngày lễ rồi tạo lại cùng (Year,Date) → app-check PASS nhưng DB UNIQUE reject →DbUpdateException500 reachable. - Fix:
.HasFilter("[IsDeleted] = 0")— khớp pattern 13× sẵn có (Catalogs ×4, Contract/PE/Proposal/Budget/WorkflowApps code-unique). Mig 43FilterHolidayUniqueIndexByIsDeleted(DropIndex + CreateIndex filter; Down reverse sạch). Applied Dev + Design LocalDB. - Test flip: Case 7 từ assert
DbUpdateException→ assert SUCCESS (reuse slot, 1 active + 1 soft-deleted). Spec-change → update test cùng commit. - Table count vẫn 91 (index-only mig, no CREATE TABLE).
3. cicd verify (🟩 Run #368 PASS)
test gate 181 · Mig 43 applied prod (__EFMigrationsHistory top) · IX_Holidays_Year_Date filter_definition = ([IsDeleted]=(0)) live (was NULL) · FE bundle UNCHANGED Krjvg_3j/6sNStgxa (đúng — BE-only push, KHÔNG flag ship-fail) · health 200 · 0 regression.
4. P11-C pre-flight (🟦 investigator-codebase)
Vehicle+Driver catalog: chưa có master entity (chỉ VehicleBooking free-text Mig 39). Recommend: extend HrmConfigs +2 kind (vehicles+drivers) declarative KIND_CONFIG, Mig 44, giữ VehicleBooking free-text (FK link defer). Caught gotcha #57 backlog (LeaveType/Shift unfiltered).
Learnings
- gotcha #57 NEW: soft-delete + UNIQUE → MUST
.HasFilter("[IsDeleted]=0"). Backlog: LeaveType.Code + ShiftPattern.Code vẫn unfiltered. feedback_background_spawn_visibility: spawn agent foreground = im lặng vài phút = "looks frozen" (anh phản hồi). → đẩy long work background + report "đã launch X" ngay. Cũng có 1 dead turn ("No response requested") = hiccup thật, em main nhận.- Test theo CODE = single source of truth → test lòi drift thật (Holiday) → REPORT → fix proper. Closed loop: gap test → bug surfaced → fixed + verified prod cùng session.
- EF model-metadata assertion (
db.Model.FindEntityType(...).GetForeignKeys()...DeleteBehavior) = cách lock schema intent (cascade) không cần DB round-trip — Pattern-10-style cho EF model.
Next (S46, anh pick)
P11-C Vehicle+Driver (Mig 44, recon ready) · gotcha #57 fix LeaveType/Shift filtered-unique (gộp P11-C) · P11-D ItTicket SLA / P11-E AttendanceReport / P11-F MaTicket · Phase 9 Ops.