Files
solution-erp/docs/STATUS.md
pqhuy1987 5e6dcc1479 [CLAUDE] Docs: S63 closeout S60-62 — re-tier STATUS/HANDOFF + count-flush (Mig 50, 88 bang, 263 test, 64 gotcha) + reconcile stray reviewer + gotcha #63/#64
Viet bu docs cho S60/S61/S62 (ship code prod-verified nhung chua closeout — drift bat o /session-start S63 qua git log).

- Reconcile stray reviewer cwd-misland: MOVE 2 file con fe-admin/.claude -> canonical + pointer (no overwrite 31KB) + xoa stray

- Commit harvest S61/S62: cicd-monitor MEMORY (Run #286) + gotcha #63 (EF RenameColumn sai-semantics) + #64 (Design-DB vs Dev-DB data-migrate)

- Count-flush 4 file: Mig 49->50, tables 93->88, test 240->263 (45D+218I), gotcha 62->64, menu 57->53, Budget module REMOVED->PeWorkItemBudgets

- Session-log bu 2026-06-12-S60-S62-pe-budget-workitem-softwarning.md. Docs-only -> CI skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:41:47 +07:00

280 lines
69 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# STATUS — Snapshot hiện tại
> **Update rule:** trước khi bắt đầu 1 task → ghi row `🔥 In Progress`. Xong → `✅ Recently Done`.
> **Tiering rule (S40):** chỉ giữ **state hiện tại + 3 session gần nhất** ở file này. Session cũ hơn → `docs/changelog/sessions/`. Full history pre-S40 → `docs/_archive/STATUS-preS40-fullhistory.md`. (Tránh over-context — xóa double, không cắt nội dung.)
**Last updated:** 2026-06-15 (S63 docs-closeout bù S60/S61/S62 — **State THẬT: Mig 50 · 88 bảng · 263 test (45D+218I) · 64 gotcha · menu 53 · bundle admin `0xKYGhhf`/user `C81ZdG9G` Run #286**; S60-62 = PE ràng buộc gửi-duyệt + bypass drafter (S60) · gỡ "Từ chối" (S60) · Mig 50 ngân sách per-gói-thầu Excel anh Kiệt + XÓA module Budget cũ (S61) · vượt-NS cảnh-báo-mềm cho lưu (S62); + reconcile stray reviewer cwd-misland; session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`). Prev Session 59 ( **10 đợt ship prod-verified: 8 Run PASS + 2 cancelled-supersede-benign #273→#282** (run_number API — dải đếm khác #38x S58, cùng pipeline; 2 cancel = push-đè khi UAT góp ý realtime, ancestor-verified): (1) **wipe transactional testing data** theo anh Kiệt FDC — 10 PE + 7 HĐ [DEMO] + 64 notif + 1 AwV2 cũ inactive = 0, reset PeSeq/CtSeq → phiếu thật đầu tiên team tạo chiều nay = **PE/2026/A/001** ✓, app-recycle KHÔNG resurrect (DemoSeed gate held), uploads orphan dọn (`56882ac` #273); (2+3) **PE tree Panel 1 chốt 4 tầng "📅 Năm > 📁 Dự án > 🧱 Hạng mục > Phiếu"** (anh chốt follow-up sau bản gộp "Dự án (Năm)"; `yearGroups` useMemo, expand-key v3, FE-only — list DTO đã có workItemName S57bis) (`0eafcd3` #274); (4) **dọn 15 mã hạng mục demo tự chế** theo chị Trà Sol "xóa cái đám phần thô phần hoàn thiện… MÀ ANH TỰ ĐẺ RA" — WorkItems 86→**71**, GỠ HẲN block seed demo khỏi DbInitializer, đối chiếu 71/71 khớp bảng PMH từng dòng (`bbd1554` #275, bundle frozen BE-only); (5) **rename 71 mã đúng format PMH anh Kiệt chốt** "MÃ CV gồm chữ MEP-SUB-1 rồi tên 1 MEP Sub MEP (Full) — đúng kiểu vậy" → `MAT-n`/`SUB-n`/`MEP-SUB-n`/`MEP-EQU-n` + Name "STT nhóm tên"; **DB-trước-code-sau** (gotcha **#62** NEW — seed per-code idempotent, sai thứ tự = 142 rows) + sqlcmd `-f 65001` (gotcha **#61** NEW — verify data qua API JSON, KHÔNG tin console mojibake) + FE sort numeric ×3 ×2 app (`c869d26` #276); (6) **UAT 6 vòng 11 điểm**: NEW **`ui/SearchableSelect`** combobox gõ-lọc BỎ DẤU (fold NFD — Hạng mục/Dự án/NCC) + auto Địa điểm từ Project.Location + điều khoản TT Textarea đa dòng (`faed59f` #277) · anh chốt: **ẩn cả Trả lại+Từ chối khi người duyệt = người soạn** (drafterUserId match) + **quick-add NCC ngay form** (SuppliersController POST hạ → any-auth, PUT/DELETE giữ khóa — cicd authz probe live 4/4: 401 unauth/201 nv.test/403 delete/cleanup) + upload multiple files ×2 chỗ (`9c330d2` #278) · vòng 3-6 realtime (`f21c55d` #279-cancelled / `69997da` #280 / `80b64dd` #281-cancelled / `792c030` **#282 FINAL**): **bảng NCC table-fixed** width từng cột (file dài hết vỡ layout) + **bỏ ô "Tên" ngân sách nhập tay** (chỉ còn Số tiền, hasManual detect theo amount) + **GỠ field "Điều khoản thanh toán" khỏi TẤT CẢ form phiếu** (cột per-NCC + display phiếu cũ GIỮ) + **bỏ nút "+ Thêm hạng mục"** (1 phiếu = 1 hạng mục header). Bundle FINAL admin **`B1DtNT9C`**/user **`D6uF3Mln`** (Run #282). Test 240 ×2 local + 8× CI gate. **0/14 spawn truncated** (lần đầu sau nhiều session). → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`. Prev S58 (2026-06-11 — **4 việc prod-verified Run #382/#383/#384**: lock-demo-user fix + tạm ẩn HRM/Office/Cá nhân + Danh mục cuối sidebar + fe-user redesign theo UI/UX guide AI_INFRA. **Việc 1 — lock fix** (Run #382, `5998163` ~3m31s): Run #381 cicd phát hiện S57bis lock = NO-OP (14 email named-person là population Dev-only). Recon dump prod: demo thật = 20 UAT-matrix `{dept}.{nv,pp,tp}@`+`bod.{1,2}@` tạo TAY 05-13; root cause sâu = `DemoUserPassword` 11 ký tự < prod `RequiredLength=12` `CreateAsync` silent-fail MỌI startup từ trước tới giờ (= root cause "helpdesk inert phòng IT 0 user" S56). Fix: union 20 email + password 12 tự. Prod sau deploy: **55 user / 21 active / 34 locked** 20 UAT + 14 named-person locked ✓, **nv.cao/nv.truong CREATED+ACTIVE (helpdesk S56 RESOLVED)** ✓, 5 real staff created ✓, guard admin/catalog.manager/nv.test/chuong.phan-typo active (anh chốt 3 quyết định AskUserQuestion). Bundle FROZEN. gotcha **#60** NEW (seed silent-fail vs prod password policy dump population thật trước khi lock/seed-by-email). +Closeout S57bis residual: gotcha #59 commit, 4 spawn-record on-behalf (H2 4-MISS), H1 5-patch doc-drift, test 240 re-verified local. Prev S57bis (2026-06-11 sáng) **PE gắn Hạng mục công việc (Mig 49) + mở quyền Pe all-role + menu "Cá nhân" + khóa demo user** (sếp Zalo deadline 15:00): commit `17b23a4` (Harness-4 two-tier runtime-VERIFIED spawn-test 2 chiều) + `dd117b7` (product) Run #381 PASS ~4m25s. Mig 49 `AddWorkItemToPurchaseEvaluation`: PE.WorkItemId `Guid?` loose-Guid KHÔNG FK vật (convention PE database-agent design) + IX + validator NotEmpty create + FK-guard handler Conflict + UpdateDraft null-safe. FE ×2 app PeWorkspaceCreateView/PeHeaderForm (SHA256 identical)/PeDetailTabs "Dự án Hạng mục". Pe_* 11 key CanRead+CanCreate mọi role (130 rows/13 role Pe_* leaf KHÔNG nằm MenuKeys.All, build qua factory). Menu Personal root@30 + Chấm công re-parent + Master write-lock `Admin,CatalogManager` ×3 controller. Test 228→**240** (+12 PeWorkItemGuardTests). Bundle rotate cả 2: admin `CP4CB1ym` / user `BmZ3VHnm`. 2 builder truncated #53 + reviewer die-0-byte ×2 em main solo cross-stack + self-gate. Excel (3) đối chiếu = NO-CHANGE (S55 data identical). Prev S56 **Pre-golive verify sweep + golive-harden 4 fix — HMW 2-workflow, prod-verified**: commit `a20cde8` Run #379 PASS ~4m20s. WF1 `pre-golive-verify` 7-stream song song + adversarial 6 PASS/1 CONCERN/0 blocker = **GO**; key finds = **ops not code** (prod IT-dept 0 active user helpdesk inert + S43 LeaveBalance lost-update còn nguyên). WF2 `golive-harden` fix 4: **#3** LeaveBalance lost-updateatomic `ExecuteUpdateAsync`+Serializable tx (NO mig, exactly-once nguyên) · **#5** ItTicket authz Forbidden-trước-NotFound (fail-closed) · **#6** DocxRenderer null-guard (2 warn0) · **#4** Travel/Vehicle ApproveV2 +4 smoke. Test **216→228**. Bundle FROZEN `4SUwDLD8`/`XdKzt9LL` (BE-only). `sys.tables` re-ground **92→93** (cicd ground-truth, Mig 48 col-only). reviewer stage StructuredOutput-failem main đỡ cross-stack review (3 diff clean) + bump Serializable đóng MAJOR. gotcha **#58** NEW (EF read-modify-write lost-updateExecuteUpdate atomic). **2 ops VPS pending** (gán user phòng IT + `tzutil` UTC+7). FE Phase 2 redesign **deferred** (recon ready). Prev S55 **Nạp master data thật từ Excel + Project +4 cột (Mig 48), HMW-mode ON**: commit `69cb393` Run #377 PASS ~4m33s, prod-verified. Anh giao file Excel "HẠNG MỤC CÔNG VIỆC DỰ ÁN" `/ultra-on "workflow làm xong hết"`. Nạp **62 dự án + 71 hạng mục + 3 NCC** vào Project/WorkItem/Supplier qua `SeedRealMasterDataAsync` (per-code idempotent, **UNGATED** coexist demo, tự lên prod). **Mig 48 `AddProjectMasterFields`**: Project +4 cột nullable (Year/Investor/Location/Package, NO new table). FE ProjectsPage form +4 input ×2 app SHA256 mirror. Test 216 (compile-fix MasterCatalogFilteredUniqueTests +4 null args, no new test). Bundle admin `DmjI8Cmn``B-d6893W`/user `YxL_MljK``XdKzt9LL` (cả 2 rotate). Prod verify: Mig 48 applied · Projects spot-6/6 · WorkItems VT/TP/MEP/TB=71 · Suppliers 3 · CAL01.Investor="Công ty TNHH Calofic". **2 agent return truncated** (implementer-backend + reviewer, gotcha #53) em main disk/runtime-recover (build/test/sqlcmd/git truth); cicd verdict-FIRST PASS clean no-truncate. Data-quality catch: MEP col gộp 2 nhóm + divider "THIẾT BỊ" split đúng 71/4-category. Provenance `scripts/master-import-data.generated.md`. Prev S54 **IT staff tự reassign ticket (cross-stack authz, HMW-mode ON)**: 1 code commit `ca4b602` Run #376 PASS ~4m18s, prod-verified. Cho tổ IT (dept Code=="IT") + Admin reassign ItTicket trên CẢ 2 app. BE: NEW `GetAssignableItStaffQuery` capability endpoint `{canReassign,staff}` + `AssignItTicketHandler` authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict) + controller `/assign` hạ `[Authorize(Roles=Admin)]``[Authorize]` (handler fine-grained). FE: fe-admin+fe-user ItTicketsPage **SHA256-identical** (REVERSE S53 divergence) gate nút by `canReassign`, dropdown từ `/assignable-staff` (không `/users`). Test 203→**216** (+13 authz guard test-before-merge). NO migration (DepartmentId reuse). Bundle admin `DfCfHUE9``DmjI8Cmn` / user `_3S0BPJ2``YxL_MljK` (cả 2 rotate). 6-agent fan-out (BEFEtestreviewercicd) + em main reconcile stray-memory residual (3 agent ghi MEMORY nhầm `src/Backend/.claude` harvest về canonical). reviewer PASS 0 blocker (role-string "Admin" chain-verified). Task 1 Phase 9 Ops KHÔNG làm (anh dừng). flag: cicd `sys.tables=93` vs STATUS 92 monthly audit re-ground.) Prev S53 (gotcha #57 EXT Master Mig 47 + P11-D reassign-UI fe-admin + P11-E menu + database-agent verified-runtime: `44b9e54` Run #260 + `dbf6648` Run #261, test203, bundle`DfCfHUE9`). Prev S52 (Phase 11 P11-D+E+F deployed + database-agent adopt, HMW-mode ON): 3 commit `e9ee97f` (database-agent DB1DB11 read-advisory, roster 1011, executed-file CHỜ restart) + `6a66429` Wave 1 (P11-E AttendanceReport+Excel+OtPolicy multiplier + P11-F MaTicket codegen, migration-free) + `dcf76f8` Wave 2 (P11-D ItTicket round-robin assign dept-IT + SLA timer, Mig 46). Test 186→**200**. Bundle admin `DYfjnpY0`/user `_3S0BPJ2` (cả 2 deploy verified curl độc lập Wave 1 BE 401 wired + Wave 2 /assign 401 + Mig 46 applied health-200). **Session-limit hit giữa Wave 2** recovery: BE/test verify-on-disk + em main solo FE redo + curl-self-verify thay cicd-spawn (multi-agent resilience, git/disk/prod = source-of-truth). RAG recovered (chunk 2416 rerank live) nhưng stale 05-29. Prev S51: P11-C Vehicle+Driver.)
---
## 🎯 CURRENT STATE (verified S40)
| Metric | Value | Note |
|---|---|---|
| Migrations | **50** | +S61 Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (bảng `PeWorkItemBudgets` per-gói-thầu + DROP module Budget + backfill BudgetManualBudgetPeriod TRƯỚC DropColumn + DROP PE/Contracts.BudgetId; gotcha #63/#64). Prev Mig 49 PE WorkItemId (S57bis) |
| SQL tables | **88** | re-ground S62 (cicd `sys.tables` Run #286 Mig 50 XÓA module Budget (drop nhiều bảng) + CREATE `PeWorkItemBudgets` net 9388) |
| Master data (prod) | **71 WorkItems PMH-only S59** | 62 Projects + **WorkItems = ĐÚNG 71 mã PMH** (S59: wipe 15 demo + rename format anh Kiệt `MAT-1..16`/`SUB-1..30`/`MEP-SUB-1..9`/`MEP-EQU-1..16`, Name "STT nhóm tên") + Suppliers 22 (3 real + demo; POST mở any-auth S59 quick-add). Transactional testing data wiped S59 (PE//Notif = 0 baseline, phiếu thật từ A/001). Provenance `scripts/master-import-data.generated.md` |
| API endpoints | **~253** | +1 S54 `GET /it-tickets/assignable-staff` (capability endpoint); +3 S52 (attendances/report + report/excel + it-tickets/{id}/assign) |
| FE pages | **68** | unchanged S54 (ItTicketsPage reassign = in-place 2 app); +1 S52 AttendanceReportPage |
| Menu keys | **53** | re-ground S61 (`MenuKeys.cs` const Mig 50 gỡ 4 `Bg_*` Budget menu ). Prev 57 (S58) |
| Tests | **263 PASS** | 45 Domain + 218 Infra · 0 fail / 0 skip · S61 +22 `PeWorkItemBudgetTests` 14 `BudgetPolicyTests` 1 263 · S60 +14 `PeSubmitGuardAndBypassTests` +2 spec 256 (Domain 5845 do drop Budget module tests) |
| Gotchas | **64** | +2 S61: **#63** EF scaffold tự sinh `RenameColumn` SAI-semantics khi drop+add cùng type (test xanh không bắt SQLite EnsureCreated không replay migration) · **#64** `dotnet ef database update` áp Design-DB 0-rows Dev-DB data-migrate `Sql()` chạy thật lần đầu trên prod. Prev +2 S59 (#61 sqlcmd `-f 65001` · #62 rename natural-key UPDATE trước deploy) |
| User memory | **20** | re-grounded S54 (H1 disk-count S53 base thật 19 không phải 18); +1 S54 `feedback_agent_cwd_relative_memory_misland` (sub cd subdir MEMORY Write stray) |
| Skills | 6 | 3 domain + 3 ops |
| Sub-agents | **11** | **two-tier H4 (06-10):** em main Fable 5 (1M) Max · 4 promote `inherit`=Fable 5 (reviewer·investigator-codebase·database-agent·harvest-curator) · 7 demote pin `claude-opus-4-8` (**runtime-VERIFIED 06-11** spawn-test 2 chiều S57bis: H1 tooling-auditor self-report `claude-opus-4-8[1m]` + H2 harvest-curator `claude-fable-5[1m]`; `[1m]` 1M-resolve SE tự verify) · effort Max ×2 tier. 9 product/quality + 2 monitor INFORM-only. database-agent **verified-runtime S53** (spawn-test PASSED caught Mig 46-unapplied-local drift) |
| RAG chunks | **2423** | re-check S63 (`list_projects` alive, +3 vs S58). Stale `last_indexed 05-29` (S42-S62 via store_memory stopgap; full re-index = AI_INFRA op cần VOYAGE_API_KEY). |
**Bundle hash live (prod):** admin **`0xKYGhhf`** · user **`C81ZdG9G`** (S62 Run **#286** `7926c21` PE vượt-NS cảnh-báo-mềm; source = cicd-monitor MEMORY, live-curl chưa re-verify S63). **Prev S59:** admin `B1DtNT9C` · user `D6uF3Mln` (Run **#282** `792c030` FINAL bỏ nút Thêm hạng mục; ships kèm `80b64dd` gỡ Điều khoản TT, #281 cancelled-benign ancestor-verified). Chuỗi S59 cùng ngày: #280 `69997da` (`BKy_8OO9`/`XcZ6PRyA`, ships kèm `f21c55d` table-fixed #279-cancelled) · #278 `9c330d2` self-approve+quick-add-NCC (`BSh2fG2X`/`D22KfpPc`, authz probe 4/4) · #277 `faed59f` SearchableSelect (`ex7Tc92G`/`DzUeSk96`) · #276 `c869d26` rename 71 PMH (`BBA0KSWu`/`DzdTI18G`) · #275 `bbd1554` dọn demo WorkItems (FROZEN BE-only) · #274 `0eafcd3` tree 4 tầng (`DuU7OTym`/`DWyeTzf3`) · #273 `56882ac` wipe + tree v1 (`R9uGRxvw`/`DikfX1RD`). Prev S58: Run #386 `3ebaf84` admin `DMm9rtNA`/user `BUkOMn_Y` (chi tiết session log S58).
**Phase:** Phase 10 COMPLETE · **Phase 11 product backlog ĐÓNG TRỌN** · **PE ngân sách per-gói-thầu** (Mig 50 S61 XÓA module Budget , nhập role PRO/CCM, vượt=cảnh-báo-mềm S62) prod-verified · 🚫 Phase 9 Ops blocked (anh main coordinate anh dừng).
> ⚠️ **Count drift fixed S40:** endpoints ~223→**211**, FE pages 53→**65**, menu keys 85→**~53**. Tables **84 confirmed correct** (DbSet 77 + Identity 7). 3 số "khó fake" (mig/gotcha/git) luôn đúng. Cause: số "incremented mỗi session" over/under-count optimistic — re-ground định kỳ.
---
## 🔥 In Progress (S63)
| Task | Owner | Status |
|---|---|---|
| _(**S63 docs-closeout S60-62 ✅** — reconcile stray reviewer cwd-misland (2 file → canonical + xóa stray) + commit harvest (cicd MEMORY Run #286 + gotcha #63/#64) + count-flush 4 file (ef-core/README/dep-audit/CLAUDE root) + session-log bù `2026-06-12-S60-S62-*`. **S60-62 product ĐÓNG TRỌN prod-verified:** Mig 50 ngân sách per-gói-thầu (Excel anh Kiệt) + XÓA module Budget cũ + gỡ "Từ chối" + vượt-NS cảnh-báo-mềm. **🔴 Ops còn — của anh (giữ từ S58/S59):** (1) `tzutil /g` VPS · (2) anh Chương email → dọn typo · (3) báo 5 real staff password `User@1234567` · (4) gán người thật CNTT → lock nv.cao/nv.truong. **NEXT (anh pick):** test-after guard suppliers authz + LockDemoSampleUsers · F4 approver-edit-budget UI (BE sẵn scope, chờ anh Kiệt) · PE panels polish · monthly audit 2026-07-01 (STATUS/HANDOFF re-tier trim S53-S56 → logs · curate L1 cicd-monitor **63.6KB** over-cap lần 5 + investigator-codebase 32.7KB · schema-diagram §16+ Mig 32-50 ERD). · Prev S59 ĐÓNG TRỌN 10 đợt Run #273→#282 (8 PASS + 2 cancelled-benign): wipe testing data (phiếu thật đầu = PE/2026/A/001 ✓) · tree 4 tầng Năm>Dự án>Hạng mục · 71 mã PMH chuẩn (wipe 15 demo + rename format anh Kiệt) · UAT 6 vòng 11 điểm (SearchableSelect gõ-lọc bỏ dấu + auto địa điểm + ẩn nút self-approve + quick-add NCC + multi-file + bảng NCC table-fixed + bỏ ô Tên ngân sách + GỠ field Điều khoản TT mọi form + bỏ nút Thêm hạng mục). Bundle FINAL `B1DtNT9C`/`D6uF3Mln`. **🔴 Ops còn — của anh (giữ từ S58):** (1) `tzutil /g` VPS → confirm `SE Asia Standard Time` · (2) xác nhận anh Chương email nào → dọn `chuong.phan@solution.com.vn` typo · (3) báo 5 real staff password mặc định `User@1234567` + yêu cầu đổi · (4) khi gán người thật vào CNTT → thêm nv.cao/nv.truong vào lock list. **NEXT (anh pick):** test-after guard (🟪 test-specialist: `LockDemoSampleUsersAsync` S58 + suppliers asymmetric authz POST-open/PUT-DELETE-locked S59) · PE panels polish sâu (PeDetailTabs 111KB session riêng) · FE PermissionGuard per-route khi golive HRM/Office (flip revoke) · Phase 9 Ops (SMTP/backup/creds/UAT) · monthly audit 2026-07-01 (**STATUS/HANDOFF re-tier — defer ×2, ƯU TIÊN** · curate L1 cicd-monitor **~56KB** (S59 +9 cicd-spawn, H2-đo 54KB + 2 entry cuối) + investigator-codebase 32.9KB · schema-diagram §16+ Mig 32-49 ERD debt). → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`)_ | 👤 | |
**S40 done:** Consolidation (`d2f52ba`) · Curate 4 agent MEMORY >25KB→<8.4KB (`78c9de3`) · RAG catch-up chunk S37-S40 (rerank 0.867) · **AI_INFRA bulletin 2026-05-29 adopt 4/4** (MỤC2 Tiered Memory Policy v1 `6f08d1f` + MỤC3 /session-start+/session-end slash commands `c8ff5e1`). Full RAG re-index = AI_INFRA op (cần VOYAGE_API_KEY).
> ⚙️ **NEW slash command** (`.claude/commands/`) — anh main **restart CLI** để activate (không hot-reload) → session sau gõ `/session-start` + `/session-end` thay paste prompt thủ công.
---
## ✅ Recently Done (newest on top — 3 session; cũ hơn → session logs)
### S60S62 (2026-06-12→06-13) — ✅ PE workflow polish + ngân sách per-gói-thầu (Mig 50, XÓA module Budget) + soft-warning vượt NS — 4 commit prod-verified Run ~#283→#286 [docs viết bù S63]
- **S60 `37122f0`+`6db195d`:** ràng buộc gửi duyệt đủ 4 thông tin mục 3 (đơn vị được chọn + giá chào>0 + ngân sách + bảng so sánh đính kèm, áp cả Admin) + rename mục 3 "Đơn vị NCC/TP được chọn" + bypass drafter-in-chain V2 bước-đầu (audit 3 tầng) · gỡ hành động "Từ chối" khỏi cả 4 policy (chỉ còn Duyệt/Trả lại, guard chặn TuChoi mọi caller). Test 240→256.
- **S61 `79ef8da` Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets`:** bảng `PeWorkItemBudgets` per-gói-thầu (Dự án×Hạng mục, UNIQUE filtered) + **XÓA module Budget cũ** + drop PE/Contracts.BudgetId + backfill BudgetManual→BudgetPeriod TRƯỚC DropColumn (phiếu UAT giữ số) + bảng "Tổng hợp ngân sách trình ký" 2-block 9-dòng Excel anh Kiệt + nhập role PRO/CCM (Forbidden fail-closed) + XÓA FE budgets pages/types/menu `Bg_*`. Test → **263** (45D+218I). database-agent advise (no FK vật lý · DropIndex trước DropColumn SQL 5074 · IN-list). **gotcha #63** (EF RenameColumn sai-semantics) + **#64** (Design-DB 0-rows ≠ Dev-DB data-migrate).
- **S62 `7926c21`:** vượt ngân sách = cảnh báo mềm (gỡ validator `ExpectedRemaining>=0`, allowNegative row8, banner amber) — mirror LeaveBalance allow-negative. Reviewer PASS 0 issue. cicd **Run #286** bundle admin `0xKYGhhf`/user `C81ZdG9G`, DATA-PRESERVE 8/8 phiếu giữ số (gồm phiếu 1.243.820.600 đ anh Kiệt).
- **⚠️ docs closeout muộn:** 3 session ship code KHÔNG closeout → drift S59→S62 bắt ở S63 `/session-start` (git log). Reconcile stray reviewer (cwd-misland S62) + count-flush. → session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`.
### S59 (2026-06-11 chiều→tối) — ✅ Wipe testing data + PE tree 4 tầng + 71 mã PMH + 6 vòng UAT — 10 đợt prod-verified Run #273→#282 (8 PASS + 2 cancelled-benign)
- **Đợt 1 — wipe (anh Kiệt "xoá các cái testing trước đi em", `56882ac` #273):** recon → anh chốt scope (AskUserQuestion) → `scripts/s59-wipe-testing-data.sql`: 10 PE + child 252 + 7 HĐ [DEMO] + 64 notif + 1 AwV2 inactive = 0 · reset PeSeq/CtSeq (generator INSERT-if-missing → mã từ 001) · KEEP master 70/86/22 + users 55 + 7 workflow ghim · uploads orphan dọn. App-recycle KHÔNG resurrect. **Team vào testing chiều: phiếu thật đầu tiên = PE/2026/A/001 ✓.**
- **Đợt 2+3 — tree Panel 1 (`0eafcd3` #274):** v1 "Dự án (Năm) > Hạng mục" theo anh Kiệt → anh chốt follow-up **4 tầng 📅 Năm (DESC) > 📁 Dự án (A-Z) > 🧱 Hạng mục > phiếu**. FE-only (list DTO có workItemName S57bis), expand-key v3, SHA256 mirror ×2.
- **Đợt 4 — dọn 15 mã demo (chị Trà Sol, `bbd1554` #275):** WorkItems 86→**71** (Phần thô/Hoàn thiện/Cơ điện/Khác = mã "tự đẻ") + **GỠ HẲN seed demo block** DbInitializer (diệt gốc DB-mới) · đối chiếu **71/71 khớp bảng PMH từng dòng** · LocalDB Dev sync · bundle FROZEN (BE-only) · recycle giữ 71.
- **Đợt 5 — rename 71 mã format PMH (anh Kiệt "đúng kiểu vậy", `c869d26` #276):** `VT→MAT-n · TP→SUB-n · MEP-0n→MEP-SUB-n · TB→MEP-EQU-n`, Name "STT nhóm tên" ("1 MEP Sub MEP (Full)"). **DB-trước-code-sau** (gotcha **#62**: seed per-code idempotent — sai thứ tự = 142 rows; Run #276 verify đúng 71) · sqlcmd **`-f 65001`** + verify data qua API JSON (gotcha **#61**) · FE sort numeric ×3 · spec provenance sync.
- **Đợt 6+7 — UAT vòng 1+2 (`faed59f` #277 + `9c330d2` #278):** NEW **`ui/SearchableSelect`** (~140 LOC no-lib, fold bỏ dấu "be tong"→"Bê tông", keyboard, clear) áp Hạng mục/Dự án/NCC ×2 form · auto Địa điểm từ `Project.Location` (track lastAutoLoc, không đè tay) · anh chốt ×2 (AskUserQuestion): **ẩn Trả lại+Từ chối khi drafter tự duyệt** + **quick-add NCC** (POST /suppliers any-auth, PUT/DELETE giữ khóa — **cicd authz probe live 4/4**: 401/201/403/cleanup-204) · upload **multiple** files (báo giá + bảng so sánh).
- **Đợt 8-10 — UAT vòng 3-6 realtime (`f21c55d` #279-cancelled → `69997da` #280`80b64dd` #281-cancelled → `792c030` **#282 FINAL**):** **bảng NCC table-fixed** + width % từng cột + min-w-860 (file đính kèm tên dài hết vỡ layout, chip/email truncate kích hoạt) · **bỏ ô "Tên" ngân sách nhập tay** (user không hiểu — chỉ còn Số tiền; hasManual detect theo amount cho phiếu name-null) · **GỠ field "Điều khoản thanh toán" khỏi TẤT CẢ form phiếu** (Create + HeaderForm + inline-edit, PAYMENT_PRESETS drop 142 LOC; cột per-NCC + display read-only phiếu cũ GIỮ) · **bỏ nút "+ Thêm hạng mục"** (1 phiếu = 1 hạng mục header, AddItemDialog giữ dead để flip lại). 2 cancelled = Gitea concurrency push-đè khi UAT góp ý realtime — ancestor-verified preserved, pattern #385 S58.
- **Quality:** test 240/240 ×2 local + 8× CI gate · **0/14 spawn truncated** (H1×2+H2×2+recon+cicd×9 — verdict-FIRST + scoped prompt works) · 3 SQL script committed vào repo · Suppliers note: GET list = page (đếm thật qua DB 22).
- ⚠️ Carry: test-after guard suppliers authz + LockDemoSampleUsers · cicd-monitor L1 ~56KB curate monthly. → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`.
### S58 chiều (2026-06-11) — ✅ Tạm ẩn modules + Danh mục cuối (Run #383) + fe-user redesign guide AI_INFRA (Run #384)
- **Ẩn + thu hồi quyền (anh yêu cầu từ screenshot eoffice, commit `6c5fd26` → Run #383 PASS):** NEW `RevokeTemporarilyHiddenModulesAsync` — set 4 cờ CRUD=false mọi role TRỪ Admin trên `Hrm*` + `Off*` + `Personal` (menu tự ẩn 2 app; giữ row flip-lại-nhanh khi golive) + grant seed thu hẹp scope (không re-grant). Menu `Master` Order 20→**80** (Danh mục cuối sidebar). Prod verified: non-Admin CanRead=0 · Admin giữ 29 · Pe 120 · Master 48 · **menu-tree đối chứng 2 chiều** (nv.test mất 3 nhóm, admin còn). User thường eoffice giờ chỉ thấy: Hộp thư · Quy trình chọn TP-NCC · Danh mục (cuối). ⚠️ Mức che = menu + permission matrix; URL gõ trực tiếp chưa chặn (FE không PermissionGuard per-route — chấp nhận "tạm ẩn", note sẵn khi golive flip lại).
- **`/check-email ai_infra`:** nhận `2026-06-11-ui-ux-design-guide` (hash ✓✓ whole-file + body, processed) — **UI/UX Design Guide canonical 13 mục** (anh-approved, lineage NAMGROUP→BVAAU→AI_INFRA) + FYI lỗi stamp hash email H4-report SE (không tamper — lesson stamp lần send tới) + **ACK H4 ACCEPT** (SE = sister đầu tiên trọn vòng H4.7 email-back).
- **fe-user redesign (commit `e959f72` → Run #384 PASS):** 🩷 frontend-designer 14 file (index.css + 6 ui primitives + 6 shell + LoginPage) — density-first theo guide, **BRAND GIỮ** #1F7DC1 + Be Vietnam Pro + slate. Variant/size keys + props STABLE, RowActions/RowActionButton additive. Build ×2 PASS. **Bundle asymmetric đúng:** user `CKjwqnGL` rotate / admin `CP4CB1ym` frozen; brand verified trong HTML+CSS prod. ⚠️ Designer truncated #53 **lần 2 liên tiếp cùng điểm** (trước FD2 screenshot) → em main disk-recover + self-gate (lesson: emit file-list verdict TRƯỚC screenshot loop — ghi MEMORY nó).
- **Brand polish "thấy rõ" (anh: "có thấy khác gì đâu, trang trí lên 1 tý" — commit `ea793a4`, 8 file ×2 app, em main solo):** dải gradient brand 4px đỉnh app + logo zone sidebar tint brand-50 + PageHeader accent bar dọc + **thead mọi DataTable `bg-brand-50/60 text-brand-700`** + TopBar title semibold. Lý do anh chưa thấy đợt đầu: density tinh tế + PE panels (chỗ anh nhìn) chưa đụng (file shared 111KB).
- **PE gộp "Tên gói thầu" = chọn Hạng mục công việc (anh Kiệt FDC Zalo 14:06: "hạng mục chính là tên gói thầu, cho chọn chỗ đó" — commit `3ebaf84` → Run #386 PASS):** `PeWorkspaceCreateView` + `PeHeaderForm` — field "a. Tên gói thầu" Input tay → **1 Select từ 71 hạng mục** (`[Category] Code — Name`), chọn 1 phát set cả `workItemId` + `tenGoiThau` (= tên hạng mục); gỡ field "c" S57bis (trùng ý nghĩa). Phiếu cũ: option "Giữ nguyên: «tên cũ»" — không ép, PUT null-safe. NO BE change. **SHA256 mirror ×2 app** ✓. Run #385 cancelled supersede-benign (cicd ancestor-verified polish intact #386).
### S58 (2026-06-11) — ✅ Fix lock-demo-user prod NO-OP + password-seed root-cause — prod-verified Run #382
- **Commit `5998163` (1 file `DbInitializer.cs` +28/-5) → Run #382 PASS ~3m31s, prod-verified.** Anh: `/session-start` → bootstrap phát hiện Run #381 PARTIAL (lock NO-OP) + 2 file dirty S57bis → recon → anh chốt 3 quyết định (AskUserQuestion): union+password-fix · giữ chuong.phan-typo · giữ nv.test.
- **Root cause 2 tầng (🟦 recon dump prod + Dev + git pickaxe):** (1) lock list 14 email named-person = population **Dev-only** — demo prod thật = 20 UAT-matrix `{dept}.{nv,pp,tp}@`+`bod.{1,2}@` tạo TAY 05-13 chưa từng trong code; (2) `DemoUserPassword` 11 ký tự < prod `RequiredLength=12` `CreateAsync` **silent-fail mọi startup từ trước tới giờ** (LogWarning-only) = root cause "helpdesk inert phòng IT 0 user" S56 + 5 real staff thiếu account.
- **Fix:** union 20 email (exact-email, KHÔNG pattern `binh.le@` người thật sát scheme demo) + password `User@1234567` 12 tự. **🟩 cicd Run #382 PASS:** prod Users **55/21 active/34 locked** · 20 UAT + 14 named-person locked · **nv.cao/nv.truong CREATED+ACTIVE (ops S56 "gán user IT" RESOLVED)** · 5 real staff created · guard 6/6 active · nv.test login 200 · bundle FROZEN `CP4CB1ym`/`BmZ3VHnm` · Mig giữ 49 · 93 tables.
- **Closeout kèm:** gotcha **#59** (PS5.1 `git commit -F`) + **#60** (seed silent-fail vs password policy) NEW · 4 spawn-record on-behalf APPEND (database-agent/implementer-backend/implementer-frontend/reviewer H2 4-MISS đóng) · H1 doc-drift 5-patch (ef-core +row Mig 49, skills/README, dep-audit, CLAUDE.md root) · menu keys re-ground 57 · test 240 re-verified local · bundle hash curl-verified.
- **Lessons:** test xanh + deploy PASS + health 200 data tồn tại seed `IdentityResult` silent-fail chỉ lộ khi **dump population env đích** (cicd PASS+PARTIAL + recon = tầng bắt được, CI gate không). Trade-off deadline: ship trước, test-specialist guard test sau (test-after, list-data fix).
### S57bis (2026-06-11 sáng) — ✅ PE gắn Hạng mục công việc (Mig 49) + Pe all-role + menu "Cá nhân" + Harness-4 runtime-VERIFIED — Run #381 PASS+PARTIAL
- **2 commit `17b23a4` (governance) + `dd117b7` (product, 26 file +7.4K) Run #381 PASS ~4m25s** (Run #380 cancelled superseded đúng). Sếp Zalo 11:02-11:17 deadline 15:00: mapping master data + phân quyền PE all-user + flow tạo phiếu chọn Dự ánHạng mụcNCC + clear data . Anh chốt: khóa CHỈ user sample · quyền Xem+Tạo · 1 phiếu 1 hạng mục header-level.
- **Mig 49 `AddWorkItemToPurchaseEvaluation`** (🔵 database-agent design): PE.WorkItemId `Guid?` **loose-Guid KHÔNG FK vật lý** (convention PE ProjectId/SelectedSupplierId đều loose) + IX + validator `NotEmpty` create-only (DB nullable backward-compat 4 phiếu ) + FK-guard `AnyAsync(IsActive)`Conflict + UpdateDraft null-safe. WorkItems = catalog GLOBAL 2 dropdown độc lập, "Dự án (năm) Hạng mục" = chuỗi ghép. 3 projection LEFT-join.
- **FE ×2 app:** PeWorkspaceCreateView select "c. Hạng mục *" + PeHeaderForm (SHA256 IDENTICAL) + PeDetailTabs subtitle. **Pe_* all-role:** 11 key CanRead+CanCreate=true 13 role (130 rows, upgrade-only Pe_* leaf KHÔNG nằm `MenuKeys.All`, build qua factory; PeWf_*/AwV2 GIỮ Admin). **Menu "Cá nhân"** Personal root@30 + Chấm công re-parent + HrmConfigMaster + Master write-lock `Admin,CatalogManager` ×3 controller. `LockDemoSampleUsersAsync` 14 email (→ NO-OP prod, RESOLVED S58). Excel (3) đối chiếu = NO-CHANGE.
- **Test 228240** (+12 `PeWorkItemGuardTests` finding: `NotEmpty()` trên `Guid?` không chặn `Guid.Empty` handler guard locked 2 test). **Harness-4 runtime-VERIFIED** spawn-test 2 chiều (H1 `claude-opus-4-8[1m]` + H2 `claude-fable-5[1m]`) + email-back AI_INFRA.
- **Lessons:** 2 builder return-truncated #53 (BE trước Mig, FE giữa mirror) + reviewer **die-0-byte ×2** (class mới resume-kill) em main solo cross-stack + self-gate evidence-checklist. Session đóng VỘI sau commit 2 file dirty (gotcha #59 + cicd Run #381 entry) trôi sang S58 harvest. session log `2026-06-11-S57bis-pe-workitem-perm-golive-prep.md`.
### S56 (2026-06-09) — ✅ Pre-golive verify sweep + golive-harden 4 fix — HMW 2-workflow, prod-verified
- **2 Workflow fan-out + 1 code commit `a20cde8` Gitea Run #379 PASS ~4m20s, prod-verified.** Anh: `/session-start` hỏi NAMGROUP UI density-first "Tiếp Phase 2 redesign" (dismiss scope defer) "kiểm tra lại tính năng + master data, sắp golive" + `/ultra-on` "fix hết workflow luôn" `/session-end`.
- **WF1 `pre-golive-verify`** (7 stream song song adversarial-per-issue): prod-truth(🟩cicd) · schema(🔵database-agent) · 4× logic(🟦investigator) · authz-curl(🟥reviewer). **6/7 PASS · 1 CONCERN(non-blocker) · 0 blocker · 8 issue (adversarial confirm 6 real, refute 2 false-pos).** Verdict **GO**. Insight: phát hiện đáng giá nhất = **ops/data, không phải bug code** prod phòng IT (CNTT) tồn tại nhưng **0 active user** ItTicket auto-assign/reassign/SLA-notify đều inert (chỉ live-curl+sqlcmd thấy, test xanh không bắt). + S43 LeaveBalance lost-update còn nguyên + master-data idempotency PROVEN.
- **WF2 `golive-harden`** (DesignBuildTestReview∥): **#3** LeaveBalance lost-update database-agent design **atomic `ExecuteUpdateAsync`+Serializable tx** (NO migration, exactly-once `Status!=DaGuiDuyet:296` nguyên, server-side `UPDATE SET UsedDays=UsedDays+n` race-free) · **#5** ItTicket `AssignItTicketHandler` authz Forbidden-trước-NotFound (fail-closed, hết existence-oracle) · **#6** DocxRenderer null-guard MainDocumentPart+Document (CS8602 20) · **#4** Travel/Vehicle ApproveV2 +4 smoke test (trước đó 0 coverage).
- **Test 216228** (+12). Build 0 warn. Bundle FROZEN admin `4SUwDLD8`/user `XdKzt9LL` (BE-only đúng). Mig 48 unchanged. `sys.tables` re-ground **92→93** (cicd ground-truth Mig 48 col-only, prior under-count).
- **🟥 reviewer stage StructuredOutput-FAIL** em main đỡ cross-stack review (đọc 3 production diff = clean). **🔵 database-agent review PASS** nêu 1 MAJOR (tx READ COMMITTED vs convention Serializable + rare auto-create-race) **em main bump `IsolationLevel.Serializable`** đóng nốt + align convention. **🟩 cicd Run #379 PASS:** test 228 · health 200 ×3 · bundle frozen verified 3× · endpoint 401 (control 404 chứng minh auth thật) · Mig 48 top.
- **Lessons:** (1) **workflow-agent StructuredOutput-fail = class mới** của agent-return-unreliable em main đỡ qua git-diff/disk truth (extends `feedback_agent_kill_recovery`). (2) workflow-agent self-write MEMORY (G-015 residual sub giữ Write MODE-A) em main verify sane + bundle harvest commit. (3) **gotcha #58** NEW. (4) HMW full-cycle: verifyfixreviewem-main-đỡre-verifyshipcicd-PASS adversarial tách-vai bắt lỗ phụ build+test-xanh không thấy.
- **🔴 NEXT:** 2 ops VPS (gán user IT + tzutil) · FE Phase 2 (recon ready) · Phase 9 Ops · monthly audit 2026-07-01. session log `2026-06-09-S56-pre-golive-verify-harden.md`.
### S55 cont. (2026-06-09) — ✅ Phase 1 FE redesign fe-admin (density-first, giữ brand) — HMW-mode ON, prod-verified
- **Commit `7feb53e` Gitea Run #378 PASS ~4m24s, prod-verified.** Anh: `/check-email NAMGROUP` (nhận bộ quy ước UI density-first) "thiết kế lại giao diện cho đẹp hơn, tham khảo NAMGROUP, cho designer làm, workflow plan + làm luôn".
- **🩷 frontend-designer** redesign **14 file fe-admin** (Phase 1 foundation): `index.css` density heading-ladder + `.label-eyebrow` util (drop font-bold) · 6 UI primitive (Button/Input/Label/Select/Textarea/Dialog `text-xs font-semibold`, `py-1.5` 36px, `rounded-lg`, brand focus-ring) · 6 shell (DataTable sticky-thead+RowActions / Layout brand-rail / TopBar / PageHeader / PhaseBadge / EmptyState) · **DashboardPage** flagship (KPI cards + brand-50 icon chips + uppercase labels + accent bars).
- **GIỮ brand** #1F7DC1 + Be Vietnam Pro (NAMGROUP nói brand=Solution tự quyết chỉ mượn cấu trúc density). Visual-only, **functionality nguyên** (Button variant/size keys stable 51 call-sites, props/forwardRef intact).
- **🟥 reviewer PASS** 0 blocker (regression all-preserved, brand-confirmed `index.css:3/22/34`, exactly 14 file) 2 minor a11y defer (slate-400 hint nhỏ). **🟩 cicd Run #378:** admin bundle `B-d6893W``4SUwDLD8`, user `XdKzt9LL` UNCHANGED (asymmetric FE-admin-only verify), no mig, health 200.
- **2 agent truncated** (designer + reviewer-#1, gotcha #53) em main recover disk (build+login-visual+diff-review). **Dashboard live-screenshot bị chặn** dev auth-rig (API HTTPS vs proxy HTTP + protected route) xem live qua deploy. Designer rig-gotcha #3 logged. ** Phase 2** (Suppliers/Projects/Contracts pages) + **Phase 3** (mirror fe-user) pending. session log `2026-06-09-S55-master-data-import.md` (redesign §).
### S55 (2026-06-09) — ✅ Nạp master data thật từ Excel + Project +4 cột (Mig 48) — HMW-mode ON, prod-verified
- **Commit `69cb393` Gitea Run #377 PASS ~4m33s, prod-verified.** Anh: `/session-start` giao file Excel "HẠNG MỤC CÔNG VIỆC DỰ ÁN" "nạp master data vào đi nhé" `/ultra-on "workflow làm xong hết"`.
- **Nạp 3 nguồn thật** (Excel 7-sheet loadable): **62 Projects** (+Năm; ~6 CĐT/địa điểm/gói thầu) · **71 WorkItems** hạng mục (Vật tư16/Thầu phụ30/MEP9/Thiết bị16) · **3 Suppliers** (TRUONGGIANG/TANPHU/TGN). `WorkItem` master ĐÃ tồn tại no new table cho hạng mục.
- **🟨 BE:** `Project.cs` +4 prop nullable (Year/Investor/Location/Package) + `ProjectConfiguration` maxlen 250/500/300 + **Mig 48 `AddProjectMasterFields`** (3-file, 4 AddColumn reversible) + `ProjectFeatures` DTO/Create/Update +4 + **`SeedRealMasterDataAsync`** (62+71+3 tuple-loop per-code idempotent, wired **UNGATED** line 118 sau SeedCatalogsAsync reaches prod, coexist demo).
- **🟧 FE:** `ProjectsPage.tsx` form +4 input (Năm/Chủ đầu /Địa điểm/Gói thầu) + bonus cột "Chủ đầu " + `types/master.ts` +4 **2 app SHA256-identical**. npm build ×2 PASS.
- **Verify:** build 0-err · test **216 PASS** (compile-fix `MasterCatalogFilteredUniqueTests` +4 null args, no new test) · **runtime Dev proof** (data landed, Investor col works) · **cicd Run #377 PASS** (Mig 48 applied prod · Projects spot-6/6 · WorkItems 71 · Suppliers 3 · CAL01.Investor exact · bundle admin `B-d6893W`/user `XdKzt9LL` · health 200).
- **Decisions (anh chốt):** Q1 thêm cột thật+migration (không Note-pack) · Q2 cả 3 Dev+deploy prod. **FLOCK01 collision** per-code skip (demo wins). Prod totals: Projects=70 (62 real+8 demo), WorkItems=86.
- **2 agent return truncated** (implementer-backend + reviewer, gotcha #53) em main recover qua disk/runtime truth (`feedback_agent_kill_recovery`); cicd verdict-FIRST PASS clean. Data-quality catch: MEP col gộp MEP-Sub+THIẾT BỊ divider split đúng. session log `2026-06-09-S55-master-data-import.md`.
### S54 (2026-06-08) — ✅ IT staff tự reassign ticket (cross-stack authz, HMW-mode ON) — 1 commit prod-verified
- **Commit `ca4b602` Gitea Run #376 PASS ~4m18s, prod-verified.** Anh: `/session-start` "2 xong sau đó 1" (task 2 reassign trước, task 1 Phase 9 Ops sau) task 2 done, task 1 anh dừng `/session-end`.
- **Feature (cho tổ IT tự reassign KHÔNG chỉ Admin như S53):** "IT staff" = `User.DepartmentId == Department(Code=="IT").Id` (reuse round-robin S52 predicate). Cross-stack, **NO migration** (DepartmentId reuse), no menu change.
- **🟨 BE** (`WorkflowAppsFeatures.cs` REGION 5 + `ItTicketsController.cs`): NEW `GetAssignableItStaffQuery``AssignableStaffResult{CanReassign,Staff}` capability endpoint (`[Authorize]` any-auth, trả `{false,[]}` cho người ngoài **0 silent-403 chống gotcha #44**) + `AssignItTicketHandler` authz Admin-OR-dept-IT (`ForbiddenException`) + assignee-must-IT (`ConflictException`) + controller `/assign` hạ `[Authorize(Roles="Admin")]``[Authorize]` (handler enforce fine-grained data-driven).
- **🟧 FE** (2 app): `ItTicketsPage.tsx` **SHA256-identical `4bcaf2f…`** REVERSE divergence S53 (cả 2 cùng gate nút by BE-computed `canReassign`, dropdown từ `/assignable-staff` thay `/users`). +2 type `AssignableStaff`/`AssignableStaffResult`. npm build ×2 PASS.
- **🟪 Test** (`ItTicketReassignAuthzTests.cs`): +13 (203→**216**) test-before-merge SECURITY GetAssignableItStaff 6 (canReassign matrix + 0-leak empty + inactive-excluded) + AssignItTicket 7 (Forbidden guard-proof by-contrast + Conflict assignee-not-IT + side-effect no-mutation). No prod bug.
- **🟥 reviewer PASS** 0 blocker/0 major/1 minor: điểm chí mạng **role-string "Admin" chain-verified real** (`AppRoles.Admin``SeedRoles Role.Name``JwtTokenService Claim(ClaimTypes.Role)``cu.Roles` decoy "QTV" chỉ ShortName, không vào JWT). Fail-closed verified, defense-in-depth nguyên.
- **🟩 cicd Run #376:** test 216 · bundle admin `DfCfHUE9``DmjI8Cmn`/user `_3S0BPJ2``YxL_MljK` (cả 2 rotate) · smoke health 200 + /assignable-staff 401 + /assign 401(body) · Mig giữ 47. Note: 411-bodyless-PUT = IIS Content-Length pre-`[Authorize]` (không phải routing miss).
- **Residual caught + fixed (em main single-writer):** 3 agent (BE/FE/test) ghi MEMORY nhầm `src/Backend/.claude/` (cwd-relative Write khi cd subdir) em main git-status scan bắt stray + reconcile 2 pattern file về canonical + APPEND S54 delta vào 3 canonical MEMORY (harvest B2/B3). memory `feedback_agent_cwd_relative_memory_misland`.
- 📌 **flag monthly audit 2026-07-01:** cicd đo `sys.tables=93` vs STATUS 92 **RECONCILED S56** (93 authoritative, cicd ground-truth Run #379; Mig 48 col-only added no table STATUS Current State updated 9293).
- session log `2026-06-08-S54-it-ticket-reassign-cross-stack.md`.
### S53 (2026-06-08) — ✅ gotcha #57 EXT Master (Mig 47) + P11-D reassign-UI + P11-E menu-key — all prod-verified · database-agent verified-runtime (HMW-mode ON, "làm hết" full closeout)
- **2 code commit deployed prod:** `44b9e54` Task B (Mig 47 `FilterMasterCatalogUniqueIndexesByIsDeleted` Department/Supplier/Project filtered-unique Code, gotcha #57 EXT) Run #260 · `dbf6648` Task C+D Run #261. Test 200→**203** (+3 `MasterCatalogFilteredUniqueTests` REDGREEN). Bundle admin `DYfjnpY0`→**`DfCfHUE9`** (rotated C+D FE) · user `_3S0BPJ2` unchanged.
- **Bootstrap:** database-agent **verified-runtime** (first real spawn since S52 adopt caught **Mig 46 committed-but-unapplied-local** drift that 203 SQLite-tests + CI-applied-prod both MISS bonus closed via Mig 47 deploy applying 46+47 to LocalDB Dev+Design). H1+H2 monitors re-reported (S52 closeout debt cleared; H2 confirmed S52 proxy-append present, 0 orphan).
- **Task B (Mig 47, Run #260):** workflow 🟪 test-specialist 🟨 implementer-backend 🟥 reviewer (PASS 0 issues). 3 prod indexes `filter_definition` NULL`([IsDeleted]=(0))` live. gotcha #57 EXT cumulative now **6×** (Holiday 43 + 3 HRM 45 + 3 Master 47) **backlog CLOSED**. Root cause: app dup-check `AnyAsync(Code==req)` đi qua `HasQueryFilter(!IsDeleted)` (bỏ qua soft-deleted) nhưng bare unique index đếm cả delete+re-add = UNIQUE-500 reachable.
- **Task C+D (`dbf6648`, Run #261):** workflow 🟨 implementer-backend 🟧 implementer-frontend 🟥 reviewer (PASS 0 issues). C = ItTicket admin reassign dialog (fe-admin only, intentional mirror-break; reuse `PUT /assign` + `GET /users`). D = `Off_AttendanceReport` menu leaf (order 8, no migration DbInitializer idempotent seed, admin-perm auto via `All[]`, menu-key byte-identical 5 mirror points). Prod: menu row seeded + admin bundle rotated + smoke 200/401.
- **Doc-drift E:** H1 top-5 patched (ef-core skill 4347, agents/README roster 1011, CLAUDE.md root 4547 mig + 186203 test, docs/CLAUDE.md 5657 + 9192 ERD). database-agent adap-report verified-runtime.
- **cicd-monitor truncated 2×** (gotcha #53/#55; C+D verify cut mid-Q3) recovered via curl-self-verify (Gitea run + bundle hashes public; menu-row from agent's pre-truncation sqlcmd). `feedback_agent_kill_recovery` reinforced.
- session log `2026-06-08-S53-gotcha57-ext-p11-cd-closeout.md`.
### S52 (2026-06-08) — 🎉 Phase 11 product backlog ĐÓNG TRỌN (P11-D+E+F deployed) + database-agent adopt — HMW-mode ON, session-limit recovery
- **3 commit deployed prod:** `e9ee97f` (database-agent governance .md, CI-skip) + `6a66429` Wave 1 (P11-E+F code) + `dcf76f8` Wave 2 (P11-D, Mig 46). Test 186191→**200**. Bundle admin `DYfjnpY0`/user `_3S0BPJ2` (cả 2 rotate; deploy verified curl độc lập không cicd-spawn do limit).
- **🔌 database-agent adopt** (AI_INFRA broadcast `2026-06-08-Agent-database-codebase-agents`): floor DB1DB11 **READ-advisory tier** (implementer-backend vẫn author file) · skill `sql-database-assistant`+`ef-core-migration` · color OMIT (8 standard hết mirror monitor precedent) · `store_memory` strip · DB11 RowVersion tie-in S43 lost-update gap. **codebase-agent SKIP n-a** (investigator cover + csharp-lsp Windows no-op). Roster 10→**11**. Nấc executed-file **🔴 CHỜ CLI restart** verified-runtime. adap-report 5-trường LOCK written.
- **P11-F MaTicket codegen** (Wave 1): `WorkflowAppCodeGen.GenerateMaDonTuAsync(db,"IT",clock.Now.Year,...)` gen-on-**Create** (kanban no-workflow, khác Leave/OT gen-on-Submit), `IT/2026/NNN` Serializable atomic. Migration-free.
- **P11-E AttendanceReport** (Wave 1): `GetAttendanceReportQuery` monthly aggregate (day-type weekday/weekend/holiday OT × OtPolicy multiplier, **classify in-memory** không EF-translate `.DayOfWeek`) + `AttendanceReportExcelExporter` (ClosedXML, sync no-DB) + 2 endpoint Admin-only + fe-admin `AttendanceReportPage` (download authed `api.get(blob)`). Migration-free. `Holiday.Date`=DateOnly (agent verify source-of-truth, không tin spec ).
- **P11-D ItTicket assign+SLA** (Wave 2, **Mig 46** AddSlaFieldsToItTicket): round-robin least-loaded dept-"IT" (DbInitializer seed dept IT + 2 sample staff nv.cao/nv.truong, **ordering sau SeedDemoUsers** reconcile dept) + SlaDueAt theo Priority (Urgent4/High8/Medium24/Low72h) + `ItTicketSlaJob` (breach+warning notify, **KHÔNG auto-transition** khác Contract) + PUT /assign admin override + FE badge 2-app SHA256 mirror.
- **⚠ Session-limit hit giữa Wave 2** (3 agent killed: FE/test/cicd) recovery (multi-agent resilience proof): Wave 2 BE/test verify-on-disk (build 0-err + 200 test) + **em main solo FE redo** (gotcha #53-class fallback) + **curl-self-verify** Wave 1+2 deploy thay cicd-spawn. Lesson: **git/disk/prod = source-of-truth, KHÔNG agent return-message**.
- **reviewer (Wave 1) PASS** independent re-verify (build/test/tsc) + gotcha #44 role-string "Admin" disarmed (decoy `"QTV"`=display-code KHÔNG phải role-name). Wave 2 = **em main self-review** (seed↔query dept-code cross-check PASS, nv.cao/nv.truong tồn tại) do limit pressure.
- session log `2026-06-08-S52-phase11-def-close-database-agent.md`.
### S51 (2026-06-08) — ✅ P11-C Vehicle+Driver catalogs (Mig 44) + gotcha #57 ext 3 HRM catalog (Mig 45) — HMW fan-out, deployed prod
- **Commit `30a99aa` Gitea Run #371 PASS ~4m18s, verified prod.** HMW-mode ON, 7-agent fan-out: 🟦 recon 🟨 BE 🟧 FE (parallel file-disjoint) 🟪 test-before 🟥 reviewer 🟩 cicd. RAG/Qdrant DOWN cả session ground-truth on-disk (đáng tin hơn stale RAG index 05-29).
- **Mig 44 `AddVehicleAndDriverCatalogs`** 2 catalog table (Vehicles + Drivers, `AuditableEntity`), filtered-unique Code day-1 (gotcha #57 từ đầu). Extend HrmConfigs declarative: BE Region 5/6 CRUD (mirror LeaveType) + Controller +2 route-group (8 endpoint, GET public / write Roles=Admin) + MenuKeys +2 +All (auto Admin perm) + DbInitializer idempotent seed 2 veh/2 drv. FE KIND_CONFIG +2 kind ×2 app (SHA256 mirror) + 4-place (types/page/menuKeys/Layout staticMap), `:kind`-driven (no new App.tsx route). Tables 91→**92** (cicd `sys.tables` ground-truth).
- **Mig 45 `FilterHrmCatalogUniqueIndexesByIsDeleted`** (bundled gotcha #57) LeaveType + ShiftPattern + **OtPolicy** bare `.IsUnique()` `.HasFilter("[IsDeleted]=0")`. **OtPolicy BỊ BỎ SÓT khỏi backlog "2 catalog" → em main bắt được khi grep toàn bộ config** (= 3 HRM catalog). test-before: +5 `HrmConfigFilteredUniqueTests` (181→**186**), REDGREEN observed.
- **🟥 reviewer caught 1 MAJOR** (pre-commit): Driver FEBE required-field mismatch (FE optional vs BE `NotEmpty`+NOT NULL) root = inconsistent em-main brief across BE/FE fixed (FE +`required:true`). Lesson: parallel fan-out shared-contract inconsistency chỉ lộ lúc integration; green tests correct contract.
- **🟩 cicd Run #371 PASS:** test 186 · Mig 44+45 prod · 5 `IX_*_Code` filtered `([IsDeleted]=(0))` live (3 HRM was NULL) · bundle rotate admin `Cg9mvltU`/user `YgqDvsqr` · health 200 · /hrm-configs/{vehicles,drivers} 401 unauth + 200 authed (2 seed each).
- **gotcha #57 EXT** (investigator audit complete): Department/Supplier/Project (Master, confirmed-reachable via global query-filter quirk) **worktree session** Mig 46 (3 idx). ContractClause/MeetingRoom/EmployeeProfile = SKIP (not reachable). session log `2026-06-08-S51-p11c-vehicle-driver-gotcha57.md`.
### S50 (2026-06-07) — ✅ S49 Harness 1·2·3 verified-runtime closeout (HMW-mode ON · infra-finish, no product code, CI-skip)
- **`/session-start` bootstrap** spawned **2 monitor sub** (tooling-auditor H1 + harvest-curator H2) RE-REPORT **verified-runtime CONFIRMED** (S49 milestone (a) closed). H1 caught 3 doc-freshness drifts em main patched (plugin 1518 · skill-index 3143 mig + 4957 gotcha · verified-runtime markers). H2 harvest 🟢 clean (0-byte/orphan/corruption=0). Test gate **181 PASS**, RAG 2415.
- **(b) H2 wave-mode VERIFIED** wave-run `h2-verify` (Workflow Run `wf_b7e4d6ef-787`, 2-agent: investigator-codebase read-only + test-specialist write-direct). **B6 isolation HELD**: git status = 6-baseline only (0 canonical/agent-memory leak), sub-MDs gitignored, **chunk 2415→2415** (0 rogue RAG write). B4 both-paths exercised. Bonus: gotcha #57 confirmed open + exact coords (`LeaveTypeConfiguration.cs:19` + `ShiftPatternConfiguration.cs:19` vs fixed `HolidayConfiguration.cs:18`).
- **(c) H3 email send-path VERIFIED** `/send-email ai_infra` handshake `broadcasts/outbox/ai_infra/`, body SHA256 `c9656c19…` self-verified MATCH + `_index.md` OUTBOUND logged. AI_INFRA `/check-email se` pull = their step (completes 2-way byte-identical proof).
- **§L.b(d)(f)(g) session-end:** H2 GATE **PASS 5/5** + B5 wave-gom (2 sub-MD agent-memory/{investigator-codebase,test-specialist}). H1 freshness CHỐT (3 drifts patched, 0 new-alloc). 4 sub spawn-records all nấc=verified. **Rig fact:** Bash subs = `/usr/bin/bash` not PowerShell POSIX only. session log `2026-06-07-S50-harness-verified-runtime.md`.
### S49 (2026-06-07) — 🌐 AI_INFRA Harness 1·2·3 adopt (HMW-mode ON · governance/infra, no product code, CI-skip)
- **HMW-mode BẬT** (`/ultra-on` marker `.claude/hmw-mode.on` gitignored) anh `/adap-apply harness 1·2·3`. **Recon fan-out 4 read-only agent @P2** (3× investigator-codebase H1/H2/H3 gap + 1× investigator-api plugin/skill audit · return-delta · 367K tok · ~4m46s) em main single-writer WRITE ~25 file. **Containment audit post-P2:** git-diff = 1 file-write (inv-api self-MEMORY, benign verified) + chunk-count **2414=2414** (0 RAG-write) defense-in-depth proven (sub giữ Bash/Write G-015).
- **Harness 1 (Self-observability):** roster **8→10** NEW 2 sub **TÁCH BIỆT** (anh-mandate) `tooling-auditor` (H1 tooling/docs-freshness 4-mặt skill·sub-role·plugin·docs) + `harvest-curator` (H2 harvest-integrity 5-trục), INFORM-only (4 RAG-read, NO store_memory/Write). Wire `session-start.md` Phase 2.1.1 RE-REPORT + `session-end.md` §L.b **6→7-step** (H2 5-trục GATE + H1 chốt + B5 wave-gom). H3 plugin/skill = gộp-vai doc (0 agent mới code-modernization/code-reviewer KHÔNG enable).
- **Harness 2 (wave-folder isolation):** `hmw.js` +wave-mode (subMdPath schema + tool-aware writeGuard) · `.gitignore` +`wave-*/`+`agent-teams/` (B6 **VERIFIED** `git check-ignore`) · NEW `.claude/workflows/README.md` convention. A agent-team = n-a (Windows in-process, convention-ready).
- **Harness 3 (email channel):** NEW `broadcasts/` (outbox/{6 others+all}/ + inbox/{6 others}/ + _index + inbox/README + **13 .gitkeep**, committed not-gitignored) + 2 cmd `send/check-email` (self=`se`, 6 others short-id `{ai_infra,vipix,dyd,namgroup,ashico,bvaau}`) + fix `adap-apply.md` base-path `outbox/all/` (latent bug đóng luôn).
- **3 adap-report** `docs/governance/adap-reports/2026-06-07-Agent-harness-{1,2,3}.md` (nấc executed-file/verified-pending + evidence + tailored/skip + G-015 honest-caveat). 🟥 reviewer P4 **PASS all 3 — no blocker** (genuinely tailored not copy-paste · B6 git-check-ignore verified · SHA256 byte-identical · 1 MINOR pre-existing README diagram drift fixed). **Test 181 unchanged** (no .cs). 🔴 **NEXT: anh restart CLI** activate 2 sub + 2 cmd + hmw.js wave-mode spawn-test confirm verified-runtime. session log `2026-06-07-S49-harness-1-2-3-adopt.md`.
### S48 (2026-06-02) — ✅ adap-* verification closure post-restart + FD2 proof + Gov-v2 error-ledger (governance + 1 a11y fix)
- **CLI restart confirmed done** (registry has frontend-designer + adap-* cmds + 8 subs sans store_memory) S47 "verified-pending" upgraded. `/adap-apply all-pending` = 0 new (all 3 applied S47); `/adap-report all-applied` re-assessed + updated 3 reports honest C5/G-015).
- **#1 store_memory strip VERIFIED-runtime:** `grep` agents `tools:` = 0 · loaded registry grants 0 `store_memory` to all **8** subs. NOT "read-only" (subs keep Bash/Write defense-in-depth caveat holds).
- **#2 frontend-designer FD2 loop VERIFIED-RAN** (🩷 first real spawn, background): full loop on fe-user `/login` DS read (Tailwind v4 CSS-first) Vite dev Playwright screenshot 375+1440 viewed PNGs FD4 rubric all-PASS 1-line contrast fix re-shot build PASS. em main mirrored fix to fe-admin (parity). 2 Vite-dev rig gotchas + Tailwind-v4 fact in FD MEMORY.
- **#3 Gov-v2 delta CLOSED (executed-file):** NEW [`docs/governance/error-ledger.md`](governance/error-ledger.md) (blameless RCA E-001..E-004 + Active-Guards 2-strike index + §L.a AS-1..AS-9 deterministic-detect + 3-ledger triad map) + §L.b 6-step wired `session-end.md` Phase 1.5 (ran live this session = demo).
- **Code:** `fe-{admin,user}/src/pages/LoginPage.tsx` subtitle `text-slate-500→600` (a11y contrast ~7.5:1). Build × 2 PASS 0 TS error. **Test 181 unchanged** (FE-only, no .cs). Commit `350b2bf` 🟩 **cicd Run #369 PASS** (~4m13s · bundle admin `DPPTx2Kw`/user `CjoUEsoV` rotated · Mig stays 43 · health 200 ×4). session log `2026-06-02-S48-adap-verify-fd2-error-ledger.md`.
### S47 (2026-06-02) — 🔌 AI_INFRA adap-* adoption channel + 3 broadcasts (infra/governance, no product code)
- **Federated adoption channel installed** (AI_INFRA relay): 3 slash-commands forked `.claude/commands/adap-{apply,report,request}.md`. Read AI_INFRA `broadcasts/outbox/` read-only J2) apply own repo `docs/governance/adap-reports/<id>.md` (5-field LOCK); AI_INFRA `/adap-audit` reads cross-repo 2-way. 0 agents spawned (em main solo governance task).
- **#1 store_memory strip** removed from ALL 8 subs' `tools:` **lead (em main) = sole RAG-writer** (failure-safe). 4 RAG-read retained ×8. `agents/README.md` synced + G-015 note (NOT "read-only" subs keep Bash/Write). Corroborates SE S41 re-bootstrap-loss lesson.
- **#2 frontend-designer (8th agent, pink)** adopted (user call), forked AI_INFRA canonical FD1FD10 visual-verification floor (Playwright screenshot 2 viewport rubric fix). Tailored SE stack + use-existing-DS (#1F7DC1/Be Vietnam Pro) + boundary implementer-frontend (design/UX vs mechanical-mirror). memory seed + roster doc 78.
- **#3 Gov-v2** already-applied S44 (`ae30f8f`); delta report flags 1 gap (no formal error-ledgerL.b checklist defer).
- **Nấc all executed-file / verified-pending** (restart + spawn-test). Test **181 unchanged** (no product code). CI-skip (all .md). session log `2026-06-02-S47-aiinfra-adap-channel.md` · memory `feedback_aiinfra_adap_channel` · restart-batching lesson (front-load .md edits 1 restart).
### S46 (2026-06-01) — 🧹 Memory integrity repair (no code, docs-only)
- **`/session-start` audit caught 2 user-memory files at 0 bytes** (S45 close-out truncation, gotcha #53): `MEMORY.md` index + `feedback_background_spawn_visibility.md`. Empty index = S46 bootstrap chạy KHÔNG memory auto-inject (degrade thầm lặng).
- **Repaired (👤 em main solo):** rebuilt `MEMORY.md` index (14 entries: 8 feedback + 3 project + 2 pattern) · repopulate `feedback_background_spawn_visibility` từ HANDOFF/STATUS S45 ref (marked reconstructed) · NEW `feedback_session_end_memory_write_verify` (verify byte>0 sau closeout Write). **0 empty `.md` remain** (verified `find -size 0`).
- **No production/repo code touched.** Memory files ngoài repo (`~/.claude/.../memory/`) — không git-tracked → repo unchanged từ S45 `7fbe05a`. Test gate re-confirm **181 PASS** (58+123) lúc bootstrap.
- **Residual:** STATUS "27 user memory" stale → corrected **14**. Recommend thêm verify-byte-count step vào `/session-end` skill mechanism (AI_INFRA op per charter v2) — auto-catch class lỗi này.
### S45 (2026-06-01) — 🧪 HRM test-gap stabilization + Holiday drift fix (Mig 43)
- **2 commit `051b62b` (Tests) + `0c5a014` (Mig 43) → push → Gitea Run #368 PASS, verified prod.** "Stabilize before extend": đóng 3 test-gap deferred S35-S38 TRƯỚC khi chồng schema mới.
- **+27 test (154→181):** Gap1 Holiday composite UNIQUE (7) · Gap2 EmployeeSatellite FK-invariant+soft-delete+cascade (10) · Gap3 gotcha #44 authz regression HrmConfigs+Employees (10). 🟪 test-specialist viết (return truncated gotcha #53 → 👤 em main verify-on-disk + proxy MEMORY).
- **Mig 43 `FilterHolidayUniqueIndexByIsDeleted`** (👤 em main solo, bug-fix chain): Gap1 test lòi drift — Holiday DB UNIQUE (Year,Date) unfiltered vs handler `!IsDeleted` → admin xoá+thêm lại ngày lễ cùng date = **500 reachable**. Fix `.HasFilter("[IsDeleted]=0")` (khớp pattern 13× sẵn có). Flip Case 7 assert success. Table vẫn 91 (index-only).
- **🟩 cicd Run #368 PASS** ~4m20s: test gate 181 · Mig 43 applied prod · `IX_Holidays_Year_Date` filter=`([IsDeleted]=(0))` live (was NULL) · FE bundle UNCHANGED `Krjvg_3j`/`6sNStgxa` (đúng — BE-only) · health 200 · 0 regression.
- **🟦 investigator P11-C pre-flight** (Vehicle+Driver catalog): chưa có master → extend HrmConfigs +2 kind declarative, Mig 44, giữ VehicleBooking free-text. **gotcha #57 caught:** LeaveType.Code + ShiftPattern.Code cũng unfiltered (backlog).
- **gotcha #57 NEW** (soft-delete UNIQUE phải `.HasFilter`). Process: foreground spawn = im lặng = "looks frozen" → đẩy background + report-ngay (`feedback_background_spawn_visibility`).
### S44 (2026-06-01) — 🗓️ Monthly drift audit + AI_INFRA bundle 06-01 adoption (docs-only, CI-skip)
- **Cadence audit** (cron 2026-06-01) + adopt AI_INFRA bundle 06-01 (federated, team chọn full scope). 🟦 investigator-codebase drift scan (read-only, ground-truth verified) → 👤 em main patch. No code touched → **154 test PASS unchanged**.
- **42 count-drift fixes:** CLAUDE.md root + docs/CLAUDE.md + `ef-core-migration` SKILL + `dependency-audit-erp` SKILL + schema-diagram + database-guide — `40→42 mig · 84/59/55/47→91 tables · 130/111→154 test · 52/49→56 gotcha`.
- **Schema-diagram:** migration table extended Mig 17-42 (was stop ở 16) + total 55→91; detailed-§ gap (Mig 27-42 modules) flagged **explicit** (không silent → deferred backlog). `ef-core` SKILL migration history extended Mig 27-42.
- **AI_INFRA bundle:** §A RAG T1/T2 auto-ack · §B Gov-v2 align (no new layer) · §C hygiene **7/7 agent-mem L1 ≤16KB**, "25KB"→"~30KB tiered" wording ×7 · §D `#4` self-sustaining adoption-report step → `/session-end` (skip #1 đã có / #3 helper) · §E report + §F ledger `docs/governance/`.
### S43 (2026-05-30) — 🔄 Phase 11 P11-B: LeaveBalance business logic (trừ phép + số dư)
- **Commit `82d7fcf` → Gitea #367 PASS ~4m08s, deployed prod.** 7-agent (recon → BE → FE ∥ test → reviewer → cicd), agents Max → **0 bug lọt**.
- **Mig 42 `AddLeaveBalances`** (additive): `LeaveBalances` (User×LeaveType×Year + Entitled/Used/Adjustment, UNIQUE composite + FK LeaveTypes Restrict). 90→91 tables.
- **Trừ phép**: hook `ApproveLeaveRequestHandler` nhánh terminal DaDuyet — exactly-once (guard chặn re-approve), upsert auto-create từ `DaysPerYear`, `UsedDays += NumDays`, Year=StartDate.Year. Policy **cho phép âm + cảnh báo** (anh chốt).
- **FK invariant guard** (em Max-review thêm sau test reveal): Create + UpdateDraft validate LeaveTypeId tồn tại → ConflictException (đóng cửa, tránh 500 kẹt đơn lúc deduction FK insert).
- **CQRS** `LeaveBalanceFeatures.cs`: GetMy (self lazy-merge active LeaveType) + GetUser (admin) + Adjust (admin upsert). Embed balance NGƯỜI TẠO vào leave detail (approver xem đúng).
- **FE**: `WorkflowAppDetailPage` ×2 block "Số dư phép" + cảnh báo vượt (kind=leave, SHA256 identical, tích hợp trang đơn nghỉ — không trang riêng).
- **Test**: 144→**154** (+11 LeaveBalance/guard + repair 2 template terminal FK). Reviewer Max PASS (deduction exactly-once + FK fully closed; 2 minor defer: concurrency lost-update no-RowVersion + stale comment).
- Verified prod: Mig 42 applied, LeaveBalances UNIQUE+FK ✓, `/leave-balances/my` 200 → 5 LeaveType lazy-default, bundle rotate.
### S42 (2026-05-30) — 🔄 Phase 11 P11-A: wire ApproveV2 + LevelOpinions 4 WorkflowApps module
- **Commit `e7b66cd` (Gitea #364) + fix `75df04e` (#365) → PASS, deployed prod.** Cookie-cutter mirror Proposal (Mig 38). 7-agent end-to-end (recon → BE×3 → FE → test → reviewer → cicd). (Run-id "#250" memory truncated ghi sai → Max re-verify reconcile #364/#365.)
- **Mig 41 `WireWorkflowAppsApprovalV2`** (additive): +4 bảng `{Leave,Ot,Travel,Vehicle}LevelOpinions` (UNIQUE composite + Cascade/Restrict) + `WorkflowAppCodeSequences` (shared atomic MaDonTu) + 4 cột `RejectedFromStatus` + enum `TravelRequest=9`.
- **BE:** 30 handler (`LeaveOt` + `TravelVehicle` ApprovalFeatures.cs) — GetById/Update/Submit/Approve(UPSERT+advance)/Reject/Return + verify ApplicableType per module. 8 controller route. Seed 4 WF mẫu (QT-NP/OT/CT/XE-V2-001, AppType 5/6/7/9) — gotcha #51 INFRASTRUCTURE-gated PASS prod.
- **FE:** `WorkflowAppDetailPage.tsx` declarative 4-kind (admin+user SHA256 identical) — workflow status + opinion timeline + Submit/Approve/Reject/Return actions; gỡ banner skeleton + row nav.
- **Test:** +11 `WorkflowAppApproveV2Tests` (130→141) — state machine + UPSERT invariant + guards + forbidden + placeholder + codegen. No prod bug.
- **Verified:** Mig 41 applied prod (5 bảng EXIST) · bundle rotate cả 2 app · 4 endpoint live · seed prod · reviewer checklist (no copy-paste bug, [Authorize] OK).
- ⚠️ **Gotcha #53/#55 tái diễn 3× session này** (FE + reviewer + cicd-monitor truncate output cuối) — mỗi lần recover qua MEMORY + em main manual verify. Anti-truncation lesson reinforced.
- 🔬 **Max re-review (agents chạy High) phát hiện + fix 2 bug FE picker** (chưa commit lúc deploy đầu): (#1) `pinWorkflow` PUT `/{id}` partial → 400 validator; (#2) fetch expect array nhưng endpoint trả `{types}` object → picker rỗng. Fix: thêm endpoint chuyên dụng `PUT /{id}/workflow` (set workflow only, verify ApplicableType) + sửa fetch mirror PE/Contract `data.types.find().history.filter(isUserSelectable)`. +3 test SetWorkflow (141→144). **Bonus phát hiện:** `ProposalCreatePage` (S37) có bug #2 có sẵn → spawn task riêng.
- 📌 Follow-up minor (non-blocking): known-minor unreachable (Reject/Return actor-check khi CurrentApprovalLevelOrder null) · deploy.yml stale comment "54/17 test" (cosmetic) · test Travel/Vehicle mirror pending (Leave full + Ot smoke có).
### S41 (2026-05-29) — RAG corpus cleanup (w/ AI_INFRA)
- AI_INFRA RAG audit → SE-side prep: `.claude/rag.json` exclude root-anchored→`**/`-anchored (defeats gotcha #10: `node_modules/**`+`docs/_archive/**` weren't matching nested paths) + retired stale `_decision_log` "+321%/11,922".
- **store_memory reconcile (anti-data-loss, NAMGROUP lesson):** unified at-risk rule = content reproducible từ file {exists ∧ matches corpus glob ∧ not excluded}. 5/5 accounted: 3 broadcasts disk-twinned + `16a6b6db` audit-response twin-safe + `0307141b` S37-S40 catch-up **promoted-to-disk** (`docs/changelog/sessions/2026-05-29-S37-S40-rag-catchup.md` — anchor was virtual, not real STATUS section).
- AI_INFRA re-bootstrap host-side `--config`: **3080→2406** (674 junk), node_modules=0 / _archive=0 / manual-marker=0, user-memory 60 chunks (slug fix). SE post-verify PASS (promoted catch-up returns file-indexed real heading, not `(manual)`). Commits `282cbd0`+`e8cbbe5` pushed (docs/infra → CI skip).
- ⏳ Standing infra backlog (AI_INFRA, non-blocking): bootstrap glob→0 warn · auto_reindex hook fire · search_code corpus gap (src/*.cs+fe/*.tsx, v0 design) · registry sync.
### S40 (2026-05-29) — Init audit + doc consolidation
- 7-agent smoke verify (🟪 test-specialist + 🟦 investigator-api load OK), RAG re-rank PASS (top 0.8789 Voyage rerank-2.5), 130 test confirm.
- Doc consolidation: STATUS 170KB→5.7KB + HANDOFF 224KB→3.4KB (archive full → `docs/_archive/`). Count re-ground (endpoints 211, FE pages 65, menu ~53; tables 84 confirmed). Stale credential `admin@solutionerp.local``admin@solutions.com.vn` fixed. CLAUDE.md root patch (mig/table/test).
- Curate 4 agent MEMORY >25KB→<8.4KB (~130KB41KB, foundation preserved + verbatim git). RAG store_memory S37-S40 catch-up chunk. 2 commit push `d2f52ba`+`78c9de3` (docs-only CI skip).
### S39 (2026-05-29) — ⚙️ INFRA: Opus 4.8 1M + Multi-agent 4→7 + budget +50%
- Pure infra/governance, 1 commit `fd0554a` (docs CI skip). Model default Opus 4.8 1M. investigatorcodebase+api · implementerbackend+frontend · +test-specialist (purple). 5 RAG MCP/agent. 2 gotcha NEW #54 (529 fallback) + #55 (truncation mid-exploration). CLI restart registry hot-reload (done S40).
- `docs/changelog/sessions/2026-05-29-S36-S39-phase10-complete-7agent.md`
### S38 (2026-05-28) — 🎊 PHASE 10 COMPLETE 11/11 (SKELETON combo)
- Mig 39+40 + BE ~1100 LOC + FE 5 file × 2 app + 8 menu. Run #247 PASS 3m25s. G-O4/O5/O6/P1/H3 skeleton. Trade-off DEFER Phase 11: ApproveV2 wire + LevelOpinions per-module + LeaveBalance + CodeGen atomic + Vehicle/Driver catalog + ItTicket auto-assign/SLA.
- same session log
---
## 🎯 Next up
### ✅ Phase 11 — Polish/wire skeleton (COMPLETE S52)
- **P11-A** wire ApproveV2 + LevelOpinions 4 module **DONE S42** (prod).
- **P11-B** LeaveBalance business logic **DONE S43** (Mig 42, prod).
- **P11-C** Vehicle+Driver catalog **DONE S51** (Mig 44/45, prod).
- **P11-D** ItTicket round-robin assign + SLA timer **DONE S52** (Mig 46, `dcf76f8`, prod). Dept-IT pool + `ItTicketSlaJob` no-auto-transition. _Follow-up minor: reassign-UI defer (endpoint `/assign` sẵn)._
- **P11-E** AttendanceReport + Excel + OtPolicy multiplier **DONE S52** (`6a66429`, prod). Admin-only, weighted-OT-hours (no salary field quy-đổi-giờ not pay, MVP). _Follow-up: menu-key promote (hiện via button)._
- **P11-F** CodeGen atomic MaTicket **DONE S52** (`6a66429`, prod). gen-on-Create `IT/2026/NNN`.
### 🔧 Maintenance backlog
- RAG re-ingest `solution_erp` S42-S43 content (store_memory stopgap live; full re-index = AI_INFRA op)
- **gotcha #57 LeaveType+ShiftPattern+OtPolicy filtered-unique DONE S51** (Mig 45, **3 HRM catalog** OtPolicy bị bỏ sót khỏi backlog "2 catalog", bắt được via grep + test-before 5 case). **EXT (worktree session, Mig 46):** Department/Supplier/Project (Master, confirmed-reachable via global query-filter quirk); ContractClause/MeetingRoom/EmployeeProfile = SKIP (audit-verified not-reachable).
- Skill + doc drift audit cron **2026-06-01 DONE (S44)** 42 count-drift fixes + AI_INFRA bundle adopt; next **2026-07-01**
### 🚫 Phase 9 Ops (blocked — anh main coordinate)
- SMTP email outbound · Rotate prod creds · SQL auto-backup (backup-sql.ps1 ready, chờ Task Scheduler register) · UAT 2-3 user 1 tuần
---
## 🚨 Blockers / risks
- **Email SMTP chưa có** blocker notification outbound
- **Credentials trong chat** rotate trước go-live thật
- **SQL backup chưa auto** risk data loss (script ready, chờ register)
- **UAT real user chưa chạy** risk edge-case bug
- **Cert** `api.solutions.com.vn` expire ~2026-07-23 (auto-renew ~06-23)
---
## 🔑 Credentials + URLs
```
Prod login: admin@solutions.com.vn / Admin@123456 (⚠️ rotate sau login đầu)
```
- API prod `https://api.solutions.com.vn` (`/health/live` + `/health/ready`) · dev `http://localhost:5443` (`/swagger`)
- Admin FE prod `https://admin.solutions.com.vn` · dev `:8082`
- User FE prod `https://eoffice.solutions.com.vn` · dev `:8080`
- Gitea `https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp` · SSH `ssh vietreport-vps`
- SQL prod `.\SQLEXPRESS` / `SolutionErp` · dev `(localdb)\MSSQLLocalDB` / `SolutionErp_Dev`
---
> **Session history:** S0→S39 full detail trong `docs/changelog/sessions/` + `docs/_archive/STATUS-preS40-fullhistory.md`. File này chỉ giữ state hiện tại + 3 session gần nhất.