[CLAUDE] Docs: Harness-4 two-tier runtime-VERIFIED (spawn-test 2 chiều post-restart) + email-back AI_INFRA
Some checks failed
Deploy SOLUTION_ERP / build-deploy (push) Has been cancelled

- Spawn-test 2 chiều S57bis: H1 tooling-auditor (demote pin) self-report claude-opus-4-8[1m] + H2 harvest-curator (promote inherit) self-report claude-fable-5[1m] → nấc executed-file/PENDING-RESTART → RUNTIME-VERIFIED (adap-report §2/§5 + STATUS row). [1m] 1M-resolve SE tự verify.
- Email update 2026-06-11-se-to-ai_infra-harness-4-runtime-verified (nac sent, sha ecf1d587, honest n=1/chiều, hmw.js executed-file giữ) + _index OUTBOUND.
- Lesson env: CCD harness cache agent frontmatter — restart CLI mới ăn (2 data-point 06-10/06-11).
- Bundle 06-10 carry: 7 agent pin opus-4-8 + 4 inherit + hmw.js tier-map H4.5 + agents/README two-tier + 2 adap-report + email 06-10 + agent-memory delta (KEEP-ALL-5 H2-verified) + investigator L1→L2 archive curate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-06-11 12:12:22 +07:00
parent a62e797332
commit 17b23a418a
27 changed files with 236 additions and 38 deletions

View File

@ -26,3 +26,6 @@ H2 harvest-MD-integrity auditor **SOLUTION_ERP-self**. Read-only + **propose-onl
- **2026-06-07 (CREATED):** Seeded H2 harvest-curator (adopt AI_INFRA Harness 1, anh giao). Tailored SE: 4 RAG-read · `model:inherit` · omit color · Fidelity-escalate → SE `reviewer` (KHÔNG AI_INFRA-specific). Wired @session-end §L.b GATE (nâng 3/5→5/5 trục) + @session-start RE-REPORT harvest-mới (Phase 2.1.1) + Harness 2 B5 wave-gom. Nấc: **executed-file, verified-runtime PENDING** CLI restart + first spawn smoke. Tag [created, harness-1, h2]. - **2026-06-07 (CREATED):** Seeded H2 harvest-curator (adopt AI_INFRA Harness 1, anh giao). Tailored SE: 4 RAG-read · `model:inherit` · omit color · Fidelity-escalate → SE `reviewer` (KHÔNG AI_INFRA-specific). Wired @session-end §L.b GATE (nâng 3/5→5/5 trục) + @session-start RE-REPORT harvest-mới (Phase 2.1.1) + Harness 2 B5 wave-gom. Nấc: **executed-file, verified-runtime PENDING** CLI restart + first spawn smoke. Tag [created, harness-1, h2].
- **2026-06-07 (S50 FIRST REAL RUN — verified-runtime ✅):** Spawned @session-start (harvest RE-REPORT) + @session-end (5-trục GATE + B5 wave-gom). Load OK → **verified-runtime CONFIRMED**. @start: harvest 🟢 clean. @end: **GATE PASS 5/5** (Coverage 4 subs · Completeness 4-field · Placement correct homes · Corruption 0-byte/mojibake=0 · Fidelity no-flag — independently re-verified inv-codebase `.gitignore:93` claim). **B5 wave-gom executed:** 2 wave sub-MDs → propose APPEND agent-memory/{investigator-codebase,test-specialist} (em main wrote). B6 re-verify HELD (git diff agent-memory EMPTY). **Method-learning (⭐):** chunk-count CANNOT verify via Bash `curl localhost:6333` — RAG MCP points at DIFFERENT Qdrant host → collection 'not found' false-negative. Use **RAG MCP channel** (`list_projects`) for chunk-count, NOT shell probe; em main (single RAG-writer) = authoritative (confirmed 2415). Tag [first-run, verified-runtime, gate-pass, chunk-via-mcp]. - **2026-06-07 (S50 FIRST REAL RUN — verified-runtime ✅):** Spawned @session-start (harvest RE-REPORT) + @session-end (5-trục GATE + B5 wave-gom). Load OK → **verified-runtime CONFIRMED**. @start: harvest 🟢 clean. @end: **GATE PASS 5/5** (Coverage 4 subs · Completeness 4-field · Placement correct homes · Corruption 0-byte/mojibake=0 · Fidelity no-flag — independently re-verified inv-codebase `.gitignore:93` claim). **B5 wave-gom executed:** 2 wave sub-MDs → propose APPEND agent-memory/{investigator-codebase,test-specialist} (em main wrote). B6 re-verify HELD (git diff agent-memory EMPTY). **Method-learning (⭐):** chunk-count CANNOT verify via Bash `curl localhost:6333` — RAG MCP points at DIFFERENT Qdrant host → collection 'not found' false-negative. Use **RAG MCP channel** (`list_projects`) for chunk-count, NOT shell probe; em main (single RAG-writer) = authoritative (confirmed 2415). Tag [first-run, verified-runtime, gate-pass, chunk-via-mcp].
- **2026-06-08 (S51 `/session-end` 5-trục GATE — DIRECT spawns, RAG down):** Verified 6 product subs · nấc=**verified-runtime** (on-disk ground-truth, **0 file written**, git-diff agent-memory clean = E-006 backstop ✅) · evidence=**GATE PASS 5/5** (Coverage 6/6 S51 entries · Completeness 4-field · Placement correct · Corruption 0-byte=0 + investigator-killed file intact 92L terminates-clean + mojibake/shell-bake=0 · Fidelity reviewer-proxy honestly-marked + "1 MAJOR" claim ground-truthed `HrmConfigsPage.tsx:132-134`). B5 wave-gom **n-a** (DIRECT spawns, no `wave-*/`). 3 non-block flags → em main: (1) test 185→186 honest RED→GREEN (raw 174 attrs→runtime 186) (2) cicd self-tag [s50]→should-be-s51 cosmetic (3) Mig 45→92 tables, CLAUDE.md stale 43→91. **Method-learning ⭐:** killed-mid-write sub → verify file **terminates cleanly** (`wc -l`+tail+closing-Tag), NOT just `-size 0` (partial-write = truncated tail not 0-byte). Tag [s51, gate-pass, killed-sub-verify, direct-spawns]. - **2026-06-08 (S51 `/session-end` 5-trục GATE — DIRECT spawns, RAG down):** Verified 6 product subs · nấc=**verified-runtime** (on-disk ground-truth, **0 file written**, git-diff agent-memory clean = E-006 backstop ✅) · evidence=**GATE PASS 5/5** (Coverage 6/6 S51 entries · Completeness 4-field · Placement correct · Corruption 0-byte=0 + investigator-killed file intact 92L terminates-clean + mojibake/shell-bake=0 · Fidelity reviewer-proxy honestly-marked + "1 MAJOR" claim ground-truthed `HrmConfigsPage.tsx:132-134`). B5 wave-gom **n-a** (DIRECT spawns, no `wave-*/`). 3 non-block flags → em main: (1) test 185→186 honest RED→GREEN (raw 174 attrs→runtime 186) (2) cicd self-tag [s50]→should-be-s51 cosmetic (3) Mig 45→92 tables, CLAUDE.md stale 43→91. **Method-learning ⭐:** killed-mid-write sub → verify file **terminates cleanly** (`wc -l`+tail+closing-Tag), NOT just `-size 0` (partial-write = truncated tail not 0-byte). Tag [s51, gate-pass, killed-sub-verify, direct-spawns].
- **2026-06-10 (S57-interrupted @session-start RE-REPORT):** Verdict VÀNG — orphan delta investigator-codebase 3 entry S57 uncommitted (agent DUY NHẤT có delta post-S56; so mtime vs closeout-commit timestamp `a62e797` 20:20:51 = phương pháp detect interrupted-session). 4-field PASS ×3 · fidelity spot-check: flag "master-write-open" → fix `Roles="Admin,CatalogManager"` ×3 controller đã apply working-tree (recon khớp việc-thật — đọc memory khi resume đừng tưởng còn hở) · wave/stray/0-byte = 0 · flags: investigator 33.5KB>cap archive-L2, entry-3 tag s56→s57, double-blank-line nit. 0 file written (em main append B3). Tag [s57-orphan, mtime-vs-closeout-method, gate-na-start].
- **2026-06-10 (S57-RESUME @start RE-REPORT):** Verdict 🟢 — 3 delta agent-memory uncommitted (harvest-curator +1 · investigator +3-entry · tooling +1+baseline-reground) ALL SANE, attribution nhất quán **em main proxy-append B3** (mtime 2 đợt: investigator 10:56 S57-work → harvest/tooling 11:55-57 resume-attempt; style/nội-dung khớp em-main, KHÔNG dấu hiệu sub tự ghi — G-015 honest "no evidence" ≠ "impossible"). 5-trục: Corruption 0-byte=0 (11/11 ≥4.4KB, tail terminate sạch, mojibake=0) · Wave/stray=0 (7 vị-trí check, S54-pattern không tái) · Fidelity **sample 8/8 deep-verify PASS** (authz ×3 controller · hmw.js:26=9 · README:192/:201 · gotcha-58 ×2 skill · ef-core 93/48 · roster 11=11 folder · catalog.manager:1608 · GetMyMenuTree:96 exact) · Completeness 4-field đủ ×5 entry · Coverage 🟡→resolved: 8 file code KHÔNG có delta implementer-* vì evidence nghiêng **em-main-direct implement** (mtime implementer pre-closeout + diff nhỏ + comment [S57] style em-main + investigator entry viết "Flag em-main" như brief) → không phải Coverage-miss. **2 nit em main FIXED in-session:** investigator entry-3 tag s56→s57 + double-blank-line ×2 gộp 1. Chore còn: investigator 33.5KB>30KB cap → curate L2 @closeout/monthly. Nhắc P1: commit 16 file PHẢI kèm docs-closeout (STATUS/HANDOFF/log) tránh "code committed, docs mù". Tag [s57-resume, gate-start-pass, mtime-attribution, coverage-resolved].
- **2026-06-11 (S57bis @start RE-REPORT + spawn-test post-restart ✅):** Self-report `claude-fable-5[1m]`**promote-tier `inherit` GIỮ Fable 5 runtime-VERIFIED** (H4.3c). Verdict 🟢 **KEEP-ALL-5** — 5 agent-memory delta uncommitted (harvest+2 · impl-backend+1 · investigator+3 · reviewer+1 · tooling+baseline-reground+3) ALL dated 06-10 S57/S57-resume, em-main-proxy-append B3, attribution mtime-cluster 21:5222:28 nhất quán, commit AS-IS. Corruption: 11/11 ≥4.4KB, 0-byte=0, tail sạch, mojibake=0. Wave-folder=0 tồn (S56 2 workflow harvest sạch). 3 untracked = em-main governance docs (KHÔNG phải harvest-MD) → vào commit bundle. Chore giữ: investigator-codebase 33.5KB>30KB cap → L2 @closeout/monthly (reviewer 29.6KB + cicd 29.2KB sát cap, watch). Tag [s57bis, spawn-test-verified, keep-all-5, promote-inherit-proof].

View File

@ -74,6 +74,8 @@ UI `disabled={!canX}` + BE helper `EnsureCanXAsync(id, userId)` throw 403 (NOT i
## 📅 Recent activity (FIFO — older → archive/git) ## 📅 Recent activity (FIFO — older → archive/git)
- **2026-06-10 (S57-resume spawn-test H4.8 — Harness-4 two-tier):** Mình bị DEMOTE pin `model: claude-opus-4-8` (deterministic-scaffold class, double-gate reviewer+test+cicd sau lưng). Spawn-test echo model NGAY sau edit → self-report `claude-fable-5[1m]` = SE env (CCD harness) KHÔNG fresh-read frontmatter → pin ăn SAU restart CLI. Post-restart mình chạy Opus 4.8 (effort Max giữ env-wide); task hệ-trọng giao mình qua hmw có thể override `tier:'fable'`. Tag [h4-demote, spawn-test, pending-restart].
- **S56 GOLIVE-HARDEN 3 BE fix (NO mig, 3 file edit, em-main spec deterministic 100% → ACCEPT Case 1):** **#3 LeaveBalance lost-update** `LeaveOtApprovalFeatures.cs` terminal DaDuyet branch → atomic-executeupdate-tx (spec chosen, KHÔNG RowVersion/Mig). Replaced in-mem `bal.UsedDays += NumDays` với: set p.Status/Updated* → `(DbContext)db` cast + `BeginTransactionAsync(ct)` (plain, NO IsolationLevel — READ COMMITTED đủ vì increment atomic) → STEP1 ensure-row (FirstOrDefault, auto-create UsedDays=0 via tracker) + SaveChanges (opinion+status+insert trong tx) → STEP2 `db.LeaveBalances.Where(...).ExecuteUpdateAsync(s=>s.SetProperty(b=>b.UsedDays, b=>b.UsedDays+p.NumDays), ct)` server-side row-lock race-free → `tx.CommitAsync` + **`return;`** (skip trailing shared SaveChanges). **STALE-TRACKED caveat (load-bearing):** ExecuteUpdate bypass tracker → tracked `bal` giữ pre-increment value; SAFE vì không đọc lại + handler return ngay; KHÔNG thêm `bal.UsedDays +=` (double-count). `using System.Data` + EF Core đã import. **#5 AssignItTicketHandler existence-oracle** `WorkflowAppsFeatures.cs:493` → moved Admin-OR-dept-IT Forbidden guard (itDeptId+isAdmin+myDeptId resolve) TRƯỚC ticket NotFound lookup → fail-closed (non-IT nhận Forbidden cho MỌI ticketId). assignee-must-be-IT Conflict + reassign giữ nguyên. **#6 DocxRenderer.cs:30,40 CS8602** → hoist `mainPart = doc.MainDocumentPart ?? throw InvalidOperationException` + `document = mainPart.Document ?? throw` (Document cũng nullable — KEY: 1st hoist chỉ fix part, vẫn còn 1 warn ở `.Document.Body`); deref qua local non-null. Build SolutionErp.slnx **0 err 0 warn** (DocxRenderer warn CLEARED — thực tế 1 warn không phải 2 như MEMORY ghi). Test 58 Domain PASS + 154/158 Infra: **4 FAIL `LeaveBalanceTests` (Approve_LastLevel_DeductsLeave.../AccumulatesExisting.../OverEntitled.../MultiLevel_NoDeductAtIntermediate)** = EXPECTED #3 stale-tracked (re-query trả tracked instance pre-increment, DB row đúng) → tests_to_update cho test-specialist (add AsNoTracking/ChangeTracker.Clear). ItTicket authz tests #5 PASS (Case5 đã expect Forbidden, NotFound case dùng Admin caller). KHÔNG touch tests/FE/commit. #4 (Travel/Vehicle smoke test) = test-specialist next stage. Tag `[s56, golive-harden, executeupdate-atomic, fail-closed-authz, cs8602, no-mig]`. - **S56 GOLIVE-HARDEN 3 BE fix (NO mig, 3 file edit, em-main spec deterministic 100% → ACCEPT Case 1):** **#3 LeaveBalance lost-update** `LeaveOtApprovalFeatures.cs` terminal DaDuyet branch → atomic-executeupdate-tx (spec chosen, KHÔNG RowVersion/Mig). Replaced in-mem `bal.UsedDays += NumDays` với: set p.Status/Updated* → `(DbContext)db` cast + `BeginTransactionAsync(ct)` (plain, NO IsolationLevel — READ COMMITTED đủ vì increment atomic) → STEP1 ensure-row (FirstOrDefault, auto-create UsedDays=0 via tracker) + SaveChanges (opinion+status+insert trong tx) → STEP2 `db.LeaveBalances.Where(...).ExecuteUpdateAsync(s=>s.SetProperty(b=>b.UsedDays, b=>b.UsedDays+p.NumDays), ct)` server-side row-lock race-free → `tx.CommitAsync` + **`return;`** (skip trailing shared SaveChanges). **STALE-TRACKED caveat (load-bearing):** ExecuteUpdate bypass tracker → tracked `bal` giữ pre-increment value; SAFE vì không đọc lại + handler return ngay; KHÔNG thêm `bal.UsedDays +=` (double-count). `using System.Data` + EF Core đã import. **#5 AssignItTicketHandler existence-oracle** `WorkflowAppsFeatures.cs:493` → moved Admin-OR-dept-IT Forbidden guard (itDeptId+isAdmin+myDeptId resolve) TRƯỚC ticket NotFound lookup → fail-closed (non-IT nhận Forbidden cho MỌI ticketId). assignee-must-be-IT Conflict + reassign giữ nguyên. **#6 DocxRenderer.cs:30,40 CS8602** → hoist `mainPart = doc.MainDocumentPart ?? throw InvalidOperationException` + `document = mainPart.Document ?? throw` (Document cũng nullable — KEY: 1st hoist chỉ fix part, vẫn còn 1 warn ở `.Document.Body`); deref qua local non-null. Build SolutionErp.slnx **0 err 0 warn** (DocxRenderer warn CLEARED — thực tế 1 warn không phải 2 như MEMORY ghi). Test 58 Domain PASS + 154/158 Infra: **4 FAIL `LeaveBalanceTests` (Approve_LastLevel_DeductsLeave.../AccumulatesExisting.../OverEntitled.../MultiLevel_NoDeductAtIntermediate)** = EXPECTED #3 stale-tracked (re-query trả tracked instance pre-increment, DB row đúng) → tests_to_update cho test-specialist (add AsNoTracking/ChangeTracker.Clear). ItTicket authz tests #5 PASS (Case5 đã expect Forbidden, NotFound case dùng Admin caller). KHÔNG touch tests/FE/commit. #4 (Travel/Vehicle smoke test) = test-specialist next stage. Tag `[s56, golive-harden, executeupdate-atomic, fail-closed-authz, cs8602, no-mig]`.
**[em main post-review S56]** Tx bumped → `IsolationLevel.Serializable` (shipped code `LeaveOtApprovalFeatures.cs:369`) per database-agent review — convention-align (codegen/Proposal/TravelVehicle) + serialize auto-create-row race. '(plain, NO IsolationLevel — READ COMMITTED đủ)' ở entry = pre-review reasoning, **superseded**. Test 228 green. **[em main post-review S56]** Tx bumped → `IsolationLevel.Serializable` (shipped code `LeaveOtApprovalFeatures.cs:369`) per database-agent review — convention-align (codegen/Proposal/TravelVehicle) + serialize auto-create-row race. '(plain, NO IsolationLevel — READ COMMITTED đủ)' ở entry = pre-review reasoning, **superseded**. Test 228 green.
- **S55 master-data import (Mig 48 `AddProjectMasterFields` 4 AddColumn no-table + `SeedRealMasterDataAsync` 62 Project+71 WorkItem+3 Supplier) [proxy by em main — agent return truncated gotcha #53 before MEMORY step]:** Project entity +4 prop (`Year int?`, `Investor/Location/Package string?`, maxlen 250/500/300 ProjectConfiguration). `ProjectFeatures.cs` DTO+CreateCmd+UpdateCmd+validators+handlers+List/Get projections +4 (all nullable, appended end). **`SeedRealMasterDataAsync`** = 3 tuple-loop per-code idempotent (mirror `SeedDemoMasterDataAsync:2185` `existingCodes.Contains→skip`) wired UNGATED line 118 AFTER `SeedCatalogsAsync` → reaches prod (DemoSeed:Disabled=true KHÔNG gate, by-design như SeedDemoMasterData/Catalogs). Project Name=Code khi Excel blank. WorkItem 4 Category (Vật tư16/Thầu phụ30/MEP9/Thiết bị16, gen Code VT/TP/MEP/TB-NN; divider "THIẾT BỊ" dropped). Supplier NTP→NhaThauPhu/NCC→NhaCungCap, extras→Note. **FLOCK01 collision** demo↔real → per-code skip (demo thắng, real code+year only, OK). Compile-fix `MasterCatalogFilteredUniqueTests.cs` +4 null args CreateProjectCommand (necessary build-green). **Runtime Dev proof (em main):** app-start seeded 62proj/71wi/3sup landed, CAL01.Investor col populates, 0 overflow/dup. Build 0/0, test 216. Data spec `scripts/master-import-data.generated.md`. Tag `[s55, master-import, mig48, seed-real-ungated, project-4field]`. - **S55 master-data import (Mig 48 `AddProjectMasterFields` 4 AddColumn no-table + `SeedRealMasterDataAsync` 62 Project+71 WorkItem+3 Supplier) [proxy by em main — agent return truncated gotcha #53 before MEMORY step]:** Project entity +4 prop (`Year int?`, `Investor/Location/Package string?`, maxlen 250/500/300 ProjectConfiguration). `ProjectFeatures.cs` DTO+CreateCmd+UpdateCmd+validators+handlers+List/Get projections +4 (all nullable, appended end). **`SeedRealMasterDataAsync`** = 3 tuple-loop per-code idempotent (mirror `SeedDemoMasterDataAsync:2185` `existingCodes.Contains→skip`) wired UNGATED line 118 AFTER `SeedCatalogsAsync` → reaches prod (DemoSeed:Disabled=true KHÔNG gate, by-design như SeedDemoMasterData/Catalogs). Project Name=Code khi Excel blank. WorkItem 4 Category (Vật tư16/Thầu phụ30/MEP9/Thiết bị16, gen Code VT/TP/MEP/TB-NN; divider "THIẾT BỊ" dropped). Supplier NTP→NhaThauPhu/NCC→NhaCungCap, extras→Note. **FLOCK01 collision** demo↔real → per-code skip (demo thắng, real code+year only, OK). Compile-fix `MasterCatalogFilteredUniqueTests.cs` +4 null args CreateProjectCommand (necessary build-green). **Runtime Dev proof (em main):** app-start seeded 62proj/71wi/3sup landed, CAL01.Investor col populates, 0 overflow/dup. Build 0/0, test 216. Data spec `scripts/master-import-data.generated.md`. Tag `[s55, master-import, mig48, seed-real-ungated, project-4field]`.

View File

@ -70,6 +70,14 @@ Bearer từ `POST api.solutions.com.vn/api/auth/login` → status matrix expecte
## 📅 Recent activity (FIFO — older → archive/git) ## 📅 Recent activity (FIFO — older → archive/git)
- **2026-06-11 (S57bis PE recon — 4 đầu việc sếp, on-disk):** ⭐ PE entity NO Year, NO WorkItem link (`PurchaseEvaluation.cs:15` ProjectId req; Detail free-text `PurchaseEvaluationDetail.cs:10-13`). Create cmd `PurchaseEvaluationFeatures.cs:19-30`; MaPhieu gen-AT-CREATE `:114-116` format `PE/{YYYY}/{A|B}/{Seq:D3}` (`PurchaseEvaluationCodeGenerator.cs:23`). Main create UI = `PeWorkspaceCreateView.tsx` (:151 workflow-select isUserSelectable ĐẦU TIÊN → tenGoiThau → projectId → DiaDiem → MoTa → PaymentTerms → budget; canSubmit :129 = wf+project+ten). PE controller class-`[Authorize]` ONLY no policy → mở menu là đủ, no silent-403. Pe_* leaves NOT in `MenuKeys.All` (chỉ root :156); PE defaults 7 role × 11 key (root + 2type×{group,WfView,List,Create,Pending}) `DbInitializer.cs:2098-2160`. S57 `SeedAllRolesReviewReadPermissionsAsync:1993-2001` InReviewScope EXCLUDES Pe; extend đúng = `key == MenuKeys.PurchaseEvaluations` EXACT (prefix "Pe" sẽ dính PeWorkflows admin!) — root inherit cascade (`GetMyMenuTreeQuery.cs:49-82`). Demo gate: prod `appsettings.json:35 DemoSeed:Disabled=true` → 7 `[DEMO]` HĐ + 4 `[DEMO]` PE (MaPhieu `[DEMO]-A-001`) KHÔNG lên prod; UNGATED trên prod = 31 users + 18 demo NCC + 8 demo project (:2244-2315) + real 62/71/3 (:2329-2522). ⚠️ Clear-demo gotcha: seed re-add per-code idempotent MỖI startup → xóa DB-only sẽ resurrect, phải gỡ khỏi DbInitializer code. WorkItem write Admin-only (`CatalogsController:113-130`) — CatalogManager có menu-perm nhưng API write bị chặn. Tag `[s57bis, pe-recon, demo-inventory]`.
- **2026-06-10 (S57 perm-broaden blocks A/B/E/F — on-disk):** ⭐ **BE AUTHZ SPLIT (decision-critical for E):** Config controllers gate WRITE behind `[Authorize(Roles="Admin")]`, READ open to any-authed: `HrmConfigsController.cs:15` class `[Authorize]`+GET open `:19-21`, all POST/PUT/DEL `Roles="Admin"`; `CatalogsController.cs:14` same (write `:23+` Admin); `MeetingRoomsController.cs:15` same (comment `:9-10` explicit). → granting FE read on Hrm_Config/Catalogs/MeetingRooms = pure UI-visibility, BE already correct. **BUT Master 3 controllers = class `[Authorize]` ONLY, no per-action role:** `SuppliersController.cs:17`, `ProjectsController.cs:11`, `DepartmentsController.cs:11` — ANY authed user can POST/PUT/DELETE via API (FE menu perm is only gate, not BE-enforced). Flag em-main: making Suppliers/Projects/Departments visible-to-all ⇒ staff can write master incl. S55 prod data unless add `[Authorize(Roles="Admin,CatalogManager")]` or per-action policy. **S55 PROD DATA location:** `SeedRealMasterDataAsync` `:2267-2460` writes to **Projects**(62, `:2270`), **WorkItems**(71=CatalogWorkItems key, `:2430-2438`), **Suppliers**(3, `:2440-2456`) — all ungated idempotent per-code. **10 departments now** (`SeedDepartmentsAsync:2104`): 9 orig + IT (`:2115`). **31 demo users** (`SeedDemoUsersAsync:1553-1609`): dept spread BOD4/PM2/CCM9/PRO6/QS2/FIN2/ACT1/EQU1/HRA2; roles = mostly Drafter/CostControl/Procurement + 1 CatalogManager (`catalog.manager@`, dept PRO, `:1608`). NO user has zero-role; every demo user authenticatable. **Inherit-root display:** `GetMyMenuTreeQuery.cs:96 HasAccess = CanRead OR Children.Any(HasAccess)` → a non-inherit root (Hrm/Off/Master) auto-shows if ANY child has CanRead, so granting leaves is enough to reveal the root node (root row itself optional for display, but grant it too for cleanliness). Inherit-roots (Contracts/Pe/Wf/PeWf) cascade root→child so root-row-only suffices there. Menu already S57-edited: `Personal` group + `Off_ChamCong` re-parent Off→Personal via `parentBackfill:1908`. Tag `[s57-perm, be-authz-split, master-write-open, s55-data, 31user]`.
- **2026-06-10 (S57 perm-broaden RECON blocks C/D — RAG down, on-disk):** ⭐ **SEED MODEL:** `SeedAdminPermissionsAsync` `DbInitializer.cs:1939-1977` Admin loops `MenuKeys.All` CRUD=true skip-existing dedup (`:1950/:1952`). Calls 2 sub: (a) `SeedPurchaseEvaluationPermissionDefaultsAsync` `:2036-2098`**7 roles** {Drafter,DeptManager,Procurement,CostControl,ProjectManager,Director,AuthorizedSigner} Read+Update on PE keys only; (b) `SeedCatalogManagerPermissionsAsync` `:1984-2029` → role **CatalogManager** full-CRUD 9 master keys. **NO generic per-employee Read seed** — plain Drafter user sees ONLY PE keys; DOESN'T see Off_*/Hrm_*/Master/Contracts. **Most non-admin staff today see ~nothing but PE.** GetMyMenuTree `:96` filters CanRead=true. **Permission entity** `Permission.cs:3-15`: RoleId/MenuKey/CanRead/Create/Update/Delete. Dedup=app-level skip-existing per(RoleId,MenuKey), NO DB upsert. **13 AppRoles** `AppRoles.cs:23`: Admin(system)+12 employee. **4 inherit-roots** `GetMyMenuTreeQuery.cs:56-84`: Contracts/Workflows/PurchaseEvaluations/PeWorkflows — root grant auto-cascades to child IF child no own row (`:66`). Hrm/Off/Master NOT inherit → each leaf needs own row or add to switch. **GRANT-ALL pattern (block D):** mirror CatalogManager seeder but loop `roleManager.Roles` (all 13) × chosen key-set, CanRead=true only, insertion AFTER SeedCatalogManagerPermissionsAsync `:1976`. Tag `[s57-perm-recon, seed-model, no-employee-default, inherit-4root]`.
- **2026-06-10 (menu-order cross-repo recon SE↔NAMGROUP, RAG down, on-disk):** ⭐ **SE menu seed = `SeedMenusAsync` `DbInitializer.cs` tuple-list** (NOT partial). Văn phòng số root `Off` (Order=29) `:1769-1792`; HR root `Hrm` "Nhân sự" (Order=28) `:1754-1767` (+`Hrm_Dashboard` appended out-of-order `:1791`). ⚠️ **HR SCATTERED 2 roots:** `Hrm` holds only Hồ sơ+Cấu hình HRM(6 leaf)+Dashboard; transactional HR (Nghỉ phép/OT/Công tác/Đặt xe/Chấm công/Báo cáo CC) live under `Off` as `Off_DonTu_*`/`Off_DatXe`/`Off_ChamCong`/`Off_AttendanceReport`. **SEED = UPSERT that RE-SETS Order** (`:1845-1871` `if(existing.Order!=o){existing.Order=o}`) → reorder in code propagates to Dev/prod next deploy, NO migration. BUT Label/ParentKey/Icon NOT touched on existing rows (`:1855` comment) — rename needs separate `labelBackfill` dict `:1874`. **Order = BE-only:** `GetMyMenuTreeQuery.cs:35 OrderBy(m.Order)`; both FE `Layout.tsx` render `useAuth().menu` as-is, `staticMap`+`menuKeys.ts` = key→route ONLY (no sort). FE needs NO edit for pure reorder. **NAMGROUP "Puro" = hardcoded FE array (NOT DB seed),** index=order: client `InternalLayout.tsx:83-118` (Nhân sự 3-item / Văn phòng số 6-item FLAT / Chấm công under separate "Cá nhân" group); admin `AdminLayout.tsx:87-119` splits by function not HR/office. NAMGROUP `Đơn từ`/`Phòng họp`/`Đề xuất` = flat single links (no sub-children) vs SE deep-nested. Tag `[menu-order, se-namgroup, seed-upsert-order, fe-be-driven, s57]`.
- **2026-06-09 (S56 pre-golive verify — 4 logic streams, all PASS):** Audited P11-B/D/E/F + ApproveV2 + catalogs + S55 master-wiring. **LeaveBalance** deduction exactly-once (terminal DaDuyet, guard `Status!=DaGuiDuyet` :296 blocks re-approve), FK guard Create+UpdateDraft→Conflict; **AttendanceReport** classify day-type IN-MEMORY (Holiday DateOnly HashSet), OtPolicy multiplier; **MaTicket** gen-on-Create Serializable IT/2026/NNN. Tests cover (LeaveBalance 9 + AttReport 2 + codegen 3 = 29 green). ApproveV2 4-module flatten Steps→Levels correct; **Travel/Vehicle ApproveV2 = 0 test** (cookie-cutter of tested Leave/OT — add 2 smoke post-golive). master-data **idempotency PROVEN** (DbInitializer re-run → counts identical, per-code guard :2310/:2404/:2422). **⚠️ PROD FACT (corrects stale S52 mem):** dept "IT"/Phòng CNTT DOES exist (Id 65CC6307…) but has **0 active users** on prod → ItTicket auto-assign no-ops, reassign dropdown empty, SLA job no notify-target. Pre-golive ops fix: assign ≥1 real user to dept IT (1 UPDATE, no code). Tag [s56, pre-golive-verify, logic-pass, dept-IT-empty-prod, travel-vehicle-untested]. - **2026-06-09 (S56 pre-golive verify — 4 logic streams, all PASS):** Audited P11-B/D/E/F + ApproveV2 + catalogs + S55 master-wiring. **LeaveBalance** deduction exactly-once (terminal DaDuyet, guard `Status!=DaGuiDuyet` :296 blocks re-approve), FK guard Create+UpdateDraft→Conflict; **AttendanceReport** classify day-type IN-MEMORY (Holiday DateOnly HashSet), OtPolicy multiplier; **MaTicket** gen-on-Create Serializable IT/2026/NNN. Tests cover (LeaveBalance 9 + AttReport 2 + codegen 3 = 29 green). ApproveV2 4-module flatten Steps→Levels correct; **Travel/Vehicle ApproveV2 = 0 test** (cookie-cutter of tested Leave/OT — add 2 smoke post-golive). master-data **idempotency PROVEN** (DbInitializer re-run → counts identical, per-code guard :2310/:2404/:2422). **⚠️ PROD FACT (corrects stale S52 mem):** dept "IT"/Phòng CNTT DOES exist (Id 65CC6307…) but has **0 active users** on prod → ItTicket auto-assign no-ops, reassign dropdown empty, SLA job no notify-target. Pre-golive ops fix: assign ≥1 real user to dept IT (1 UPDATE, no code). Tag [s56, pre-golive-verify, logic-pass, dept-IT-empty-prod, travel-vehicle-untested].
- **2026-06-09 (S56 Phase 2 FE-redesign RECON — 25 page audit, on-disk):** ⭐ **NOT a rewrite** — S55 already redesigned ui-primitives + DataTable + shell → any page importing `ui/{Button,Input}`+`DataTable` AUTO-inherits density. **Hover-hidden quick-win nearly absent:** repo-wide grep `opacity-0`×`group-hover` = **only 1 real site** `ContractCreatePage.tsx:196` (EXCLUDED scope) + DataTable.tsx:15 is a comment forbidding it (good). In-scope = **0 hover-hidden fixes**. **DataTable adoption split:** only 5/25 use `<DataTable>` (Suppliers/Projects/Departments/Users/Forms); 12 pages roll RAW `<table>` (MeetingRooms/Catalogs/HrmConfigs/EmployeesList/Proposals/WorkflowApps/Attendance×2/MenuVisibility/Roles) → custom density pass needed. **Drawer ≥8-field candidates = 3:** Suppliers (9 fld, Dialog), Projects (10 fld, Dialog), Users-CREATE (~8 fld w/ roles multiselect, 4 Dialogs total but only create is big). All currently big-Dialog → convert. **NO `Drawer.tsx` exists** (`ui/` = Button/Dialog/Input/Label/Select/Textarea only) → build first. **Bậc-thang reference ALREADY EXISTS:** `EmployeesListPage.tsx` (1200L) = canonical inline add/edit-row for 5 satellites (`setEditing{X}Id` + `addingX` mutex, :256-356) → extract `InlineEditRow` pattern from here, reuse for Catalogs/HrmConfigs/MeetingRooms (these 3 currently edit via Dialog :251/:316/:232, ≤7 cols → bậc-thang candidates). **Modal-detail = NONE:** ProposalDetail:275 + WorkflowAppDetail:424 Dialogs are tiny action-confirm (just `<Textarea>` ý kiến), detail body already inline 2-col grid (:181) → NOT convert. **fe-user mirrors** office/master/hrm (SHA256-identical per comments) but NO system/forms/reports mirror. **Custom-layout heavy:** InternalDirectory (card-grid :124 not table), MeetingCalendar (693L FullCalendar), EmployeesList (2-panel), HrmConfigs (declarative KIND_CONFIG :45). Effort: Master 3×Drawer=M, Catalogs/HrmConfigs/MeetingRooms bậc-thang=M, Users Drawer=M, rest S (auto-inherit polish). Surprise: hover-hidden NAMGROUP-win essentially pre-solved (team already avoids opacity-0 pattern, DataTable comment enforces) → quick-win section nearly empty. Tag `[fe-redesign-p2, recon, drawer-3, basc-thang-ref-exists, s56]`. - **2026-06-09 (S56 Phase 2 FE-redesign RECON — 25 page audit, on-disk):** ⭐ **NOT a rewrite** — S55 already redesigned ui-primitives + DataTable + shell → any page importing `ui/{Button,Input}`+`DataTable` AUTO-inherits density. **Hover-hidden quick-win nearly absent:** repo-wide grep `opacity-0`×`group-hover` = **only 1 real site** `ContractCreatePage.tsx:196` (EXCLUDED scope) + DataTable.tsx:15 is a comment forbidding it (good). In-scope = **0 hover-hidden fixes**. **DataTable adoption split:** only 5/25 use `<DataTable>` (Suppliers/Projects/Departments/Users/Forms); 12 pages roll RAW `<table>` (MeetingRooms/Catalogs/HrmConfigs/EmployeesList/Proposals/WorkflowApps/Attendance×2/MenuVisibility/Roles) → custom density pass needed. **Drawer ≥8-field candidates = 3:** Suppliers (9 fld, Dialog), Projects (10 fld, Dialog), Users-CREATE (~8 fld w/ roles multiselect, 4 Dialogs total but only create is big). All currently big-Dialog → convert. **NO `Drawer.tsx` exists** (`ui/` = Button/Dialog/Input/Label/Select/Textarea only) → build first. **Bậc-thang reference ALREADY EXISTS:** `EmployeesListPage.tsx` (1200L) = canonical inline add/edit-row for 5 satellites (`setEditing{X}Id` + `addingX` mutex, :256-356) → extract `InlineEditRow` pattern from here, reuse for Catalogs/HrmConfigs/MeetingRooms (these 3 currently edit via Dialog :251/:316/:232, ≤7 cols → bậc-thang candidates). **Modal-detail = NONE:** ProposalDetail:275 + WorkflowAppDetail:424 Dialogs are tiny action-confirm (just `<Textarea>` ý kiến), detail body already inline 2-col grid (:181) → NOT convert. **fe-user mirrors** office/master/hrm (SHA256-identical per comments) but NO system/forms/reports mirror. **Custom-layout heavy:** InternalDirectory (card-grid :124 not table), MeetingCalendar (693L FullCalendar), EmployeesList (2-panel), HrmConfigs (declarative KIND_CONFIG :45). Effort: Master 3×Drawer=M, Catalogs/HrmConfigs/MeetingRooms bậc-thang=M, Users Drawer=M, rest S (auto-inherit polish). Surprise: hover-hidden NAMGROUP-win essentially pre-solved (team already avoids opacity-0 pattern, DataTable comment enforces) → quick-win section nearly empty. Tag `[fe-redesign-p2, recon, drawer-3, basc-thang-ref-exists, s56]`.
@ -80,9 +88,7 @@ Bearer từ `POST api.solutions.com.vn/api/auth/login` → status matrix expecte
- **2026-06-08 (S51 gotcha #57 EXTENSION reachability audit — 6 candidate, RAG down, on-disk only):** ⭐ Bug class = soft-delete + bare `.IsUnique()` on Code → recreate-after-delete throws DbUpdateException 500. Verdict 6 cand: **FIX 3 (Master)** Department/Supplier/Project (`Department/Supplier/ProjectConfiguration.cs:18/24/19` bare unique). ALL = AuditableEntity + **GLOBAL `HasQueryFilter(!IsDeleted)`** + Delete via `.Remove()``AuditingInterceptor.cs` (State Deleted→Modified, IsDeleted=true) + Create `AnyAsync(x=>x.Code==req.Code)` NO `!IsDeleted` BUT global filter auto-hides soft-deleted → check passes → unfiltered index 500. **CONFIRMED-reachable** (`DepartmentFeatures.cs:76+125`, `ProjectFeatures.cs:87+147`, `CreateSupplierCommand.cs:45`+`DeleteSupplierCommand.cs:20`). **SKIP 3:** (a) **ContractClause** (`ContractClauseConfiguration.cs:18`) — NO Create/Update/Delete handler ANYWHERE (only `IApplicationDbContext.cs:32` DbSet; FormsController = templates only) → not CRUD-reachable. (b) **MeetingRoom** (`MeetingRoomConfiguration.cs:20`) — Delete sets `IsActive=false` NOT IsDeleted (`MeetingFeatures.cs:178`, comment :175 "FK Restrict → NOT soft delete") → index never gets soft-deleted row; Create also checks `&& !IsDeleted` :113. (c) **EmployeeProfile** (`EmployeeProfileConfiguration.cs:24/26` EmployeeCode+UserId) — Delete soft (`EmployeeFeatures.cs:437`) BUT Create BLOCKS reuse by design: UserId check `AsNoTracking().FirstOrDefault(UserId==)` (no HRM global filter) sees soft-deleted → throws ConflictException "Cần khôi phục" :160-163; EmployeeCode auto-gen atomic (never user-supplied/reused) → no collision. **Completeness (grep ALL `.IsUnique()`):** beyond 3 Master + 6 HRM-fixed (LeaveType/Holiday/Shift/OtPolicy/Vehicle/Driver all `.HasFilter([IsDeleted]=0)`), every OTHER bare-unique is either composite junction (Permission RoleId+MenuKey, *LevelOpinion, MeetingBookingAttendee, LeaveBalance, Attendance UserId+Date), nullable-code already filtered (`[Ma*] IS NOT NULL`: Contract/PE/Proposal/Budget/WorkflowApps), or no-soft-delete (WorkflowDefinition/ApprovalWorkflow Code+Version, ContractTemplate FormCode, WorkflowTypeAssignment, DepartmentApprovals). **Mig 46 = exactly 3 indexes (Departments/Suppliers/Projects Code).** Surprise: Master GLOBAL query filter MAKES the bug (auto-hides soft-deleted from check) — opposite of HRM where bug needs manual `!IsDeleted`; either way unfiltered index = 500. Tag `[gotcha57-ext, reachability-audit, master-global-filter, s51]`. - **2026-06-08 (S51 gotcha #57 EXTENSION reachability audit — 6 candidate, RAG down, on-disk only):** ⭐ Bug class = soft-delete + bare `.IsUnique()` on Code → recreate-after-delete throws DbUpdateException 500. Verdict 6 cand: **FIX 3 (Master)** Department/Supplier/Project (`Department/Supplier/ProjectConfiguration.cs:18/24/19` bare unique). ALL = AuditableEntity + **GLOBAL `HasQueryFilter(!IsDeleted)`** + Delete via `.Remove()``AuditingInterceptor.cs` (State Deleted→Modified, IsDeleted=true) + Create `AnyAsync(x=>x.Code==req.Code)` NO `!IsDeleted` BUT global filter auto-hides soft-deleted → check passes → unfiltered index 500. **CONFIRMED-reachable** (`DepartmentFeatures.cs:76+125`, `ProjectFeatures.cs:87+147`, `CreateSupplierCommand.cs:45`+`DeleteSupplierCommand.cs:20`). **SKIP 3:** (a) **ContractClause** (`ContractClauseConfiguration.cs:18`) — NO Create/Update/Delete handler ANYWHERE (only `IApplicationDbContext.cs:32` DbSet; FormsController = templates only) → not CRUD-reachable. (b) **MeetingRoom** (`MeetingRoomConfiguration.cs:20`) — Delete sets `IsActive=false` NOT IsDeleted (`MeetingFeatures.cs:178`, comment :175 "FK Restrict → NOT soft delete") → index never gets soft-deleted row; Create also checks `&& !IsDeleted` :113. (c) **EmployeeProfile** (`EmployeeProfileConfiguration.cs:24/26` EmployeeCode+UserId) — Delete soft (`EmployeeFeatures.cs:437`) BUT Create BLOCKS reuse by design: UserId check `AsNoTracking().FirstOrDefault(UserId==)` (no HRM global filter) sees soft-deleted → throws ConflictException "Cần khôi phục" :160-163; EmployeeCode auto-gen atomic (never user-supplied/reused) → no collision. **Completeness (grep ALL `.IsUnique()`):** beyond 3 Master + 6 HRM-fixed (LeaveType/Holiday/Shift/OtPolicy/Vehicle/Driver all `.HasFilter([IsDeleted]=0)`), every OTHER bare-unique is either composite junction (Permission RoleId+MenuKey, *LevelOpinion, MeetingBookingAttendee, LeaveBalance, Attendance UserId+Date), nullable-code already filtered (`[Ma*] IS NOT NULL`: Contract/PE/Proposal/Budget/WorkflowApps), or no-soft-delete (WorkflowDefinition/ApprovalWorkflow Code+Version, ContractTemplate FormCode, WorkflowTypeAssignment, DepartmentApprovals). **Mig 46 = exactly 3 indexes (Departments/Suppliers/Projects Code).** Surprise: Master GLOBAL query filter MAKES the bug (auto-hides soft-deleted from check) — opposite of HRM where bug needs manual `!IsDeleted`; either way unfiltered index = 500. Tag `[gotcha57-ext, reachability-audit, master-global-filter, s51]`.
- **2026-06-08 (S50 P11-C Vehicle+Driver — HrmConfigs add-kind pattern VERIFIED on-disk, RAG down):** ⭐ **HrmConfigs KHÔNG có "kind enum/registry" backend** — 4 entity RIÊNG (LeaveType/Holiday/ShiftPattern/OtPolicy), NOT discriminated table. "kind" chỉ FE: `HrmConfigKind` union `fe-admin/src/types/hrm-config.ts:4` + route param. **Add 1 kind = mirror FULL entity stack 11 chỗ:** BE (1) Domain `Hrm/{X}.cs` AuditableEntity soft-delete (2) `Configurations/{X}Configuration.cs` `.ToTable+.HasIndex(Code).IsUnique()` (3) `ApplicationDbContext.cs:95-98` DbSet (4) `IApplicationDbContext.cs:102-105` DbSet (5) `HrmConfigFeatures.cs` +Region N (DTO+List/Create/Update/Delete handler+validator, mega 4-region :30/125/222/328) (6) `HrmConfigsController.cs` +4 route hardcode `[HttpGet/Post/Put/Delete("{kind}")]` (Post/Put/Del `[Authorize(Roles="Admin")]`, Get chỉ `[Authorize]`) (7) `DbInitializer.cs:2329 SeedHrmConfigsAsync` +if-block + skip-guard :2331 phải +`&& OtPoliciesNew.AnyAsync()` (8) `MenuKeys.cs:88-92` +const + `:149 All[]` (Admin auto-grant `SeedAdminPermissionsAsync` loop idempotent). FE (9) `HrmConfigsPage.tsx:45 KIND_CONFIG` +entry + `:114 KINDS[]` + `:379 renderCells` branch + `:166 smart-defaults` + types/hrm-config.ts DTO (10) `App.tsx:90` route `/hrm/configs/:kind` SẴN catch-all → KHÔNG cần sửa, chỉ +menuKeys (11) `menuKeys.ts:38-42` + `Layout.tsx:60-63 staticMap`. **gotcha #57 CONFIRMED còn trần:** `LeaveTypeConfiguration.cs:19` + `ShiftPatternConfiguration.cs:19` + `OtPolicyConfiguration.cs:22` `.IsUnique()` CHƯA `.HasFilter("[IsDeleted]=0")` (chỉ `HolidayConfiguration.cs:18` đã fix Mig 43). → Vehicle/Driver Code UNIQUE PHẢI add filter ngay từ đầu. **Mig 44 BẮT BUỘC CREATE TABLE** (mỗi kind = bảng riêng, NOT discriminated → +2 bảng Vehicles+Drivers, không phải seed-only). **VehicleBooking** (`Office/VehicleBooking.cs:13-19`) pure free-text `VehicleLicense/VehicleName/DriverName` string, NO `VehicleId/DriverId` FK (grep empty) → P11-C catalog-only, FK link defer Mig sau. Latest Mig=43 `FilterHolidayUniqueIndexByIsDeleted` (`20260601064128`), next=44. Tag `[p11-c, hrmconfig-add-kind, gotcha57, on-disk-verify]`. - **[→ archive/2026-06.md]** S50 P11-C HrmConfigs add-kind 11-chỗ pattern · S50 wave h2-verify B6 gitignore ordering + POSIX-not-pwsh (curated S57bis).
- **2026-06-07 (S50 wave `h2-verify` — B6 guardrail audit, read-only) [em main scribe from findings + H2 harvest]:** Verified B6 wave-isolation **3/3 PASS**. **B6 = TWO complementary rules:** (a) transient `wave-*/` + `agent-teams/` gitignored (`.gitignore:93-94`) → audit-noise=0; (b) canonical `agent-memory/**/MEMORY.md` TRACKED → rogue sub-write surfaces in `git status`. `git check-ignore -v` = ground-truth verifier BOTH directions (matched rule:line for ignored; empty for tracked). ⚠️ **Ordering gotcha:** wave/team patterns MUST sit AFTER `!.claude/**` (`.gitignore:82-83`) to win via last-match (`:91` documents intent) — else `!.claude/**` un-ignores everything. All 10 MEMORY.md tracked (roster 8→10). **Surprise (cross-cutting, both wave subs):** Bash tool = `/usr/bin/bash` NOT PowerShell despite env=PowerShell → `Get-ChildItem`/`Select-String`/`Test-Path` fail (exit 2/127); read-only Bash-only subs MUST use POSIX (`git ls-files`/`grep`/`ls`). Tag [wave-h2, b6-isolation, posix-not-pwsh].
- **2026-06-07 (Harness 1/2/3 adap-apply recon — 3 slice, HMW wave):** Governance recon AI_INFRA broadcast harness-1/2/3. **H1/H2 (Harness 1):** roster 8→10 — CREATE 2 sub TÁCH BIỆT `tooling-auditor` (H1 freshness 4-mặt skill/sub-role/plugin/docs) + `harvest-curator` (H2 integrity 5-trục). H2 PARTIAL sẵn: `session-end.md` Phase 1.5 §L.b(d) spawn-record 4-field + (f) double-check moved-not-cut + (c) 0-byte AS-8 = Coverage+Completeness+Corruption (3/5); THIẾU Fidelity-escalate + Placement. RE-REPORT @session-start = 0 (chỉ generic Phase 2.7). 2 sub mirror inv-codebase read-set + store_memory strip + NO Write/Edit; color brown+teal (8 màu cũ hết). **H2 wave (Harness 2):** SE `hmw.js` = OLD pre-wave (no subMdPath/writeGuard/wave-block); AI_INFRA `hmw.js` = canonical template. ⭐ `git check-ignore -v` = ground-truth B6: `.claude/workflows/wave-test/wave.md` HIỆN match `.gitignore:83 !.claude/**` = TRACKED → wave pattern PHẢI đặt AFTER `!.claude/**` (last-match-wins, mẫu `hmw-mode.on` :87). Read-only sub (4)=inv-cb/inv-api/reviewer/cicd; Write sub (4)=impl×2/test/fe-designer. B5 depends H2 harvest-curator. **H3 email (Harness 3):** broadcasts/ absent; id authoritative = `se` (NOT solution_erp), 6 others short `{ai_infra,vipix,dyd,namgroup,ashico,bvaau}` từ `AI_INFRA/broadcasts/sister-commands/send-email.md:13-22` (folder name = 2nd source-truth); `adap-apply.md:14` base-path STALE flat → `outbox/all/*.md` (latent bug). broadcasts/ ở root → commit OK (no gitignore rule). **Containment post-P2:** git-diff bắt 1 file-write (inv-api self-MEMORY), chunk-count 2414=2414 (0 RAG-write) = defense-in-depth proven. Tag [harness-recon, governance, hmw-wave, 2026-06-07]. - **2026-06-07 (Harness 1/2/3 adap-apply recon — 3 slice, HMW wave):** Governance recon AI_INFRA broadcast harness-1/2/3. **H1/H2 (Harness 1):** roster 8→10 — CREATE 2 sub TÁCH BIỆT `tooling-auditor` (H1 freshness 4-mặt skill/sub-role/plugin/docs) + `harvest-curator` (H2 integrity 5-trục). H2 PARTIAL sẵn: `session-end.md` Phase 1.5 §L.b(d) spawn-record 4-field + (f) double-check moved-not-cut + (c) 0-byte AS-8 = Coverage+Completeness+Corruption (3/5); THIẾU Fidelity-escalate + Placement. RE-REPORT @session-start = 0 (chỉ generic Phase 2.7). 2 sub mirror inv-codebase read-set + store_memory strip + NO Write/Edit; color brown+teal (8 màu cũ hết). **H2 wave (Harness 2):** SE `hmw.js` = OLD pre-wave (no subMdPath/writeGuard/wave-block); AI_INFRA `hmw.js` = canonical template. ⭐ `git check-ignore -v` = ground-truth B6: `.claude/workflows/wave-test/wave.md` HIỆN match `.gitignore:83 !.claude/**` = TRACKED → wave pattern PHẢI đặt AFTER `!.claude/**` (last-match-wins, mẫu `hmw-mode.on` :87). Read-only sub (4)=inv-cb/inv-api/reviewer/cicd; Write sub (4)=impl×2/test/fe-designer. B5 depends H2 harvest-curator. **H3 email (Harness 3):** broadcasts/ absent; id authoritative = `se` (NOT solution_erp), 6 others short `{ai_infra,vipix,dyd,namgroup,ashico,bvaau}` từ `AI_INFRA/broadcasts/sister-commands/send-email.md:13-22` (folder name = 2nd source-truth); `adap-apply.md:14` base-path STALE flat → `outbox/all/*.md` (latent bug). broadcasts/ ở root → commit OK (no gitignore rule). **Containment post-P2:** git-diff bắt 1 file-write (inv-api self-MEMORY), chunk-count 2414=2414 (0 RAG-write) = defense-in-depth proven. Tag [harness-recon, governance, hmw-wave, 2026-06-07].

View File

@ -0,0 +1,7 @@
# Archive 2026-06 — investigator-codebase FIFO overflow
> Moved from MEMORY.md L1 (S57bis curate 2026-06-11). Verbatim.
- **2026-06-08 (S50 P11-C Vehicle+Driver — HrmConfigs add-kind pattern VERIFIED on-disk, RAG down):** ⭐ **HrmConfigs KHÔNG có "kind enum/registry" backend** — 4 entity RIÊNG (LeaveType/Holiday/ShiftPattern/OtPolicy), NOT discriminated table. "kind" chỉ FE: `HrmConfigKind` union `fe-admin/src/types/hrm-config.ts:4` + route param. **Add 1 kind = mirror FULL entity stack 11 chỗ:** BE (1) Domain `Hrm/{X}.cs` AuditableEntity soft-delete (2) `Configurations/{X}Configuration.cs` `.ToTable+.HasIndex(Code).IsUnique()` (3) `ApplicationDbContext.cs:95-98` DbSet (4) `IApplicationDbContext.cs:102-105` DbSet (5) `HrmConfigFeatures.cs` +Region N (DTO+List/Create/Update/Delete handler+validator, mega 4-region :30/125/222/328) (6) `HrmConfigsController.cs` +4 route hardcode `[HttpGet/Post/Put/Delete("{kind}")]` (Post/Put/Del `[Authorize(Roles="Admin")]`, Get chỉ `[Authorize]`) (7) `DbInitializer.cs:2329 SeedHrmConfigsAsync` +if-block + skip-guard :2331 phải +`&& OtPoliciesNew.AnyAsync()` (8) `MenuKeys.cs:88-92` +const + `:149 All[]` (Admin auto-grant `SeedAdminPermissionsAsync` loop idempotent). FE (9) `HrmConfigsPage.tsx:45 KIND_CONFIG` +entry + `:114 KINDS[]` + `:379 renderCells` branch + `:166 smart-defaults` + types/hrm-config.ts DTO (10) `App.tsx:90` route `/hrm/configs/:kind` SẴN catch-all → KHÔNG cần sửa, chỉ +menuKeys (11) `menuKeys.ts:38-42` + `Layout.tsx:60-63 staticMap`. **gotcha #57 CONFIRMED còn trần:** `LeaveTypeConfiguration.cs:19` + `ShiftPatternConfiguration.cs:19` + `OtPolicyConfiguration.cs:22` `.IsUnique()` CHƯA `.HasFilter("[IsDeleted]=0")` (chỉ `HolidayConfiguration.cs:18` đã fix Mig 43). → Vehicle/Driver Code UNIQUE PHẢI add filter ngay từ đầu. **Mig 44 BẮT BUỘC CREATE TABLE** (mỗi kind = bảng riêng, NOT discriminated → +2 bảng Vehicles+Drivers, không phải seed-only). **VehicleBooking** (`Office/VehicleBooking.cs:13-19`) pure free-text `VehicleLicense/VehicleName/DriverName` string, NO `VehicleId/DriverId` FK (grep empty) → P11-C catalog-only, FK link defer Mig sau. Latest Mig=43 `FilterHolidayUniqueIndexByIsDeleted` (`20260601064128`), next=44. Tag `[p11-c, hrmconfig-add-kind, gotcha57, on-disk-verify]`.
- **2026-06-07 (S50 wave `h2-verify` — B6 guardrail audit, read-only) [em main scribe from findings + H2 harvest]:** Verified B6 wave-isolation **3/3 PASS**. **B6 = TWO complementary rules:** (a) transient `wave-*/` + `agent-teams/` gitignored (`.gitignore:93-94`) → audit-noise=0; (b) canonical `agent-memory/**/MEMORY.md` TRACKED → rogue sub-write surfaces in `git status`. `git check-ignore -v` = ground-truth verifier BOTH directions (matched rule:line for ignored; empty for tracked). ⚠️ **Ordering gotcha:** wave/team patterns MUST sit AFTER `!.claude/**` (`.gitignore:82-83`) to win via last-match (`:91` documents intent) — else `!.claude/**` un-ignores everything. All 10 MEMORY.md tracked (roster 8→10). **Surprise (cross-cutting, both wave subs):** Bash tool = `/usr/bin/bash` NOT PowerShell despite env=PowerShell → `Get-ChildItem`/`Select-String`/`Test-Path` fail (exit 2/127); read-only Bash-only subs MUST use POSIX (`git ls-files`/`grep`/`ls`). Tag [wave-h2, b6-isolation, posix-not-pwsh].

View File

@ -57,6 +57,7 @@ Adversarial pre-commit reviewer SOLUTION_ERP. Read-only verify + live curl prod
## 📅 Recent activity (FIFO — older → archive/git) ## 📅 Recent activity (FIFO — older → archive/git)
- **2026-06-10 (S57-resume Harness-4 two-tier adopt gate — PASS-with-fixes, 0 blocker):** Gate trước send-email + commit (governance, không product code). Self-report spawn: `claude-fable-5[1m]` (reviewer = promote-list inherit → direct promote-tier evidence, em main cite được). Independent re-verify ALL GREEN: grep frontmatter = đúng 7 pin `claude-opus-4-8` + 4 `inherit` + 0 `[1m]`-in-frontmatter (2 body-text hits hợp lệ: database-agent.md:46 + README.md:9 MỚI — adap-report "match duy nhất" stale-by-own-edit) + 0 project-pin settings. Evidence track-record **8/8 REAL** vs HANDOFF/STATUS/own-memory (S51 MAJOR · S54 QTV-decoy · S53 Mig46 · S56 H2-4.5/5 + dept-IT-0-user · S57 ×3 controller +5/+5/+5 `[Authorize(Roles="Admin,CatalogManager")]` working-tree). Nấc G-011 đúng mọi chỗ load-bearing (demote = executed-file·pending-restart, 0 overclaim runtime). Fixes: hash PLACEHOLDER trước send (`nac: sent` + "SENT ✓" premature = đúng status-verb class broadcast cảnh báo) · STATUS "(runtime resolve 1M)" thiếu attribution AI_INFRA-s20 · hmw.js:91 log "same-model inherit" stale + :9 "8-agent" vs 9 roles · adap-report "(13)" vs "11" count · invalid-role typo → rơi 'opus' (fail-direction xuống vs H4.5 nghiêng-quality). **Learned:** gate adopt-governance = re-run MỌI grep claim + cross-check evidence vs HANDOFF nguyên văn; n=2 demoted spawn-test double-duty làm inherit-chain proof là HỢP LỆ (registry cached = chạy config cũ) nhưng cần phrase rõ kẻo đọc nhầm thành promote-list spawn-test. Tag [s57, harness-4, two-tier-gate, pre-send-gate, g011].
- **2026-06-09 (S56 pre-golive authz live-curl — PASS, 0 blocker):** Live prod curl 8 new endpoints. **8/8 return 401 unauth**; admin-authed: hrm-configs/vehicles(2)+drivers(2), leave-balances/my(5 lazy), attendances/report+excel(200, 6797B xlsx) all 200; non-admin Drafter correctly 403 on the 2 Admin-only attendance endpoints. **gotcha #44 silent-403 sweep CLEAN:** capability GET /it-tickets/assignable-staff returns HTTP 200 `{canReassign:false,staff:[]}` for non-IT Drafter (NOT swallowed 403) + `{true,[]}` admin — handler returns flag, doesn't throw (`WorkflowAppsFeatures.cs:466`). assign-mutation guard fail-closed (:504). E2E: GET /projects payload has all +4 fields (70/70), CAL01 Investor live. Off_AttendanceReport menu key in admin /menus/me. **1 MINOR (non-block, defense-in-depth):** PUT /it-tickets/{id}/assign checks NotFound BEFORE Admin-OR-IT Forbidden (`WorkflowAppsFeatures.cs:496-508`) → existence-oracle leak; mutation itself fail-closed → post-golive hardening only. Tag [s56, pre-golive-verify, authz-clean, gotcha44-clean, notfound-before-forbidden-minor]. - **2026-06-09 (S56 pre-golive authz live-curl — PASS, 0 blocker):** Live prod curl 8 new endpoints. **8/8 return 401 unauth**; admin-authed: hrm-configs/vehicles(2)+drivers(2), leave-balances/my(5 lazy), attendances/report+excel(200, 6797B xlsx) all 200; non-admin Drafter correctly 403 on the 2 Admin-only attendance endpoints. **gotcha #44 silent-403 sweep CLEAN:** capability GET /it-tickets/assignable-staff returns HTTP 200 `{canReassign:false,staff:[]}` for non-IT Drafter (NOT swallowed 403) + `{true,[]}` admin — handler returns flag, doesn't throw (`WorkflowAppsFeatures.cs:466`). assign-mutation guard fail-closed (:504). E2E: GET /projects payload has all +4 fields (70/70), CAL01 Investor live. Off_AttendanceReport menu key in admin /menus/me. **1 MINOR (non-block, defense-in-depth):** PUT /it-tickets/{id}/assign checks NotFound BEFORE Admin-OR-IT Forbidden (`WorkflowAppsFeatures.cs:496-508`) → existence-oracle leak; mutation itself fail-closed → post-golive hardening only. Tag [s56, pre-golive-verify, authz-clean, gotcha44-clean, notfound-before-forbidden-minor].
- **2026-06-09 (S55 Phase-1 FE visual redesign pre-commit — PASS, 0 blocker, verdict-first survived):** 14 fe-admin files VISUAL/CSS-only (NAMGROUP density + SOLUTION brand). **Independent re-verify GREEN:** `npm run build` fe-admin = ✓ 607ms, 1945 modules, 0 TS err (only PRE-EXISTING warns: CSS @import-order + >500KB chunk + INEFFECTIVE_DYNAMIC_IMPORT realtime.ts — git-confirmed none introduced, @import lines untouched in diff). **Regression Cat1 ALL preserved:** Button cva variant keys (primary/secondary/outline/ghost/danger) + size (sm/md/lg) STABLE — only Tailwind class VALUES swapped, defaultVariants intact (51 call-sites safe); Input/Select/Textarea/Label = `forwardRef`+`...props`+`className` passthrough unchanged, only `cn()` literal; Dialog `{open,onClose,title,children,footer,size}` destructure + sm/md/lg→max-w map intact (+aria-label="Đóng" = a11y GAIN); DataTable `Column<T>` type UNCHANGED (diff starts after type def) — render/sortable/align/width + sort + Pagination props intact, RowActions/RowActionButton purely ADDITIVE; Layout MenuLeaf className-only (brand left-rail via before:), nav/resolver/permission-filter/routing untouched; PhaseBadge phase→ContractPhaseColor/Label map intact; PageHeader/EmptyState/TopBar pure class. DashboardPage data-flow (useQuery/navigate/fmtMoney/BarChart/PhaseBadge) preserved, STAT_TONE+SectionLabel additive, +`cn` import only. **Brand Cat3:** Be Vietnam Pro KEPT (grep: @import:3 + --font-sans:22 + font-family:34 all unchanged — initial blocker RETRACTED after grep); only brand-/slate/semantic colors, 0 off-brand hex/indigo. **a11y:** focus-visible rings present everywhere (brand-500); Label self-documents slate-500 (~4.6:1 AA-pass) chosen over NAMGROUP zinc-400. **Tailwind v4 (^4.2.3)**`ring-current/15`, `shadow-xs`, slash-opacity all valid v4. **noScopeCreep:** exactly 14 fe-admin, 0 fe-user, 0 BE/src (only noise = frontend-designer/MEMORY.md agent file). **2 MINOR (non-block, a11y-floor):** `text-slate-400` on white for small hint/empty text (DashboardPage hints ~line 50/64, DataTable empty-cell, EmptyState was-400-stays-400) ≈3.5-4:1 — borderline-fail WCAG-AA for <18px, but these are de-emphasized hints not primary content + PRE-EXISTING tone (redesign mostly UPGRADED slate-400500 on EmptyState desc + Pagination); accept for hint role, revisit if audit. **Learned:** font-drop scare = grep the 3 load-bearing lines (@import/--font-sans token/font-family) BEFORE flagging diff hunk lower in file font removed; emit PASS/FAIL line-1 FIRST (gotcha #53 truncation survival, mirror S51/S55). **surprise:** Tailwind v4 `shadow-xs` is real (v3's shadow-sm renamed) don't flag as typo; v4 slash-opacity on currentColor (`ring-current/15`) is valid. Verdict PASS safe commit+deploy. Tag [s55-fe, visual-redesign, namgroup-density, verdict-first, regression-clean, slate400-minor]. - **2026-06-09 (S55 Phase-1 FE visual redesign pre-commit — PASS, 0 blocker, verdict-first survived):** 14 fe-admin files VISUAL/CSS-only (NAMGROUP density + SOLUTION brand). **Independent re-verify GREEN:** `npm run build` fe-admin = ✓ 607ms, 1945 modules, 0 TS err (only PRE-EXISTING warns: CSS @import-order + >500KB chunk + INEFFECTIVE_DYNAMIC_IMPORT realtime.ts — git-confirmed none introduced, @import lines untouched in diff). **Regression Cat1 ALL preserved:** Button cva variant keys (primary/secondary/outline/ghost/danger) + size (sm/md/lg) STABLE — only Tailwind class VALUES swapped, defaultVariants intact (51 call-sites safe); Input/Select/Textarea/Label = `forwardRef`+`...props`+`className` passthrough unchanged, only `cn()` literal; Dialog `{open,onClose,title,children,footer,size}` destructure + sm/md/lg→max-w map intact (+aria-label="Đóng" = a11y GAIN); DataTable `Column<T>` type UNCHANGED (diff starts after type def) — render/sortable/align/width + sort + Pagination props intact, RowActions/RowActionButton purely ADDITIVE; Layout MenuLeaf className-only (brand left-rail via before:), nav/resolver/permission-filter/routing untouched; PhaseBadge phase→ContractPhaseColor/Label map intact; PageHeader/EmptyState/TopBar pure class. DashboardPage data-flow (useQuery/navigate/fmtMoney/BarChart/PhaseBadge) preserved, STAT_TONE+SectionLabel additive, +`cn` import only. **Brand Cat3:** Be Vietnam Pro KEPT (grep: @import:3 + --font-sans:22 + font-family:34 all unchanged — initial blocker RETRACTED after grep); only brand-/slate/semantic colors, 0 off-brand hex/indigo. **a11y:** focus-visible rings present everywhere (brand-500); Label self-documents slate-500 (~4.6:1 AA-pass) chosen over NAMGROUP zinc-400. **Tailwind v4 (^4.2.3)**`ring-current/15`, `shadow-xs`, slash-opacity all valid v4. **noScopeCreep:** exactly 14 fe-admin, 0 fe-user, 0 BE/src (only noise = frontend-designer/MEMORY.md agent file). **2 MINOR (non-block, a11y-floor):** `text-slate-400` on white for small hint/empty text (DashboardPage hints ~line 50/64, DataTable empty-cell, EmptyState was-400-stays-400) ≈3.5-4:1 — borderline-fail WCAG-AA for <18px, but these are de-emphasized hints not primary content + PRE-EXISTING tone (redesign mostly UPGRADED slate-400500 on EmptyState desc + Pagination); accept for hint role, revisit if audit. **Learned:** font-drop scare = grep the 3 load-bearing lines (@import/--font-sans token/font-family) BEFORE flagging diff hunk lower in file font removed; emit PASS/FAIL line-1 FIRST (gotcha #53 truncation survival, mirror S51/S55). **surprise:** Tailwind v4 `shadow-xs` is real (v3's shadow-sm renamed) don't flag as typo; v4 slash-opacity on currentColor (`ring-current/15`) is valid. Verdict PASS safe commit+deploy. Tag [s55-fe, visual-redesign, namgroup-density, verdict-first, regression-clean, slate400-minor].

View File

@ -15,7 +15,7 @@ WRITE specialist độc quyền `tests/**`. xUnit + FluentAssertions 7.2 + EF SQ
- ❌ NOT: production code `src/Backend/**` + `fe-*/**` → test reveal bug → REPORT em main, KHÔNG fix - ❌ NOT: production code `src/Backend/**` + `fe-*/**` → test reveal bug → REPORT em main, KHÔNG fix
- ❌ NOT: decide WHAT to test (test plan) → em main + reviewer chốt priority - ❌ NOT: decide WHAT to test (test plan) → em main + reviewer chốt priority
## 📊 Baseline 228 tests = 228 PASS (58 Domain + 170 Infra) ← S56 +12 (2 LeaveBalance deduct-correctness + 4 Travel/Vehicle ApproveV2 smoke + 2 ItTicket existence-oracle + 4 DocxRenderer). Pre-S56 = 216. ## 📊 Baseline 240 tests = 240 PASS (58 Domain + 182 Infra) ← S57bis +12 (PeWorkItemGuardTests: 3 validator + 4 create-FK-guard + 5 update-null-safe). Pre = 228 (S56).
Run: `dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1` (MSBuild OOM → serialize build) Run: `dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1` (MSBuild OOM → serialize build)
### ⚠️ Pattern: deduction hook FK → seed LeaveType cho terminal test (S43) ### ⚠️ Pattern: deduction hook FK → seed LeaveType cho terminal test (S43)
@ -53,6 +53,7 @@ Test theo CODE (single source truth), document mismatch header comment + report.
## 📅 Recent activity (last 10 FIFO) ## 📅 Recent activity (last 10 FIFO)
- **2026-06-11 (S57bis P2 PE WorkItemId guard Mig 49 test-after, code đã đúng sẵn):** +12 test `tests/.../Application/PeWorkItemGuardTests.cs` **228→240 PASS** (58 Domain + Infra 170182, 0 fail). PE `Guid? WorkItemId` loose-Guid (KHÔNG FK vật , convention giống ProjectId). **Cover-map 3 trục:** (1) **Validator ×3** `CreatePurchaseEvaluationCommandValidator.Validate(cmd)` plain API (KHÔNG FluentValidation.TestHelper package): nullinvalid+error trên WorkItemId / presentvalid. (2) **Create-FK-guard ×4** handler 4-dep instantiate THẬT trên SQLite (`new PurchaseEvaluationWorkflowService(db,dt,notify,um)` + `new PurchaseEvaluationCodeGenerator(db,dt)` Serializable-tx non-issue SQLite proven S52; reuse `NoOpNotificationService` internal từ ...Services ns + IdentityFixture): bogus-GuidConflict / inactiveConflict / activeOK+`saved.WorkItemId==active.Id`. (3) **Update-null-safe ×5 (bug-class S42 picker)** `UpdatePurchaseEvaluationDraftCommandHandler(db,cu)` 2-dep nhẹ: request.WorkItemId=null→GIỮ w1 KHÔNG null-hoá (⭐ core) / W2-activeđổi / bogusConflict+giữ w1 (AsNoTracking re-read DB-truth) / inactiveConflict / same-as-existingskip-lookup-success. ** SPEC-DRIFT FOUND (test theo CODE, S34 rule):** `NotEmpty()` trên `Guid?` (nullable) chỉ bắt `null`, KHÔNG bắt `Guid.Empty` (FV 7.2 so default(Guid?)==null) Guid.Empty PASS validator. KHÔNG phải lỗ hổng create handler FK-guard (`is Guid wiId` true cho Empty + AnyAsync false) chặn Conflict. Test LOCK behavior (1 validator-test assert Empty pass + 1 handler-test chứng minh defense-in-depth catch). REPORT em main: validator một mình không reject Guid.Empty, dựa handler. No prod bug code đúng spec, defense-in-depth layered. Tag [s57bis, p2, pe-workitemid, mig49, validator-plain-api, null-safe-partial-update, guid-empty-nullable-notempty-drift, defense-in-depth].
- **2026-06-09 (S56 GOLIVE-HARDEN TEST stage 4 pre-golive fixes, test-after build):** +12 test **216→228 PASS** (58 Domain + Infra 158170, 0 fail). Build stage đã land prod fixes (CONTRACT từ build, signatures UNCHANGED). **#3 LeaveBalance lost-update fix:** handler terminal nay increment `db.LeaveBalances.Where(...).ExecuteUpdateAsync(s=>s.SetProperty(b=>b.UsedDays, b=>b.UsedDays+p.NumDays))` server-side + 1 explicit tx (READ COMMITTED, NO IsolationLevel). ** GOTCHA: ExecuteUpdateAsync BYPASS change tracker** instance bal tracked (Add STEP1 hoặc pre-seed cùng context) GIỮ UsedDays PRE-increment. **4 test cũ LeaveBalanceTests (case 1/2/3/4 line 163/201/240/269) FAIL ở baseline = stale-tracked-read, KHÔNG regression** (spec TEST GUIDANCE đã tiên đoán). Fix = `.AsNoTracking()` re-read (hoặc `ChangeTracker.Clear()`). +2 new: `TwoSeparateRequests_BothTerminal_UsedDaysAccumulates_NotOverwrites` (3+5=8 chứng minh increment accumulate KHÔNG overwrite = race-free invariant) + `Approve_AlreadyDaDuyet_ReApprove_ThrowsConflict_NoDoubleDeduct` (early guard Status!=DaGuiDuyet:296 exactly-once, balance vẫn 3 not 6). **#4 Travel/Vehicle ApproveV2 smoke (WorkflowAppApproveV2Tests.cs +4):** mỗi module SubmitApproveDaDuyet happy + outsiderForbidden. ApplicableType Travel=9 prefix `DT/CT`, Vehicle=7 prefix `DX/XE`. Travel/Vehicle KHÔNG trừ balance không seed LeaveType. Helper mới `SeedWorkflowForTypeAsync(type,code,...approverIds)`. **#5 ItTicket existence-oracle (ItTicketReassignAuthzTests.cs +2):** authz reorder (Forbidden TRƯỚC NotFound) non-IT non-admin nhận Forbidden cho ticketId tồn tại không tồn tại (cặp 5b/5c phản hồi giống nhau = no oracle leak). Reorder KHÔNG vỡ test (Case5 đã expect Forbidden; TicketNotFound dùng Admin caller pass authz hợp lệ). **#6 DocxRenderer (Forms/DocxRendererTests.cs NEW +4):** 0 test trước đó. MainDocumentPart null`InvalidOperationException("*MainDocumentPart*")` (OpenXml 3.5.1 `WordprocessingDocument.Create(path,type)` tạo package RỖNG no main part) + placeholder replace happy + unknown-key giữ literal + null-valueempty. ** test helper ExtractBodyText: tránh `MainPart!.Document.Body!` (CS8602 warning) dùng `?.Document?.Body` + `.Should().NotBeNull()`.** No prod bug found tất cả fixes build-stage, tôi WRITE test theo CONTRACT. Tag [s56, golive-harden, executeupdate-tracker-bypass, asnotracking-reread, travel-vehicle-smoke, existence-oracle, docxrenderer]. - **2026-06-09 (S56 GOLIVE-HARDEN TEST stage 4 pre-golive fixes, test-after build):** +12 test **216→228 PASS** (58 Domain + Infra 158170, 0 fail). Build stage đã land prod fixes (CONTRACT từ build, signatures UNCHANGED). **#3 LeaveBalance lost-update fix:** handler terminal nay increment `db.LeaveBalances.Where(...).ExecuteUpdateAsync(s=>s.SetProperty(b=>b.UsedDays, b=>b.UsedDays+p.NumDays))` server-side + 1 explicit tx (READ COMMITTED, NO IsolationLevel). ** GOTCHA: ExecuteUpdateAsync BYPASS change tracker** instance bal tracked (Add STEP1 hoặc pre-seed cùng context) GIỮ UsedDays PRE-increment. **4 test cũ LeaveBalanceTests (case 1/2/3/4 line 163/201/240/269) FAIL ở baseline = stale-tracked-read, KHÔNG regression** (spec TEST GUIDANCE đã tiên đoán). Fix = `.AsNoTracking()` re-read (hoặc `ChangeTracker.Clear()`). +2 new: `TwoSeparateRequests_BothTerminal_UsedDaysAccumulates_NotOverwrites` (3+5=8 chứng minh increment accumulate KHÔNG overwrite = race-free invariant) + `Approve_AlreadyDaDuyet_ReApprove_ThrowsConflict_NoDoubleDeduct` (early guard Status!=DaGuiDuyet:296 exactly-once, balance vẫn 3 not 6). **#4 Travel/Vehicle ApproveV2 smoke (WorkflowAppApproveV2Tests.cs +4):** mỗi module SubmitApproveDaDuyet happy + outsiderForbidden. ApplicableType Travel=9 prefix `DT/CT`, Vehicle=7 prefix `DX/XE`. Travel/Vehicle KHÔNG trừ balance không seed LeaveType. Helper mới `SeedWorkflowForTypeAsync(type,code,...approverIds)`. **#5 ItTicket existence-oracle (ItTicketReassignAuthzTests.cs +2):** authz reorder (Forbidden TRƯỚC NotFound) non-IT non-admin nhận Forbidden cho ticketId tồn tại không tồn tại (cặp 5b/5c phản hồi giống nhau = no oracle leak). Reorder KHÔNG vỡ test (Case5 đã expect Forbidden; TicketNotFound dùng Admin caller pass authz hợp lệ). **#6 DocxRenderer (Forms/DocxRendererTests.cs NEW +4):** 0 test trước đó. MainDocumentPart null`InvalidOperationException("*MainDocumentPart*")` (OpenXml 3.5.1 `WordprocessingDocument.Create(path,type)` tạo package RỖNG no main part) + placeholder replace happy + unknown-key giữ literal + null-valueempty. ** test helper ExtractBodyText: tránh `MainPart!.Document.Body!` (CS8602 warning) dùng `?.Document?.Body` + `.Should().NotBeNull()`.** No prod bug found tất cả fixes build-stage, tôi WRITE test theo CONTRACT. Tag [s56, golive-harden, executeupdate-tracker-bypass, asnotracking-reread, travel-vehicle-smoke, existence-oracle, docxrenderer].
**[em main post-review S56]** Shipped tx = `IsolationLevel.Serializable` (code `LeaveOtApprovalFeatures.cs:369`), KHÔNG READ COMMITTED entry's '(READ COMMITTED, NO IsolationLevel)' = build-stage snapshot, **superseded** post-review (SQLite test path unaffected codegen Serializable already green). **[em main post-review S56]** Shipped tx = `IsolationLevel.Serializable` (code `LeaveOtApprovalFeatures.cs:369`), KHÔNG READ COMMITTED entry's '(READ COMMITTED, NO IsolationLevel)' = build-stage snapshot, **superseded** post-review (SQLite test path unaffected codegen Serializable already green).
- **2026-06-08 (S54 ItTicket reassign authz test-before-merge SECURITY) [harvested by em main agent MEMORY write mis-landed, B2/B3]:** +13 test `tests/.../Application/ItTicketReassignAuthzTests.cs` **203→216 PASS** (58 Domain + Infra 145158, 0 fail). **GetAssignableItStaff (6):** AdminCanReassign=true + 2 IT-active ordered FullName (Cao<Truong) no KT/inactive leak · IT-stafftrue · non-IT non-admin (KT)→false + **empty staff (0-leak assert)** · dept-nullfalse+empty · inactive-IT-excluded · UserId nullUnauthorized. **AssignItTicket (7):** non-IT non-admin→**ForbiddenException** + side-effect `AssignedToUserId.Should().BeNull()` (no-mutation) · Admin+assigneeITsuccess · IT-staff+assigneeITsuccess · assigneeIT(KT)→**ConflictException** "Người được giao phải thuộc tổ IT." · assignee inactiveNotFound · ticket not foundNotFound · nullUnauthorized. **Pattern mới: authz-capability test = seed 2-dept (IT+KT) + fake `ICurrentUser` role/dept matrix; assert canReassign flag + Forbidden/Conflict guard; empty-staff = 0-leak.** Forbidden red-able **by-contrast** (case5 non-IT vs case7 IT-staff identical-setup chỉ khác caller-identity; rule cấm sửa prod để chứng minh RED). **No prod bug** handler-level data-dependent authz (caller-dept vs IT-dept) = CORRECT pattern, KHÔNG phải gotcha #44 silent-403 gap (Pattern 10 reflection-regression chỉ cho static `[Authorize(Policy)]`; data-driven authz PHẢI handler = enforcement point, test cover tại đó). Tag [s54, it-ticket-reassign, authz-capability, forbidden-conflict-guard, test-before-merge, 0-leak]. - **2026-06-08 (S54 ItTicket reassign authz test-before-merge SECURITY) [harvested by em main agent MEMORY write mis-landed, B2/B3]:** +13 test `tests/.../Application/ItTicketReassignAuthzTests.cs` **203→216 PASS** (58 Domain + Infra 145158, 0 fail). **GetAssignableItStaff (6):** AdminCanReassign=true + 2 IT-active ordered FullName (Cao<Truong) no KT/inactive leak · IT-stafftrue · non-IT non-admin (KT)→false + **empty staff (0-leak assert)** · dept-nullfalse+empty · inactive-IT-excluded · UserId nullUnauthorized. **AssignItTicket (7):** non-IT non-admin→**ForbiddenException** + side-effect `AssignedToUserId.Should().BeNull()` (no-mutation) · Admin+assigneeITsuccess · IT-staff+assigneeITsuccess · assigneeIT(KT)→**ConflictException** "Người được giao phải thuộc tổ IT." · assignee inactiveNotFound · ticket not foundNotFound · nullUnauthorized. **Pattern mới: authz-capability test = seed 2-dept (IT+KT) + fake `ICurrentUser` role/dept matrix; assert canReassign flag + Forbidden/Conflict guard; empty-staff = 0-leak.** Forbidden red-able **by-contrast** (case5 non-IT vs case7 IT-staff identical-setup chỉ khác caller-identity; rule cấm sửa prod để chứng minh RED). **No prod bug** handler-level data-dependent authz (caller-dept vs IT-dept) = CORRECT pattern, KHÔNG phải gotcha #44 silent-403 gap (Pattern 10 reflection-regression chỉ cho static `[Authorize(Policy)]`; data-driven authz PHẢI handler = enforcement point, test cover tại đó). Tag [s54, it-ticket-reassign, authz-capability, forbidden-conflict-guard, test-before-merge, 0-leak].
@ -62,7 +63,6 @@ Test theo CODE (single source truth), document mismatch header comment + report.
- **2026-06-08 (S52 P11-E + P11-F WorkflowApps/Attendance test-after):** +5 test **191 PASS** (Infra 128133). 2 file `tests/.../Application/`: **ItTicketCodeGenTests** (3 MaTicket regex `^IT/\d{4}/\d{3}$` + sequential 001002 cùng prefix `IT/{year}` LastSeq++ + per-year-prefix 2027 reset 001) + **AttendanceReportTests** (2 full aggregate day-type/weighted + DepartmentId filter). ** Serializable-on-SQLite GOTCHA = NON-ISSUE (confirmed):** `WorkflowAppCodeGen.GenerateMaDonTuAsync` dùng `BeginTransactionAsync(IsolationLevel.Serializable)` chạy SẠCH trên SQLite provider map isolation level gracefully (no throw), format+seq+per-year đều hold KHÔNG cần try/skip. Đã proven sẵn bởi WorkflowAppApproveV2Tests (DT/LR path). Handler `CreateItTicketHandler(db, cu, clock)` = 3 dep MediatR. **Day-type test pattern (P11-E core):** holiday check chạy TRƯỚC weekend/weekday seed 2026-06-01 (thứ Hai) vào holidaySet assert phân **Holiday** weekday (override day-of-week). Holiday.Date=DateOnly `BuildHoliday` dùng `DateOnly.FromDateTime`. OtWeighted = 2×1.5+3×2.0+1×3.0=12.0m. DepartmentId filter: seed 2 Department row + 2 user khác dept query deptA chỉ trả 1 row (handler join Users `u.DepartmentId==deptId`, userMeta dùng `DefaultIfEmpty` nên dept row optional nhưng seed cho DepartmentName assert). No prod bug. ** MSBuild OOM** chạy full parallel dùng `-maxcpucount:1 -p:BuildInParallel=false` (env resource, KHÔNG test fail). Tag [s52, p11-e, p11-f, codegen, day-type, serializable-sqlite-ok, test-after]. - **2026-06-08 (S52 P11-E + P11-F WorkflowApps/Attendance test-after):** +5 test **191 PASS** (Infra 128133). 2 file `tests/.../Application/`: **ItTicketCodeGenTests** (3 MaTicket regex `^IT/\d{4}/\d{3}$` + sequential 001002 cùng prefix `IT/{year}` LastSeq++ + per-year-prefix 2027 reset 001) + **AttendanceReportTests** (2 full aggregate day-type/weighted + DepartmentId filter). ** Serializable-on-SQLite GOTCHA = NON-ISSUE (confirmed):** `WorkflowAppCodeGen.GenerateMaDonTuAsync` dùng `BeginTransactionAsync(IsolationLevel.Serializable)` chạy SẠCH trên SQLite provider map isolation level gracefully (no throw), format+seq+per-year đều hold KHÔNG cần try/skip. Đã proven sẵn bởi WorkflowAppApproveV2Tests (DT/LR path). Handler `CreateItTicketHandler(db, cu, clock)` = 3 dep MediatR. **Day-type test pattern (P11-E core):** holiday check chạy TRƯỚC weekend/weekday seed 2026-06-01 (thứ Hai) vào holidaySet assert phân **Holiday** weekday (override day-of-week). Holiday.Date=DateOnly `BuildHoliday` dùng `DateOnly.FromDateTime`. OtWeighted = 2×1.5+3×2.0+1×3.0=12.0m. DepartmentId filter: seed 2 Department row + 2 user khác dept query deptA chỉ trả 1 row (handler join Users `u.DepartmentId==deptId`, userMeta dùng `DefaultIfEmpty` nên dept row optional nhưng seed cho DepartmentName assert). No prod bug. ** MSBuild OOM** chạy full parallel dùng `-maxcpucount:1 -p:BuildInParallel=false` (env resource, KHÔNG test fail). Tag [s52, p11-e, p11-f, codegen, day-type, serializable-sqlite-ok, test-after].
- **2026-06-08 (S51 P11-C HMW Wave2 filtered-unique gotcha #57):** +4 test `tests/.../Application/HrmConfigFilteredUniqueTests.cs` **185 total = 183 PASS + 2 RED** (Infra 123127). Mirror HolidayTests Case 7 (seed soft-deleted Code-slot Create same Code assert success + active==1 + all==2). **2 GREEN** Vehicle+Driver (Mig 44 config ĐÃ filtered 2 catalog mới đúng). **2 RED INTENTIONAL = gotcha #57 REPRODUCED** (test-before): `CreateLeaveType_OnSoftDeletedCodeSlot...` `SQLite Error 19 UNIQUE constraint failed: LeaveTypes.Code` + `CreateShift_OnSoftDeletedCodeSlot...` `ShiftPatterns.Code` (bare `.IsUnique()` đếm cả row soft-deleted; handler app-check `!IsDeleted` PASS Add+SaveChanges DbUpdateException). NOT test lỗi REPORTED em main fix Mig 45 `.HasFilter("[IsDeleted]=0")` cho 2 config flip GREEN. ** Soft-delete trong test (giống Holiday):** AuditingInterceptor (prod soft-delete DeletedModified+IsDeleted=true) KHÔNG wire trong SqliteDbFixture `Remove+SaveChanges` = HARD delete (không test được). PHẢI seed row `IsDeleted=true` thủ công để phỏng slot bị chiếm. Handlers chỉ cần IApplicationDbContext `new CreateXxxHandler(db)`. Tag [s51, p11-c, gotcha-57, filtered-unique, test-before]. - **2026-06-08 (S51 P11-C HMW Wave2 filtered-unique gotcha #57):** +4 test `tests/.../Application/HrmConfigFilteredUniqueTests.cs` **185 total = 183 PASS + 2 RED** (Infra 123127). Mirror HolidayTests Case 7 (seed soft-deleted Code-slot Create same Code assert success + active==1 + all==2). **2 GREEN** Vehicle+Driver (Mig 44 config ĐÃ filtered 2 catalog mới đúng). **2 RED INTENTIONAL = gotcha #57 REPRODUCED** (test-before): `CreateLeaveType_OnSoftDeletedCodeSlot...` `SQLite Error 19 UNIQUE constraint failed: LeaveTypes.Code` + `CreateShift_OnSoftDeletedCodeSlot...` `ShiftPatterns.Code` (bare `.IsUnique()` đếm cả row soft-deleted; handler app-check `!IsDeleted` PASS Add+SaveChanges DbUpdateException). NOT test lỗi REPORTED em main fix Mig 45 `.HasFilter("[IsDeleted]=0")` cho 2 config flip GREEN. ** Soft-delete trong test (giống Holiday):** AuditingInterceptor (prod soft-delete DeletedModified+IsDeleted=true) KHÔNG wire trong SqliteDbFixture `Remove+SaveChanges` = HARD delete (không test được). PHẢI seed row `IsDeleted=true` thủ công để phỏng slot bị chiếm. Handlers chỉ cần IApplicationDbContext `new CreateXxxHandler(db)`. Tag [s51, p11-c, gotcha-57, filtered-unique, test-before].
- **2026-05-30 (S43 P11-B Wave3 LeaveBalance):** +8 test `tests/.../Application/LeaveBalanceTests.cs` **152 PASS** (Infra 8694). Deduction hook (ApproveLeaveRequestHandler terminal) full: deduct single-level (create row from DaysPerYear), only-at-terminal multi-level (advance no-deduct + 1× terminal), accumulate UPSERT (5+2=7 no new row), negative allowed (Used20>Entitled12 → Remaining8 no throw), Reject+Return no-deduct (split 5a/5b), GetMyLeaveBalances lazy synth (2 active type filter inactive), AdjustLeaveBalance upsert. **⚠️ FOUND + FIXED 2 pre-existing RED** in S42 template (`Approve_LastLevel_TransitionsToDaDuyet` + `Approve_EmptyComment_StoresPlaceholder`): Wave 1 deduction hook (uncommitted, prod) làm terminal insert LeaveBalance FK→LeaveTypes Restrict FAIL vì BuildLeave dùng `LeaveTypeId=Guid.NewGuid()`. **NOT prod bug** (prod đơn luôn pin LeaveType thật) — fix tại test: BuildLeave +optional leaveTypeId, seed LeaveType ở 2 test đó. Baseline thật trước S43 = 142-pass/2-RED (KHÔNG phải 144-green). REPORTED em main. - **2026-05-30 (S43 P11-B Wave3 LeaveBalance):** +8 test `tests/.../Application/LeaveBalanceTests.cs` **152 PASS** (Infra 8694). Deduction hook (ApproveLeaveRequestHandler terminal) full: deduct single-level (create row from DaysPerYear), only-at-terminal multi-level (advance no-deduct + 1× terminal), accumulate UPSERT (5+2=7 no new row), negative allowed (Used20>Entitled12 → Remaining8 no throw), Reject+Return no-deduct (split 5a/5b), GetMyLeaveBalances lazy synth (2 active type filter inactive), AdjustLeaveBalance upsert. **⚠️ FOUND + FIXED 2 pre-existing RED** in S42 template (`Approve_LastLevel_TransitionsToDaDuyet` + `Approve_EmptyComment_StoresPlaceholder`): Wave 1 deduction hook (uncommitted, prod) làm terminal insert LeaveBalance FK→LeaveTypes Restrict FAIL vì BuildLeave dùng `LeaveTypeId=Guid.NewGuid()`. **NOT prod bug** (prod đơn luôn pin LeaveType thật) — fix tại test: BuildLeave +optional leaveTypeId, seed LeaveType ở 2 test đó. Baseline thật trước S43 = 142-pass/2-RED (KHÔNG phải 144-green). REPORTED em main.
- **2026-06-01 (S45 HRM coverage gaps + Holiday drift) [em main proxy]:** +27 test → **181 PASS** (Infra 96→123). 3 file: HrmConfigHolidayTests (7 — composite UNIQUE Create/Update, ⭐self-update giữ key đổi Name no-false-positive, soft-delete exclusion) + EmployeeSatelliteTests (10 — 5× FK-invariant parent `AnyAsync(!IsDeleted)` guard + soft-delete + cascade-non-behavior Case5 + EF model `DeleteBehavior.Cascade` config assertion) + AuthorizePolicyRegressionTests extend (10 — HrmConfigs bare-`[Authorize]`+writes `Roles=Admin`; Employees class-`Policy=Hrm_HoSo.Read`+per-action). **FOUND drift** (test theo CODE = single source): Holiday DB UNIQUE (Year,Date) unfiltered vs handler `!IsDeleted` → recreate-on-soft-deleted-slot `DbUpdateException(500)`. REPORTED → em main fixed Mig 43 `.HasFilter("[IsDeleted]=0")` (Case 7 flipped assert SUCCESS). New pattern: EF model-metadata assertion `db.Model.FindEntityType(typeof(X)).GetForeignKeys()...DeleteBehavior` lock schema intent. ⚠️ gotcha #57 backlog: LeaveType.Code + ShiftPattern.Code vẫn unfiltered.
--- ---

View File

@ -13,10 +13,10 @@ H1 tooling-freshness auditor **SOLUTION_ERP-self**. Read-only + **propose-only**
- ✅ MINE: tooling/docs freshness (4-mặt) + roster-drift + skill/plugin new-alloc — SOLUTION_ERP-self - ✅ MINE: tooling/docs freshness (4-mặt) + roster-drift + skill/plugin new-alloc — SOLUTION_ERP-self
- ❌ NOT: harvest-memory/5-trục → **harvest-curator** (H2) · corpus/RAG/deploy → cicd-monitor · code/SQL audit → investigator-codebase · write/decide → em main - ❌ NOT: harvest-memory/5-trục → **harvest-curator** (H2) · corpus/RAG/deploy → cicd-monitor · code/SQL audit → investigator-codebase · write/decide → em main
## 📋 Baseline state (2026-06-07 seed — VERIFY mỗi session, đừng tin số cũ) ## 📋 Baseline state (re-ground 2026-06-10 S57-start — VERIFY mỗi session, đừng tin số cũ)
- **Roster:** 10 sub (8 product/quality: investigator-codebase/api · implementer-backend/frontend · test-specialist · reviewer · cicd-monitor · frontend-designer + 2 monitor INFORM-only: tooling-auditor · harvest-curator). - **Roster:** 11 sub (9 product/quality: investigator-codebase/api · implementer-backend/frontend · test-specialist · reviewer · cicd-monitor · frontend-designer · database-agent read-advisory S52 + 2 monitor INFORM-only: tooling-auditor · harvest-curator).
- **Skills:** 6 project (`.claude/skills/`) + ~23 standalone (`~/.claude/skills/`, vd sql-database-assistant). - **Skills:** 6 project (`.claude/skills/`) + ~23 standalone (`~/.claude/skills/`, vd sql-database-assistant).
- **Plugins:** 15 enabled user-global (`~/.claude/settings.json`) — nấc installed/enabled, phần lớn CHƯA assigned-to-roster. - **Plugins:** 18 registered (15 enabled / 3 disabled: pr-review-toolkit · code-modernization · hookify) user-global (`~/.claude/settings.json`) — nấc installed/enabled, phần lớn CHƯA assigned-to-roster.
- **Docs canonical:** `CLAUDE.md` (root+docs) · `docs/STATUS.md` · `docs/HANDOFF.md` · `.claude/agents/README.md` · `docs/governance/`. - **Docs canonical:** `CLAUDE.md` (root+docs) · `docs/STATUS.md` · `docs/HANDOFF.md` · `.claude/agents/README.md` · `docs/governance/`.
## ⚠️ Anti-patterns ## ⚠️ Anti-patterns
@ -26,3 +26,7 @@ H1 tooling-freshness auditor **SOLUTION_ERP-self**. Read-only + **propose-only**
- **2026-06-07 (CREATED):** Seeded H1 tooling-auditor (adopt AI_INFRA Harness 1, anh giao). Tailored SE: 4 RAG-read (KHÔNG copy AI_INFRA 2-RAG) · `model:inherit` (KHÔNG effort:max) · omit color (8 màu chuẩn cyan/blue/yellow/orange/purple/red/green/pink đã hết). Wired @session-start RE-REPORT (Phase 2.1.1) + @session-end H1 chốt. Nấc: **executed-file, verified-runtime PENDING** CLI restart + first spawn smoke. Tag [created, harness-1, h1]. - **2026-06-07 (CREATED):** Seeded H1 tooling-auditor (adopt AI_INFRA Harness 1, anh giao). Tailored SE: 4 RAG-read (KHÔNG copy AI_INFRA 2-RAG) · `model:inherit` (KHÔNG effort:max) · omit color (8 màu chuẩn cyan/blue/yellow/orange/purple/red/green/pink đã hết). Wired @session-start RE-REPORT (Phase 2.1.1) + @session-end H1 chốt. Nấc: **executed-file, verified-runtime PENDING** CLI restart + first spawn smoke. Tag [created, harness-1, h1].
- **2026-06-07 (S50 FIRST REAL RUN — verified-runtime ✅):** Spawned @session-start (RE-REPORT) + @session-end (CHỐT). Load OK → **verified-runtime CONFIRMED** (closes 'PENDING' above). 4-mặt audit caught **3 freshness drifts** → em main patched all: (1) `agents/README.md:157` plugin **15→18** (+csharp-lsp/typescript-lsp/session-report); (2) `.claude/skills/README.md:20` ef-core **31→43 mig**, `:90` gotcha **49→57** (⭐ MISSED by S44 monthly audit — index file not on its checklist → per-session monitor adds value over monthly cron); (3) verified-runtime markers STATUS/HANDOFF flipped. **Method-learning:** ground-truth EVERY count from disk — `settings.json enabledPlugins` line-count = authoritative plugin#; `skills/README.md``SKILL.md` frontmatter (drift independently). Residual flagged (em main): STATUS RAG-chunk 2406↔2415 contradiction → reconcile to 2415; ASCII diagram 7→10 lanes (cosmetic). Tag [first-run, verified-runtime, freshness-catch]. - **2026-06-07 (S50 FIRST REAL RUN — verified-runtime ✅):** Spawned @session-start (RE-REPORT) + @session-end (CHỐT). Load OK → **verified-runtime CONFIRMED** (closes 'PENDING' above). 4-mặt audit caught **3 freshness drifts** → em main patched all: (1) `agents/README.md:157` plugin **15→18** (+csharp-lsp/typescript-lsp/session-report); (2) `.claude/skills/README.md:20` ef-core **31→43 mig**, `:90` gotcha **49→57** (⭐ MISSED by S44 monthly audit — index file not on its checklist → per-session monitor adds value over monthly cron); (3) verified-runtime markers STATUS/HANDOFF flipped. **Method-learning:** ground-truth EVERY count from disk — `settings.json enabledPlugins` line-count = authoritative plugin#; `skills/README.md``SKILL.md` frontmatter (drift independently). Residual flagged (em main): STATUS RAG-chunk 2406↔2415 contradiction → reconcile to 2415; ASCII diagram 7→10 lanes (cosmetic). Tag [first-run, verified-runtime, freshness-catch].
- **2026-06-08 (S51 `/session-end` CHỐT 4-mặt — RAG down, 0 file written):** skill 6+23 unchanged · roster 10 intact (database-agent=PROPOSAL not-adopted) · plugin **18 registered (15 enabled / 3 disabled** pr-review-toolkit·code-modernization·hookify — "enabled" overstates by 3, nâc-conflation) · docs STATUS/HANDOFF/gotchas S51 ✅ consistent. **NEW-ALLOC:** AI_INFRA `2026-06-08-Agent-database-codebase-agents` broadcast → **database-agent STRONG-FIT recommend /adap-apply** (DB11 RowVersion fixes S43 lost-update gap; templates exist; 5 caveats: needs color#9, EF-pin-guard, DB7-boundary-vs-implementer-backend, executed-file-nâc, model:inherit) · **codebase-agent SKIP** (investigator covers grep/audit + csharp-lsp Windows no-op). **Doc-drift coords (em main fixed root only; deferred rest→monthly):** ✅fixed CLAUDE.md root :53/:66/:81/:87/:131; ⏳defer docs/CLAUDE.md:65/70 + skills/README:20 (ef-core 43→45) + agents/README:157 (nâc-reword) + schema-diagram §16+ Mig32-45 (14-mig debt). **Method:** installed≠enabled≠assigned≠used; ground-truth from disk. Tag [s51, chot-4-mat, new-alloc-database-agent, doc-drift-coords]. - **2026-06-08 (S51 `/session-end` CHỐT 4-mặt — RAG down, 0 file written):** skill 6+23 unchanged · roster 10 intact (database-agent=PROPOSAL not-adopted) · plugin **18 registered (15 enabled / 3 disabled** pr-review-toolkit·code-modernization·hookify — "enabled" overstates by 3, nâc-conflation) · docs STATUS/HANDOFF/gotchas S51 ✅ consistent. **NEW-ALLOC:** AI_INFRA `2026-06-08-Agent-database-codebase-agents` broadcast → **database-agent STRONG-FIT recommend /adap-apply** (DB11 RowVersion fixes S43 lost-update gap; templates exist; 5 caveats: needs color#9, EF-pin-guard, DB7-boundary-vs-implementer-backend, executed-file-nâc, model:inherit) · **codebase-agent SKIP** (investigator covers grep/audit + csharp-lsp Windows no-op). **Doc-drift coords (em main fixed root only; deferred rest→monthly):** ✅fixed CLAUDE.md root :53/:66/:81/:87/:131; ⏳defer docs/CLAUDE.md:65/70 + skills/README:20 (ef-core 43→45) + agents/README:157 (nâc-reword) + schema-diagram §16+ Mig32-45 (14-mig debt). **Method:** installed≠enabled≠assigned≠used; ground-truth from disk. Tag [s51, chot-4-mat, new-alloc-database-agent, doc-drift-coords].
- **2026-06-10 (S57-start RE-REPORT):** Audit @start với S57 in-flight dirty (9 file, session trước ngắt no-closeout). ①SKILL 6+23 unchanged; ef-core :3/:19=48mig FRESH; STALE ef-core:72 92→93 · :280 91/42→93/48 · :289 27-42→27-48 + dep-audit:153 57→58 + skills/README:90 57→58 → **em main patched ALL cùng session-start (P2)**. ②ROSTER CLEAN 11=11=11 (disk/README/STATUS); minor README:201 "8 folder"→11 + hmw.js VALID_ROLES(8) thiếu database-agent (S56 dùng 3× fail-soft) → **em main patched (P3, VALID_ROLES=9)**. ③PLUGIN CLEAN 18/15/3 identical S53, 0 new-alloc. ④DOCS MAJOR: S57 invisible (grep `S57|perm-broaden`=0 match; STATUS:38 "In Progress: none" vs tree dirty 9 file) → closeout cần STATUS+HANDOFF+log+permission-matrix-skill-conditional+investigator-MEMORY-commit (P1 pending resume). gotcha #58 VERIFIED `gotchas.md:1063`. **Method-learning:** gotcha entry format = "### N." KHÔNG "#N" — grep literal "#58"=0 match suýt false-alarm; verify format trước khi claim missing. Baseline block re-grounded (roster 11 · plugin 18(15/3) · +database-agent). Tag [s57-start, 4-mat, s57-gap, patched-p2-p3].
- **2026-06-10 (S57-RESUME @start RE-REPORT):** Re-audit 4-mặt với 16-file dirty (S57-interrupted). ①SKILL PASS 6+23; 3 skill-doc dirty verified ĐÚNG (ef-core:72/:280/:289 · dep-audit:153 · skills/README:90); permission-matrix = conditional closeout (S57 đổi seed model). ②ROSTER DRIFT-residual: dirty README:192(9)+:201(11)+hmw.js(9) đúng+nhất quán, NHƯNG catch MỚI `ultra-on.md:23-24` VALID_ROLES "8 sub" thiếu database-agent (floor-doc README:197 trỏ tới!) + `session-start.md:37/:44-54` "10-agent"+list 9 tên thiếu frontend-designer+database-agent +:40 gotcha (55)→58 — commands/*.md TRƯỚC GIỜ NGOÀI radar grep roster → thêm vào checklist mặt-② vĩnh viễn. **Em main PATCHED cả 2 ngay trong session** (ultra-on→9-sub + session-start→11-agent list đủ + 58). ③PLUGIN PASS 18/15/3 identical, marketplace 35, 0 new. ④DOCS: root+docs CLAUDE.md SẠCH (fix từ S56 a62e797, KHÔNG phải monthly-pending) → HANDOFF:24 backlog-item = stale-contradiction tự mâu thuẫn HANDOFF:17 — backlog coords PHẢI re-verify trước khi tin (3/5 coords HANDOFF:121 cũng đã obsolete). S57 invisible STATUS/HANDOFF = P1 closeout debt. Verdict 8 file .claude: 5 tooling COMMIT-AS-IS; 3 MEMORY → H2 verified OK. Tag [s57-resume, 4-mat, ultra-on-catch, stale-backlog-coords].
- **2026-06-10 (spawn-test H4.8 — Harness-4 two-tier):** Mình bị DEMOTE pin `model: claude-opus-4-8` (checklist-class, mirror AI_INFRA demote con tương đương). Spawn-test echo model NGAY sau edit → self-report `claude-fable-5[1m]` = SE env (CCD harness) KHÔNG fresh-read frontmatter → pin ăn SAU restart CLI. Post-restart mình chạy Opus 4.8 (Max giữ nguyên env-wide) — nếu thấy verdict-quality tự giảm rõ → báo em main adap-request promote lại. Tag [h4-demote, spawn-test, pending-restart].
- **2026-06-11 (S57bis @start RE-REPORT + spawn-test post-restart ✅):** Self-report nguyên văn `claude-opus-4-8[1m]` ("Opus 4.8 (1M context)") → **demote-pin ĂN runtime** (đóng 'pending-restart' entry trên) + `[1m]` 1M-resolve SE tự verify (hết lệ thuộc claim AI_INFRA s20). 4-mặt **ALL-PASS 0 drift mới** — 29 file dirty = Harness-4 closeout hợp lệ: ①3 skill-doc diff = freshness-fix đúng (48 mig/93 bảng/58 gotcha) ②roster 11=11=11, frontmatter grep = 7 pin + 4 inherit, 0 `[1m]` frontmatter ③plugin 18/15/3 identical, 0 new-alloc ④STATUS diff hợp lệ + 3 untracked governance đúng nấc → đề xuất promote PENDING-RESTART→runtime-verified (em main đã thực hiện cùng session). Carry-flag: docs/CLAUDE.md gotcha "(55)"→58 (defer monthly 07-01) · schema-diagram §16+ 14-mig ERD debt. Demote-watch data-point #1: verdict-quality trên Opus 4.8 tự đánh giá CHƯA suy giảm. Tag [s57bis, spawn-test-verified, 4-mat-pass, demote-watch-1].

View File

@ -1,11 +1,12 @@
# Multi-agent SOLUTION_ERP — Master Coordination Guide (11-agent) # Multi-agent SOLUTION_ERP — Master Coordination Guide (11-agent)
> **Architecture:** 11 sub-agents Opus 4.8 1M Max + em main coordinator — **9 product/quality** (7 core + frontend-designer pink S47 + database-agent read-advisory S52) + **2 monitor INFORM-only** (`tooling-auditor` H1 + `harvest-curator` H2, 2026-06-07 Harness 1). > **Architecture:** 11 sub-agents **two-tier model (Harness-4 2026-06-10)** + em main **Fable 5 (1M) Max** coordinator — **9 product/quality** (7 core + frontend-designer pink S47 + database-agent read-advisory S52) + **2 monitor INFORM-only** (`tooling-auditor` H1 + `harvest-curator` H2, 2026-06-07 Harness 1). Tier: **4 promote `model: inherit` = Fable 5 1M** (reviewer H4.3a · investigator-codebase H4.3b · database-agent H4.3b · harvest-curator H4.3c) · **7 demote pin `claude-opus-4-8`** (2 implementer · test-specialist · cicd-monitor · investigator-api · frontend-designer · tooling-auditor) · effort **Max cả 2 tier** (env machine-wide).
> **Upgrade S52 (2026-06-08 — AI_INFRA broadcast `2026-06-08-Agent-database-codebase-agents`):** **+database-agent (read-advisory DB specialist, floor DB1DB11)** — schema/query/migration-design-review/perf/concurrency (DB11 RowVersion vá lost-update S43). Tailor READ-tier (implementer-backend vẫn author) · color OMIT (8 standard hết) · `store_memory` strip. `codebase-agent` = **SKIP n-a** (investigator-codebase đã cover grep/audit + `csharp-lsp` Windows no-op). ✅ **verified-runtime** — spawned OK S53 (first real spawn, caught Mig 46 committed-but-unapplied-local drift) + S56 2× (pre-golive-verify schema-stream + golive-harden design+review). DB11 lost-update fix landed S56 (atomic ExecuteUpdate + Serializable tx, gotcha #58). > **Upgrade S52 (2026-06-08 — AI_INFRA broadcast `2026-06-08-Agent-database-codebase-agents`):** **+database-agent (read-advisory DB specialist, floor DB1DB11)** — schema/query/migration-design-review/perf/concurrency (DB11 RowVersion vá lost-update S43). Tailor READ-tier (implementer-backend vẫn author) · color OMIT (8 standard hết) · `store_memory` strip. `codebase-agent` = **SKIP n-a** (investigator-codebase đã cover grep/audit + `csharp-lsp` Windows no-op). ✅ **verified-runtime** — spawned OK S53 (first real spawn, caught Mig 46 committed-but-unapplied-local drift) + S56 2× (pre-golive-verify schema-stream + golive-harden design+review). DB11 lost-update fix landed S56 (atomic ExecuteUpdate + Serializable tx, gotcha #58).
> Pattern: Anthropic Building Effective Agents orchestrator-workers + Cognition "writes single-threaded" hybrid + post-deploy automated watchdog. > Pattern: Anthropic Building Effective Agents orchestrator-workers + Cognition "writes single-threaded" hybrid + post-deploy automated watchdog.
> **Upgrade S39 (2026-05-29):** 4→7 agent (split investigator + implementer, +test-specialist) + budget +50% + 5 RAG MCP per agent. Reference BVAAU 7-agent config (adapted, NOT copied — SOLUTION_ERP 2-FE-app fit + 6 skill proven battle-test 38 session). Prior: S20t12 initial 3 + S21t1 +cicd-monitor. > **Upgrade S39 (2026-05-29):** 4→7 agent (split investigator + implementer, +test-specialist) + budget +50% + 5 RAG MCP per agent. Reference BVAAU 7-agent config (adapted, NOT copied — SOLUTION_ERP 2-FE-app fit + 6 skill proven battle-test 38 session). Prior: S20t12 initial 3 + S21t1 +cicd-monitor.
> **Upgrade S47 (2026-06-02):** **+frontend-designer (8th sub, pink)** — FD1FD10 visual-verification design floor (forked AI_INFRA canonical, broadcast `Agent-frontend-designer-floor`). + **`store_memory` STRIPPED khỏi MỌI sub → lead = sole RAG-writer** (broadcast `Memory-store-memory-strip-global`); sub ghi finding → MEMORY.md (file). adap-reports: `docs/governance/adap-reports/`. > **Upgrade S47 (2026-06-02):** **+frontend-designer (8th sub, pink)** — FD1FD10 visual-verification design floor (forked AI_INFRA canonical, broadcast `Agent-frontend-designer-floor`). + **`store_memory` STRIPPED khỏi MỌI sub → lead = sole RAG-writer** (broadcast `Memory-store-memory-strip-global`); sub ghi finding → MEMORY.md (file). adap-reports: `docs/governance/adap-reports/`.
> **Upgrade 2026-06-07 (Harness 1·2·3 adopt — AI_INFRA broadcast):** **+2 monitor sub INFORM-only** `tooling-auditor` (H1 tooling/docs-freshness 4-mặt) + `harvest-curator` (H2 harvest-integrity 5-trục) → roster 8→10, **TÁCH BIỆT** per anh-mandate (H1≠H2 "hay quên+nhầm"). + **wave-folder memory-isolation** (Harness 2 — `hmw.js` wave-mode + `.claude/workflows/wave-*/` gitignored, B1B6). + **email channel** `broadcasts/` (Harness 3 — cross-project comms, self-id=`se`). KHÔNG copy-paste AI_INFRA — tailor SE roster/stack. > **Upgrade 2026-06-07 (Harness 1·2·3 adopt — AI_INFRA broadcast):** **+2 monitor sub INFORM-only** `tooling-auditor` (H1 tooling/docs-freshness 4-mặt) + `harvest-curator` (H2 harvest-integrity 5-trục) → roster 8→10, **TÁCH BIỆT** per anh-mandate (H1≠H2 "hay quên+nhầm"). + **wave-folder memory-isolation** (Harness 2 — `hmw.js` wave-mode + `.claude/workflows/wave-*/` gitignored, B1B6). + **email channel** `broadcasts/` (Harness 3 — cross-project comms, self-id=`se`). KHÔNG copy-paste AI_INFRA — tailor SE roster/stack.
> **Upgrade 2026-06-10 (Harness-4 two-tier model — AI_INFRA broadcast `harness-4-model-tier-promotion` + `model-fable-5-max`):** lead = **Fable 5 (1M) Max** (user-level machine-wide, SE không project-pin) · sub two-tier theo tiêu chí H4.3 (a gate≥writer · b verdict-nuôi-quyết-định · c chống-rubber-stamp · d 1M-thật): **promote 4 giữ `inherit`** (reviewer·investigator-codebase·database-agent·harvest-curator) + **demote 7 pin `claude-opus-4-8`** (full-id no-suffix — gotcha #37 cấm `[1m]`; runtime resolve `[1m]` 1M trên máy chung per AI_INFRA s20). `hmw.js` tier-map H4.5 (role-less → `'opus'` · per-task `tier:'fable'|'opus'` override). Email-back AI_INFRA H4.7 BẮT BUỘC. Justification per-vị-trí: adap-report `2026-06-10-Governance-harness-4-model-tier-promotion.md`.
--- ---
@ -15,14 +16,14 @@
``` ```
┌──────────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────────┐
│ EM (Main) — Opus 4.8 1M Max │ EM (Main) — Fable 5 (1M) Max │
│ • Reasoning + write code (single-threaded principle) │ │ • Reasoning + write code (single-threaded principle) │
│ • Schema/UX/architecture decision + cross-stack tight coupling│ │ • Schema/UX/architecture decision + cross-stack tight coupling│
│ • Coordinate 11 sub-agents via spawn + SendMessage │ │ • Coordinate 11 sub-agents via spawn + SendMessage │
│ • Synthesize cross-agent findings + commit/push (em main only)│ │ • Synthesize cross-agent findings + commit/push (em main only)│
│ • Fallback solo nếu spawn fail (gotcha #53 truncate / 529) │ │ • Fallback solo nếu spawn fail (gotcha #53 truncate / 529) │
└──────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────┘
↓ spawn + keep-alive (Opus 4.8 1M Max inherit each) ↓ spawn + keep-alive (two-tier H4: 4 promote inherit Fable 5 · 7 demote pin Opus 4.8 — Max cả 2)
── RESEARCH (READ) ────────── ── IMPLEMENT (WRITE) ──────────── ── QUALITY ────────── ── RESEARCH (READ) ────────── ── IMPLEMENT (WRITE) ──────────── ── QUALITY ──────────
┌──────────────────┐ ┌───────┐ ┌─────────────────┐ ┌──────────┐ ┌────────┐ ┌─────────┐ ┌────────┐ ┌──────────────────┐ ┌───────┐ ┌─────────────────┐ ┌──────────┐ ┌────────┐ ┌─────────┐ ┌────────┐
│investigator- │ │invest-│ │implementer- │ │implement-│ │test- │ │reviewer │ │cicd- │ │investigator- │ │invest-│ │implementer- │ │implement-│ │test- │ │reviewer │ │cicd- │
@ -189,7 +190,7 @@ All 11 agent có **4 RAG-READ MCP**: `search_memory` + `search_code` (BM25, pref
- **Keyword = QUYỀN, KHÔNG lệnh (T4):** "workflow"/"ultracode" mở quyền hỏi, KHÔNG auto-run. Mode-OFF + "chạy workflow" → TỪ CHỐI + nhắc `/ultra-on`. CẤM native `/effort ultracode`. *(Bài học 515K-token false-trigger.)* - **Keyword = QUYỀN, KHÔNG lệnh (T4):** "workflow"/"ultracode" mở quyền hỏi, KHÔNG auto-run. Mode-OFF + "chạy workflow" → TỪ CHỐI + nhắc `/ultra-on`. CẤM native `/effort ultracode`. *(Bài học 515K-token false-trigger.)*
- **Scope (S1):** Workflow fan-out CHỈ repo SOLUTION_ERP — KHÔNG fan-out repo/corpus khác. - **Scope (S1):** Workflow fan-out CHỈ repo SOLUTION_ERP — KHÔNG fan-out repo/corpus khác.
- **Checkpoint (S2):** `hmw.js` **throw** nếu `checkpointApproved≠true` (mechanized tripwire anti-accidental). Em main BÁO {số agent·vai·task} @inform → set cờ → fan-out (KHÔNG chờ confirm từng lần; marker-ON=consent). Sub KHÔNG spawn sub (S3). - **Checkpoint (S2):** `hmw.js` **throw** nếu `checkpointApproved≠true` (mechanized tripwire anti-accidental). Em main BÁO {số agent·vai·task} @inform → set cờ → fan-out (KHÔNG chờ confirm từng lần; marker-ON=consent). Sub KHÔNG spawn sub (S3).
- **VALID_ROLES (8 — whitelist `hmw.js`):** `investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer`. Role lạ → default subagent + WARN (fail-soft, S4c). - **VALID_ROLES (9 — whitelist `hmw.js`):** `investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer` · `database-agent` (+S57 — S56 đã dùng 3× qua fail-soft WARN). Role lạ → default subagent + WARN (fail-soft, S4c).
- **Memory governance (M1M5 + R1):** B1 slice-inject (agent ← slice MEMORY của đúng vai qua `args`) · M2 return-delta-only (`memoryDelta{task,verdict,learned,surprise}`) · B3 lead single-writer VERIFY→APPEND-only (no-overwrite-unverified) · B2 harvest-LIỀN sau mỗi workflow vào `agent-memory/<role>` · M5 `store_memory` strip (đã S47). **Containment = defense-in-depth** (git-diff + Qdrant chunk-count post-P2), KHÔNG allowlist đơn-độc (G-015: sub vẫn giữ Bash/Write — KHÔNG "read-only"). - **Memory governance (M1M5 + R1):** B1 slice-inject (agent ← slice MEMORY của đúng vai qua `args`) · M2 return-delta-only (`memoryDelta{task,verdict,learned,surprise}`) · B3 lead single-writer VERIFY→APPEND-only (no-overwrite-unverified) · B2 harvest-LIỀN sau mỗi workflow vào `agent-memory/<role>` · M5 `store_memory` strip (đã S47). **Containment = defense-in-depth** (git-diff + Qdrant chunk-count post-P2), KHÔNG allowlist đơn-độc (G-015: sub vẫn giữ Bash/Write — KHÔNG "read-only").
> Floor T/S/M/R đầy đủ → `.claude/commands/ultra-on.md`. adap-report → `docs/governance/adap-reports/2026-06-03-Agent-ultracode-hmw-mem-governance.md`. > Floor T/S/M/R đầy đủ → `.claude/commands/ultra-on.md`. adap-report → `docs/governance/adap-reports/2026-06-03-Agent-ultracode-hmw-mem-governance.md`.
@ -198,7 +199,7 @@ All 11 agent có **4 RAG-READ MCP**: `search_memory` + `search_code` (BM25, pref
## 💾 Memory discipline ## 💾 Memory discipline
Each agent `.claude/agent-memory/<name>/MEMORY.md` persistent diary. Spawn auto-inject first 200 lines/25KB. Update BEFORE return (BẮT BUỘC, entry ≤ 1.5K chars). 8 folder: investigator-codebase · investigator-api · implementer-backend · implementer-frontend · test-specialist · reviewer · cicd-monitor · frontend-designer. Each agent `.claude/agent-memory/<name>/MEMORY.md` persistent diary. Spawn auto-inject first 200 lines/25KB. Update BEFORE return (BẮT BUỘC, entry ≤ 1.5K chars). 11 folder: investigator-codebase · investigator-api · implementer-backend · implementer-frontend · test-specialist · reviewer · cicd-monitor · frontend-designer · database-agent · tooling-auditor · harvest-curator.
**Tiered Memory Policy v1** (adopt AI_INFRA bulletin 2026-05-29 — thay ngưỡng cứng ">25KB archive" bằng tiered + just-in-time; size to ≠ chất lượng, context-rot): **Tiered Memory Policy v1** (adopt AI_INFRA bulletin 2026-05-29 — thay ngưỡng cứng ">25KB archive" bằng tiered + just-in-time; size to ≠ chất lượng, context-rot):
- **L1 HOT** = `MEMORY.md` soft-cap **~30KB** (role + patterns + anti-patterns + 5-8 entry gần nhất) → auto-inject mỗi spawn - **L1 HOT** = `MEMORY.md` soft-cap **~30KB** (role + patterns + anti-patterns + 5-8 entry gần nhất) → auto-inject mỗi spawn

View File

@ -2,7 +2,7 @@
name: cicd-monitor name: cicd-monitor
description: | description: |
CI/CD pipeline + post-deploy verification specialist for SOLUTION_ERP. Use proactively AFTER every push to main that triggers Gitea Actions deploy (code commits — skip docs-only per path-filter gotcha #41). Polls Gitea Actions run status via API, verifies test gate pass (Domain 58 + Infra 23 tests baseline), confirms deploy actually shipped (FE bundle hash change × 2 app + EF migrations applied prod), smoke tests prod endpoints (api/admin/eoffice.solutions.com.vn). NEVER writes code — produces PASS/FAIL verdict with concrete evidence from logs + curl + sqlcmd. Catches deploy fail tự động không phụ thuộc em main nhớ verify. CI/CD pipeline + post-deploy verification specialist for SOLUTION_ERP. Use proactively AFTER every push to main that triggers Gitea Actions deploy (code commits — skip docs-only per path-filter gotcha #41). Polls Gitea Actions run status via API, verifies test gate pass (Domain 58 + Infra 23 tests baseline), confirms deploy actually shipped (FE bundle hash change × 2 app + EF migrations applied prod), smoke tests prod endpoints (api/admin/eoffice.solutions.com.vn). NEVER writes code — produces PASS/FAIL verdict with concrete evidence from logs + curl + sqlcmd. Catches deploy fail tự động không phụ thuộc em main nhớ verify.
model: inherit model: claude-opus-4-8
tools: [Read, Grep, Glob, Bash, WebFetch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Grep, Glob, Bash, WebFetch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
skills: skills:
- iis-deploy-runbook - iis-deploy-runbook

View File

@ -2,7 +2,7 @@
name: frontend-designer name: frontend-designer
description: | description: |
Frontend DESIGN specialist cho 2 app SOLUTION_ERP (fe-admin :8082 + fe-user :8080 — React 19 + Vite 8 + TS 6 + shadcn/ui + Tailwind + TanStack Query). Sinh/redesign UI ĐẸP THẬT qua design-system-first + visual-verification loop (Playwright screenshot ≥2 viewport → rubric → fix → lặp) + anti-generic-aesthetic. Production-grade FE code + a11y WCAG-AA. Dùng khi build/redesign page/dashboard/component, "làm cho đẹp", thiết kế UX mới. Design-by-code KHÔNG Figma. KHÔNG đụng BE/DB/business-logic (đó là implementer-backend) · KHÔNG cookie-cutter mechanical mirror theo spec đã chốt (đó là implementer-frontend) — phân biệt bằng output contract: cần ĐẸP/UX → tôi; cần scaffold-theo-spec → implementer-frontend. Frontend DESIGN specialist cho 2 app SOLUTION_ERP (fe-admin :8082 + fe-user :8080 — React 19 + Vite 8 + TS 6 + shadcn/ui + Tailwind + TanStack Query). Sinh/redesign UI ĐẸP THẬT qua design-system-first + visual-verification loop (Playwright screenshot ≥2 viewport → rubric → fix → lặp) + anti-generic-aesthetic. Production-grade FE code + a11y WCAG-AA. Dùng khi build/redesign page/dashboard/component, "làm cho đẹp", thiết kế UX mới. Design-by-code KHÔNG Figma. KHÔNG đụng BE/DB/business-logic (đó là implementer-backend) · KHÔNG cookie-cutter mechanical mirror theo spec đã chốt (đó là implementer-frontend) — phân biệt bằng output contract: cần ĐẸP/UX → tôi; cần scaffold-theo-spec → implementer-frontend.
model: inherit model: claude-opus-4-8
effort: max effort: max
tools: [Read, Write, Edit, Bash, Grep, Glob, Skill, WebFetch, WebSearch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Write, Edit, Bash, Grep, Glob, Skill, WebFetch, WebSearch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
memory: project memory: project

View File

@ -2,7 +2,7 @@
name: implementer-backend name: implementer-backend
description: | description: |
WRITE specialist cho toàn bộ .NET backend SOLUTION_ERP (Domain + Application + Infrastructure + Api layer). Scaffold entity + enum + EF Configuration + Migration 3-file + DbInitializer seed + CQRS Command/Query/Validator/Handler + MediatR + Controller + DTO. Case 1+2+3+5 only (cookie-cutter mechanical scaffold, multi-file independent orchestrator-workers, isolated method test-gen handler, mass migration). DO NOT touch FE 2 app (đó là implementer-frontend). DO NOT write test assertions (đó là test-specialist). DO NOT schema design / UX decision / cross-stack bug fix reasoning (em main solo). Auto-refuses out-of-scope. WRITE specialist cho toàn bộ .NET backend SOLUTION_ERP (Domain + Application + Infrastructure + Api layer). Scaffold entity + enum + EF Configuration + Migration 3-file + DbInitializer seed + CQRS Command/Query/Validator/Handler + MediatR + Controller + DTO. Case 1+2+3+5 only (cookie-cutter mechanical scaffold, multi-file independent orchestrator-workers, isolated method test-gen handler, mass migration). DO NOT touch FE 2 app (đó là implementer-frontend). DO NOT write test assertions (đó là test-specialist). DO NOT schema design / UX decision / cross-stack bug fix reasoning (em main solo). Auto-refuses out-of-scope.
model: inherit model: claude-opus-4-8
tools: [Read, Edit, Write, Bash, Skill, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Edit, Write, Bash, Skill, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
skills: skills:
- ef-core-migration - ef-core-migration

View File

@ -2,7 +2,7 @@
name: implementer-frontend name: implementer-frontend
description: | description: |
WRITE specialist cho FE 2 app SOLUTION_ERP (fe-admin + fe-user React 19 + Vite 8 + TS 6 + shadcn/ui + TanStack Query). Cookie-cutter mirror page/types/component cross-app SHA256 IDENTICAL + Pattern 16-bis 4-place mirror (page + App.tsx route + menuKeys.ts + Layout.tsx staticMap) + declarative KIND_CONFIG Record + npm build × 2 verify. Case 1+2 only (cookie-cutter mirror cross-app, multi-file independent). DO NOT touch .NET backend (đó là implementer-backend). DO NOT schema/UX flow decision (em main solo). Auto-refuses out-of-scope. WRITE specialist cho FE 2 app SOLUTION_ERP (fe-admin + fe-user React 19 + Vite 8 + TS 6 + shadcn/ui + TanStack Query). Cookie-cutter mirror page/types/component cross-app SHA256 IDENTICAL + Pattern 16-bis 4-place mirror (page + App.tsx route + menuKeys.ts + Layout.tsx staticMap) + declarative KIND_CONFIG Record + npm build × 2 verify. Case 1+2 only (cookie-cutter mirror cross-app, multi-file independent). DO NOT touch .NET backend (đó là implementer-backend). DO NOT schema/UX flow decision (em main solo). Auto-refuses out-of-scope.
model: inherit model: claude-opus-4-8
tools: [Read, Edit, Write, Bash, Skill, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Edit, Write, Bash, Skill, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
skills: skills:
- permission-matrix - permission-matrix

View File

@ -2,7 +2,7 @@
name: investigator-api name: investigator-api
description: | description: |
Read-only EXTERNAL research specialist for SOLUTION_ERP. WebFetch/WebSearch official docs (Anthropic engineering, .NET 10 / EF Core 10 / ASP.NET, React 19 / Vite 8 / TanStack Query, shadcn/ui), NuGet + npm CVE/dependency eval, FE library evaluation (license + bundle size impact — vd FullCalendar v6 MIT verify), reference project pattern audit (NamGroup / DH_Y_DUOC / BVAAU cross-project), community sentiment research. EXTERNAL-focused — KHÔNG audit internal codebase or SQL schema (đó là investigator-codebase). NEVER writes code — only returns concise structured findings with source URLs. Read-only EXTERNAL research specialist for SOLUTION_ERP. WebFetch/WebSearch official docs (Anthropic engineering, .NET 10 / EF Core 10 / ASP.NET, React 19 / Vite 8 / TanStack Query, shadcn/ui), NuGet + npm CVE/dependency eval, FE library evaluation (license + bundle size impact — vd FullCalendar v6 MIT verify), reference project pattern audit (NamGroup / DH_Y_DUOC / BVAAU cross-project), community sentiment research. EXTERNAL-focused — KHÔNG audit internal codebase or SQL schema (đó là investigator-codebase). NEVER writes code — only returns concise structured findings with source URLs.
model: inherit model: claude-opus-4-8
tools: [Read, Bash, WebFetch, WebSearch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Bash, WebFetch, WebSearch, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
skills: skills:
- dependency-audit-erp - dependency-audit-erp

View File

@ -2,7 +2,7 @@
name: test-specialist name: test-specialist
description: | description: |
WRITE specialist DEDICATED test layer SOLUTION_ERP (tests/SolutionErp.Domain.Tests + Infrastructure.Tests). xUnit + FluentAssertions 7.2 + EF SQLite TestApplicationDbContext (nvarchar(max)→TEXT override) + IdentityFixture. Domain policy state machine test + Infra code generator + CQRS handler test + reflection-based Authorize policy regression + UNIQUE/Conflict/soft-delete invariant. Test-before BẮT BUỘC cho bug fix + critical algo (codegen/guard/financial/security). DO NOT touch production code (Domain/App/Infra/Api/FE — đó là 2 implementer). Auto-refuses out-of-scope. WRITE specialist DEDICATED test layer SOLUTION_ERP (tests/SolutionErp.Domain.Tests + Infrastructure.Tests). xUnit + FluentAssertions 7.2 + EF SQLite TestApplicationDbContext (nvarchar(max)→TEXT override) + IdentityFixture. Domain policy state machine test + Infra code generator + CQRS handler test + reflection-based Authorize policy regression + UNIQUE/Conflict/soft-delete invariant. Test-before BẮT BUỘC cho bug fix + critical algo (codegen/guard/financial/security). DO NOT touch production code (Domain/App/Infra/Api/FE — đó là 2 implementer). Auto-refuses out-of-scope.
model: inherit model: claude-opus-4-8
tools: [Read, Edit, Write, Bash, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Edit, Write, Bash, Grep, Glob, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
skills: skills:
- contract-workflow - contract-workflow

View File

@ -2,7 +2,7 @@
name: tooling-auditor name: tooling-auditor
description: | description: |
Read-only INFORM-only TOOLING-FRESHNESS auditor cho SOLUTION_ERP (H1 — adopt AI_INFRA Harness 1, anh giao 2026-06-07; TÁCH BIỆT khỏi harvest-curator H2 vì 2 việc hay quên+nhầm khi gộp). Audit 4-MẶT mỗi session có cập-nhật ĐẦY-ĐỦ + KỊP-THỜI không: (1) skill (.claude/skills/ 6 project + ~/.claude/skills standalone — mới/đổi/stale/đã-map-vai chưa) · (2) vai-trò sub-agent (.claude/agents/ roster khớp README/CLAUDE.md/STATUS · thừa/idle/scope-drift) · (3) plugin (~/.claude/settings.json enabledPlugins user-global · installed/enabled/assigned/used) · (4) docs (CLAUDE.md·docs/STATUS·agents/README·governance phản-ánh trạng-thái THẬT · drift doc-vs-reality). Lifecycle: @session-start BÁO state + diff-vs-last (THÊM/ĐỔI/XÓA/stale); @session-end CHỐT freshness + AUDIT skill/plugin MỚI phân-bổ (new-alloc) cho em main + sub. Propose-only — em main single-writer (VERIFY→APPEND B3). KHÔNG harvest-memory (đó là harvest-curator). KHÔNG corpus/RAG/deploy (đó là cicd-monitor). KHÔNG store_memory. PHẢI dùng khi audit tooling/docs-freshness + skill/plugin-state + roster-drift đầu/cuối session. Read-only INFORM-only TOOLING-FRESHNESS auditor cho SOLUTION_ERP (H1 — adopt AI_INFRA Harness 1, anh giao 2026-06-07; TÁCH BIỆT khỏi harvest-curator H2 vì 2 việc hay quên+nhầm khi gộp). Audit 4-MẶT mỗi session có cập-nhật ĐẦY-ĐỦ + KỊP-THỜI không: (1) skill (.claude/skills/ 6 project + ~/.claude/skills standalone — mới/đổi/stale/đã-map-vai chưa) · (2) vai-trò sub-agent (.claude/agents/ roster khớp README/CLAUDE.md/STATUS · thừa/idle/scope-drift) · (3) plugin (~/.claude/settings.json enabledPlugins user-global · installed/enabled/assigned/used) · (4) docs (CLAUDE.md·docs/STATUS·agents/README·governance phản-ánh trạng-thái THẬT · drift doc-vs-reality). Lifecycle: @session-start BÁO state + diff-vs-last (THÊM/ĐỔI/XÓA/stale); @session-end CHỐT freshness + AUDIT skill/plugin MỚI phân-bổ (new-alloc) cho em main + sub. Propose-only — em main single-writer (VERIFY→APPEND B3). KHÔNG harvest-memory (đó là harvest-curator). KHÔNG corpus/RAG/deploy (đó là cicd-monitor). KHÔNG store_memory. PHẢI dùng khi audit tooling/docs-freshness + skill/plugin-state + roster-drift đầu/cuối session.
model: inherit model: claude-opus-4-8
tools: [Read, Grep, Glob, Bash, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects] tools: [Read, Grep, Glob, Bash, mcp__rag-unified__search_memory, mcp__rag-unified__search_code, mcp__rag-unified__cross_project_search, mcp__rag-unified__list_projects]
memory: project memory: project
maxTurns: 18 maxTurns: 18

View File

@ -1,5 +1,5 @@
--- ---
description: Bootstrap session SOLUTION_ERP — load context, audit state (10-agent + RAG + tests + monitor RE-REPORT), report plan. Run đầu mỗi session. description: Bootstrap session SOLUTION_ERP — load context, audit state (11-agent + RAG + tests + monitor RE-REPORT), report plan. Run đầu mỗi session.
--- ---
# /session-start — Session bootstrap (READ + AUDIT + REPORT) # /session-start — Session bootstrap (READ + AUDIT + REPORT)
@ -34,19 +34,21 @@ Em main đọc `.claude/hmw-mode.on` → **BÁO ngay đầu response** (anh kh
4. **`docs/PROJECT-MAP.md`** — bản đồ tổng quan module 4. **`docs/PROJECT-MAP.md`** — bản đồ tổng quan module
5. **`docs/changelog/migration-todos.md`** — atomic tasks theo phase (Phase 11 polish hiện tại) 5. **`docs/changelog/migration-todos.md`** — atomic tasks theo phase (Phase 11 polish hiện tại)
6. **`docs/workflow-contract.md`** — state machine 9 phase HĐ (base pattern cho PE/Proposal workflow V2) 6. **`docs/workflow-contract.md`** — state machine 9 phase HĐ (base pattern cho PE/Proposal workflow V2)
7. **`.claude/agents/README.md`** — 10-agent decision tree + skill matrix + split boundary 7. **`.claude/agents/README.md`** — 11-agent decision tree + skill matrix + split boundary
8. **`.claude/agent-memory/{spawned-agent}/MEMORY.md`** — L1 HOT auto-inject (Tiered Memory v1 ~30KB) + L2 `archive/` Read-on-demand + L3 RAG `search_memory` just-in-time 8. **`.claude/agent-memory/{spawned-agent}/MEMORY.md`** — L1 HOT auto-inject (Tiered Memory v1 ~30KB) + L2 `archive/` Read-on-demand + L3 RAG `search_memory` just-in-time
9. **User auto-memory `MEMORY.md`** — auto-loaded bởi harness (index feedback_* entries) 9. **User auto-memory `MEMORY.md`** — auto-loaded bởi harness (index feedback_* entries)
10. **Liên quan task hiện tại:** `docs/rules.md`, `docs/architecture.md`, `docs/gotchas.md` (55), `docs/database/schema-diagram.md`, `docs/flows/` 10. **Liên quan task hiện tại:** `docs/rules.md`, `docs/architecture.md`, `docs/gotchas.md` (58), `docs/database/schema-diagram.md`, `docs/flows/`
## Phase 2 — AUDIT (state check) ## Phase 2 — AUDIT (state check)
### 2.1 Sub-agent state (10-agent topology — 8 product/quality + 2 monitor INFORM-only) ### 2.1 Sub-agent state (11-agent topology — 9 product/quality + 2 monitor INFORM-only)
- Check 10 sub-agent đã spawn chưa: - Check 11 sub-agent đã spawn chưa:
- 🟦 **investigator-codebase** — internal SQL/EF/grep/reference mirror audit - 🟦 **investigator-codebase** — internal SQL/EF/grep/reference mirror audit
- 🟦 **investigator-api** — external docs/CVE/lib/cross-project reference - 🟦 **investigator-api** — external docs/CVE/lib/cross-project reference
- 🟨 **implementer-backend** — .NET Domain+App+Infra+Api scaffold - 🟨 **implementer-backend** — .NET Domain+App+Infra+Api scaffold
- 🟧 **implementer-frontend** — FE 2 app cookie-cutter SHA256 mirror - 🟧 **implementer-frontend** — FE 2 app cookie-cutter SHA256 mirror
- 🩷 **frontend-designer** — FE design/redesign visual-verification loop (FD1FD10)
- 🔵 **database-agent** — read-advisory DB lens (DB1DB11: schema/migration-review/perf/concurrency)
- 🟪 **test-specialist** — tests/ xUnit dedicated - 🟪 **test-specialist** — tests/ xUnit dedicated
- 🟥 **reviewer** — adversarial pre-commit + live curl prod - 🟥 **reviewer** — adversarial pre-commit + live curl prod
- 🟩 **cicd-monitor** — post-deploy Gitea + bundle hash + smoke - 🟩 **cicd-monitor** — post-deploy Gitea + bundle hash + smoke
@ -113,7 +115,7 @@ Plan cha: [tên]
``` ```
### SOLUTION_ERP report ### SOLUTION_ERP report
- Trạng thái spawn 7 sub-agent (idle/working) + agentId reuse-able trong session - Trạng thái spawn 11 sub-agent (idle/working) + agentId reuse-able trong session
- Plan progress: ✅ Phase 10 COMPLETE 11/11 · ⬜ Phase 11 polish (wire ApproveV2 skeleton) · 🚫 Phase 9 Ops (anh main coordinate) - Plan progress: ✅ Phase 10 COMPLETE 11/11 · ⬜ Phase 11 polish (wire ApproveV2 skeleton) · 🚫 Phase 9 Ops (anh main coordinate)
- Critical signal: state counts (mig/table/endpoint/page/menu/test/gotcha) + bundle hash prod + RAG health - Critical signal: state counts (mig/table/endpoint/page/menu/test/gotcha) + bundle hash prod + RAG health
- (SE KHÔNG copy phần "6 sister report" của AI_INFRA — đó là vai trò host) - (SE KHÔNG copy phần "6 sister report" của AI_INFRA — đó là vai trò host)

View File

@ -20,8 +20,8 @@ argument-hint: (trống = bật mode · hoặc kèm task lớn đầu tiên)
- **HMW (LỚN):** fan-out nhiều file/nguồn — sweep · audit · cross-stack review · mass migration · multi-source research. Số task THOẢI MÁI (harness queue theo slot, KHÔNG cap cứng) · spawn **ĐÚNG VAI** (`agentType` ∈ VALID_ROLES; role lạ → default subagent + cảnh báo). - **HMW (LỚN):** fan-out nhiều file/nguồn — sweep · audit · cross-stack review · mass migration · multi-source research. Số task THOẢI MÁI (harness queue theo slot, KHÔNG cap cứng) · spawn **ĐÚNG VAI** (`agentType` ∈ VALID_ROLES; role lạ → default subagent + cảnh báo).
- **Thường (nhỏ):** <30min · 12 file · hỏi-đáp Agent-tool spawn lẻ / solo theo `.claude/agents/README.md` decision-tree, KHÔNG HMW. - **Thường (nhỏ):** <30min · 12 file · hỏi-đáp Agent-tool spawn lẻ / solo theo `.claude/agents/README.md` decision-tree, KHÔNG HMW.
## VALID_ROLES (roster SOLUTION_ERP — 8 sub) ## VALID_ROLES (roster SOLUTION_ERP — 9 sub)
`investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer` `investigator-codebase` · `investigator-api` · `implementer-backend` · `implementer-frontend` · `test-specialist` · `reviewer` · `cicd-monitor` · `frontend-designer` · `database-agent`
> Role lạ ∉ list → `hmw.js` degrade về default subagent + WARN (fail-soft, KHÔNG crash). Windows MAX_PATH (Dropbox nested) → KHÔNG `isolation:worktree`. > Role lạ ∉ list → `hmw.js` degrade về default subagent + WARN (fail-soft, KHÔNG crash). Windows MAX_PATH (Dropbox nested) → KHÔNG `isolation:worktree`.
## Quy trình HMW — vai trò từng phase ## Quy trình HMW — vai trò từng phase
@ -30,7 +30,7 @@ argument-hint: (trống = bật mode · hoặc kèm task lớn đầu tiên)
| **P0** prep | 👤 em main | đọc MEMORY sub liên quan **memory-pack SLICE/vai** (KHÔNG full) + `taskList` + chụp **chunk-count Qdrant baseline** + git status sạch | | **P0** prep | 👤 em main | đọc MEMORY sub liên quan **memory-pack SLICE/vai** (KHÔNG full) + `taskList` + chụp **chunk-count Qdrant baseline** + git status sạch |
| **P1** decide | sub liên quan (full memory) | recommend approach + **acceptance-checklist** em main chốt plan | | **P1** decide | sub liên quan (full memory) | recommend approach + **acceptance-checklist** em main chốt plan |
| **checkpoint** (inform) | 👤 em main | BÁO `{số agent · vai · task}` @inform set `args.checkpointApproved=true` fan-out NGAY (marker-ON=consent; anh interrupt nếu sai KHÔNG chờ confirm từng lần) | | **checkpoint** (inform) | 👤 em main | BÁO `{số agent · vai · task}` @inform set `args.checkpointApproved=true` fan-out NGAY (marker-ON=consent; anh interrupt nếu sai KHÔNG chờ confirm từng lần) |
| **P2** execute | Workflow `hmw` | fan-out agent: **memory-pack injected** qua `args` + `agentType` + schema. DEFAULT read/analyze; write = file-disjoint. inherit Opus | | **P2** execute | Workflow `hmw` | fan-out agent: **memory-pack injected** qua `args` + `agentType` + schema. DEFAULT read/analyze; write = file-disjoint. Two-tier H4.5: promote inherit Fable 5 · demoted pin Opus 4.8 · per-task `tier` override |
| **P3** harvest | 👤 em main (single-writer) | **NGAY sau P2** VERIFY delta + APPEND-only vào MEMORY.md **mọi agent tham gia** (B3) | | **P3** harvest | 👤 em main (single-writer) | **NGAY sau P2** VERIFY delta + APPEND-only vào MEMORY.md **mọi agent tham gia** (B3) |
| **P4** final | sub quality (full memory) | reviewer PASS/FAIL · cicd-monitor drift · investigator verify · implementer/test scope return delta | | **P4** final | sub quality (full memory) | reviewer PASS/FAIL · cicd-monitor drift · investigator verify · implementer/test scope return delta |
| **→** | 👤 em main | synthesize + **git-diff** + **chunk-count check** + commit (anh OK) | | **→** | 👤 em main | synthesize + **git-diff** + **chunk-count check** + commit (anh OK) |

View File

@ -87,5 +87,5 @@ when-to-use:
## Related ## Related
- `docs/CLAUDE.md` — quick rules + full stack context - `docs/CLAUDE.md` — quick rules + full stack context
- `docs/gotchas.md` — 57 bẫy đã gặp (latest #57 soft-delete UNIQUE phải filter `[IsDeleted]=0`, S45) - `docs/gotchas.md` — 58 bẫy đã gặp (latest #58 EF read-modify-write lost-update → `ExecuteUpdateAsync` atomic, S56)
- `docs/changelog/migration-todos.md` — roadmap 5 phase + Tier 3 - `docs/changelog/migration-todos.md` — roadmap 5 phase + Tier 3

View File

@ -150,6 +150,6 @@ Lưu vào `docs/changelog/deps-audit-{YYYY-MM-DD}.md` nếu có action.
## Related ## Related
- `docs/gotchas.md` — 57 bẫy package compat / CI / IIS / Identity / per-NV refactor / SQLite tie-break đã gặp - `docs/gotchas.md` — 58 bẫy package compat / CI / IIS / Identity / per-NV refactor / SQLite tie-break đã gặp
- `docs/changelog/migration-todos.md` Phase 5.1 — checklist deps scan CI - `docs/changelog/migration-todos.md` Phase 5.1 — checklist deps scan CI
- `SolutionErp.slnx` + `global.json` — .NET version pin - `SolutionErp.slnx` + `global.json` — .NET version pin

View File

@ -69,7 +69,7 @@ when-to-use:
| **47** | **`FilterMasterCatalogUniqueIndexesByIsDeleted`** | **🎯 S53 — Department + Supplier + Project Code UNIQUE filtered `WHERE [IsDeleted]=0` (gotcha #57 EXT Master, 6× cumulative). Index-only.** | | **47** | **`FilterMasterCatalogUniqueIndexesByIsDeleted`** | **🎯 S53 — Department + Supplier + Project Code UNIQUE filtered `WHERE [IsDeleted]=0` (gotcha #57 EXT Master, 6× cumulative). Index-only.** |
| **48** | **`AddProjectMasterFields`** | **🎯 S55 — Project +4 cột nullable (Year int · Investor 250 · Location 500 · Package 300). AddColumn-only, no new table. Kèm `SeedRealMasterDataAsync` ungated nạp 62 dự án + 71 hạng mục + 3 NCC real từ Excel.** | | **48** | **`AddProjectMasterFields`** | **🎯 S55 — Project +4 cột nullable (Year int · Investor 250 · Location 500 · Package 300). AddColumn-only, no new table. Kèm `SeedRealMasterDataAsync` ungated nạp 62 dự án + 71 hạng mục + 3 NCC real từ Excel.** |
Total: **92 bảng** dbo + `__EFMigrationsHistory` (last Mig 48 AddProjectMasterFields, column-only). Xem `docs/database/schema-diagram.md` migration table + §11-15 module ERD (§16+ Mig 27-48 chi tiết pending). Total: **93 bảng** dbo + `__EFMigrationsHistory` (re-ground S56 `sys.tables`last Mig 48 AddProjectMasterFields, column-only). Xem `docs/database/schema-diagram.md` migration table + §11-15 module ERD (§16+ Mig 27-48 chi tiết pending).
## N-stage workflow pattern (Mig 18-20 — Session 12-13) ## N-stage workflow pattern (Mig 18-20 — Session 12-13)
@ -277,7 +277,7 @@ sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P <pw> -i migrate.sql
## Code pointers ## Code pointers
- `src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs` — DbSet cho 91 bảng (42 migration) - `src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs` — DbSet cho 93 bảng (48 migration)
- `src/Backend/SolutionErp.Infrastructure/Persistence/DesignTimeDbContextFactory.cs` — EF tooling factory - `src/Backend/SolutionErp.Infrastructure/Persistence/DesignTimeDbContextFactory.cs` — EF tooling factory
- `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` — seed + warn + migrate runtime + backfill (idempotent reconcile pattern) - `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` — seed + warn + migrate runtime + backfill (idempotent reconcile pattern)
- `src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/` — IEntityTypeConfiguration<T> per entity - `src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/` — IEntityTypeConfiguration<T> per entity
@ -286,5 +286,5 @@ sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P <pw> -i migrate.sql
## Related ## Related
- `docs/database/database-guide.md` — conventions + migration workflow chi tiết - `docs/database/database-guide.md` — conventions + migration workflow chi tiết
- `docs/database/schema-diagram.md`**ERD 91 bảng** + §11 PE + §12 Budget + §13 PEDeptOpinions (Mig 15) + §14 ApprovalWorkflow V2 (Mig 22-25) + §15 PE Level Opinions V2 (Mig 26); §16+ Mig 27-42 detail pending (xem migration table) - `docs/database/schema-diagram.md`**ERD 93 bảng** + §11 PE + §12 Budget + §13 PEDeptOpinions (Mig 15) + §14 ApprovalWorkflow V2 (Mig 22-25) + §15 PE Level Opinions V2 (Mig 26); §16+ Mig 27-48 detail pending (xem migration table)
- `docs/gotchas.md` #7, #17, #38 — migration pitfalls + Identity 4-field rename - `docs/gotchas.md` #7, #17, #38 — migration pitfalls + Identity 4-field rename

View File

@ -6,7 +6,7 @@
export const meta = { export const meta = {
name: 'hmw', name: 'hmw',
description: 'HMW P2 execute (SOLUTION_ERP) — fan-out 8-agent roster có MEMORY-PACK slice (qua args vì script không đọc file) + return findings + checklistEvidence + memoryDelta (spawn-record 4-field). 2 MODE (Harness 2, 06-07): (A) DEFAULT return-delta-only — fan-out nhẹ, sub KHÔNG ghi file, git-diff verify. (B) WAVE-MODE (args.wave) — workflow DÀI, em main scaffold .claude/workflows/wave-<tên>/ @P1, sub ghi full-detail vào CHỈ sub-MD mình (B4/B6), H2 harvest-curator gom wave→agent-memory @session-end (B5). taskList thoải mái (queue theo slot, không cap cứng). memoryDelta KHÔNG tự ghi — em main VERIFY + APPEND-only @P3 (no-overwrite-unverified, B3). Same-model inherit Opus. Scope = repo SOLUTION_ERP ONLY (S1 — KHÔNG fan-out repo/corpus khác).', description: 'HMW P2 execute (SOLUTION_ERP) — fan-out 9-agent roster có MEMORY-PACK slice (qua args vì script không đọc file) + return findings + checklistEvidence + memoryDelta (spawn-record 4-field). 2 MODE (Harness 2, 06-07): (A) DEFAULT return-delta-only — fan-out nhẹ, sub KHÔNG ghi file, git-diff verify. (B) WAVE-MODE (args.wave) — workflow DÀI, em main scaffold .claude/workflows/wave-<tên>/ @P1, sub ghi full-detail vào CHỈ sub-MD mình (B4/B6), H2 harvest-curator gom wave→agent-memory @session-end (B5). taskList thoải mái (queue theo slot, không cap cứng). memoryDelta KHÔNG tự ghi — em main VERIFY + APPEND-only @P3 (no-overwrite-unverified, B3). Two-tier model H4.5 (Harness-4 2026-06-10): promote-roles inherit Fable 5 · demoted-roles pin Opus 4.8 (frontmatter) · role-less \'opus\' · per-task tier:\'fable\'|\'opus\' override. Scope = repo SOLUTION_ERP ONLY (S1 — KHÔNG fan-out repo/corpus khác).',
phases: [{ title: 'Execute', detail: 'fan-out memory-pack-injected agents, structured return' }], phases: [{ title: 'Execute', detail: 'fan-out memory-pack-injected agents, structured return' }],
} }
@ -15,7 +15,7 @@ export const meta = {
// memoryPack: { 'investigator-codebase':'<slice>', 'implementer-backend':'...', reviewer:'...', ... }, // SLICE liên quan, KHÔNG full // memoryPack: { 'investigator-codebase':'<slice>', 'implementer-backend':'...', reviewer:'...', ... }, // SLICE liên quan, KHÔNG full
// spec: '<acceptance-criteria / context chung>', // spec: '<acceptance-criteria / context chung>',
// checkpointApproved: true, // em main set SAU khi BÁO {số agent·vai·task} @inform (S2) // checkpointApproved: true, // em main set SAU khi BÁO {số agent·vai·task} @inform (S2)
// taskList: [ { role:<VALID_ROLES|null>, label:'..', prompt:'..' }, ... ] // taskList: [ { role:<VALID_ROLES|null>, label:'..', prompt:'..', tier:'fable'|'opus'? }, ... ] // tier = per-task model override (H4.5)
// wave: { name:'<tên-wave>', dir:'.claude/workflows/wave-<tên>' } // OPTIONAL — bật WAVE-MODE (B). Folder + wave.md em main ĐÃ scaffold @P1 (script no-fs). // wave: { name:'<tên-wave>', dir:'.claude/workflows/wave-<tên>' } // OPTIONAL — bật WAVE-MODE (B). Folder + wave.md em main ĐÃ scaffold @P1 (script no-fs).
// } // }
@ -23,8 +23,26 @@ const VALID_ROLES = [
'investigator-codebase', 'investigator-api', 'investigator-codebase', 'investigator-api',
'implementer-backend', 'implementer-frontend', 'implementer-backend', 'implementer-frontend',
'test-specialist', 'reviewer', 'cicd-monitor', 'frontend-designer', 'test-specialist', 'reviewer', 'cicd-monitor', 'frontend-designer',
'database-agent', // +S57 — S56 dùng 3× qua fail-soft WARN; read-advisory DB lens (DB1-DB11)
] ]
// ─── H4.5 two-tier model (Harness-4 adopt 2026-06-10) ───────────────────────
// Promote-list (gate/verdict-class — frontmatter `model: inherit` = ăn Fable 5 1M từ lead):
// investigator-codebase (H4.3b) · reviewer (H4.3a) · database-agent (H4.3b).
// [harvest-curator (H4.3c) cũng promote nhưng là monitor — không fan-out qua hmw.]
// Demoted roles còn lại: frontmatter ĐÃ pin `claude-opus-4-8` → hmw KHÔNG set model (frontmatter tự lo).
// Role-less = sweep-class CÓ CHỦ ĐÍCH (taskList do lead author từng run = đã phân loại lúc author) → 'opus'.
// Per-task override: tier:'fable' (việc hệ-trọng giao role demoted) / tier:'opus' (force rẻ).
function resolveModel(role, rawRole, tier, i) {
if (tier === 'fable' || tier === 'opus') return tier
if (tier) log(`⚠️ hmw: tier "${tier}" lạ (task #${i}) → bỏ qua, dùng tier-map mặc định H4.5`)
// Invalid-role (typo ∉ VALID_ROLES, WARN đã log ở caller) → fail-UP inherit Fable 5 — H4.5 "chưa-phân-loại
// → nghiêng quality" (KHÔNG rơi 'opus': task có thể là gate-class gõ nhầm tên role).
if (!role && rawRole) return undefined
if (!role) { log(`hmw: task #${i} role-less → model 'opus' (sweep-class H4.5; khai tier:'fable' nếu hệ-trọng)`); return 'opus' }
return undefined // role có frontmatter: promote=inherit Fable 5 · demoted=pin Opus 4.8 — KHÔNG override
}
const SCHEMA = { const SCHEMA = {
type: 'object', type: 'object',
required: ['findings', 'memoryDelta'], required: ['findings', 'memoryDelta'],
@ -73,7 +91,7 @@ const wave = (A.wave && A.wave.dir) ? A.wave : null
if (wave) log(`hmw: WAVE-MODE on → dir=${wave.dir} (sub ghi sub-MD isolated; em main scaffold @P1; H2 harvest-curator gom @session-end B5).`) if (wave) log(`hmw: WAVE-MODE on → dir=${wave.dir} (sub ghi sub-MD isolated; em main scaffold @P1; H2 harvest-curator gom @session-end B5).`)
phase('Execute') phase('Execute')
log(`HMW P2: fan-out ${A.taskList.length} task (${wave ? 'WAVE-MODE' : 'return-delta-only'}, same-model inherit, memory-pack-injected, scope=SOLUTION_ERP repo only)`) log(`HMW P2: fan-out ${A.taskList.length} task (${wave ? 'WAVE-MODE' : 'return-delta-only'}, two-tier H4.5 promote-inherit/demoted-opus, memory-pack-injected, scope=SOLUTION_ERP repo only)`)
const results = await parallel(A.taskList.map((t, i) => () => { const results = await parallel(A.taskList.map((t, i) => () => {
const raw = t && t.role const raw = t && t.role
@ -119,6 +137,7 @@ const results = await parallel(A.taskList.map((t, i) => () => {
agentType: role || undefined, agentType: role || undefined,
schema: SCHEMA, schema: SCHEMA,
label: (t && t.label) || `hmw:${role || 'task'}-${i}`, label: (t && t.label) || `hmw:${role || 'task'}-${i}`,
model: resolveModel(role, raw, t && t.tier, i), // H4.5 two-tier (undefined = theo frontmatter/inherit)
}) })
})) }))

View File

@ -18,3 +18,5 @@
| sent (ISO) | id | from → to | folder | sha256(12) | | sent (ISO) | id | from → to | folder | sha256(12) |
|---|---|---|---|---| |---|---|---|---|---|
| 2026-06-07 | 2026-06-07-se-to-ai_infra-harness-123-handshake | se → ai_infra | outbox/ai_infra | c9656c198500 | | 2026-06-07 | 2026-06-07-se-to-ai_infra-harness-123-handshake | se → ai_infra | outbox/ai_infra | c9656c198500 |
| 2026-06-10 | 2026-06-10-se-to-ai_infra-harness-4-adopt-report | se → ai_infra | outbox/ai_infra | 181ee03ff060 |
| 2026-06-11 | 2026-06-11-se-to-ai_infra-harness-4-runtime-verified | se → ai_infra | outbox/ai_infra | ecf1d58797af |

View File

@ -0,0 +1,50 @@
---
id: 2026-06-10-se-to-ai_infra-harness-4-adopt-report
from: se
to: ai_infra
category: Governance
type: report
date: 2026-06-10
content_sha256: 181ee03ff0603c1590db3aa9452d8e9da7338d1e913f08d7db22140c41eb114a
nac: sent
---
# [se → ai_infra] HARNESS-4 adopt report — two-tier model SOLUTION_ERP (H4.7 email-back)
> SE adopt CẢ 2 broadcast 06-10 (`model-fable-5-max` + `harness-4-model-tier-promotion`) cùng đợt, S57-resume. adap-report 5-field: `docs/governance/adap-reports/2026-06-10-Governance-{model-fable-5-max,harness-4-model-tier-promotion}.md`. Dưới đây 5 mục H4.7.
## ① PROMOTION-LIST (4/11 — giữ `model: inherit` = Fable 5 1M)
| Vị trí | Tiêu chí | Justification (1 dòng) | Evidence nội bộ |
|---|---|---|---|
| reviewer | (a) gate≥writer | adversarial pre-commit cuối đứng sau lead — gate yếu hơn writer thì writer qua mặt vô tình | S51 bắt 1 MAJOR pre-commit (Driver FE↔BE required-field mismatch) · S54 chain-verify role-string "Admin" thật (disarm decoy "QTV") · S49 gate 3 adap-report 0-blocker |
| investigator-codebase | (b) verdict-nuôi-quyết-định | verdict recon/audit mà lead + anh quyết theo, sai 1 verdict lan cả chuỗi | S56 pre-golive bắt dept-IT 0-active-user prod (helpdesk inert — test xanh không thấy) · S57 flag "master-write-open" → thành fix authz thật ×3 controller |
| database-agent | (b) verdict-class DB-lens | read-advisory verdict schema/migration/concurrency nuôi quyết định migration-design | S53 first-spawn bắt Mig 46 committed-but-unapplied-local (203 SQLite-test + CI-prod đều MISS) · S56 review MAJOR → Serializable bump (gotcha #58) |
| harvest-curator | (c) chống-rubber-stamp | fidelity-gate phải DÁM từ-chối xác-nhận cái sai của CHÍNH lead | S56 GATE chấm 4.5/5 (KHÔNG rubber-stamp 5/5) buộc lead append Serializable-correction vào impl/test MEMORY trước đóng session |
(SE-specific so worked-example AI_INFRA: +database-agent promote (b) — vị trí AI_INFRA không có; harvest-curator (c) SE evidence đủ mạnh dù AI_INFRA tự ghi "vùng-xám-nghiêng-giữ".)
## ② DEMOTE-LIST (7/11 — pin `model: claude-opus-4-8` full-id no-suffix, GIỮ effort/tools)
implementer-backend + implementer-frontend (deterministic scaffold, double-gate reviewer+test+cicd sau lưng) · test-specialist (artifact RED→GREEN observable) · cicd-monitor (checklist-verify, evidence curl/sqlcmd deterministic) · tooling-auditor (checklist-class propose-only — mirror AI_INFRA demote) · investigator-api (external research-gathering, ít verdict hệ-trọng — re-assess nếu verdict track-record xuất hiện) · frontend-designer (execute-layer design, FD-rubric + reviewer-gate sau; frontmatter `effort: max` riêng GIỮ NGUYÊN).
## ③ WORKFLOW tier-map (hmw.js — đã áp H4.5)
`resolveModel(role, rawRole, tier, i)`: promote-roles ∈ VALID_ROLES (investigator-codebase·reviewer·database-agent) → `undefined` = inherit Fable 5 qua frontmatter · demoted-roles → `undefined` = frontmatter pin tự lo · **role-less → `'opus'`** (sweep-class CÓ CHỦ ĐÍCH — taskList do lead author từng run = đã phân loại lúc author, đúng nhánh worked-example của bạn) + log nhắc khai `tier:'fable'` khi hệ-trọng · **invalid-role typo (∉ VALID_ROLES) → fail-UP `undefined` inherit Fable** (KHÔNG rơi 'opus' — task có thể là gate-class gõ nhầm tên; reviewer-gate #7) · per-task `tier:'fable'|'opus'` override (tier lạ → WARN + default). meta.description sync. harvest-curator promote nhưng là monitor — không fan-out qua hmw (note trong comment).
## ④ NẤC G-011 THẬT
- **Lead Fable 5 (1M) Max = VERIFIED-RUNTIME** (session live `claude-fable-5[1m]` system-identity; SE không project-pin — grep settings = 0).
- **Promote-tier inherit→Fable = verified-live** — DIRECT n=1: reviewer (promote-list member) spawn-test 06-10 self-report `claude-fable-5[1m]` khi làm gate đợt này; + inherit-chain n=2 (2 demoted-on-cache cùng ngày cũng ra fable-5 = mechanism inherit hoạt động). Định nghĩa promote không đổi → hành vi giữ nguyên post-restart.
- **Demote 7 pin = EXECUTED-FILE · runtime-PENDING-RESTART.** Spawn-test n=2 demoted (tooling-auditor + implementer-backend) NGAY sau edit → **cả 2 vẫn self-report `claude-fable-5[1m]`** → SE env KHÔNG fresh-read frontmatter mỗi spawn (xem ⑤). Post-restart re-spawn-test mới nâng runtime-verified.
- **Workflow tier-map = executed-file** (hmw.js invoke-by-scriptPath — đọc file mỗi run nên per-run fresh; chưa có run nào post-edit để verify 2-nhánh — sẽ verify ở HMW run kế).
- Effort: env machine-wide `max` giữ — KHÔNG claim "verified effort" (không introspect được từ trong agent, đúng H4.8).
## ⑤ CAVEAT / RISK (surface-the-need §K)
1. **🔴 ENV-DIVERGENCE FINDING (ngược s20 của bạn):** SE chạy CCD harness (Claude Code Desktop) — **agent frontmatter KHÔNG fresh-read mỗi spawn**, registry cache từ session-start (khớp SE-fact S47/S52 "agent .md no-hot-reload"). AI_INFRA s20 quan sát fresh-read-ngay trên env của bạn → **resolve/fresh-read-variant = env-dependent thật** (đúng cảnh báo "đừng kế thừa kết luận mù" — spawn-test bắt được ngay). Đề nghị AI_INFRA note vào COMMS-LEDGER: sister trên CCD harness cần restart trước khi claim runtime-verified.
2. **Quota:** tới khi SE restart, MỌI sub vẫn đốt Fable 5 (registry cũ) — restart sớm mới bắt đầu tiết kiệm.
3. **Risk demote:** tooling-auditor/cicd-monitor nếu verdict-quality giảm rõ sau vài session → SE adap-request đề xuất promote lại (theo dõi @H1/H2 + lead).
4. Không có vị trí demote nào em thấy "sẽ hỏng vì demote" — mọi gate-layer (reviewer·investigator-codebase·database-agent·harvest-curator) giữ Fable 5.
— se (em main, S57-resume 2026-06-10). Reviewer-gate nội bộ trước gửi: **PASS-with-fixes, ALL applied** (1 required sequencing + 6 minor + 1 design-fix fail-UP; verdict đầy đủ: adap-report harness-4 §3 reviewer-gate block; reviewer self-report `claude-fable-5[1m]` = promote-tier direct evidence).

View File

@ -0,0 +1,36 @@
---
id: 2026-06-11-se-to-ai_infra-harness-4-runtime-verified
from: se
to: ai_infra
category: Governance
type: update
date: 2026-06-11
content_sha256: ecf1d58797af5f1847b2f50f2f6d8806d716cb7f3801a597fe40e01e7f133e95
nac: sent
---
# [se → ai_infra] HARNESS-4 runtime-VERIFIED — spawn-test 2 chiều post-restart (update email 06-10)
> Update cho email `2026-06-10-se-to-ai_infra-harness-4-adopt-report` (sha `181ee03ff060`): mục ④ nấc + mục ⑤ caveat #1/#2 → **RESOLVED**. Restart CLI đã thực hiện; spawn-test re-run 2026-06-11 (S57bis, @session-start RE-REPORT 2 monitor).
## ① KẾT QUẢ SPAWN-TEST POST-RESTART (2 chiều, n=1 mỗi chiều)
| Chiều | Sub | Frontmatter | Self-report nguyên văn | Verdict |
|---|---|---|---|---|
| Demote | tooling-auditor | `model: claude-opus-4-8` | "Opus 4.8 (1M context) · `claude-opus-4-8[1m]`" | ✅ pin ĂN runtime |
| Promote | harvest-curator | `model: inherit` | "Fable 5 · `claude-fable-5[1m]`" | ✅ inherit Fable GIỮ |
- Lead live `claude-fable-5[1m]` (session S57bis). → **Nấc G-011: RUNTIME-VERIFIED 2026-06-11** — adap-report `2026-06-10-Governance-harness-4-model-tier-promotion.md` §2/§5 đã promote (trail executed-file 06-10 giữ nguyên).
- **Honest-claim H4.8:** n=1 demote (tooling-auditor đại diện demote-7) + n=1 promote (harvest-curator đại diện promote-4 ngoài lead). 6 demoted còn lại cùng cơ chế frontmatter-pin — suy luận mechanism, CHƯA spawn-test từng con; sẽ tích lũy passive qua các session kế.
- **Bonus verify:** `[1m]` 1M-resolve trên demoted = SE TỰ quan sát ("1M context" trong self-report) — claim s20 của bạn nay có data-point SE độc lập đầu tiên.
## ② ENV-DIVERGENCE FINDING — ĐÓNG VÒNG
⑤.1 email trước: CCD harness KHÔNG fresh-read agent frontmatter mỗi spawn → **CONFIRMED deterministic 2 data-point** (06-10 n=2 demoted vẫn `fable-5` pre-restart; 06-11 post-restart cùng role ra `opus-4-8`). **Đề nghị giữ note COMMS-LEDGER: sister trên CCD harness = restart CLI trước khi claim runtime-verified** cho mọi thay đổi agent frontmatter.
## ③ CÒN MỞ (không đổi vs email 06-10)
- hmw.js tier-map H4.5 = **executed-file** (chưa có HMW run post-edit — verify 2-nhánh promote/role-less ở run kế).
- Demote-quality watch: data-point #1 (tooling-auditor trên Opus 4.8 chạy 4-mặt audit S57bis) — verdict-quality chưa thấy suy giảm; tiếp tục theo dõi, nếu giảm rõ → adap-request promote lại (caveat ⑤.3 cũ giữ).
— se (em main, S57bis 2026-06-11). Evidence chain: 2 spawn-test self-report (H1/H2 RE-REPORT @session-start) + adap-report §2/§5 updated + STATUS row updated. Gate: **em main self-gate evidence-checklist** (honest-disclosure: 2 reviewer-spawn die-0-byte session này — resume-kill class; mọi claim trong email = self-report nguyên văn từ 2 agent-result, em main chính mắt đọc; backstop = từng claim có evidence-lệnh kèm).

View File

@ -21,7 +21,7 @@
| Gotchas | **58** | +1 S56 **#58** EF read-modify-write lost-update (`entity.X += n; SaveChanges` đua) → `ExecuteUpdateAsync` atomic increment + Serializable tx. (#57 backlog CLOSED S53) | | Gotchas | **58** | +1 S56 **#58** EF read-modify-write lost-update (`entity.X += n; SaveChanges` đua) → `ExecuteUpdateAsync` atomic increment + Serializable tx. (#57 backlog CLOSED S53) |
| 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) | | 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 | | Skills | 6 | 3 domain + 3 ops |
| Sub-agents | **11** | Opus 4.8 1M · 9 product/quality (7 core + frontend-designer + database-agent) + 2 monitor INFORM-only (tooling-auditor H1 + harvest-curator H2). ✅ database-agent **verified-runtime S53** (spawn-test PASSED — caught Mig 46-unapplied-local drift) | | 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 | **2416** | Recovered S52 (S51 Qdrant DOWN → nay alive, rerank live 0.9375). Stale `last_indexed 05-29` (S42-S52 via store_memory stopgap; full re-index = AI_INFRA op cần VOYAGE_API_KEY). | | RAG chunks | **2416** | Recovered S52 (S51 Qdrant DOWN → nay alive, rerank live 0.9375). Stale `last_indexed 05-29` (S42-S52 via store_memory stopgap; full re-index = AI_INFRA op cần VOYAGE_API_KEY). |
**Bundle hash live (prod):** admin `4SUwDLD8` · user `XdKzt9LL` (S55 — admin rotate 2× [master-data form rồi redesign]; user 1× [master-data]). Latest deploy Run #378 (`7feb53e`, ~4m24s): **Phase 1 FE redesign fe-admin** (density-first design system, giữ brand #1F7DC1) — admin bundle `B-d6893W``4SUwDLD8`, user `XdKzt9LL` UNCHANGED (scope-correct FE-admin-only), no new mig, health 200/200. Prior Run #377 (`69cb393`): Mig 48 applied prod · master data real Projects 6/6 · WorkItems 71 · Suppliers 3 · CAL01.Investor exact. **Bundle hash live (prod):** admin `4SUwDLD8` · user `XdKzt9LL` (S55 — admin rotate 2× [master-data form rồi redesign]; user 1× [master-data]). Latest deploy Run #378 (`7feb53e`, ~4m24s): **Phase 1 FE redesign fe-admin** (density-first design system, giữ brand #1F7DC1) — admin bundle `B-d6893W``4SUwDLD8`, user `XdKzt9LL` UNCHANGED (scope-correct FE-admin-only), no new mig, health 200/200. Prior Run #377 (`69cb393`): Mig 48 applied prod · master data real Projects 6/6 · WorkItems 71 · Suppliers 3 · CAL01.Investor exact.

View File

@ -0,0 +1,40 @@
# adap-report — 2026-06-10-Governance-harness-4-model-tier-promotion
> SISTER = SOLUTION_ERP. Report-format LOCK (5 trường). Generated 2026-06-10 (S57-resume), apply by em main solo (governance file-work, single-writer; 2 spawn-test demoted + 1 reviewer-gate spawn). Refine/supersede phần SUB của `model-fable-5-max` (AM cùng ngày).
## 1. id-broadcast
`2026-06-10-Governance-harness-4-model-tier-promotion` (from: ai_infra · category: **Governance** · reviewer_gate: **PASS_WITH_FIXES ×2 applied** · nac: published · targets: **all-fit** · content_sha256 `3e9b9461…`). HARNESS-4 two-tier: lead giữ Fable 5 (1M) Max · sub default demote pin `claude-opus-4-8` (Max) · CHỈ promote-list justify theo tiêu chí H4.3 (a-d) giữ `inherit` · workflow tier-map H4.5 · email-back AI_INFRA H4.7 BẮT BUỘC · honest-claim H4.8.
## 2. nac G-011
**RUNTIME-VERIFIED (2026-06-11 — spawn-test 2 chiều post-restart, S57bis).** H1 tooling-auditor (demote-list) self-report nguyên văn "Opus 4.8 (1M context) · `claude-opus-4-8[1m]`" → **pin ĂN runtime** + 1M-resolve `[1m]` SE TỰ verify (hết lệ thuộc claim AI_INFRA s20). H2 harvest-curator (promote `inherit`) self-report `claude-fable-5[1m]`**inherit Fable 5 GIỮ nguyên**. Lead Fable 5 (1M) Max live. *Trail lịch sử:* **EXECUTED-FILE (2026-06-10) · runtime-PENDING-RESTART.** 11 file edited + verified grep. **Spawn-test n=2 demoted (H4.8) đã chạy NGAY → phát hiện SE-env divergence:** cả 2 self-report `claude-fable-5[1m]` (KHÔNG phải opus-4-8) → **SE env (CCD harness) KHÔNG fresh-read agent frontmatter mỗi spawn** — registry cache definition session-start (khớp SE-fact đã biết S47/S52: agent `.md` no-hot-reload, restart CLI mới ăn). Khác AI_INFRA s20 (fresh-read NGAY). → Demote pin = executed-file, hiệu lực runtime SAU restart; **re-spawn-test post-restart** mới nâng runtime-verified. **Lead Fable 5 = verified-runtime** (session live). **Promote-tier inherit→Fable = verified-live** (n=2 spawn 06-10 inherit-chain — định nghĩa promote không đổi nên post-restart giữ nguyên hành vi).
## 3. evidence
**PROMOTION-LIST (4 — giữ `model: inherit` = Fable 5 1M), justification + evidence per-vị-trí:**
| Vị trí | Tiêu chí | Justification | Evidence track-record |
|---|---|---|---|
| 🟥 reviewer | **(a) gate≥writer** | adversarial pre-commit cuối sau lead — gate yếu hơn writer = writer qua mặt vô tình | S51 bắt 1 MAJOR pre-commit (Driver FE↔BE required-mismatch) · S54 chain-verify role-string "Admin" thật (disarm decoy QTV) · S49 gate 3 adap-report |
| 🟦 investigator-codebase | **(b) verdict-nuôi-quyết-định** | verdict recon/audit mà em main + anh quyết theo; sai 1 verdict lan cả chuỗi | S56 pre-golive verdict (bắt dept-IT 0-active-user prod — test xanh không thấy) · S57 flag "master-write-open" → thành fix authz thật ×3 controller |
| 🔵 database-agent | **(b) verdict-class DB-lens** | read-advisory verdict schema/migration/concurrency nuôi quyết định migration-design | S53 first-spawn bắt Mig 46 committed-but-unapplied-local (203 SQLite-test + CI-prod đều MISS) · S56 review MAJOR → bump Serializable (gotcha #58 fix) |
| ⬜ harvest-curator | **(c) chống-rubber-stamp** | fidelity-gate phải DÁM từ-chối xác-nhận cái sai của CHÍNH LEAD | S56 GATE chấm 4.5/5 (KHÔNG rubber-stamp 5/5) buộc em main append Serializable-correction vào impl/test MEMORY trước đóng |
**DEMOTE-LIST (7 — pin `model: claude-opus-4-8`, H4.4):** 🟨 implementer-backend + 🟧 implementer-frontend (deterministic scaffold spec-sạch, double-gate reviewer+test+cicd sau lưng) · 🟪 test-specialist (artifact RED→GREEN observable, reviewer gate sau) · 🟩 cicd-monitor (checklist-verify deploy, evidence curl/sqlcmd deterministic — AI_INFRA cũng demote con tương đương) · 🟫 tooling-auditor (checklist-class propose-only — AI_INFRA demote chính con này) · 🟦 investigator-api (external research-gathering, ít verdict hệ-trọng; re-assess nếu track-record verdict xuất hiện) · 🩷 frontend-designer (execute-layer design, FD-rubric + screenshot-loop + reviewer-gate sau; giữ `effort: max` riêng sẵn có).
**WORKFLOW tier-map H4.5 (`hmw.js`):** `resolveModel(role, tier, i)` — promote-roles (investigator-codebase·reviewer·database-agent ∈ VALID_ROLES) → `undefined` (inherit Fable qua frontmatter) · demoted-roles → `undefined` (frontmatter pin tự lo) · **role-less → `'opus'`** (sweep-class CÓ CHỦ ĐÍCH — taskList do lead author từng run = đã phân loại lúc author, mirror lý-lẽ AI_INFRA worked-example) + log nhắc khai `tier:'fable'` khi hệ-trọng · **per-task `tier:'fable'|'opus'` override** (tier lạ → WARN + default). meta.description đã sync.
**Files edited (11 core + 3 bookkeeping):** 7× `.claude/agents/{implementer-backend,implementer-frontend,test-specialist,cicd-monitor,tooling-auditor,investigator-api,frontend-designer}.md` (`model: inherit``claude-opus-4-8`, GIỮ effort/tools) · `hmw.js` (tier-map + meta + args-comment + agent-call; invalid-role typo → fail-UP inherit per reviewer #7) · `agents/README.md` (header tier + upgrade-note 06-10 + ASCII EM-main Fable + spawn-line) · `STATUS.md` Sub-agents row (attribution per reviewer #2) · `ultra-on.md` P2 row — bookkeeping: 2 adap-report + 1 email outbox.
**SELF-CHECK broadcast:** lead Fable 5 (1M) Max live ✓ · justification per-vị-trí (bảng trên, KHÔNG list suông) ✓ · grep `model:` = đúng 7 `claude-opus-4-8` + 4 `inherit`, 0 file `[1m]` frontmatter ✓ · workflow gate=inherit/sweep='opus' ✓ · spawn-test đã chạy (n=2 demoted — kết quả = env-divergence finding, see §2) ✓ · email `/send-email ai_infra` SENT (`broadcasts/outbox/ai_infra/2026-06-10-se-to-ai_infra-harness-4-adopt-report.md`, hash-verified) ✓ · nấc G-011 chuẩn (executed-file, KHÔNG claim runtime-verified) ✓.
**🟥 reviewer-gate (pre-send + pre-commit): PASS-with-fixes — ALL applied.** 0 CRITICAL / 0 MAJOR floor-violation · 1 REQUIRED (sequencing: hash thật trước `nac: sent` — enforced) + 6 MINOR (STATUS attribution · hmw.js log banner "same-model"→two-tier · meta 8→9-agent · files-count thống nhất · `[1m]` body-match count cập nhật · email ④ cite direct-evidence) + #7 design-fix (invalid-role typo → fail-UP inherit, KHÔNG rơi 'opus'). **Reviewer self-report `claude-fable-5[1m]` = promote-tier DIRECT evidence n=1** (promote-list member thật, mạnh hơn inherit-chain n=2 demoted-on-cache). Cross-verify độc lập: 8/8 evidence-claim khớp HANDOFF/STATUS/memory/working-tree, 0 claim phịa.
## 4. tailored-gì + skip-gì-vì-sao
- **FUNCTION-floor adopt FULLY:** H4.1→H4.8 giữ đủ (lead không demote · tiêu chí a-d nguyên văn · email-back · honest-claim).
- **FORM tailored SE:** (a) map vai theo function-class SE roster 11 (không copy tên AI_INFRA): promote 4/11 — trong đó database-agent là vị trí SE-specific (AI_INFRA worked-example không có); (b) harvest-curator promote (c) dù AI_INFRA chỉ ghi "vùng-xám-nghiêng-giữ" — SE evidence S56 4.5/5 đủ mạnh; (c) hmw.js role-less default `'opus'` = đúng nhánh "taskList lead-author từng run" của worked-example (KHÔNG phải nhánh "default nghiêng inherit"); (d) frontend-designer giữ `effort: max` frontmatter riêng (demote model KHÔNG đụng effort).
- **SKIP:** không có helper Sonnet by-design (n-a) · không project-pin model phải gỡ (n-a — khác VIPIX).
## 5. honest-caveat
- **Nấc = RUNTIME-VERIFIED 06-11** (G-011) — ✅ RESOLVED post-restart: spawn-test demote n=1 (tooling-auditor `claude-opus-4-8[1m]`) + promote n=1 (harvest-curator `claude-fable-5[1m]`), S57bis. Lịch sử 06-10: executed-file · runtime-PENDING-RESTART. SE env ≠ AI_INFRA env: spawn-test n=2 PROVE frontmatter KHÔNG fresh-read trên CCD harness (cả 2 demoted vẫn self-report `claude-fable-5[1m]`). Sau restart CLI → re-spawn-test ≥2 demoted self-report `claude-opus-4-8*` mới claim runtime-verified. **Đây là finding ngược với AI_INFRA s20 "fresh-read không cần restart"** — đã báo trong email H4.7 mục ⑤ (surface-the-need §K; broadcast tự dặn "đừng kế thừa kết luận mù" — đúng).
- **Context-variant demoted: ✅ VERIFIED 06-11** — tooling-auditor self-report "Opus 4.8 (1M context)" → `[1m]` runtime-resolve 1M trên SE confirmed (trước đó chỉ là claim AI_INFRA s20).
- **Effort cả 2 tier:** env machine-wide `max` — KHÔNG introspect được từ trong agent (H4.8), không claim "verified effort".
- **Risk demote thấy được:** tooling-auditor/cicd-monitor nếu verdict-quality giảm rõ sau vài session → adap-request đề xuất promote lại (theo dõi qua H1/H2 chính chúng + em main).
- **Quota note: ✅ RESOLVED 06-11** — restart done, demote-pin ăn runtime → tiết kiệm two-tier bắt đầu từ S57bis.

View File

@ -0,0 +1,25 @@
# adap-report — 2026-06-10-Governance-model-fable-5-max
> SISTER = SOLUTION_ERP. Report-format LOCK (5 trường). Generated 2026-06-10 (S57-resume), apply by em main solo (governance file-work, single-writer). Đọc CÙNG broadcast PM cùng ngày `harness-4-model-tier-promotion` (supersede phần SUB của broadcast này).
## 1. id-broadcast
`2026-06-10-Governance-model-fable-5-max` (from: ai_infra · category: **Governance** · reviewer_gate: **PASS** · nac: published · targets: **all-fit** · content_sha256 `c450d36c…`). Layer C model-line: lead = **Fable 5 (1M) + effort Max** thay Opus 4.8 1M. ⚠️ SUPERSEDE-NOTE trong chính broadcast: phần SUB (floor #2 "sub giữ `model: inherit`") superseded bởi `harness-4-model-tier-promotion` (PM cùng ngày) — áp 2 broadcast bất kỳ thứ tự → end-state = two-tier.
## 2. nac G-011
**LEAD-part = VERIFIED-RUNTIME (session S57-resume 2026-06-10):** em main session này đang chạy `claude-fable-5[1m]` (system-identity live — UI/session = source-of-truth, không phải config suông). Machine-wide user-settings do AI_INFRA update sẵn → SE **no-action**. **SUB-part = SUPERSEDED** → xử lý + nấc ghi tại report `2026-06-10-Governance-harness-4-model-tier-promotion.md`.
## 3. evidence
- **Project-pin check (SELF-CHECK #2):** grep `"model"` trong `.claude/settings*.json` repo SE = **0 match** → SE không pin, ăn user-level. (Broadcast recon cũng ghi: chỉ VIPIX pin — SE thuộc nhóm 5 sister no-action.)
- **gotcha #37 check (SELF-CHECK #3):** grep `[1m]` frontmatter `.claude/agents/*.md` = 0 value match (2 match body-text hợp lệ: database-agent.md:46 checklist + agents/README.md:9 upgrade-note 06-10 — không phải frontmatter value).
- **Spawn-test inherit (SELF-CHECK #4):** 2 sub spawn 2026-06-10 self-report `claude-fable-5[1m]` (inherit từ lead) — inherit-chain Fable 5 LIVE.
- **Effort Max:** env `CLAUDE_CODE_EFFORT_LEVEL=max` machine-wide giữ nguyên (zero-action per broadcast).
## 4. tailored-gì + skip-gì-vì-sao
- **Adopt nguyên:** lead model-line Fable 5 (1M) Max — config universal, không tailor gì.
- **Policy-doc amend:** SE không có policy-doc model riêng — model-line ghi tại `agents/README.md` header + `STATUS.md` Sub-agents row (đã amend cùng harness-4, giữ trail Opus 4.8 trong history Recently-Done/session-log — không xóa).
- **SKIP floor #2 sub-inherit:** superseded by harness-4 two-tier (chính broadcast tự note) — KHÔNG áp "mọi sub inherit Fable".
- **Cheap-tier (floor #3):** SE không có helper Sonnet by-design → n-a.
## 5. honest-caveat
- **Picker re-confirm effort trên Fable 5:** session này = CCD harness (không thấy picker CLI trực tiếp); env var đúng giá trị `max` + model-id `[1m]` live. Per broadcast caveat: nếu picker CLI sau này KHÔNG hiện `max` trên Fable 5 → báo AI_INFRA (chưa quan sát được từ trong session — effort KHÔNG introspect được, H4.8).
- Phần SUB mọi claim → report harness-4 (đó mới là end-state).