From d4f60212a52669623ea486b18e824c3c87298ef2 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Tue, 23 Jun 2026 15:52:46 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Docs:=20S85=20closeout=20=E2=80=94?= =?UTF-8?q?=20CV=20PRO=20batch=20+=20clear-data=20+=206=20UAT=20round=20+?= =?UTF-8?q?=202=20root-cause=20+=205=20SQL-fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STATUS/HANDOFF prepend S85 (Mig 57 · 88 tables · 374 test · gotcha 73 · bundle admin aKuNip19/user BUsL0HeQ Run #341). gotchas +2: #72 DateTime serialize no-Z -> FE +7h (UtcDateTimeJsonConverter UTC-with-Z) · #73 UPDATE absolute-set clears field on FE-omit (bug-class S42, null-safe guard). + session log + scripts/s85-wipe-uat-data.sql (prod UAT wipe, backup-first, executed) + agent-memory residuals (inv-codebase PE-recon, test-specialist baseline 374). Co-Authored-By: Claude Opus 4.8 --- .../investigator-codebase/MEMORY.md | 1 + .../agent-memory/test-specialist/MEMORY.md | 7 +- docs/HANDOFF.md | 2 +- docs/STATUS.md | 2 +- ...026-06-23-S85-pe-uat-cvpro-rootcause-tz.md | 73 +++++++++++++ docs/gotchas.md | 24 +++++ scripts/s85-wipe-uat-data.sql | 102 ++++++++++++++++++ 7 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 docs/changelog/sessions/2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md create mode 100644 scripts/s85-wipe-uat-data.sql diff --git a/.claude/agent-memory/investigator-codebase/MEMORY.md b/.claude/agent-memory/investigator-codebase/MEMORY.md index 25f3ff9..44b0b7c 100644 --- a/.claude/agent-memory/investigator-codebase/MEMORY.md +++ b/.claude/agent-memory/investigator-codebase/MEMORY.md @@ -70,6 +70,7 @@ Bearer từ `POST api.solutions.com.vn/api/auth/login` → status matrix expecte ## 📅 Recent activity (compressed — full verbatim → `archive/2026-06.md` via `archive/_INDEX.md`) +- **2026-06-23 PE UAT recon D2/D4/D5 (anh Kiệt FDC go-live):** ⭐ (D2-urgent authz) `PurchaseEvaluationUrgentFeatures.cs:49-50` BẤT-ĐỐI-XỨNG `isPro=IsUrgent?hasPro:(hasPro&&isDeptManager)` — GẮN=role-only / GỠ=DeptManager-only. NO DrafterUserId match (handler chỉ load entity, never reads DrafterUserId). Để drafter gỡ cờ mình: sửa :49-50 OR `actor.Id==entity.DrafterUserId`. Endpoint `PUT /purchase-evaluations/{id}/urgent` (controller:91). ⚠️ cờ KHÔNG split-by-drafter (PRO/CCM = role, drafter ≠ tất nhiên PRO/CCM). (D5) FE PE-create dropdown=`PeWorkspaceCreateView.tsx:94-104` GET `/approval-workflows-v2?applicableType={1|2}` filter `isUserSelectable`. **Dev DB: PE type1/type2 selectable=0** (6 selectable đều type3-9 Contract/Proposal/Leave/OT/Xe/Ticket NOT PE) → prod UNVERIFIED (SSH-paren-quote-trap). Validator REQUIRE workflow CẢ 2 tầng: `PurchaseEvaluationFeatures.cs:48` create NotEmpty (S83) + submit-guard `PurchaseEvaluationWorkflowService.cs:225` ConflictException. (D4 required) create-validator `:35-57`: Type/TenGoiThau≤500/ProjectId/WorkItemId/ApprovalWorkflowId NotEmpty + BudgetPeriodAmount>0-when-present. Submit-guard `:174-228`: SelectedSupplierId + winnerQuoteTotal>0 + BudgetPeriodAmount>0 + Bảng-so-sánh-attachment + ApprovalWorkflowId. → _INDEX. - **2026-06-20 governance-landing map (RC-sig + User-Mark H12/13 + objective-criteria):** ⭐ WHERE-to-land 3 AI_INFRA gov broadcasts. `harness-11-engine.md` = CANONICAL engine (D5/D6/D7 safety-tier + D8 one-direction-lock + D9 single-writer + D10 Bash-residual + CAVEAT no-OS-hook). `error-ledger.md` = §L.a AS-1..13 + §L.b 7-step. adap-report FORMAT richest = `2026-06-18-Governance-harness-11.md`. rules.md §6.6 = objective-criteria. **report-before-stamp ⊂ D7 (extend, đừng duplicate → C3 vocab-fork).** → _INDEX. - **2026-06-20 Harness-14 Eval/Budget/Outcome audit:** ⭐ H-14 = time/age/recency-decay KHÔNG được làm căn-cứ cắt feature. (1) BUDGET aligned: `memory-budget.json` 0 decay/TTL/age hit; `keep_floor=5`=newest-protection (drains OLDEST), cap seed-by-MEASURE. (2) detectors = canonical-anchor-vs-STATUS + disk-cross-check, ZERO age-window. (3) EVAL genuine: `eval/golden-set-solution_erp.jsonl` (14q) + `evaluator.md` recall@5≥0.7 — weekly-manual no-automation. (4) anti-downgrade = Harness-8 "all-inherit chất-lượng>chi-phí" PARTIAL (no generic rule in rules.md, grep 0). → _INDEX. - **PE recon cluster (S69→S76, → _INDEX):** "Giá chào thầu" mục-c = `WinnerQuoteTotal`=SUM(Quote.ThanhTien WHERE supplier==Selected) DERIVED (3 nơi đồng-predicate) — PRO-Min/Max+CCM-proposed = Mig 54 NEW field. **Budget gate = PURE ROLE no-phase** (`canEditPro=Admin||Procurement`/`canEditCcm=Admin||CostControl` `PurchaseEvaluationFeatures.cs:800-801`; comment "bảng NS=tài-liệu-sống như Excel"); **submission-count-lock NEXISTS** (grep 0) → "khóa Initial sau lần-trình-đầu" = feature-MỚI. **Value-threshold HOOK B** = `ApproveV2Async` advance `:816-845` (reuse skipToFinal mechanic); **urgent flag** = AddColumn mirror `ItTicketPriority`. Badge ✎NS = +2 bool DTO via `GetUsersInRoleAsync` batch (no-N+1) both sites. PRO/CCM/CEO = `Procurement/CostControl/Director` (domain-shorthand NOT constants); V2 routing IGNORES roles (= specific ApproverUserId), 100% LINEAR no value/threshold config. diff --git a/.claude/agent-memory/test-specialist/MEMORY.md b/.claude/agent-memory/test-specialist/MEMORY.md index bfb0cca..1b7625f 100644 --- a/.claude/agent-memory/test-specialist/MEMORY.md +++ b/.claude/agent-memory/test-specialist/MEMORY.md @@ -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: decide WHAT to test (test plan) → em main + reviewer chốt priority -## 📊 Baseline 354 tests = 354 PASS (45 Domain + 309 Infra) ← S77c CORRECTION urgent-toggle SYMMETRIC→ASYMMETRIC (S77b symmetric tests RED vs prod): anh chốt FINAL gate BẤT-ĐỐI-XỨNG theo `request.IsUrgent` — em main đã sửa prod `PurchaseEvaluationUrgentFeatures.cs:49-55` `isPro = IsUrgent ? hasPro : (hasPro && isDeptManager)` + `isCcm = IsUrgent ? hasCcm : (hasCcm && isDeptManager)`; Forbidden-msg nhánh-theo-IsUrgent (SET `*đánh dấu phiếu gấp*` / UNSET `*GỠ cờ gấp*`). REWRITE `PeUrgentToggleAuthzTests.cs` 12→11: **SET = role-chức-năng-đủ** (plain Procurement SET→OK ByPro / plain CostControl SET→OK ByCcm / Admin SET→both) — bỏ hết 2b/2c/2d DeptManager-alone-restriction của S77b (không còn áp cho SET); **UNSET = role AND DeptManager** (plain-PRO UNSET→Forbidden`*GỠ*`+no-mutate flag-still-true pre-seed urgent / plain-CCM UNSET→Forbidden / PRO+DM UNSET→clear-ByPro CCM-preserved / CCM+DM UNSET→clear-ByCcm PRO-preserved / Admin UNSET→both-clear); 9a Drafter-SET→Forbidden`*đánh dấu*` / 9b Finance-SET→Forbidden / 9c UnknownPe→NotFound TRƯỚC authz. No prod touch — prod ĐÃ asymmetric, test theo CODE (S34). Prev S77b 354 (symmetric, superseded) ← S77 +7 PE Mig 57 suggested-price NOTE (test-after, mirror S74 §4b CcmNote): `UpdatePeSuggestedPricePro/CcmCommand` +`Note` (string?) absolute-set→`Pro/CcmSuggestedPriceNote` (overwrite always incl null=clear); rides SAME role-gate as price (PRO/Admin · CCM/Admin) fail-closed TRƯỚC side-effect; validator `Note.MaximumLength(1000)`. Handler ctor `(db, ICurrentUser)` 2-dep + record arity UNCHANGED on existing args (Note=null default → 5 existing `new UpdatePeSuggestedPrice*Command(...)` call-sites still compile, KHÔNG cần vá). NEW 7 → `PeSuggestedPriceSetterAuthzTests.cs`: PRO-note+Min/Max persist (note KHÔNG clobber price) / Admin-PRO-note / CCM-note+price persist / null-clear PRO (pre-seed note→null=cleared) / null-clear CCM / non-priv→Forbidden+note&price unchanged (no partial-write) / PRO↔CCM note independent + validator 1001-char invalid·1000 valid. No prod bug — code đúng spec (note absolute-set + rides price gate, intentional). Prev 344 ← S76 +5 PE Mig 56 PRO-column-split (spec-change+compile-fix arity): UpdatePeBudgetProCommand record 3→4 param `(PeId, ProInitialAmount, ProAdjustmentAmount, ProNote)`; handler set ProInitial+ProAdjust absolute-set (KHÔNG còn ProEstimateAmount). Vá 5 PRO call-site `new UpdatePeBudgetProCommand(...)` thêm arg ProAdjust + rename assert `.ProEstimateAmount`→`.ProInitialAmount` (handler giờ set ProInitial). Capability `FullAmount`: hasCcm?CCM:proFull(ProInitial+ProAdjust); FullIsEstimate=!hasCcm&&hasPro; DTO +2 field cuối ProInitial/ProAdjust. NEW 5: PRO set both incl ProAdjust ÂM persist / validator ProInitial<0 invalid + ProAdjust ÂM valid (mirror CCM no-sign-constraint) / full=proFull(100+50=150)+DTO-surface / full=proFull ÂM-adjust(100-30=70 no-clamp). Full-fallback seed `ProEstimateAmount=500`→`ProInitialAmount=500` (capability đọc ProInitial). **Handler ctor `(db, ICurrentUser)` 2-dep UNCHANGED**. ProEstimateAmount=LEGACY (Mig 56 backfill→ProInitial, FE bỏ). No prod bug. Prev 339 ← S74 +5 PE Mig 55 CcmNote (compile-fix arity + test-after): UpdatePeBudgetCcmCommand record +`string? CcmNote` (4 param) → fix 3 existing `new UpdatePeBudgetCcmCommand(...)` thêm `null` arg4 (PeWorkItemBudgetTests.cs line 388/407/421); NEW 5 test mirror ProNote: CostControl-set / Admin-set / null=clear-absolute-set (pre-seed prove not vốn-dĩ-null) / Procurement→Forbidden no-mutate (fail-closed role-gate TRƯỚC EnsureTrackedAsync+side-effect, AsNoTracking re-read) / Initial+Adjustment+CcmNote all-persist-together. **Handler ctor `(db, ICurrentUser)` 2-dep UNCHANGED** — chỉ COMMAND record +CcmNote. No prod bug. Prev 334 ← S72 +28 PE Mig 54 (spec-change+test-after): PeCcmThresholdFinalizeTests 6→11 (AUTO→OPT-IN finalizeByCcmDelegation) + NEW PeApprovedPriceFinalizeTests 10 (giá chốt) + NEW PeSuggestedPriceSetterAuthzTests 13 (2 setter role-gate). Prev 306 ← S69b +14 PE 2 feature anh Kiệt FDC (test-before-merge SECURITY/FINANCIAL): `PeCcmThresholdFinalizeTests.cs` (5, Services ns, value-threshold CCM-finalize ApproveV2Async) + `PeUrgentToggleAuthzTests.cs` (9, Application ns, urgent-toggle role authz). Prev 292 ← S69 +6 Office golive permission-seed (`OfficeModulePermissionSeedTests.cs`, test-after, mirror HrmProfilePermissionSeedTests S67). Prev 286 ← S67 +23 HRM test-after [DepartmentTreeTests 8 cycle-guard/rollup/orphan + PeHoSoLinkTests 9 absolute-set (⚠️spec-drift: HoSoLink gửi null=CLEAR, KHÔNG null-safe như Budget*/WorkItemId) + HrmProfilePermissionSeedTests 6 reflection private-static revoke→seed chain]. **em main PROXY-RECORD** — return truncated #53 (chết lúc update MEMORY), 3 file delivered + `dotnet test` 286 PASS verify-on-disk. Prev 263 (S61 +22 PeWorkItemBudget −14 BudgetPolicy; Domain 58→45 drop Budget module). Pre = 254 (S60). +## 📊 Baseline 374 tests = 374 PASS (45 Domain + 329 Infra) ← S85b +3 PE UpdateDraft WF-preserve ROOT-FIX bug-class S42 (test-after BUG-FIX disc): em main fix `UpdatePurchaseEvaluationDraftCommandHandler` (PurchaseEvaluationFeatures.cs:285) ABSOLUTE-SET→NULL-SAFE `if(request.ApprovalWorkflowId is not null) entity.ApprovalWorkflowId=...` (form Sửa header KHÔNG gửi WF → trước = CLEAR WF → kết submit "chưa chọn quy trình" whack-a-mole). NEW `PeUpdateDraftWorkflowPreserveTests.cs` 3: (1) PRESERVE phiếu Nháp WF=W + UpdateDraft ApprovalWorkflowId=null (field text có giá trị) → entity GIỮ W (reproduce: trước-fix null, sau-fix W) + sanity TenGoiThau/DiaDiem vẫn update / (2) CHANGE WF=W1 + gửi W2 (≠null) → đổi W2 (null-safe chỉ chặn null KHÔNG chặn đổi) / (3) bonus mirror BudgetPeriodAmount null-safe S61 (cùng pattern bug-class S42). ⚠️GOTCHA: `PurchaseEvaluation.ApprovalWorkflowId` FK Restrict thật → PE seed PHẢI ref WF row thật (random Guid → SQLite Error 19 FK fail; lần đầu RED). Fix: `SeedWorkflowAsync(db, code)` ApplicableType=DuyetNcc khớp PE Type (CHANGE case validate block line 253-266 cũng cần WF thật); PRESERVE case request-null short-circuit validate NHƯNG seed vẫn cần FK hợp lệ. IdentityFixture (Changelog Add). No prod bug — code đúng spec sau fix. Tag [s85b, pe-updatedraft, wf-preserve, root-fix-bug-class-s42, null-safe-guard, absolute-set→null-safe, approvalworkflowid-fk-restrict-seed-real, mirror-budget-nullsafe, test-after-bugfix]. Prev 371 (S85 +5 PE urgent DRAFTER-self-unset) ← S85 +5 PE urgent DRAFTER-self-unset (test-after authz, mirror PeUrgentToggle): em main S85 restructure handler `PurchaseEvaluationUrgentFeatures.cs` thêm nhánh UNSET cho NGƯỜI KHAI (`isDrafter = currentUser.UserId == entity.DrafterUserId`) → drafter GỠ clear CẢ 2 cờ (giống Admin), SET vẫn role-only (drafter KHÔNG tự gắn). EXTEND `PeUrgentToggleAuthzTests.cs` 11→16: FakeCurrentUser.UserId→`init` (settable) + SeedPeAsync +`drafterUserId` opt param. NEW 5: (10) Drafter role-thường UNSET→clear cả 2 no-Forbidden (pre-seed ByPro để prove CLEAR) / (11) Finance(non-drafter non-TP) UNSET→Forbidden`*GỠ*`+no-mutate cả 2 / (12) Drafter SET→Forbidden`*đánh dấu*` (drafter chỉ gỡ, không gắn) / (13) Drafter UNSET chỉ-ByCcm-bật→clear cả 2 (drafter-clear độc lập cờ-đang-bật) / (14) Drafter+Procurement-no-DeptManager UNSET→clear CẢ 2 qua nhánh isDrafter (đối chứng test6 TP-PRO chỉ clear cờ-vai — isDrafter ưu tiên/độc lập isProTp). 11 test S77c cũ vẫn xanh (không động nhánh drafter). No prod bug — code đúng spec S85. Prev baseline 366 (task-stated, S78-S84 thêm test MEMORY chưa ghi). Tag [s85, pe-urgent, drafter-self-unset, clear-both, set-role-only, isdrafter-priority-over-isProTp, no-mutate-on-forbidden, test-after] ← S77c CORRECTION urgent-toggle SYMMETRIC→ASYMMETRIC (S77b symmetric tests RED vs prod): anh chốt FINAL gate BẤT-ĐỐI-XỨNG theo `request.IsUrgent` — em main đã sửa prod `PurchaseEvaluationUrgentFeatures.cs:49-55` `isPro = IsUrgent ? hasPro : (hasPro && isDeptManager)` + `isCcm = IsUrgent ? hasCcm : (hasCcm && isDeptManager)`; Forbidden-msg nhánh-theo-IsUrgent (SET `*đánh dấu phiếu gấp*` / UNSET `*GỠ cờ gấp*`). REWRITE `PeUrgentToggleAuthzTests.cs` 12→11: **SET = role-chức-năng-đủ** (plain Procurement SET→OK ByPro / plain CostControl SET→OK ByCcm / Admin SET→both) — bỏ hết 2b/2c/2d DeptManager-alone-restriction của S77b (không còn áp cho SET); **UNSET = role AND DeptManager** (plain-PRO UNSET→Forbidden`*GỠ*`+no-mutate flag-still-true pre-seed urgent / plain-CCM UNSET→Forbidden / PRO+DM UNSET→clear-ByPro CCM-preserved / CCM+DM UNSET→clear-ByCcm PRO-preserved / Admin UNSET→both-clear); 9a Drafter-SET→Forbidden`*đánh dấu*` / 9b Finance-SET→Forbidden / 9c UnknownPe→NotFound TRƯỚC authz. No prod touch — prod ĐÃ asymmetric, test theo CODE (S34). Prev S77b 354 (symmetric, superseded) ← S77 +7 PE Mig 57 suggested-price NOTE (test-after, mirror S74 §4b CcmNote): `UpdatePeSuggestedPricePro/CcmCommand` +`Note` (string?) absolute-set→`Pro/CcmSuggestedPriceNote` (overwrite always incl null=clear); rides SAME role-gate as price (PRO/Admin · CCM/Admin) fail-closed TRƯỚC side-effect; validator `Note.MaximumLength(1000)`. Handler ctor `(db, ICurrentUser)` 2-dep + record arity UNCHANGED on existing args (Note=null default → 5 existing `new UpdatePeSuggestedPrice*Command(...)` call-sites still compile, KHÔNG cần vá). NEW 7 → `PeSuggestedPriceSetterAuthzTests.cs`: PRO-note+Min/Max persist (note KHÔNG clobber price) / Admin-PRO-note / CCM-note+price persist / null-clear PRO (pre-seed note→null=cleared) / null-clear CCM / non-priv→Forbidden+note&price unchanged (no partial-write) / PRO↔CCM note independent + validator 1001-char invalid·1000 valid. No prod bug — code đúng spec (note absolute-set + rides price gate, intentional). Prev 344 ← S76 +5 PE Mig 56 PRO-column-split (spec-change+compile-fix arity): UpdatePeBudgetProCommand record 3→4 param `(PeId, ProInitialAmount, ProAdjustmentAmount, ProNote)`; handler set ProInitial+ProAdjust absolute-set (KHÔNG còn ProEstimateAmount). Vá 5 PRO call-site `new UpdatePeBudgetProCommand(...)` thêm arg ProAdjust + rename assert `.ProEstimateAmount`→`.ProInitialAmount` (handler giờ set ProInitial). Capability `FullAmount`: hasCcm?CCM:proFull(ProInitial+ProAdjust); FullIsEstimate=!hasCcm&&hasPro; DTO +2 field cuối ProInitial/ProAdjust. NEW 5: PRO set both incl ProAdjust ÂM persist / validator ProInitial<0 invalid + ProAdjust ÂM valid (mirror CCM no-sign-constraint) / full=proFull(100+50=150)+DTO-surface / full=proFull ÂM-adjust(100-30=70 no-clamp). Full-fallback seed `ProEstimateAmount=500`→`ProInitialAmount=500` (capability đọc ProInitial). **Handler ctor `(db, ICurrentUser)` 2-dep UNCHANGED**. ProEstimateAmount=LEGACY (Mig 56 backfill→ProInitial, FE bỏ). No prod bug. Prev 339 ← S74 +5 PE Mig 55 CcmNote (compile-fix arity + test-after): UpdatePeBudgetCcmCommand record +`string? CcmNote` (4 param) → fix 3 existing `new UpdatePeBudgetCcmCommand(...)` thêm `null` arg4 (PeWorkItemBudgetTests.cs line 388/407/421); NEW 5 test mirror ProNote: CostControl-set / Admin-set / null=clear-absolute-set (pre-seed prove not vốn-dĩ-null) / Procurement→Forbidden no-mutate (fail-closed role-gate TRƯỚC EnsureTrackedAsync+side-effect, AsNoTracking re-read) / Initial+Adjustment+CcmNote all-persist-together. **Handler ctor `(db, ICurrentUser)` 2-dep UNCHANGED** — chỉ COMMAND record +CcmNote. No prod bug. Prev 334 ← S72 +28 PE Mig 54 (spec-change+test-after): PeCcmThresholdFinalizeTests 6→11 (AUTO→OPT-IN finalizeByCcmDelegation) + NEW PeApprovedPriceFinalizeTests 10 (giá chốt) + NEW PeSuggestedPriceSetterAuthzTests 13 (2 setter role-gate). Prev 306 ← S69b +14 PE 2 feature anh Kiệt FDC (test-before-merge SECURITY/FINANCIAL): `PeCcmThresholdFinalizeTests.cs` (5, Services ns, value-threshold CCM-finalize ApproveV2Async) + `PeUrgentToggleAuthzTests.cs` (9, Application ns, urgent-toggle role authz). Prev 292 ← S69 +6 Office golive permission-seed (`OfficeModulePermissionSeedTests.cs`, test-after, mirror HrmProfilePermissionSeedTests S67). Prev 286 ← S67 +23 HRM test-after [DepartmentTreeTests 8 cycle-guard/rollup/orphan + PeHoSoLinkTests 9 absolute-set (⚠️spec-drift: HoSoLink gửi null=CLEAR, KHÔNG null-safe như Budget*/WorkItemId) + HrmProfilePermissionSeedTests 6 reflection private-static revoke→seed chain]. **em main PROXY-RECORD** — return truncated #53 (chết lúc update MEMORY), 3 file delivered + `dotnet test` 286 PASS verify-on-disk. Prev 263 (S61 +22 PeWorkItemBudget −14 BudgetPolicy; Domain 58→45 drop Budget module). Pre = 254 (S60). > Pattern S67: private-static seed/init → invoke qua REFLECTION (`GetMethod(name, NonPublic|Static)` + `Invoke(null, [db, roleManager, NullLogger.Instance])`); seed MenuItem rows TRƯỚC Permission (FK MenuKey→MenuItem.Key Cascade, SQLite Error 19 nếu thiếu). Cycle-guard test: SqliteDbFixture đủ (no User); rollup-count test cần IdentityFixture (đếm User.DepartmentId active). Run: `dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1` (MSBuild OOM → serialize build) @@ -59,15 +59,14 @@ Test theo CODE (single source truth), document mismatch header comment + report. - **2026-06-18 (S74 PE Mig 55 CcmNote — compile-fix arity + test-after):** +5 test `PeWorkItemBudgetTests.cs` → **334→339 PASS** (45 Domain + Infra 289→294, 0 fail). Mig 55 additive: `PeWorkItemBudget.CcmNote` (string? nvarchar(1000)) + `UpdatePeBudgetCcmCommand` record 3→**4 param** `(PeId, InitialAmount, AdjustmentAmount, CcmNote)` + DTO `PeBudgetSummaryDto +CcmNote` (slot after AdjustmentAmount). **⚠️ Handler ctor `UpdatePeBudgetCcmCommandHandler(IApplicationDbContext db, ICurrentUser)` 2-dep UNCHANGED** — chỉ COMMAND record đổi arity, KHÔNG đụng handler signature. **Compile-fix:** grep `new UpdatePeBudgetCcmCommand` toàn tests/ = 3 hit (line 388/407/421 PeWorkItemBudgetTests), thêm `null` arg4 mỗi cái. **NEW 5 test (region 4b, mirror ProNote pattern S61):** (1) CostControl set CcmNote→persist / (2) Admin set→persist / (3) **null=clear absolute-set** (pre-seed CcmNote="cũ" → null request → BeNull, chứng minh CLEAR không phải vốn-dĩ-null) / (4) **Procurement→ForbiddenException + record no-mutate** (fail-closed: role-gate line 152-157 TRƯỚC WorkItemId-check + EnsureTrackedAsync + side-effect; AsNoTracking re-read assert CcmNote/Initial/Adjustment giữ nguyên) / (5) Initial+Adjustment+CcmNote all-persist-together 1 lệnh. Handler `rec.CcmNote = request.CcmNote` absolute-set; changelog "ghi chú CCM cập nhật" khi `oldCcmNote != request.CcmNote`. **No prod bug** — code đúng spec (mirror ProNote, fail-closed role-gate giống Initial/Adjustment). Tag [s74, pe-mig55, ccmnote, compile-fix-arity, absolute-set-null-clear, fail-closed-no-mutate, mirror-pronote, test-after]. - **2026-06-18 (S72 PE Mig 54 anh Kiệt FDC — SPEC-CHANGE + 2 test-after FINANCIAL):** +28 test → **306→334 PASS** (45 Domain + Infra 261→289, 0 fail). BE Mig 54 committed+builds. Mig 54 fields PE: `ProSuggestedMin/MaxPrice` + `CcmSuggestedPrice` + `ApprovedPriceAmount` + `ApprovedPriceSource`; `TransitionAsync`/`ApproveV2Async` +3 param `finalizeByCcmDelegation`(bool) + `approvedPriceAmount`(decimal?) + `approvedPriceSource`(string?). **① SPEC-CHANGE CCM-finalize AUTO→OPT-IN — UPDATE `PeCcmThresholdFinalizeTests` 6→11 (Services ns):** S69b AUTO (gói=ceoThreshold`→Conflict, strict-`<` giữ nguyên) → ApplyApprovedPriceOnFinalize(BẮT BUỘC giá chốt human)→DaDuyet. ApproveAsync helper +3 optional param. Cover: flag-true+ngưỡng→Conflict (no-mutation reload-assert) / flag-true non-CCM→Forbidden / flag-true threshold-null→Conflict / flag-true slot-cuối+giá→DaDuyet 1-Approval no-double / flag-true đủ-ĐK null-giá→Conflict("giá chốt"). **② NEW `PeApprovedPriceFinalizeTests` 10 (Services ns) — ApplyApprovedPriceOnFinalize (private-static):** terminal DaDuyet normal-advance human valid-price→bind / null-price human→Conflict NOT-finalized(ChoDuyet reload) / garbage-source→Conflict / Theory 4 valid-source {Ncc,ProMin,ProMax,Ccm} each-set + **isSystem null-price→no-throw no-set qua REFLECTION** (⚠️OBSERVATION report: isSystem KHÔNG reachable qua public ApproveV2Async — approve-branch gate `decision==Approve` còn isSystem cần `AutoApprove`; PE no SLA-auto-job chỉ Contract SlaExpiryJob → isSystem-exempt = defensive/dead qua V2-approve; test contract mức UNIT) + đối-chứng isSystem-false→Conflict + isSystem-true amount+garbage-source→Conflict. Reflection unwrap TargetInvocationException→inner. **③ NEW `PeSuggestedPriceSetterAuthzTests` 13 (Application ns) — 2 setter handler 2-dep db+ICurrentUser mirror PeWorkItemGuard:** PRO-cmd Procurement/Admin set Min/Max·CostControl/Drafter→Forbidden+no-set·validator Min>Max invalid+negative invalid+single/null valid·unknown-PE→NotFound(existence TRƯỚC authz). CCM-cmd CostControl/Admin set·Procurement→Forbidden·validator negative invalid·NotFound. **No prod bug** — code đúng spec (OPT-IN finalize an-toàn-hơn AUTO, fail-closed order intentional). FakeCurrentUser configurable-roles. Tag [s72, pe-mig54, ccm-finalize-opt-in, spec-change, approved-price, applyapprovedprice-private-static-reflection, issystem-unreachable-observation, suggested-price-setter-authz, fail-closed, test-after]. - **2026-06-17 (S69b PE 2 feature anh Kiệt FDC — test-before-merge SECURITY+FINANCIAL workflow):** +14 test → **292→306 PASS** (45 Domain + Infra 247→261, 0 fail). BE done+builds, mirror harness PeSubmitGuardAndBypassTests/PeWorkItemGuardTests. **FEATURE B value-threshold CCM-finalize (`PeCcmThresholdFinalizeTests.cs` 5, Services ns, ApproveV2Async line 816-854):** NV duyệt role=CostControl + `aw.CeoApprovalThreshold!=null` + `winnerQuoteTotal < ngưỡng` + chưa-slot-cuối → Phase=DaDuyet bỏ CEO + pointers/SLA null. **⭐ BOUNDARY load-bearing: predicate `winnerQuoteTotal < ceoThreshold` STRICT-less-than (line 838)** → gói==đúng-ngưỡng = KHÔNG finalize = advance. Cover: (1)⭐LOAD-BEARING CCMngưỡng→advance / (3) threshold-null→advance kể-cả-CCM+gói-1đ (backward-compat) / (4) non-CCM(PRO)PRO>CCM intentional). FakeCurrentUser configurable-roles ctor. Reuse NoOpNotificationService internal qua `using ...Tests.Services`. Tag [s69b, pe-ccm-threshold-finalize, value-threshold, strict-less-than-boundary, role-based-routing, urgent-toggle-authz, forbidden-no-mutation, else-if-short-circuit, test-before-merge]. - -- **2026-06-17 (S69 Office golive permission-seed regression — test-after SECURITY invariant, public Văn phòng số):** +6 test `tests/.../Application/OfficeModulePermissionSeedTests.cs` → **286→292 PASS** (45 Domain + Infra 241→247, 0 fail). Mirror `HrmProfilePermissionSeedTests` (S67) — SAME reflection harness (invoke 2 private-static `RevokeTemporarilyHiddenModulesAsync` + `SeedAllRolesOfficeModulePermissionsAsync` qua `GetMethod(name, NonPublic|Static).Invoke(null, [db, rm, NullLogger.Instance])`; SqliteDbFixture/IdentityFixture; seed MenuItem rows TRƯỚC Permission FK Cascade). **KHÁC HRM:** Office grant mở **CanRead AND CanCreate** (HRM read-only) trên allow-list **16 key**; HRM chỉ 2 key. Chain = revoke (StartsWith("Off")→all false non-Admin) → office-grant (allow-list→read+create, upgrade-only). **Cover:** (1) chain non-Admin allow-list-16 → read+create=true + **excluded-3 stay hidden** (`OffPhongHopManage`/`OffAttendanceReport`/`OffChamCong` ⭐ LOAD-BEARING security assert) / (2) allow-list Update+Delete stay false / (3) no-leak HRM-dashboard+Personal stay hidden / (4) Admin not-revoked keeps all incl excluded-3 / (5) create-missing-row read+create=true update/delete=false + excluded NOT created / (6) **upgrade-only preserves admin-raised Update/Delete=true** (office-grant chỉ đụng Read/Create, KHÔNG hạ). **No prod bug** — seed logic đúng spec (excluded-3 confirmed hidden, upgrade-only không phá quyền admin). Tag [s69, office-golive, permission-seed, security-invariant, excluded-3-hidden, read+create-grant, upgrade-only, reflection-private-static, test-after]. +- **S69 (aged to one-line):** Office golive permission-seed regression +6 `OfficeModulePermissionSeedTests.cs` (test-after SECURITY). Mirror HrmProfilePermissionSeedTests reflection harness (2 private-static revoke→seed via GetMethod NonPublic|Static; MenuItem rows TRƯỚC Permission FK Cascade). KHÁC HRM: Office grant Read AND Create trên 16-key allow-list. Load-bearing: excluded-3 (OffPhongHopManage/OffAttendanceReport/OffChamCong) stay hidden + upgrade-only preserves admin-raised Update/Delete. No prod bug. - **2026-06-12 (S60 UAT anh Kiệt — 2 feature PE submit branch, test-after build PASS):** +14 test `tests/.../Services/PeSubmitGuardAndBypassTests.cs` → **240→254 PASS** (58 Domain + Infra 182→196, 0 fail). Mirror `PurchaseEvaluationWorkflowServiceGuardTests` (IdentityFixture+SQLite, reuse `NoOpNotificationService` internal). **F1 Section 3 guard (8):** submit branch (DangSoanThao/TraLai→ChoDuyet) build `missing` list 4 mục → ConflictException msg gộp prefix `'Chưa đủ thông tin mục 3 "Đơn vị NCC/TP được chọn"...'` + join `' · '`. Cover: thiếu cả 4 / winner-only / winner+quote=0 / budget (cả null+manual=0) / comparison / **attachment gắn NCC (PES_Id!=null) KHÔNG đếm bảng so sánh = vẫn Conflict** (predicate PES_Id==null) / đủ-4-manual-budget→ChoDuyet / đủ-4-BudgetId→ChoDuyet. **F2 drafter-bypass (6, V2-only `ApplyDrafterBypassOnSubmitAsync`):** k=drafterSlots.Max(Order) bước đầu → auto Cấp 1..k. Cover: drafter=TP(2/2)+2bước→StepIdx=1/Lvl=1+opinion 1 row slot TP+2 AutoApprove / drafter=NV(1/2)→Lvl=2 cùng bước+opinion slot NV / drafter ngoài bước đầu→KHÔNG bypass StepIdx=0 Lvl=1 0-auto / 1-bước+drafter cấp cuối→DaDuyet pointers null SLA null / V1(awId null)→submit OK no-bypass no-crash / TraLai-resubmit→bypass áp lại opinion UPSERT 1 row + approval cộng dồn 2 vết. **⚠️ GUARD-FIRST:** mọi bypass-test PHẢI dựng PE đủ 4 ĐK Section 3 (winner+quote>0+manual-budget+comparison-attach) qua guard. **Seed pattern S60:** `SeedWinnerWithQuoteAsync`(PES+Detail+Quote ThanhTien) map winner→quote sum · `SeedComparisonAttachment`(PES_Id=null) · `SeedWorkflowAsync(Guid[][] stepApprovers)` build multi-step V2 1-NV/cấp. **Opinion-only-ownSlot invariant:** bypass cấp NV skip KHÔNG ghi opinion (chỉ Approval AutoApprove + Changelog vết); assert `opinions.HaveCount(1)` + `ApprovalWorkflowLevelId==drafterSlot.Id`. **No prod bug** — code đúng spec, test theo CODE (S34 rule). Tag [s60, pe-submit-guard, section3-completeness, drafter-bypass, v2-only, guard-first, opinion-ownslot-only, test-after]. -- **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 145→158, 0 fail). **GetAssignableItStaff (6):** Admin→CanReassign=true + 2 IT-active ordered FullName (Cao **Tiering rule (S40):** giữ **2-3 session gần nhất**. Cũ hơn → `docs/changelog/sessions/`. Full brief history pre-S40 → `docs/_archive/HANDOFF-preS40-fullhistory.md`. -**Last updated:** 2026-06-22 (S84 — **bootstrap + flush session-start cap-echo v3 + commit S83 cicd harvest-orphan (LIGHT, 0 production code)** — 2 monitor INFORM → flush `session-start.md:114` `60/20/16`→**`220/60/50`** (+canonical-pointer chống tái-drift; detector C2 không track cap-number) + commit `cicd-monitor/MEMORY.md` harvest S83 sót-closeout (Run #333 + gotcha #69-REFINE). Lesson `feedback_derived_flush_execution`: derived→canonical flush = em-main execution KHÔNG gate user-confirm; chỉ ĐỔI-số = quyền anh. ⚠️ restart CLI (command `.md` no hot-reload). State GIỮ NGUYÊN Mig 57·88·356·71·`CsJetgZH`/`BVS0ApIm`. → log `2026-06-22-S84-session-start-cap-flush.md`. · **Prev S83** — **(1) H-15 v3 memory-budget full-parity (lead 220K/sub 60K/wf 50K, anh owner-directive) + (2) fix PE require-workflow create+submit prod-verified Run #333** — 2 commit: `2c7fd63` (gov docs-only CI-skip) + `fc1f19d` (PE fix). **H-15 v3:** full AI_INFRA parity (sửa self-shrink S82) + NEW `spawn_fill_directive` (nạp sub tới budget bằng prompt GIÀU — byte-cap MEMORY.md = 1 lát) + engine §G.5 + mark **v3-delta** `RC-pqhuy1987-22-06-2026-16-35-37` (anh-directed). **PE fix:** validator `NotEmpty(ApprovalWorkflowId)` + submit-guard (sau Section-3) chặn phiếu null-workflow ("quy trình cũ", kẹt V1-legacy). Diagnose A/040 **tự-khỏi-reload = cache** (KHÔNG đụng prod). test-before RED→GREEN, full-suite bắt **9 đỏ** → triage (2 spec-conflict rewrite V1-deprecated + 6 collateral giữ + 1 validator). Test 354→**356**. **#69-REFINE:** bundle KHÔNG rotate vì 0 fe-src (Vite deterministic) — ship-signal = Last-Modified KHÔNG hash-delta. Chi tiết → `## S83` dưới. ⚠️ restart CLI (budget v3 runtime). State: Mig 57·88 bảng·**356 test**·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm` Run #333. · **Prev S82** — **adopt Harness-15-v2 (Tầng-1 hot-feed-lớn + L2/L3 bỏ-trần + %-print 2-đầu-phiên + ranh-giới vai-trò), 0 production code** — anh `/check-email AI_INFRA và /adap-apply all step by step cẩn thận`. 1 thư mới H15-v2-notify (verify ✓✓) + fan-out 29 vs 22 → CHỈ H15-v2 MỚI (7 còn lại verify đã-phủ S72/S75/S79). em-main IMPLEMENT D9 (6 edit: L1 12K→per-role lead 60K/sub 20K/wf 16K · L2/L3→NO-CAP · §G.4 · §2.1.6+§L.b(c) %-print · mark refine) + REVIEW Workflow `wf_04667b25-5fa` **3/3 PASS** (3 MINOR fixed). Ranh-giới vai-trò: con-số = quyền anh, AI thực-thi + báo-% (sửa framing S81 "lead-authority" gộp nhầm AI-lead↔owner). mark H-15 **v2-delta anh-confirm** `RC-pqhuy1987-21-06-2026-01-58-01`. commit `aa3f0fe` push (docs-only CI-skip) + email AI_INFRA `a749bb6bd1be`. Chi tiết → `## S82` dưới. ⚠️ restart CLI (%-print runtime §2.1.6 + §L.b(c)). State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. · **Prev S81** — **adopt Harness-15 memory-budget per-agent (token-governor + value-gate + work-state block), 0 production code** — anh `/check-email AI_INFRA và /adap-apply step by step, review sau lẫn imple, report trung thực`. 0 new directed email; fan-out → CHỈ H15. em-main IMPLEMENT (8/8 🔴 floor) + REVIEW Workflow `wf_b7f3c8ac-b53` (3-lane PASS/PASS/HONEST → bắt 2 CONCERN honesty → fixed). Chi tiết → `## S81` dưới + adap-report. ⚠️ restart CLI (session-start §2.1.5). ✅ mark H-15 stamped Active-High (`RC-…23-07-37`). State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. · **Prev S80** — **curate L1 over-cap memory → L2 archive (em-main single-writer, 0 production code)** — anh `/session-start` (bootstrap clean: 2 monitor CLEAN · detector 26-flag baseline-safe · test 354) → "check làm thử đi". archive-gate DRY-RUN: reviewer 45→**10KB** · investigator-codebase 40→**10KB** · cicd-monitor 39→**12KB** = cả 3 **keep-floor-hit cannot-auto-drain** → manual condense-with-archive: 31 entries byte-exact `sed` → `archive/2026-06.md` (**+N −0**, 0 byte-loss) + 31 `_INDEX` substring pointer → **A7 GATE PASS 217/217**. Stale foundation counts flushed (130/263→354·55→71·Mig40/55→57·84→88·bundle→#330). **State GIỮ NGUYÊN: Mig 57·88 bảng·354 test·gotcha 71.** **Lesson:** `_INDEX` substring **quote-free** (A7 quote-parser cắt escaped-quote `\"PURO\"` → FAIL 1, gate bắt). **🔴 NEXT (em):** frontend-designer 26KB + test-specialist 28KB WATCH (A6 strike-1<2). → log `2026-06-20-S80-curate-l1-overcap.md`. · **Prev S79** — **adopt User-Mark (H-12/13) canonical §P + Harness-14 (Eval/Budget/Outcome) + chữ-ký RC** — anh `/check-email AI_INFRA` + `/adap-apply` step-by-step (workflow double-check mỗi step), rồi gõ `/user-mark-active-high` "áp đầy-đủ chính-xác nhất theo AI_INFRA, không hỏi thêm". em main + **4 Workflow** (`wf_82337f7f-95c` invest → `wf_a7cbe93e-912` review → `wf_9d3beebb-a95` align-re-review → `wf_4d4eba6f-8a0` H14-review). **0 production code.** Bản đầu em phỏng-theo broadcast (cấp MUST/TRACK/ANCHOR/OFF) → anh trỏ canonical → **align FULL §P (P1-P10):** 4 lệnh `/user-mark-{active-high,active,medium,disable}` + ledger `.claude/governance/ACTIVE-MARKS.md` (Active-High/Active/Medium/Disable + display-filter) + `harness-11-engine.md §E`(P1-P10)+**§F**(H-14 3-mức maturity honest) + `rules.md §6.6` (objective-criteria KHÔNG quy-mô-đội/thời-gian-tuổi) + session-start §2.1.4/session-end §L.b(h) mark-display. **3 mark Active-High stamped** anh-confirm (`RC-pqhuy1987-20-06-2026-10-29-09/10/11` = objective-criteria/User-Mark/time-age, mirror AI_INFRA 3-mark, SE timestamp riêng P1 forward-only). completeness-gate H-6→H-13 **ĐẠT** (H-8 11/11 inherit no-`[1m]` · H-7 Cat-6 real). §F floor 6/6 + maturity HONEST + SE-state ACCURATE. **3 adap-report** + email ai_infra (body-hash `7b8615b3`) + check-email STAGE 2 move 2 email + `_index`. **Bài học `feedback_canonical_spec_over_broadcast`:** broadcast cô-đọng→canonical-command/§P là spec THẬT (phải pull, đừng phỏng-theo) · report-before-stamp dogfood (lệnh tự bắt báo-cáo-trước-stamp = đúng lệnh) · residual own-diary OK (D9 áp canonical, không cấm sub ghi diary riêng). detector clean sau align (0 C1/C3 mới). **State THẬT GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · menu 54 · bundle `CsJetgZH`/`BVS0ApIm`.** **🔴 NEXT (anh):** ⚠️ **restart CLI** (đầu việc) — activate 4 lệnh `/user-mark-*` + session-start §2.1.4/session-end §L.b(h) mark-display + engine §E/§F. Sau restart, session-start tự hiển-thị 3 mark Active-High. **🔴 NEXT (em):** curate L1 over-cap reviewer/cicd/investigator-codebase (carry 7-session + S79 workflow-spawn; inv 39.8KB +diary) — manual SPLIT/condense, archive-gate A7 GATE; + §7-header `rules.md` "77 test" stale → C2/monthly-audit. **Pending product (carry):** "Ngưỡng giá CEO" Mig 54 Designer UAT · "C" chuyển phiếu→dự án chờ spec. **Ops S58/S59:** tzutil VPS · anh Chương email typo · 5 real-staff pw · gán CNTT. Chi tiết → `2026-06-20-S79-user-mark-harness-14-adopt.md`. · **Prev S78** — **PE: đính kèm file khi DUYỆT (UAT Tra Sol / 5 tester)** — người duyệt tải file lên ngay lúc Duyệt thay vì Trả lại phiếu. Reuse hệ attachment + enum `ApprovalAttachment=5` **MIGRATION-FREE** (int-stored, endpoint+authz có sẵn → approver upload được). FE 2 app SHA-identical: `PeWorkflowPanel` picker multi-file + upload-trước-chuyển-phase (file lỗi=không duyệt) + mục "📎 File đính kèm khi duyệt" + 2 filter fix loại purpose=5 khỏi "Bảng so sánh" (gotcha **#71** proxy-predicate pollution). commit `7886fd0` → **Run #330 PASS** (test 354, bundle admin `CsJetgZH`/user `BVS0ApIm`, NO migration, smoke 4×200). 3 lỗi em tự bắt review-trước-deploy (authz-verify · filter-pollution #71 · Dialog mirror-truncate fe-admin). em-main-led + self-gate (grep no-leak) + cicd-monitor verify. **🔴 NEXT (em):** curate L1 over-cap (carry 6 session) reviewer **45.2KB** + cicd 38.8KB + inv 35.7KB keep-floor-hit manual-condense (archive-gate A7 GATE PASS 186/186). **NEXT UAT:** mở phiếu chờ duyệt → Duyệt → "+ Chọn file đính kèm" → Xác nhận → file ở mục "📎 File đính kèm khi duyệt". Chi tiết → `2026-06-19-S78-pe-attach-file-on-approve.md`. · **Prev S77** — **PE UX batch: 10 deploy prod-verified #320→#329 (anh Kiệt FDC + Tra Sol + Bích Phượng UAT realtime, HMW-mode ON)** — cờ GẤP pill mọi danh sách+inbox · focus→revert list bám-trái · **Mig 57** ô ghi chú giá đề xuất PRO/CCM + số phân cách VND + chính tả "Bảng so sánh giá" + guard #70 · số âm đỏ-ngoặc · mục con thụt+gạch-đầu-dòng · cờ gấp **BẤT ĐỐI XỨNG** GẮN=NV/GỠ=Trưởng phòng(DeptManager) · tách chọn-phiếu(inline) khỏi mở-rộng(overlay)+nút "Xem mở rộng" · chuông báo người duyệt vào cấp họ · banner phiếu Trả-lại. Mig 56→**57** · test 344→**354** (+10) · bundle cuối admin `BqKD3Y23`/user `Cn-i349D` (Run #329). **3 lỗi em tự bắt review-TRƯỚC-deploy** (guard#70 stale-echo · luật asymmetric Tra Sol clarify giữa-chừng · double-mount Task H). FD process-death Task H → recover-disk. **🔴 NEXT (em):** curate L1 over-cap reviewer **45KB** + cicd 37.6KB + inv 35.6KB keep-floor-hit manual-condense (archive-gate A7 GATE PASS 186/186 integrity OK). **NEXT UAT:** cờ gấp (GỠ chỉ TP) · chuông báo người duyệt · banner Trả-lại · Xem mở rộng · ô ghi chú PRO/CCM. Chi tiết → `2026-06-19-S77-pe-ux-batch-10-deploy.md`. · **Prev S76** — **PE ngân sách MA TRẬN 3 cột (Dự án|PRO|CCM) + bảng lưới `` viền-ô + badge quyền-NS theo role** — anh Kiệt FDC + chị Trà Sol go-live. anh giao `/ultra-on` "step-by-step + workflow-review-per-step, hoàn chỉnh rồi deploy". **3 commit prod-verified:** `e33481e` (feature Run #318 — Mig 56 + ma-trận-3-cột + badge designer/flow `BhFDF9IJ`/`BAkuRl3C`) → `21d1f4e` (bảng lưới `
` theo phản hồi anh "chưa chia cột giống Excel", Run #319 **`jOqxW4-p`**/**`DbsznVvR`** smoke 3×200). Mig 56 +ProInitial/ProAdjust cột PRO (additive + data-migrate ProEstimate→ProInitial 4 rows prod). Part 1 mỗi phòng sửa cột mình (PRO canEditPro / CCM canEditCcm / Dự án FE-only). Part 2+3 badge "✎ NS PRO/CCM" cạnh approver (display-only suy-role) ở Designer + flow Duyệt NCC. Test 339→**344**. reviewer bắt **race mất-dữ-liệu** Part 1 → vá `useIsFetching` 2 app (gotcha #70). **🔴 NEXT (em):** curate L1 over-cap reviewer **45KB** + inv-codebase 35KB (keep-floor-hit → manual condense) + cicd 29KB + test-spec 28KB. **NEXT (anh/anh Kiệt):** UAT bảng lưới bằng PRO/CCM (Ctrl+F5). Chi tiết → `2026-06-19-S76-pe-budget-matrix-table-grid.md`. · **Prev S75 (2026-06-18)** — **Harness-11 adopt: engine bộ-nhớ-và-governance tự-bảo-trì + 2 double-check** — anh giao `/check-email AI_INFRA` + `/adap-apply` (mỗi stage workflow-review) + double-check ×2 + finalize report + push + session-end. em main + **5 Workflow** (audit `wf_7fdc3bd5-930` → implement `wf_c5e5844e-7c1` → review `wf_d7ca1ff8-942` → double-check `wf_a0b68d2f-30e` → checklist-verify `wf_39cd4cbe-f07`). **0 production code.** Built 2 NO-API detector-script (`governance-detectors.ps1` C1-C5+B3 runtime **26 flag** bắt drift thật, C4 0-self-match · `memory-archive-gate.ps1` PHẦN A hysteresis/keep-floor/2-strike/A7 186/186) + `docs/governance/harness-11-engine.md` canonical (3-tier D5/D6/D7 + one-direction-lock D8) + **B1 ×11 count→pointer** (drift mig53→55/test306→339/gotcha68→69/table93→88 RESOLVED) + cadence-wire D1/D2 + agents/README. **completeness-gate FORMAL ĐẠT** (B 4/4 + C 5/5 + D 11/11; D5/D6/D7 explicit + D8 codify=YES). gotcha #30 reinforced (box-glyph ├└─ KHÔNG vào .ps1, kể cả qua Edit). 3 commit `e70c046`+`ae957c4`+`aa09e99` pushed + adap-report + email ai_infra (`2316773229f2`). State GIỮ NGUYÊN Mig 55·88 bảng·339 test·gotcha 69·bundle `BYF5vIMJ`/`CB-tiRxd`. **🔴 NEXT (anh):** restart CLI (cadence §2.1.3/§L.b + ef-core skill); curate reviewer 38.8KB+inv 31.5KB+cicd 26.8KB over-cap. Chi tiết → `2026-06-18-S75-harness-11-adopt.md`. · **Prev S74** — **PE ô "Ghi chú từ CCM" ngân sách gói thầu (Mig 55)** — anh forward 2 luồng Zalo (Trà Sol + Kiệt FDC) "CCM giống PRO cho nhập + ghi chú, hiện 0 hết" → em-main BE+Mig55 ∥ implementer-frontend FE 2 app SHA-mirror ∥ test-specialist (chết rate-limit → recover-disk). 2 fork anh chốt: **thêm CcmNote (Mig 55)** + **GIỮ phân vai CCM** (CostControl/Admin). Entity +CcmNote mirror ProNote · UpdatePeBudgetCcmCommand +CcmNote absolute-set role-gate · DTO+controller+mapping · FE dòng "Ghi chú từ CCM" gate canEditCcm. Test 334→**339** (+5). commit `8655ebf` (cicd **Run #315 PASS** — bundle admin `BYF5vIMJ`/user `CB-tiRxd`, Mig 55 applied prod). **"0 hết không nhập" = tài khoản thiếu role CostControl (KHÔNG bug)** → UAT bằng CCM/Admin. **🔴 NEXT (anh/anh Kiệt):** UAT ô CCM bằng tài khoản CCM/Admin + carry "Ngưỡng giá CEO" Mig 54. Chi tiết → session log `2026-06-18-S74-pe-ccm-note.md`. · **Prev S73** — **Mig 54 PE giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích (anh Kiệt FDC, go-live thứ Hai 22/06)** — em main + 6 sub + 2 review-workflow, 2 commit prod-verified (`1d86abc` feature Run #313 + `6aa4dcb` FE empty-candidates fix). Mig 54 5-cột additive-nullable + 2 setter role-gate + ApproveV2 ③ AUTO→OPT-IN + ① bind giá chốt; FE 2 app SHA-mirror; test 306→334. **Workflow review:** R1 schema-force 1/4 lane → R2 free-text 2/3 PASS (rủi ro FE empty-candidates UNREACHABLE per submit-guard `:194`). Bài học: review fan-out free-text/hmw KHÔNG ép-schema. **Governance:** em lệch mandate auto-Workflow → cam kết báo-TRƯỚC-khi-lệch. **🔴 NEXT (anh/anh Kiệt):** cấu hình "Ngưỡng giá CEO" Designer + test 3 luồng + xác nhận CCM-trước-CEO. Chi tiết → session log `2026-06-18-S73-pe-gia-de-xuat-ccm-done.md`. · **Prev S72** — **Harness-10 flat-refine + checklist-v2 adopt (re-audit 3-workflow) + sleep NO-OP** — audit `wf_13868efb-ea7` → implement `wf_ac43b5ff-7d1` → review `wf_d482e10d-5dd` (Harness-9 B1+B2). SE BEHIND flat → migrate run-trace SUBFOLDER→FLAT (hmw.js:103 + 5 doc; 5 run cũ giữ subfolder C8) + 2 broadcast 06-18 adopt + `/sleep-recovery-memory-l2` port (A8) + detector TAILORED-OUT + hmw.js H4.5→H8 doc-drift. **REVIEW (B2) bắt 2 lỗi IMPLEMENT-self-assess sót** (hmw.js:52 schema-stale + auto-check overclaim) → fixed (auto-check WIRED thật). em-main containment-check tự bắt reviewer residual-write (raw-Workflow no-writeGuard) → revert. B3 self-correct (runs path/count 14→22). Sleep `all`=NO-OP. **0 prod code, state GIỮ NGUYÊN.** adap-report + email ai_infra (`5f511fe5c0f2`). **🔴 NEXT (anh):** restart CLI (FLAT-runtime hmw.js + wired sleep-check + sleep-recovery skill). **🔴 NEXT (em):** curate investigator-codebase L1 28973 OVER + watch FD/test-spec. Chi tiết → session log `2026-06-18-S72-harness-10-flat-refine.md`. **Prev S71 — Harness-10 adopt: tracked run-trace folder + checklist 9-10** — em main + 3 Workflow (invest `wf_9c2cd2cd-2e7` → implement `wf_e4e46725-231` → review `wf_636bc95b-939`) per mandate Harness-9 PART 2. **0 production code**. Migrate `.claude/workflows/wave-*/` gitignored → `runs//` **git-TRACKED** (run.md+sub-md/+harvest/) + `_ledger.md` 2-nhịp + 3-layer anti-miss (L1 em-main@P1 / L2 session-start orphan-scan / L3 session-end close-gate idempotent) + **containment shift** (Harness-2 B6 "mọi tracked-change=vi-phạm" → "tracked-change NGOÀI run-folder + code-disjoint=vi-phạm"). hmw.js wave→run-trace (accept `args.run` + alias `wave`, path `sub-md/`, `node --check` PARSE-OK). **Review độc-lập (R2+R3) bắt C5 L1 over-claim** (doc nói hmw.js prompt-builder emit L1 reminder, grep engine=0 → engine no-fs → fixed path-a: L1 = em-main @P1 convention) — dogfood mandate B2 đúng. checklist 9-10: Part A (Harness-9 memory) + B (adap 2-workflow) done S70, Part C (Harness-10) 8/8 MỚI. **State GIỮ NGUYÊN: Mig 53·88 bảng·306 test·68 gotcha·menu 54·bundle admin `BgNCjwsG`/user `CBvh0vtf`.** + CLAUDE.md test-flush 263→306 (resolve H1 stale). **🔴 NEXT (anh):** restart CLI (hmw.js RUN-TRACE runtime + carry §2.1.2/Cat-6/H8). Chi tiết → session log `2026-06-18-S71-harness-10-run-trace.md` (pending). **Prev S70 —** **Harness-9 adopt: L2 archive dark-matter recovery + adap 2-workflow mandate** — em main + 3 Workflow (investigate `wf_be952f3c-97f` → implement `wf_a58e0d15-beb` → audit `wf_9520d8cd-4fe`) + 2 monitor bootstrap. **0 production code** (governance/memory only, commit `f36aab8` pushed). 4 over-cap sub-agent curate L1→L2 + `archive/_INDEX.md` (mục-lục substring sha-keyed) + `.gist.md` (4-field distill-gen:1, verbatim FROZEN) → **cả 4 < 25KB auto-inject cap** (P1 curate-debt CLOSED; ~240KB archive hết RAG-dark). PART 2/3 process-mandate codify (adap-apply 2-workflow + agents/README Upgrade S70 + session-start §2.1.2). **0-byte-loss git+sha verified** (Stage C audit + em-main self-gate khi 2 reviewer no-StructuredOutput → recovery-path). +memory-budget.json (seed-by-measure) + measure-agent-memory.ps1 + .ragignore + doc-drift 4-cite flush. adap-report + email-back ai_infra (`7c07b716e775`). **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** **🔴 NEXT (anh):** restart CLI để activate session-start §2.1.2 budget-audit + pending H8 inherit + reviewer Cat-6. Chi tiết → session log `2026-06-17-S70-harness-9-l2-recovery.md`. **Prev S69 —** **Văn phòng số (E-Office) port + golive + PE cờ gấp/ngưỡng CCM — 4 deploy prod-verified Run #305→#308, HMW-mode ON, 2 workflow fan-out**: #305 foundation PURO (shared PageHeader/KpiCard/WidgetCard + Dashboard 2-cột + sync fe-admin index.css đóng drift S66-S68) → #306 **re-skin TRỌN 10 page** (PURO layout + CSS Hồ sơ NS, phẫu-thuật-giữ-100%-logic) → #307 **Office golive public** read+create **16-key allow-list mọi role** (mirror S65, chạy SAU revoke; excluded Off_PhongHop_Manage/Off_AttendanceReport/Off_ChamCong; cicd DB-verify 16/16×13 role) → #308 **PE cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị** Mig 53 (anh Kiệt FDC sau họp sếp). **State THẬT: Mig 53 · 88 bảng · 306 test (45D+261I) · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf` Run #308.** 2 gotcha NEW (**#67** Tailwind accent palette thiếu-stop vỡ-màu-im-lặng · **#68** stale-diagnostic-background-agent → chỉ tin build sau-cùng). 2 truncation #53 (impl-backend positional-record + impl-frontend) → em main recover-disk + self-gate. **🔴 NEXT (anh/anh Kiệt UAT):** (1) cấu hình "Ngưỡng giá trị gói CEO" trong Workflow Designer (null=luồng cũ) + test phiếu < ngưỡng → CCM duyệt là xong, ≥ ngưỡng → lên CEO; (2) test cờ gấp PRO(đỏ)/CCM(xanh) → badge + notify CEO; (3) **xác nhận:** quy trình đặt CCM(CostControl)-trước-CEO + CEO = role Director (đích notify). **C (sau duyệt → chuyển phiếu đến dự án) chờ anh Kiệt spec form.** **NEXT (em):** 🔴 curate cicd-monitor **65.2KB** (worst, trend tăng) + inv-codebase 47 + reviewer 43.5 over-cap · doc-flush docs/CLAUDE.md full. Chi tiết → session log `2026-06-17-S69-vanphong-golive-pe-urgent-threshold.md`. **Prev S68 —** **Hồ sơ NS header chi tiết NV: làm nổi bật + fix tên render đen→trắng** — em main solo, 3 commit (2 FE + 1 docs), 2 deploy prod-verified Run #303-304 (anh UAT realtime): badge màu theo trạng thái + dòng meta đậm + tên to/drop-shadow (#303 `6983609`) → anh báo "tên đen nền xanh ko nổi bật" → diagnose **rule `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng `text-white`** (Tailwind v4 unlayered > all layers, **gotcha #66 NEW**, load-bearing ~30+ heading → fix ĐIỂM `text-white!` không move @layer) + thu nhỏ `text-lg` (#304 `37752eb`). Bootstrap: 2 monitor RE-REPORT CLEAN + 2 doc-drift fix (dep-audit 64→65 · root CLAUDE 263→286, `11bc96d`). **State THẬT: Mig 52 · 88 bảng · 286 test · 66 gotcha · menu 53 · bundle admin `CNUv1jxY`/user `CpOskeS1` Run #304.** ⚠️ curate-debt P1: cicd-monitor **44.1KB**. Chi tiết → session log `2026-06-16-S68-hoso-header-name-color-fix.md`. **Prev S67 —** **buổi sản phẩm LỚN, 6 deploy prod-verified Run #297→#302** (anh + anh Kiệt FDC UAT realtime, HMW-mode ON): fe-user Hồ sơ NS đồng nhất font + chữ đen→**xanh đậm `brand-800`** (#297) · **fe-admin mirror master-detail** + vá accent tokens index.css [đóng pending lớn nhất HRM go-live, page SHA256 ×2] (#298) · **+23 test-after HRM** → 263→**286** (#299) · **list flex-row gọn** [hết tràn ngang rail] + đồng nhất cỡ chữ ×2 (#300) · **PE Link hồ sơ auto-detect** web→hyperlink/`O:\`→Copy (#301) → **link `file://` bấm-thử** (#302). **Research 3-agent:** auto-mở `O:\` từ web = chỉ **Edge GPO `IntranetFileLinksEnabled`** (zero-per-machine) one-click thật; default chặn https→file://. **State THẬT: Mig 52 · 88 bảng · 286 test (45D+241I) · 65 gotcha · menu 53 · bundle admin `CcrZqfht`/user `DniDFUB_` Run #302.** test-specialist trunc #53→recover-disk; 0 prod bug. Chi tiết → session log `2026-06-16-S67-hoso-visual-pe-link-research.md`. **Prev S66 — session-end closeout em-main-solo:** adopt **Harness-8 all-inherit** (7 sub demoted `claude-opus-4-8`→`inherit` → cả 11=inherit, gỡ two-tier H4) + **cicd-monitor L1 curate 86.8→28.9KB** (byte-exact sed → `archive/2026-06.md`) + **ef-core skill doc-flush Mig 50→52** + check-email AI_INFRA (**0 thư mới se-directed**). ~17 file docs/gov/config, **0 production code** → state THẬT GIỮ NGUYÊN (Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle `BDwV5d0X`/`DbVv6rsf`). ⚠️ **Restart CLI** → H8 runtime (frontmatter no hot-reload) + reviewer Cat-6. adap-report + email-back ai_infra (`fa7f690d` MATCH). Chi tiết → session log `2026-06-16-S66-closeout-harness8-cicd-curate.md`. **Prev S65 — HRM go-live: public Hồ sơ Nhân sự + trang master-detail giống NamGroup + Department hierarchy Mig 51 + PE Link hồ sơ Mig 52 + gốc cây SOLUTION COMPANY**, ~6 deploy prod-verified Run #289→#295, anh + anh Kiệt FDC UAT realtime. **State THẬT: Mig 52 · 88 bảng · 263 test (45D+218I) · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf` Run #295.** Workflow fan-out chạy THẬT lần đầu [PE] — BE∥FE parallel OK nhưng FE+reviewer return-rỗng #53 → em main recover-disk + self-gate. gotcha #65 [build csproj con ≠ slnx → CS7036]. Chi tiết → session log `2026-06-16-S65-hrm-golive-employee-masterdetail-pe-link.md`. **Prev S64** adopt **Harness-7 writing-quality floor** qua `/adap-apply` + email ai_infra — em main solo, 1 commit `6afde19` docs/gov-only. Outward comms = tiếng Việt câu-hoàn-chỉnh; nội bộ giữ nén (asymmetric). reviewer +Category 6 (verified-pending-restart → cần restart CLI). Broadcast body-hash verified KHÔNG mis-stamp (gotcha #61 UTF-8). Prev S63 docs-closeout bù S60/S61/S62 — 3 session product ship CODE prod-verified nhưng KHÔNG closeout docs (UAT realtime anh Kiệt FDC). **State THẬT: Mig 50 · 88 bảng · 263 test · 64 gotcha · menu 53 · bundle admin `0xKYGhhf`/user `C81ZdG9G` Run #286.** S60-62 = PE ràng buộc gửi-duyệt + gỡ "Từ chối" (S60) · Mig 50 ngân sách per-gói-thầu Excel anh Kiệt + XÓA module Budget cũ (S61) · vượt-NS cảnh-báo-mềm (S62). Reconcile stray reviewer cwd-misland + count-flush 4 file. Chi tiết → session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`. Prev Session 59 ( **6 đợt ship prod-verified Run #273→#278**: wipe transactional testing data (10 PE + 7 HĐ demo + 64 notif = 0, mã reset → phiếu thật đầu tiên team tạo = **PE/2026/A/001** ✓) `56882ac` #273 · PE tree Panel 1 chốt 4 tầng **Năm > Dự án > Hạng mục > Phiếu** `0eafcd3` #274 · dọn 15 mã hạng mục demo "tự đẻ" (chị Trà Sol) + gỡ seed gốc, WorkItems 86→**71** `bbd1554` #275 · **rename 71 mã đúng format PMH anh Kiệt** (`MAT-n`/`SUB-n`/`MEP-SUB-n`/`MEP-EQU-n` + tên "STT nhóm tên"; **DB-trước-code-sau** gotcha #62 + sqlcmd `-f 65001` gotcha #61) `c869d26` #276 · UAT vòng 1: NEW `ui/SearchableSelect` gõ-lọc bỏ dấu (Hạng mục/Dự án) + auto Địa điểm + điều khoản đa dòng `faed59f` #277 · UAT vòng 2 (anh chốt ×2): ẩn Trả lại/Từ chối khi tự duyệt phiếu mình soạn + quick-add NCC ngay form (POST /suppliers any-auth, authz probe 4/4) + NCC gõ-tìm A-Z + upload multi-file `9c330d2` #278 · UAT vòng 3-6 realtime (#279/#281 cancelled-supersede-benign): bảng NCC table-fixed `f21c55d` + bỏ ô Tên ngân sách `69997da` #280 + GỠ field Điều khoản TT mọi form `80b64dd` + bỏ nút Thêm hạng mục `792c030` **#282 FINAL**. Tổng 10 đợt (8 PASS + 2 cancelled-benign). Bundle FINAL admin **`B1DtNT9C`**/user **`D6uF3Mln`**. Test 240. Gotchas 62. 0/14 spawn truncated. → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`. Prev S58 — **5 đợt prod-verified Run #382/#383/#384/#386** (#385 cancelled-supersede-benign): lock-demo-user fix (việc sếp deadline 15:00 ĐÓNG TRỌN — gotcha #60/E-008/AS-12, root cause password 11<12 từng phát hiện S22 nhưng const không fix) + tạm ẩn HRM/Office/Cá nhân + Danh mục cuối (`6c5fd26` #383) + **fe-user redesign theo UI/UX guide AI_INFRA giữ brand** (`e959f72` #384) + **brand polish ×2 app "thấy rõ"** (`ea793a4`: stripe 4px đỉnh + thead brand) + **PE gộp Tên-gói-thầu = chọn Hạng-mục** (anh Kiệt FDC chốt, `3ebaf84` #386 — bundle final admin `DMm9rtNA`/user `BUkOMn_Y`). Email AI_INFRA processed (guide + ACK H4 ACCEPT). Test **240**. → session log `2026-06-11-S58-lock-fix-hide-modules-redesign-pe-merge.md`. Root cause 2 tầng: lock-list = population Dev-only + `DemoUserPassword` 11 ký tự < prod RequiredLength=12 → CreateAsync silent-fail từ trước tới giờ (= "helpdesk inert" S56). Fix union 20 UAT email + password 12 ký tự → prod 55 user/34 locked, nv.cao+nv.truong sống, 5 real staff tạo. gotcha #59+#60. Commit `5998163`. Prev S57bis — **PE gắn Hạng mục (Mig 49) + Pe all-role + menu Cá nhân + Harness-4 runtime-VERIFIED**. Test 228→**240**. Bundle `CP4CB1ym`/`BmZ3VHnm`. Commit `17b23a4`+`dd117b7` → Run #381 PASS+1PARTIAL (lock NO-OP → RESOLVED S58). Prev S56 — **Pre-golive verify sweep + golive-harden 4 fix — Run #379 PASS, code golive-ready**. WF1 `pre-golive-verify` 7-stream + adversarial → 6 PASS/1 CONCERN/0 blocker = GO (key finds = ops not code). WF2 `golive-harden` fix 4: #3 LeaveBalance lost-update→atomic ExecuteUpdate+Serializable tx (NO mig) · #5 ItTicket authz Forbidden-trước-NotFound · #6 DocxRenderer null-guard · #4 Travel/Vehicle ApproveV2 tests. Test 216→**228**. Bundle FROZEN `4SUwDLD8`/`XdKzt9LL`. `sys.tables` re-ground 92→**93**. gotcha **#58** NEW. reviewer StructuredOutput-fail→em main đỡ. **2 ops VPS pending** (gán user IT + tzutil UTC+7). FE Phase 2 redesign **deferred** (recon ready). Commit `a20cde8`. Prev S55 — **Nạp master data thật từ Excel (62 dự án + 71 hạng mục + 3 NCC) + Project +4 cột (Mig 48) — prod-verified**. HMW-mode ON. Commit `69cb393` → Run #377 PASS ~4m33s. Test 216 (compile-fix only). Bundle admin `B-d6893W`/user `XdKzt9LL`. `SeedRealMasterDataAsync` ungated idempotent → coexist demo. 2 agent return truncated (BE+reviewer) → em main disk/runtime-recover. Prev S54 — IT staff tự reassign ticket (cross-stack authz) — prod-verified. 1 code commit `ca4b602` → Run #376 PASS ~4m18s. Test 203→**216**. Bundle admin `DfCfHUE9`→`DmjI8Cmn`/user `_3S0BPJ2`→`YxL_MljK` (cả 2 rotate). NO migration. Task 1 Phase 9 Ops anh dừng. ⚠️ residual: 3 agent ghi MEMORY nhầm `src/Backend/.claude` → em main reconcile. Prev S53: gotcha #57 EXT Master Mig 47 + P11-D/E + database-agent verified-runtime.) +**Last updated:** 2026-06-23 (S85 — **buổi UAT anh Kiệt FDC CỰC LỚN: CV PRO 6-fix + clear-data + 6 vòng UAT + 2 ROOT-CAUSE + 5 SQL-fix — ~10 deploy prod-verified #334→#341, HMW-mode ON**) — **Batch CV PRO** (Run #334 `5a61254`): file `Cần chỉnh sửa CV PRO.xlsx` = 8-ảnh-chú-thích → C1 ẩn c/d form tạo · C3 prefill ô8 · C4a live-recompute ô3/8 · C4b "Bằng ngân sách" · C5 hủy/đổi winner (BE `Guid?` clear) · C7 fullscreen preview. **Clear-data** (`scripts/s85-wipe-uat-data.sql`, BACKUP-trước): wipe 43 PE + 28 budgets + 21 NCC-test, reset→A/001 (AskUserQuestion chốt scope). **6 vòng UAT #335→#338:** D1 ẩn 3/4/5 · D5 auto-quy-trình · D2 drafter-gỡ-GẤP (nới S77) · D3 ngân-sách-tự-nhảy từ ban-hành · ràng-tạo-phiếu + D4 checklist xanh/đỏ + "Quy trình duyệt". **2 ROOT-CAUSE:** **R5 #339 `1263c0d`** workflow-clear-on-edit = bug-class S42 (`UpdatePeDraftHandler` absolute-set→null-safe `if (X is not null)`, gotcha **#73**, +3 test) · **R6 #341 `49ac086`** TZ +7h (timestamps UTC nhưng serialize thiếu 'Z' → `UtcDateTimeJsonConverter` UTC-with-Z, gotcha **#72**; cicd verify `createdAt:"…Z"`). **5 SQL-fix** phiếu workflow-less (gán QT-DN-V2-001). Test 356→**374**. **State: Mig 57 · 88 bảng · 374 test · gotcha 73 · menu 54 · bundle admin `aKuNip19`/user `BUsL0HeQ` Run #341.** **🔴 NEXT (anh):** ⚠️ restart CLI (carry: budget v3 runtime + lệnh `/user-mark-*` + cadence §2.1.x). **NEXT UAT (anh Kiệt/long.chau Ctrl+F5):** giờ thông-báo đúng ("vừa xong") + Sửa phiếu giữ workflow + submit OK + checklist xanh/đỏ đủ + auto-quy-trình. **🔴 NEXT (em):** curate L1 test-specialist 28.4KB WATCH strike-1 (value-protect gotcha#/guard → KEEP) · monthly **2026-07-01** (doc-cite flush ef-core/skills-README Mig→57 + STATUS/HANDOFF re-tier + **SignalR TZ-check** nếu realtime-push còn lệch + **edit-form workflow-selector** defer = đóng dead-end "mở Sửa chọn quy trình" mà form chưa có ô). **Pending product:** Ngưỡng giá CEO (Mig 54) Designer UAT · "C" chuyển phiếu→dự án chờ spec. **Ops S58/S59:** email typo anh Chương · 5 real-staff pw · gán CNTT (tzutil VPS = KHÔNG-cần-nữa, R6 fix tầng-serialize chuẩn hơn). → log `2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md`. · **Prev S84** — **bootstrap + flush session-start cap-echo v3 + commit S83 cicd harvest-orphan (LIGHT, 0 production code)** — 2 monitor INFORM → flush `session-start.md:114` `60/20/16`→**`220/60/50`** (+canonical-pointer chống tái-drift; detector C2 không track cap-number) + commit `cicd-monitor/MEMORY.md` harvest S83 sót-closeout (Run #333 + gotcha #69-REFINE). Lesson `feedback_derived_flush_execution`: derived→canonical flush = em-main execution KHÔNG gate user-confirm; chỉ ĐỔI-số = quyền anh. ⚠️ restart CLI (command `.md` no hot-reload). State GIỮ NGUYÊN Mig 57·88·356·71·`CsJetgZH`/`BVS0ApIm`. → log `2026-06-22-S84-session-start-cap-flush.md`. · **Prev S83** — **(1) H-15 v3 memory-budget full-parity (lead 220K/sub 60K/wf 50K, anh owner-directive) + (2) fix PE require-workflow create+submit prod-verified Run #333** — 2 commit: `2c7fd63` (gov docs-only CI-skip) + `fc1f19d` (PE fix). **H-15 v3:** full AI_INFRA parity (sửa self-shrink S82) + NEW `spawn_fill_directive` (nạp sub tới budget bằng prompt GIÀU — byte-cap MEMORY.md = 1 lát) + engine §G.5 + mark **v3-delta** `RC-pqhuy1987-22-06-2026-16-35-37` (anh-directed). **PE fix:** validator `NotEmpty(ApprovalWorkflowId)` + submit-guard (sau Section-3) chặn phiếu null-workflow ("quy trình cũ", kẹt V1-legacy). Diagnose A/040 **tự-khỏi-reload = cache** (KHÔNG đụng prod). test-before RED→GREEN, full-suite bắt **9 đỏ** → triage (2 spec-conflict rewrite V1-deprecated + 6 collateral giữ + 1 validator). Test 354→**356**. **#69-REFINE:** bundle KHÔNG rotate vì 0 fe-src (Vite deterministic) — ship-signal = Last-Modified KHÔNG hash-delta. Chi tiết → `## S83` dưới. ⚠️ restart CLI (budget v3 runtime). State: Mig 57·88 bảng·**356 test**·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm` Run #333. · **Prev S82** — **adopt Harness-15-v2 (Tầng-1 hot-feed-lớn + L2/L3 bỏ-trần + %-print 2-đầu-phiên + ranh-giới vai-trò), 0 production code** — anh `/check-email AI_INFRA và /adap-apply all step by step cẩn thận`. 1 thư mới H15-v2-notify (verify ✓✓) + fan-out 29 vs 22 → CHỈ H15-v2 MỚI (7 còn lại verify đã-phủ S72/S75/S79). em-main IMPLEMENT D9 (6 edit: L1 12K→per-role lead 60K/sub 20K/wf 16K · L2/L3→NO-CAP · §G.4 · §2.1.6+§L.b(c) %-print · mark refine) + REVIEW Workflow `wf_04667b25-5fa` **3/3 PASS** (3 MINOR fixed). Ranh-giới vai-trò: con-số = quyền anh, AI thực-thi + báo-% (sửa framing S81 "lead-authority" gộp nhầm AI-lead↔owner). mark H-15 **v2-delta anh-confirm** `RC-pqhuy1987-21-06-2026-01-58-01`. commit `aa3f0fe` push (docs-only CI-skip) + email AI_INFRA `a749bb6bd1be`. Chi tiết → `## S82` dưới. ⚠️ restart CLI (%-print runtime §2.1.6 + §L.b(c)). State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. · **Prev S81** — **adopt Harness-15 memory-budget per-agent (token-governor + value-gate + work-state block), 0 production code** — anh `/check-email AI_INFRA và /adap-apply step by step, review sau lẫn imple, report trung thực`. 0 new directed email; fan-out → CHỈ H15. em-main IMPLEMENT (8/8 🔴 floor) + REVIEW Workflow `wf_b7f3c8ac-b53` (3-lane PASS/PASS/HONEST → bắt 2 CONCERN honesty → fixed). Chi tiết → `## S81` dưới + adap-report. ⚠️ restart CLI (session-start §2.1.5). ✅ mark H-15 stamped Active-High (`RC-…23-07-37`). State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. · **Prev S80** — **curate L1 over-cap memory → L2 archive (em-main single-writer, 0 production code)** — anh `/session-start` (bootstrap clean: 2 monitor CLEAN · detector 26-flag baseline-safe · test 354) → "check làm thử đi". archive-gate DRY-RUN: reviewer 45→**10KB** · investigator-codebase 40→**10KB** · cicd-monitor 39→**12KB** = cả 3 **keep-floor-hit cannot-auto-drain** → manual condense-with-archive: 31 entries byte-exact `sed` → `archive/2026-06.md` (**+N −0**, 0 byte-loss) + 31 `_INDEX` substring pointer → **A7 GATE PASS 217/217**. Stale foundation counts flushed (130/263→354·55→71·Mig40/55→57·84→88·bundle→#330). **State GIỮ NGUYÊN: Mig 57·88 bảng·354 test·gotcha 71.** **Lesson:** `_INDEX` substring **quote-free** (A7 quote-parser cắt escaped-quote `\"PURO\"` → FAIL 1, gate bắt). **🔴 NEXT (em):** frontend-designer 26KB + test-specialist 28KB WATCH (A6 strike-1<2). → log `2026-06-20-S80-curate-l1-overcap.md`. · **Prev S79** — **adopt User-Mark (H-12/13) canonical §P + Harness-14 (Eval/Budget/Outcome) + chữ-ký RC** — anh `/check-email AI_INFRA` + `/adap-apply` step-by-step (workflow double-check mỗi step), rồi gõ `/user-mark-active-high` "áp đầy-đủ chính-xác nhất theo AI_INFRA, không hỏi thêm". em main + **4 Workflow** (`wf_82337f7f-95c` invest → `wf_a7cbe93e-912` review → `wf_9d3beebb-a95` align-re-review → `wf_4d4eba6f-8a0` H14-review). **0 production code.** Bản đầu em phỏng-theo broadcast (cấp MUST/TRACK/ANCHOR/OFF) → anh trỏ canonical → **align FULL §P (P1-P10):** 4 lệnh `/user-mark-{active-high,active,medium,disable}` + ledger `.claude/governance/ACTIVE-MARKS.md` (Active-High/Active/Medium/Disable + display-filter) + `harness-11-engine.md §E`(P1-P10)+**§F**(H-14 3-mức maturity honest) + `rules.md §6.6` (objective-criteria KHÔNG quy-mô-đội/thời-gian-tuổi) + session-start §2.1.4/session-end §L.b(h) mark-display. **3 mark Active-High stamped** anh-confirm (`RC-pqhuy1987-20-06-2026-10-29-09/10/11` = objective-criteria/User-Mark/time-age, mirror AI_INFRA 3-mark, SE timestamp riêng P1 forward-only). completeness-gate H-6→H-13 **ĐẠT** (H-8 11/11 inherit no-`[1m]` · H-7 Cat-6 real). §F floor 6/6 + maturity HONEST + SE-state ACCURATE. **3 adap-report** + email ai_infra (body-hash `7b8615b3`) + check-email STAGE 2 move 2 email + `_index`. **Bài học `feedback_canonical_spec_over_broadcast`:** broadcast cô-đọng→canonical-command/§P là spec THẬT (phải pull, đừng phỏng-theo) · report-before-stamp dogfood (lệnh tự bắt báo-cáo-trước-stamp = đúng lệnh) · residual own-diary OK (D9 áp canonical, không cấm sub ghi diary riêng). detector clean sau align (0 C1/C3 mới). **State THẬT GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · menu 54 · bundle `CsJetgZH`/`BVS0ApIm`.** **🔴 NEXT (anh):** ⚠️ **restart CLI** (đầu việc) — activate 4 lệnh `/user-mark-*` + session-start §2.1.4/session-end §L.b(h) mark-display + engine §E/§F. Sau restart, session-start tự hiển-thị 3 mark Active-High. **🔴 NEXT (em):** curate L1 over-cap reviewer/cicd/investigator-codebase (carry 7-session + S79 workflow-spawn; inv 39.8KB +diary) — manual SPLIT/condense, archive-gate A7 GATE; + §7-header `rules.md` "77 test" stale → C2/monthly-audit. **Pending product (carry):** "Ngưỡng giá CEO" Mig 54 Designer UAT · "C" chuyển phiếu→dự án chờ spec. **Ops S58/S59:** tzutil VPS · anh Chương email typo · 5 real-staff pw · gán CNTT. Chi tiết → `2026-06-20-S79-user-mark-harness-14-adopt.md`. · **Prev S78** — **PE: đính kèm file khi DUYỆT (UAT Tra Sol / 5 tester)** — người duyệt tải file lên ngay lúc Duyệt thay vì Trả lại phiếu. Reuse hệ attachment + enum `ApprovalAttachment=5` **MIGRATION-FREE** (int-stored, endpoint+authz có sẵn → approver upload được). FE 2 app SHA-identical: `PeWorkflowPanel` picker multi-file + upload-trước-chuyển-phase (file lỗi=không duyệt) + mục "📎 File đính kèm khi duyệt" + 2 filter fix loại purpose=5 khỏi "Bảng so sánh" (gotcha **#71** proxy-predicate pollution). commit `7886fd0` → **Run #330 PASS** (test 354, bundle admin `CsJetgZH`/user `BVS0ApIm`, NO migration, smoke 4×200). 3 lỗi em tự bắt review-trước-deploy (authz-verify · filter-pollution #71 · Dialog mirror-truncate fe-admin). em-main-led + self-gate (grep no-leak) + cicd-monitor verify. **🔴 NEXT (em):** curate L1 over-cap (carry 6 session) reviewer **45.2KB** + cicd 38.8KB + inv 35.7KB keep-floor-hit manual-condense (archive-gate A7 GATE PASS 186/186). **NEXT UAT:** mở phiếu chờ duyệt → Duyệt → "+ Chọn file đính kèm" → Xác nhận → file ở mục "📎 File đính kèm khi duyệt". Chi tiết → `2026-06-19-S78-pe-attach-file-on-approve.md`. · **Prev S77** — **PE UX batch: 10 deploy prod-verified #320→#329 (anh Kiệt FDC + Tra Sol + Bích Phượng UAT realtime, HMW-mode ON)** — cờ GẤP pill mọi danh sách+inbox · focus→revert list bám-trái · **Mig 57** ô ghi chú giá đề xuất PRO/CCM + số phân cách VND + chính tả "Bảng so sánh giá" + guard #70 · số âm đỏ-ngoặc · mục con thụt+gạch-đầu-dòng · cờ gấp **BẤT ĐỐI XỨNG** GẮN=NV/GỠ=Trưởng phòng(DeptManager) · tách chọn-phiếu(inline) khỏi mở-rộng(overlay)+nút "Xem mở rộng" · chuông báo người duyệt vào cấp họ · banner phiếu Trả-lại. Mig 56→**57** · test 344→**354** (+10) · bundle cuối admin `BqKD3Y23`/user `Cn-i349D` (Run #329). **3 lỗi em tự bắt review-TRƯỚC-deploy** (guard#70 stale-echo · luật asymmetric Tra Sol clarify giữa-chừng · double-mount Task H). FD process-death Task H → recover-disk. **🔴 NEXT (em):** curate L1 over-cap reviewer **45KB** + cicd 37.6KB + inv 35.6KB keep-floor-hit manual-condense (archive-gate A7 GATE PASS 186/186 integrity OK). **NEXT UAT:** cờ gấp (GỠ chỉ TP) · chuông báo người duyệt · banner Trả-lại · Xem mở rộng · ô ghi chú PRO/CCM. Chi tiết → `2026-06-19-S77-pe-ux-batch-10-deploy.md`. · **Prev S76** — **PE ngân sách MA TRẬN 3 cột (Dự án|PRO|CCM) + bảng lưới `
` viền-ô + badge quyền-NS theo role** — anh Kiệt FDC + chị Trà Sol go-live. anh giao `/ultra-on` "step-by-step + workflow-review-per-step, hoàn chỉnh rồi deploy". **3 commit prod-verified:** `e33481e` (feature Run #318 — Mig 56 + ma-trận-3-cột + badge designer/flow `BhFDF9IJ`/`BAkuRl3C`) → `21d1f4e` (bảng lưới `
` theo phản hồi anh "chưa chia cột giống Excel", Run #319 **`jOqxW4-p`**/**`DbsznVvR`** smoke 3×200). Mig 56 +ProInitial/ProAdjust cột PRO (additive + data-migrate ProEstimate→ProInitial 4 rows prod). Part 1 mỗi phòng sửa cột mình (PRO canEditPro / CCM canEditCcm / Dự án FE-only). Part 2+3 badge "✎ NS PRO/CCM" cạnh approver (display-only suy-role) ở Designer + flow Duyệt NCC. Test 339→**344**. reviewer bắt **race mất-dữ-liệu** Part 1 → vá `useIsFetching` 2 app (gotcha #70). **🔴 NEXT (em):** curate L1 over-cap reviewer **45KB** + inv-codebase 35KB (keep-floor-hit → manual condense) + cicd 29KB + test-spec 28KB. **NEXT (anh/anh Kiệt):** UAT bảng lưới bằng PRO/CCM (Ctrl+F5). Chi tiết → `2026-06-19-S76-pe-budget-matrix-table-grid.md`. · **Prev S75 (2026-06-18)** — **Harness-11 adopt: engine bộ-nhớ-và-governance tự-bảo-trì + 2 double-check** — anh giao `/check-email AI_INFRA` + `/adap-apply` (mỗi stage workflow-review) + double-check ×2 + finalize report + push + session-end. em main + **5 Workflow** (audit `wf_7fdc3bd5-930` → implement `wf_c5e5844e-7c1` → review `wf_d7ca1ff8-942` → double-check `wf_a0b68d2f-30e` → checklist-verify `wf_39cd4cbe-f07`). **0 production code.** Built 2 NO-API detector-script (`governance-detectors.ps1` C1-C5+B3 runtime **26 flag** bắt drift thật, C4 0-self-match · `memory-archive-gate.ps1` PHẦN A hysteresis/keep-floor/2-strike/A7 186/186) + `docs/governance/harness-11-engine.md` canonical (3-tier D5/D6/D7 + one-direction-lock D8) + **B1 ×11 count→pointer** (drift mig53→55/test306→339/gotcha68→69/table93→88 RESOLVED) + cadence-wire D1/D2 + agents/README. **completeness-gate FORMAL ĐẠT** (B 4/4 + C 5/5 + D 11/11; D5/D6/D7 explicit + D8 codify=YES). gotcha #30 reinforced (box-glyph ├└─ KHÔNG vào .ps1, kể cả qua Edit). 3 commit `e70c046`+`ae957c4`+`aa09e99` pushed + adap-report + email ai_infra (`2316773229f2`). State GIỮ NGUYÊN Mig 55·88 bảng·339 test·gotcha 69·bundle `BYF5vIMJ`/`CB-tiRxd`. **🔴 NEXT (anh):** restart CLI (cadence §2.1.3/§L.b + ef-core skill); curate reviewer 38.8KB+inv 31.5KB+cicd 26.8KB over-cap. Chi tiết → `2026-06-18-S75-harness-11-adopt.md`. · **Prev S74** — **PE ô "Ghi chú từ CCM" ngân sách gói thầu (Mig 55)** — anh forward 2 luồng Zalo (Trà Sol + Kiệt FDC) "CCM giống PRO cho nhập + ghi chú, hiện 0 hết" → em-main BE+Mig55 ∥ implementer-frontend FE 2 app SHA-mirror ∥ test-specialist (chết rate-limit → recover-disk). 2 fork anh chốt: **thêm CcmNote (Mig 55)** + **GIỮ phân vai CCM** (CostControl/Admin). Entity +CcmNote mirror ProNote · UpdatePeBudgetCcmCommand +CcmNote absolute-set role-gate · DTO+controller+mapping · FE dòng "Ghi chú từ CCM" gate canEditCcm. Test 334→**339** (+5). commit `8655ebf` (cicd **Run #315 PASS** — bundle admin `BYF5vIMJ`/user `CB-tiRxd`, Mig 55 applied prod). **"0 hết không nhập" = tài khoản thiếu role CostControl (KHÔNG bug)** → UAT bằng CCM/Admin. **🔴 NEXT (anh/anh Kiệt):** UAT ô CCM bằng tài khoản CCM/Admin + carry "Ngưỡng giá CEO" Mig 54. Chi tiết → session log `2026-06-18-S74-pe-ccm-note.md`. · **Prev S73** — **Mig 54 PE giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích (anh Kiệt FDC, go-live thứ Hai 22/06)** — em main + 6 sub + 2 review-workflow, 2 commit prod-verified (`1d86abc` feature Run #313 + `6aa4dcb` FE empty-candidates fix). Mig 54 5-cột additive-nullable + 2 setter role-gate + ApproveV2 ③ AUTO→OPT-IN + ① bind giá chốt; FE 2 app SHA-mirror; test 306→334. **Workflow review:** R1 schema-force 1/4 lane → R2 free-text 2/3 PASS (rủi ro FE empty-candidates UNREACHABLE per submit-guard `:194`). Bài học: review fan-out free-text/hmw KHÔNG ép-schema. **Governance:** em lệch mandate auto-Workflow → cam kết báo-TRƯỚC-khi-lệch. **🔴 NEXT (anh/anh Kiệt):** cấu hình "Ngưỡng giá CEO" Designer + test 3 luồng + xác nhận CCM-trước-CEO. Chi tiết → session log `2026-06-18-S73-pe-gia-de-xuat-ccm-done.md`. · **Prev S72** — **Harness-10 flat-refine + checklist-v2 adopt (re-audit 3-workflow) + sleep NO-OP** — audit `wf_13868efb-ea7` → implement `wf_ac43b5ff-7d1` → review `wf_d482e10d-5dd` (Harness-9 B1+B2). SE BEHIND flat → migrate run-trace SUBFOLDER→FLAT (hmw.js:103 + 5 doc; 5 run cũ giữ subfolder C8) + 2 broadcast 06-18 adopt + `/sleep-recovery-memory-l2` port (A8) + detector TAILORED-OUT + hmw.js H4.5→H8 doc-drift. **REVIEW (B2) bắt 2 lỗi IMPLEMENT-self-assess sót** (hmw.js:52 schema-stale + auto-check overclaim) → fixed (auto-check WIRED thật). em-main containment-check tự bắt reviewer residual-write (raw-Workflow no-writeGuard) → revert. B3 self-correct (runs path/count 14→22). Sleep `all`=NO-OP. **0 prod code, state GIỮ NGUYÊN.** adap-report + email ai_infra (`5f511fe5c0f2`). **🔴 NEXT (anh):** restart CLI (FLAT-runtime hmw.js + wired sleep-check + sleep-recovery skill). **🔴 NEXT (em):** curate investigator-codebase L1 28973 OVER + watch FD/test-spec. Chi tiết → session log `2026-06-18-S72-harness-10-flat-refine.md`. **Prev S71 — Harness-10 adopt: tracked run-trace folder + checklist 9-10** — em main + 3 Workflow (invest `wf_9c2cd2cd-2e7` → implement `wf_e4e46725-231` → review `wf_636bc95b-939`) per mandate Harness-9 PART 2. **0 production code**. Migrate `.claude/workflows/wave-*/` gitignored → `runs//` **git-TRACKED** (run.md+sub-md/+harvest/) + `_ledger.md` 2-nhịp + 3-layer anti-miss (L1 em-main@P1 / L2 session-start orphan-scan / L3 session-end close-gate idempotent) + **containment shift** (Harness-2 B6 "mọi tracked-change=vi-phạm" → "tracked-change NGOÀI run-folder + code-disjoint=vi-phạm"). hmw.js wave→run-trace (accept `args.run` + alias `wave`, path `sub-md/`, `node --check` PARSE-OK). **Review độc-lập (R2+R3) bắt C5 L1 over-claim** (doc nói hmw.js prompt-builder emit L1 reminder, grep engine=0 → engine no-fs → fixed path-a: L1 = em-main @P1 convention) — dogfood mandate B2 đúng. checklist 9-10: Part A (Harness-9 memory) + B (adap 2-workflow) done S70, Part C (Harness-10) 8/8 MỚI. **State GIỮ NGUYÊN: Mig 53·88 bảng·306 test·68 gotcha·menu 54·bundle admin `BgNCjwsG`/user `CBvh0vtf`.** + CLAUDE.md test-flush 263→306 (resolve H1 stale). **🔴 NEXT (anh):** restart CLI (hmw.js RUN-TRACE runtime + carry §2.1.2/Cat-6/H8). Chi tiết → session log `2026-06-18-S71-harness-10-run-trace.md` (pending). **Prev S70 —** **Harness-9 adopt: L2 archive dark-matter recovery + adap 2-workflow mandate** — em main + 3 Workflow (investigate `wf_be952f3c-97f` → implement `wf_a58e0d15-beb` → audit `wf_9520d8cd-4fe`) + 2 monitor bootstrap. **0 production code** (governance/memory only, commit `f36aab8` pushed). 4 over-cap sub-agent curate L1→L2 + `archive/_INDEX.md` (mục-lục substring sha-keyed) + `.gist.md` (4-field distill-gen:1, verbatim FROZEN) → **cả 4 < 25KB auto-inject cap** (P1 curate-debt CLOSED; ~240KB archive hết RAG-dark). PART 2/3 process-mandate codify (adap-apply 2-workflow + agents/README Upgrade S70 + session-start §2.1.2). **0-byte-loss git+sha verified** (Stage C audit + em-main self-gate khi 2 reviewer no-StructuredOutput → recovery-path). +memory-budget.json (seed-by-measure) + measure-agent-memory.ps1 + .ragignore + doc-drift 4-cite flush. adap-report + email-back ai_infra (`7c07b716e775`). **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** **🔴 NEXT (anh):** restart CLI để activate session-start §2.1.2 budget-audit + pending H8 inherit + reviewer Cat-6. Chi tiết → session log `2026-06-17-S70-harness-9-l2-recovery.md`. **Prev S69 —** **Văn phòng số (E-Office) port + golive + PE cờ gấp/ngưỡng CCM — 4 deploy prod-verified Run #305→#308, HMW-mode ON, 2 workflow fan-out**: #305 foundation PURO (shared PageHeader/KpiCard/WidgetCard + Dashboard 2-cột + sync fe-admin index.css đóng drift S66-S68) → #306 **re-skin TRỌN 10 page** (PURO layout + CSS Hồ sơ NS, phẫu-thuật-giữ-100%-logic) → #307 **Office golive public** read+create **16-key allow-list mọi role** (mirror S65, chạy SAU revoke; excluded Off_PhongHop_Manage/Off_AttendanceReport/Off_ChamCong; cicd DB-verify 16/16×13 role) → #308 **PE cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị** Mig 53 (anh Kiệt FDC sau họp sếp). **State THẬT: Mig 53 · 88 bảng · 306 test (45D+261I) · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf` Run #308.** 2 gotcha NEW (**#67** Tailwind accent palette thiếu-stop vỡ-màu-im-lặng · **#68** stale-diagnostic-background-agent → chỉ tin build sau-cùng). 2 truncation #53 (impl-backend positional-record + impl-frontend) → em main recover-disk + self-gate. **🔴 NEXT (anh/anh Kiệt UAT):** (1) cấu hình "Ngưỡng giá trị gói CEO" trong Workflow Designer (null=luồng cũ) + test phiếu < ngưỡng → CCM duyệt là xong, ≥ ngưỡng → lên CEO; (2) test cờ gấp PRO(đỏ)/CCM(xanh) → badge + notify CEO; (3) **xác nhận:** quy trình đặt CCM(CostControl)-trước-CEO + CEO = role Director (đích notify). **C (sau duyệt → chuyển phiếu đến dự án) chờ anh Kiệt spec form.** **NEXT (em):** 🔴 curate cicd-monitor **65.2KB** (worst, trend tăng) + inv-codebase 47 + reviewer 43.5 over-cap · doc-flush docs/CLAUDE.md full. Chi tiết → session log `2026-06-17-S69-vanphong-golive-pe-urgent-threshold.md`. **Prev S68 —** **Hồ sơ NS header chi tiết NV: làm nổi bật + fix tên render đen→trắng** — em main solo, 3 commit (2 FE + 1 docs), 2 deploy prod-verified Run #303-304 (anh UAT realtime): badge màu theo trạng thái + dòng meta đậm + tên to/drop-shadow (#303 `6983609`) → anh báo "tên đen nền xanh ko nổi bật" → diagnose **rule `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng `text-white`** (Tailwind v4 unlayered > all layers, **gotcha #66 NEW**, load-bearing ~30+ heading → fix ĐIỂM `text-white!` không move @layer) + thu nhỏ `text-lg` (#304 `37752eb`). Bootstrap: 2 monitor RE-REPORT CLEAN + 2 doc-drift fix (dep-audit 64→65 · root CLAUDE 263→286, `11bc96d`). **State THẬT: Mig 52 · 88 bảng · 286 test · 66 gotcha · menu 53 · bundle admin `CNUv1jxY`/user `CpOskeS1` Run #304.** ⚠️ curate-debt P1: cicd-monitor **44.1KB**. Chi tiết → session log `2026-06-16-S68-hoso-header-name-color-fix.md`. **Prev S67 —** **buổi sản phẩm LỚN, 6 deploy prod-verified Run #297→#302** (anh + anh Kiệt FDC UAT realtime, HMW-mode ON): fe-user Hồ sơ NS đồng nhất font + chữ đen→**xanh đậm `brand-800`** (#297) · **fe-admin mirror master-detail** + vá accent tokens index.css [đóng pending lớn nhất HRM go-live, page SHA256 ×2] (#298) · **+23 test-after HRM** → 263→**286** (#299) · **list flex-row gọn** [hết tràn ngang rail] + đồng nhất cỡ chữ ×2 (#300) · **PE Link hồ sơ auto-detect** web→hyperlink/`O:\`→Copy (#301) → **link `file://` bấm-thử** (#302). **Research 3-agent:** auto-mở `O:\` từ web = chỉ **Edge GPO `IntranetFileLinksEnabled`** (zero-per-machine) one-click thật; default chặn https→file://. **State THẬT: Mig 52 · 88 bảng · 286 test (45D+241I) · 65 gotcha · menu 53 · bundle admin `CcrZqfht`/user `DniDFUB_` Run #302.** test-specialist trunc #53→recover-disk; 0 prod bug. Chi tiết → session log `2026-06-16-S67-hoso-visual-pe-link-research.md`. **Prev S66 — session-end closeout em-main-solo:** adopt **Harness-8 all-inherit** (7 sub demoted `claude-opus-4-8`→`inherit` → cả 11=inherit, gỡ two-tier H4) + **cicd-monitor L1 curate 86.8→28.9KB** (byte-exact sed → `archive/2026-06.md`) + **ef-core skill doc-flush Mig 50→52** + check-email AI_INFRA (**0 thư mới se-directed**). ~17 file docs/gov/config, **0 production code** → state THẬT GIỮ NGUYÊN (Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle `BDwV5d0X`/`DbVv6rsf`). ⚠️ **Restart CLI** → H8 runtime (frontmatter no hot-reload) + reviewer Cat-6. adap-report + email-back ai_infra (`fa7f690d` MATCH). Chi tiết → session log `2026-06-16-S66-closeout-harness8-cicd-curate.md`. **Prev S65 — HRM go-live: public Hồ sơ Nhân sự + trang master-detail giống NamGroup + Department hierarchy Mig 51 + PE Link hồ sơ Mig 52 + gốc cây SOLUTION COMPANY**, ~6 deploy prod-verified Run #289→#295, anh + anh Kiệt FDC UAT realtime. **State THẬT: Mig 52 · 88 bảng · 263 test (45D+218I) · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf` Run #295.** Workflow fan-out chạy THẬT lần đầu [PE] — BE∥FE parallel OK nhưng FE+reviewer return-rỗng #53 → em main recover-disk + self-gate. gotcha #65 [build csproj con ≠ slnx → CS7036]. Chi tiết → session log `2026-06-16-S65-hrm-golive-employee-masterdetail-pe-link.md`. **Prev S64** adopt **Harness-7 writing-quality floor** qua `/adap-apply` + email ai_infra — em main solo, 1 commit `6afde19` docs/gov-only. Outward comms = tiếng Việt câu-hoàn-chỉnh; nội bộ giữ nén (asymmetric). reviewer +Category 6 (verified-pending-restart → cần restart CLI). Broadcast body-hash verified KHÔNG mis-stamp (gotcha #61 UTF-8). Prev S63 docs-closeout bù S60/S61/S62 — 3 session product ship CODE prod-verified nhưng KHÔNG closeout docs (UAT realtime anh Kiệt FDC). **State THẬT: Mig 50 · 88 bảng · 263 test · 64 gotcha · menu 53 · bundle admin `0xKYGhhf`/user `C81ZdG9G` Run #286.** S60-62 = PE ràng buộc gửi-duyệt + gỡ "Từ chối" (S60) · Mig 50 ngân sách per-gói-thầu Excel anh Kiệt + XÓA module Budget cũ (S61) · vượt-NS cảnh-báo-mềm (S62). Reconcile stray reviewer cwd-misland + count-flush 4 file. Chi tiết → session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`. Prev Session 59 ( **6 đợt ship prod-verified Run #273→#278**: wipe transactional testing data (10 PE + 7 HĐ demo + 64 notif = 0, mã reset → phiếu thật đầu tiên team tạo = **PE/2026/A/001** ✓) `56882ac` #273 · PE tree Panel 1 chốt 4 tầng **Năm > Dự án > Hạng mục > Phiếu** `0eafcd3` #274 · dọn 15 mã hạng mục demo "tự đẻ" (chị Trà Sol) + gỡ seed gốc, WorkItems 86→**71** `bbd1554` #275 · **rename 71 mã đúng format PMH anh Kiệt** (`MAT-n`/`SUB-n`/`MEP-SUB-n`/`MEP-EQU-n` + tên "STT nhóm tên"; **DB-trước-code-sau** gotcha #62 + sqlcmd `-f 65001` gotcha #61) `c869d26` #276 · UAT vòng 1: NEW `ui/SearchableSelect` gõ-lọc bỏ dấu (Hạng mục/Dự án) + auto Địa điểm + điều khoản đa dòng `faed59f` #277 · UAT vòng 2 (anh chốt ×2): ẩn Trả lại/Từ chối khi tự duyệt phiếu mình soạn + quick-add NCC ngay form (POST /suppliers any-auth, authz probe 4/4) + NCC gõ-tìm A-Z + upload multi-file `9c330d2` #278 · UAT vòng 3-6 realtime (#279/#281 cancelled-supersede-benign): bảng NCC table-fixed `f21c55d` + bỏ ô Tên ngân sách `69997da` #280 + GỠ field Điều khoản TT mọi form `80b64dd` + bỏ nút Thêm hạng mục `792c030` **#282 FINAL**. Tổng 10 đợt (8 PASS + 2 cancelled-benign). Bundle FINAL admin **`B1DtNT9C`**/user **`D6uF3Mln`**. Test 240. Gotchas 62. 0/14 spawn truncated. → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`. Prev S58 — **5 đợt prod-verified Run #382/#383/#384/#386** (#385 cancelled-supersede-benign): lock-demo-user fix (việc sếp deadline 15:00 ĐÓNG TRỌN — gotcha #60/E-008/AS-12, root cause password 11<12 từng phát hiện S22 nhưng const không fix) + tạm ẩn HRM/Office/Cá nhân + Danh mục cuối (`6c5fd26` #383) + **fe-user redesign theo UI/UX guide AI_INFRA giữ brand** (`e959f72` #384) + **brand polish ×2 app "thấy rõ"** (`ea793a4`: stripe 4px đỉnh + thead brand) + **PE gộp Tên-gói-thầu = chọn Hạng-mục** (anh Kiệt FDC chốt, `3ebaf84` #386 — bundle final admin `DMm9rtNA`/user `BUkOMn_Y`). Email AI_INFRA processed (guide + ACK H4 ACCEPT). Test **240**. → session log `2026-06-11-S58-lock-fix-hide-modules-redesign-pe-merge.md`. Root cause 2 tầng: lock-list = population Dev-only + `DemoUserPassword` 11 ký tự < prod RequiredLength=12 → CreateAsync silent-fail từ trước tới giờ (= "helpdesk inert" S56). Fix union 20 UAT email + password 12 ký tự → prod 55 user/34 locked, nv.cao+nv.truong sống, 5 real staff tạo. gotcha #59+#60. Commit `5998163`. Prev S57bis — **PE gắn Hạng mục (Mig 49) + Pe all-role + menu Cá nhân + Harness-4 runtime-VERIFIED**. Test 228→**240**. Bundle `CP4CB1ym`/`BmZ3VHnm`. Commit `17b23a4`+`dd117b7` → Run #381 PASS+1PARTIAL (lock NO-OP → RESOLVED S58). Prev S56 — **Pre-golive verify sweep + golive-harden 4 fix — Run #379 PASS, code golive-ready**. WF1 `pre-golive-verify` 7-stream + adversarial → 6 PASS/1 CONCERN/0 blocker = GO (key finds = ops not code). WF2 `golive-harden` fix 4: #3 LeaveBalance lost-update→atomic ExecuteUpdate+Serializable tx (NO mig) · #5 ItTicket authz Forbidden-trước-NotFound · #6 DocxRenderer null-guard · #4 Travel/Vehicle ApproveV2 tests. Test 216→**228**. Bundle FROZEN `4SUwDLD8`/`XdKzt9LL`. `sys.tables` re-ground 92→**93**. gotcha **#58** NEW. reviewer StructuredOutput-fail→em main đỡ. **2 ops VPS pending** (gán user IT + tzutil UTC+7). FE Phase 2 redesign **deferred** (recon ready). Commit `a20cde8`. Prev S55 — **Nạp master data thật từ Excel (62 dự án + 71 hạng mục + 3 NCC) + Project +4 cột (Mig 48) — prod-verified**. HMW-mode ON. Commit `69cb393` → Run #377 PASS ~4m33s. Test 216 (compile-fix only). Bundle admin `B-d6893W`/user `XdKzt9LL`. `SeedRealMasterDataAsync` ungated idempotent → coexist demo. 2 agent return truncated (BE+reviewer) → em main disk/runtime-recover. Prev S54 — IT staff tự reassign ticket (cross-stack authz) — prod-verified. 1 code commit `ca4b602` → Run #376 PASS ~4m18s. Test 203→**216**. Bundle admin `DfCfHUE9`→`DmjI8Cmn`/user `_3S0BPJ2`→`YxL_MljK` (cả 2 rotate). NO migration. Task 1 Phase 9 Ops anh dừng. ⚠️ residual: 3 agent ghi MEMORY nhầm `src/Backend/.claude` → em main reconcile. Prev S53: gotcha #57 EXT Master Mig 47 + P11-D/E + database-agent verified-runtime.) --- diff --git a/docs/STATUS.md b/docs/STATUS.md index 89569ea..543b97c 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,7 +3,7 @@ > **Update rule:** trước khi bắt đầu 1 task → ghi row `🔥 In Progress`. Xong → `✅ Recently Done`. > **Tiering rule (S40):** chỉ giữ **state hiện tại + 3 session gần nhất** ở file này. Session cũ hơn → `docs/changelog/sessions/`. Full history pre-S40 → `docs/_archive/STATUS-preS40-fullhistory.md`. (Tránh over-context — xóa double, không cắt nội dung.) -**Last updated:** 2026-06-22 (S84 — **bootstrap + flush session-start hot-feed cap-echo v3 + commit S83 cicd harvest-orphan (em-main hygiene, 0 production code)** — anh `/session-start` → 2 monitor INFORM: H1 bắt `session-start.md:114` còn cap CŨ `lead 60K/sub 20K/wf 16K` ≠ canonical budget v3 `220K/60K/50K` (S82 self-shrink chưa flush khi S83 owner-set lại); H2 bắt `cicd-monitor/MEMORY.md` = harvest S83 hợp-lệ (Run #333 + gotcha **#69-REFINE**: hash giữ-nguyên khi 0 `fe-*/src` đổi → ship-proof THẬT = `Last-Modified` in-window, KHÔNG hash-delta) sót khỏi closeout `f71654f`. Anh "Sao ko add luôn?" → em flush `session-start.md:114` echo cap → **220K/60K/50K + canonical-pointer "đọc số sống ở budget.json"** chống tái-drift (detector C2 KHÔNG track cap-number → echo-trần lệch âm-thầm lần đổi cap sau) + commit cicd harvest-orphan. **Lesson (`feedback_derived_flush_execution`):** monitor INFORM-only proposal về **derived→canonical flush** = em-main **EXECUTION** (B3 VERIFY→APPEND = verify-rồi-LÀM), KHÔNG gate user-confirm; chỉ **ĐỔI-con-số** mới = quyền anh (chủ-dự-án). archive-gate A7 GATE PASS 217/217 · 2 WATCH strike-1 (FD/test-spec, no-action). **State GIỮ NGUYÊN: Mig 57 · 88 bảng · 356 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** ⚠️ restart CLI (command `.md` no hot-reload — runtime %-print mới ăn cap đúng). → log `2026-06-22-S84-session-start-cap-flush.md`.) · **Prev S83** — **(1) adopt H-15 v3 memory-budget full-parity (anh owner-directive) + (2) fix PE require-workflow create+submit (đóng lỗ hổng "quy trình cũ") prod-verified Run #333** — anh `/session-start` → directive budget Tầng-1 **220K**/mem-sub **60K**/wf-sub **50K** "nạp đầy cho đủ" → diagnose phiếu A/040 "quy trình cũ" → "(B) vá guard BE + test-before → deploy" → `/session-end`. **Part 1 H-15 v3 (commit `2c7fd63` docs-only CI-skip):** `token_governor` lead 200K→**220K**/mem-sub 20K→**60K**/wf-sub 16K→**50K** full AI_INFRA parity (sửa self-shrink S82 = AI tự-co-nhỏ, mark `RC-…01-58-01` cấm) + NEW `spawn_fill_directive` (nạp sub tới budget bằng prompt GIÀU — byte-cap MEMORY.md = 1 lát, prompt nạp phần còn lại; retire `≤8K-brief`) + engine **§G.5** + ACTIVE-MARKS H-15 **v3-delta** `RC-pqhuy1987-22-06-2026-16-35-37` (anh-directed, report-before-stamp). **Part 2 PE fix (commit `fc1f19d`, cicd Run #333 PASS ~4m59s):** validator `NotEmpty(ApprovalWorkflowId)` + submit-guard (SAU Section-3, TRƯỚC mutate phase) → phiếu null-workflow KHÔNG gửi-duyệt được (trước: kẹt nhánh V1-legacy = banner "quy trình cũ", không Bước/Cấp, "Lịch sử duyệt 0"). **Diagnose:** banner ⟺ `approvalFlow` rỗng ⟺ `ApprovalWorkflowId` null; A/040 **tự-khỏi-khi-reload ⟹ cache** (data-hỏng reload không khỏi — em KHÔNG đụng prod). **test-before RED→GREEN**, full-suite bắt **9 đỏ** → triage: 2 genuine-spec-conflict (V1-submit deprecated, data wipe S59) rewrite + 6 collateral giữ (dời guard sau Section-3) + 1 validator fix. **Test 354→356** (+2 validator). **#69-REFINE (cicd):** bundle KHÔNG rotate vì 0 fe-src change (Vite deterministic) — ship-signal THẬT = Last-Modified in-window KHÔNG hash-delta; bundle GIỮ admin `CsJetgZH`/user `BVS0ApIm` Run #333. State THẬT: **Mig 57 · 88 bảng · 356 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`**. ⚠️ restart CLI activate budget v3 runtime. → log `2026-06-22-S83-h15v3-pe-require-workflow.md`.) · **Prev S82** — **adopt Harness-15-v2 (Tầng-1 hot-feed-lớn + L2/L3 bỏ-trần + %-print 2-đầu-phiên + ranh-giới vai-trò), 0 production code** — `/check-email AI_INFRA` (1 thư mới H15-v2-notify verify ✓✓ whole-file+body) + `/adap-apply all` (fan-out 29 broadcast vs 22 report → CHỈ H15-v2 MỚI; 7 còn lại verify = đã-phủ S72/S75/S79). em-main IMPLEMENT single-writer D9 (6 edit: `token_governor` L1 12K→per-role **lead 60K/sub 20K/wf 16K** · L2/L3 6K/4K→**NO-CAP** · engine §G.4 · session-start §2.1.6 + session-end §L.b(c) %-print · mark H-15 What-cell refine) + **REVIEW Workflow `wf_04667b25-5fa` 3-lane 3/3 PASS** (bắt 3 MINOR → fixed: volume "~42K" stale · mark pending-confirm flag · _index STAGE-2). **Ranh-giới vai-trò:** con-số = quyền CHỦ-DỰ-ÁN/anh, AI thực-thi + báo-% — sửa framing S81 "lead-authority" gộp nhầm AI-lead↔owner. mark H-15 **v2-delta anh-confirm** `RC-pqhuy1987-21-06-2026-01-58-01` (report-before-stamp). commit `aa3f0fe` push (docs-only CI-skip) + email AI_INFRA `a749bb6bd1be`. **State THẬT GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** ⚠️ restart CLI (session-start §2.1.6 + session-end §L.b(c) %-print runtime). → log `2026-06-21-S82-harness-15-v2-adopt.md`.) · **Prev S81** — **adopt Harness-15 memory-budget per-agent (token-governor + value-gate + work-state block)** — em main single-writer + 1 REVIEW Workflow (`wf_b7f3c8ac-b53` 3-lane: Part-A PASS · Part-B PASS · Honesty HONEST), **0 production code**. `/check-email AI_INFRA` STAGE 1 = **0 new directed** (outbox/se 4 file processed S79); fan-out diff → CHỈ **H15** unapplied (H14/v2.0/checklist-9-10/11 đã phủ S72/S75/S79). **8/8 🔴 floor:** A1 đo-SÀN persona-direct `Get-ChildItem` 4.3-13.3KB + harness-injected SE-ước-riêng 21K→**30K cap-riêng-SE** · A2 `token_governor` L1 12K/L2 6K/L3 4K (lead hard-cap) · A3 tách-nhà · B(a) nạp-đầy-no-token-saving · B(b) **value-gate** `value_protect` 10-pattern + gate-script FLAG **runtime-fired** (test-specialist gotcha#/guard) ⟂ keep-floor recency = mark `RC-…11` áp tầng-bộ-nhớ · B(c) **work-state block** `session-start §2.1.5` · B(d) 3-tệp-chốt verified (`hmw.js:124` MEMORY-PACK) · B(e) **2-governor** byte⟂token. **5/6 sàn = convention, chỉ (e)+đo-SÀN = mechanized (honest no-overclaim).** Review bắt **2 CONCERN** (anchoring + tool-attribution) → **fixed** (review→fix loop) + refresh stale `measured` block S71→S81. Artifacts: `memory-budget.json` + engine `§G` + `session-start §2.1.5` + `rules §6.6` + gate-FLAG + adap-report `2026-06-20-Governance-harness-15-memory-budget.md`. A7 217/217 · detector 26-flag baseline (0 new). ⚠️ **restart CLI** (session-start §2.1.5). **✅ mark H-15 stamped Active-High** (`RC-…23-07-37`, anh-confirm S81). **State GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** → log `2026-06-20-S81-harness-15-adopt.md`. · **Prev S80** — **curate L1 over-cap reviewer/inv-codebase/cicd → L2 archive** — em-main single-writer, archive-gate keep-floor-hit→manual condense-with-archive: 31 entries byte-exact (`sed`) +N−0 → `archive/2026-06.md` + 31 `_INDEX` substring pointer → **A7 GATE PASS 217/217**; stale foundation counts flushed (130/263→354 · 55→71 · Mig 40/55→57 · 84→88 · bundle→#330). **0 production code, state GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** WATCH (A6 strike-1): frontend-designer 26KB + test-specialist 28KB. Lesson: `_INDEX` substring **quote-free** (A7 quote-parser bắt escaped-quote PURO pointer self-grep miss). 9 agent-memory file, docs-only commit (CI skip). → log `2026-06-20-S80-curate-l1-overcap.md`. · **Prev S79** — **adopt User-Mark (H-12/13) canonical §P + Harness-14 (Eval/Budget/Outcome) + chữ-ký RC** — em main + 4 Workflow (invest `wf_82337f7f-95c` → review `wf_a7cbe93e-912` → align-re-review `wf_9d3beebb-a95` → H14-review `wf_4d4eba6f-8a0`), **0 production code**. Anh gõ `/user-mark-active-high` "áp đầy-đủ chính-xác nhất theo AI_INFRA" → áp **canonical §P đầy-đủ** (P1-P10): 4 lệnh `/user-mark-*` + ledger `.claude/governance/ACTIVE-MARKS.md` (Active-High/Active/Medium/Disable) + `harness-11-engine.md §E`+**§F** + `rules.md §6.6` objective-criteria. **3 mark Active-High stamped** anh-confirm (`RC-pqhuy1987-20-06-2026-10-29-09/10/11`). completeness-gate H-6→H-13 **ĐẠT** (H-8 11/11 inherit no-`[1m]`). §F floor 6/6 + maturity HONEST. 3 adap-report + email ai_infra (`7b8615b3`). Bài học: broadcast cô-đọng→canonical-command/§P là spec THẬT (bản đầu MUST/TRACK→align lại) · report-before-stamp dogfood · investigator residual-diary OK. State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. ⚠️ restart CLI. → log `2026-06-20-S79-user-mark-harness-14-adopt.md`). · **Prev S78** — **PE: đính kèm file khi DUYỆT (UAT Tra Sol / 5 tester)** — người duyệt tải file của mình lên ngay lúc Duyệt thay vì Trả lại phiếu (tình huống thay đổi nhỏ). Reuse hệ attachment + enum `ApprovalAttachment=5` **MIGRATION-FREE** (int-stored, 0 schema change); endpoint `POST {id}/attachments` + authz có sẵn (handler không guard drafter-only → approver upload được). FE 2 app SHA-identical: `PeWorkflowPanel` picker multi-file + upload-TRƯỚC-chuyển-phase (file lỗi=không duyệt) + mục "📎 File đính kèm khi duyệt" (download/preview) + 2 filter fix loại purpose=5 khỏi "Bảng so sánh" (gotcha **#71** proxy-predicate pollution). commit `7886fd0` → **Run #330 PASS** ~4m56s (test gate **354**, bundle admin **`CsJetgZH`**/user **`BVS0ApIm`**, NO migration, smoke 4×200 + attachments 401-wired). **3 lỗi em tự bắt review-trước-deploy** (authz-verify handler · filter-pollution #71 · Dialog mirror-truncate fe-admin). em-main-led + self-gate (grep no-leak thay reviewer over-cap) + cicd-monitor verify. → log `2026-06-19-S78-pe-attach-file-on-approve.md`. · **Prev S77** — **buổi sản phẩm RẤT LỚN: 10 deploy prod-verified #320→#329 (anh Kiệt FDC + Tra Sol + Bích Phượng UAT realtime, HMW-mode ON)** — bundle cuối admin **`BqKD3Y23`** / user **`Cn-i349D`** (Run #329). **Mig 56→57** `AddPeSuggestedPriceNotes` · test 344→**354** (+10) · gotcha **70** (tái dùng #70). 10 việc PE: (1) cờ GẤP **pill** 🔴PRO/🟢CCM đồng bộ MỌI danh sách + inbox (#320, NEW `PeUrgentChips` ×2 app); (2) **focus mode** bấm phiếu→overlay (#321) → **revert** list về layout gốc bám-trái lấp-đầy (#322); (3) **Mig 57** ô ghi chú giá đề xuất PRO/CCM (2 cột nvarchar(1000)) + **số phân cách VND** (`VndInlineEdit`/`BudgetCell`) + sửa chính tả "Bảng so sánh giá" + **guard #70** stale-echo (#323); (4) số âm → **đỏ + ngoặc** `(…)` hàng 7/8/9 (#324); (5) mục con **thụt dòng + gạch đầu dòng** phân biệt có-số/không-số (#325); (6) cờ gấp authz **BẤT ĐỐI XỨNG** GẮN=NV chức năng / GỠ=chỉ Trưởng phòng (DeptManager) (#326, asymmetric handler + button-by-state); (7) **tách chọn-phiếu (inline 3-panel) khỏi mở-rộng (overlay)** + nút "Xem mở rộng" mỗi dòng (`?expand=1`) (#327); (8) **chuông báo người duyệt** khi phiếu vào cấp họ — submit + mỗi approve-advance (#328, `LogTransitionAsync` notify current-level approvers); (9) banner phiếu **Trả lại** hướng dẫn gửi lại (#329). **3 lỗi em tự bắt khi review TRƯỚC deploy** (guard #70 stale-echo cho ô ghi chú · luật cờ-gấp bất-đối-xứng Tra Sol clarify giữa-chừng · double-mount PeDetailTabs Task H — intent-comment có nhưng code sót). Cách chạy: em-main + frontend-designer ×3 (focus/revert/decouple, FD2 stub-verify do backend-down #3) + implementer-frontend (pill/notes/sep/spelling) + implementer-backend ×2 (Mig 57 · approver-notify) + test-specialist ×3 (notes +7 · urgent symmetric→asymmetric REDO do clarify-after-dispatch) + cicd-monitor ×10 (10/10 PASS). **frontend-designer process-death giữa Task H → recover-disk** (edit hoàn-chỉnh trên disk, em-main build-verify + mirror). **🔴 NEXT (em): curate L1 over-cap GẤP** — reviewer **45KB** + cicd-monitor 37.6KB + inv-codebase 35.6KB (keep-floor-hit → manual SPLIT/condense; archive-gate A7 GATE PASS 186/186 integrity OK) + FD 26KB/test-spec 27.7KB WATCH strike-1. → log `2026-06-19-S77-pe-ux-batch-10-deploy.md`. · **Prev S76** — **PE ngân sách MA TRẬN 3 cột (Dự án|PRO|CCM) + bảng lưới `
` viền-ô + badge quyền-NS theo role** — anh Kiệt FDC + chị Trà Sol, go-live; anh giao `/ultra-on` "step-by-step + workflow-review-per-step, hoàn chỉnh rồi deploy". **3 commit prod-verified:** `e33481e` (feature Run #318 — Mig 56 + ma-trận-3-cột + badge designer/flow, `BhFDF9IJ`/`BAkuRl3C`) → `21d1f4e` (bảng lưới `
` theo phản hồi anh, Run #319 **`jOqxW4-p`**/**`DbsznVvR`**, smoke 3×200). **Part 1:** PRO sửa cột PRO (canEditPro), CCM sửa cột CCM (canEditCcm), Dự án FE hiển-thị-only; Mig 56 +ProInitial/ProAdjust additive + data-migrate ProEstimate→ProInitial (4 rows prod). **Part 2+3:** badge "✎ NS PRO/CCM" cạnh approver (suy từ role, display-only no-authz) ở Workflow Designer + flow Duyệt NCC. Test 339→**344** (+5). **2 workflow review** (Part 1 PASS + Part 2/3 PASS) — reviewer bắt **race mất-dữ-liệu** Part 1 (impl self-review sót) → vá `useIsFetching` 2 app, **gotcha #70 NEW**. Lessons: flex+gap KHÔNG ra "bảng" → phải `
` viền-ô · workflow-review-flaky (2-3 lane empty #53) → em-main self-gate lane rỗng. **NEXT:** 🔴 curate L1 over-cap (reviewer **45KB** + inv-codebase 35KB keep-floor-hit manual-condense; cicd 29KB + test-spec 28KB strike-1). → log `2026-06-19-S76-pe-budget-matrix-table-grid.md`. · **Prev S75 (2026-06-18)** — **Harness-11 adopt: engine bộ-nhớ-và-governance TỰ-BẢO-TRÌ + 2 double-check** — anh giao `/check-email AI_INFRA` + `/adap-apply` (mỗi stage workflow-review) + double-check ×2 + finalize report + push + session-end. em main + **5 Workflow** (audit `wf_7fdc3bd5-930` → implement `wf_c5e5844e-7c1` → review `wf_d7ca1ff8-942` → double-check `wf_a0b68d2f-30e` → checklist-verify `wf_39cd4cbe-f07`). **0 production code.** Built `scripts/governance-detectors.ps1` (C1 broken-pointer + C2/B3 staleness + C3 vocab-fork + C4 self-exclusion + C5 resolve, NO-API DÒ+FLAG, runtime **26 flag** bắt drift thật, C4 0-self-match) + `scripts/memory-archive-gate.ps1` (PHẦN A hysteresis 0.85/keep-floor 5/2-strike/A7 NO-API 186/186) + `docs/governance/harness-11-engine.md` canonical (3-tier D5/D6/D7 EXPLICIT + one-direction-lock D8) + **B1 ×11 count→pointer `docs/STATUS.md`** (drift mig53→55/test306→339/gotcha68→69/table93→88 RESOLVED) + cadence-wire session-start §2.1.3 (D1) + session-end §L.b(c) (D2) + agents/README Upgrade S75. **completeness-gate FORMAL ĐẠT** (B 4/4 + C 5/5 + D 11/11 đủ-trọn, A 🟡 tailored — A6 runtime cần 2×-Apply legit-by-design). **gotcha #30 reinforced** (box-glyph ├└─ KHÔNG vào .ps1 — PS5.1 -File ANSI mojibake, KỂ CẢ qua Edit render-normalize; detector pure-ASCII verified). 3 commit `e70c046`+`ae957c4`+`aa09e99` pushed + adap-report + email ai_infra (`2316773229f2`). **State THẬT GIỮ NGUYÊN: Mig 55 · 88 bảng · 339 test · gotcha 69 · menu 54 · bundle `BYF5vIMJ`/`CB-tiRxd`.** ⚠️ restart CLI (cadence §2.1.3/§L.b + ef-core skill). 🔴 curate-debt: reviewer 38.8KB + inv-codebase 31.5KB + cicd 26.8KB over-cap (archive-gate confirm; reviewer+inv keep-floor hit → manual split). → log `2026-06-18-S75-harness-11-adopt.md`. **Prev S74** — **PE ô "Ghi chú từ CCM" ngân sách gói thầu (Mig 55)** — anh forward 2 luồng Zalo (Trà Sol + Kiệt FDC) "CCM cũng giống PRO cho nhập + ghi chú, hiện 0 hết" → em-main BE+Mig55 ∥ implementer-frontend FE 2 app SHA-mirror ∥ test-specialist (chết rate-limit → recover-disk). 2 fork anh chốt qua AskUserQuestion: **thêm CcmNote (Mig 55)** + **GIỮ phân vai CCM** (CostControl/Admin). Entity `PeWorkItemBudget +CcmNote` mirror ProNote · `UpdatePeBudgetCcmCommand +CcmNote` absolute-set role-gate fail-closed · DTO+controller+mapping · FE dòng "Ghi chú từ CCM" gate `canEditCcm` (sau V0/hiệu chỉnh, absolute-set đủ 3 field). Mig 55 additive-nullable sạch (no #63). Test 334→**339** (+5 CcmNote). **Chẩn đoán "0 hết không nhập":** tài khoản thiếu role CostControl (KHÔNG bug) → UAT bằng CCM/Admin. commit `8655ebf` push main (cicd **Run #315 PASS** ~4m54s — Mig 55 applied prod, bundle admin `BYF5vIMJ`/user `CB-tiRxd`, smoke 4×200). Lessons: controller call-site thiếu arg sau +param record (grep+vá, #65 bắt) · agent-kill-529 recover-disk no-re-spawn · PS here-string commit-msg trong if-block mis-parse → `git commit -F`. → session log `2026-06-18-S74-pe-ccm-note.md`. **Prev S73** — **Mig 54 PE giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích (anh Kiệt FDC — go-live so-sánh-giá thứ Hai 22/06)** — em main + 6 sub + 2 review-workflow. **2 commit prod-verified:** `1d86abc` (feature, cicd Run #313 PASS — Mig 54 + bundle admin `OlNyG9OD`/user `DSzSLVtL`) + `6aa4dcb` (FE empty-candidates guard fix). **BE:** Mig 54 `AddPeSuggestedAndApprovedPrice` 5 cột additive-nullable (ProSuggestedMin/Max·CcmSuggested·ApprovedPriceAmount·Source) + 2 setter role-gate PRO/CCM (Forbidden fail-closed mirror budget) + ApproveV2 **③ AUTO→OPT-IN** (`finalizeByCcmDelegation` ô-tích, gỡ auto-threshold S69) + **① bind giá chốt** mọi nhánh DaDuyet (human bắt-buộc-chọn, isSystem-miễn) + DTO +7 field/capability. **FE 2 app SHA-mirror:** PeWorkflowPanel (bộ chọn giá + ô tích CCM + fix empty-candidates) + PeDetailTabs `SuggestedPriceRows` + types +7. **Test 306→334** (+28). **2 workflow review (bài học):** R1 schema-force CHỈ **1/4** lane returned (flaky no-StructuredOutput) → R2 **free-text 2/3 PASS** — rủi ro #1 FE empty-candidates = **UNREACHABLE** (submit-guard `:194` chặn gửi-duyệt khi winnerQuoteTotal≤0). → review fan-out dùng **free-text / hmw RUN-TRACE**, KHÔNG ép-schema inline. **Governance honest:** em lệch mandate auto-Workflow (mode-ON) + chỉ khai khi anh hỏi → **cam kết báo-TRƯỚC-khi-lệch**. Run-trace `runs/2026-06-18-mig54-pe-review/` (custom-inline, bù post-hoc). → session log `2026-06-18-S73-pe-gia-de-xuat-ccm-done.md` pending. · **Prev S72** — **Harness-10 flat-refine + checklist-v2 adopt (re-audit 3-workflow) + sleep NO-OP** — em main + 9 sub qua 3 Workflow (audit `wf_13868efb-ea7` → implement `wf_ac43b5ff-7d1` → review `wf_d482e10d-5dd`, mandate Harness-9 B1+B2). Anh chỉ "sisters làm tốt mỗi SE thiếu" → re-audit đo vs canonical: **SE BEHIND Harness-10 flat** (run-trace còn SUBFOLDER, canonical=FLAT) → migrate `hmw.js` (`:103` sub-md/→flat + `:52` schema + **H4.5→H8 doc-drift**) + `workflows/README` full-rewrite + `runs/README` + session-start/end + `agents/README` Upgrade S72 + `_ledger`; **5 run cũ S71 GIỮ subfolder** (C8 dual-accept). +2 broadcast 06-18 adopt (checklist-v2 + h10-flat-detector-refine). +`/sleep-recovery-memory-l2` port (A8, §J2-tailored SE-only, floor intact, live skill). **detector refine-b TAILORED-OUT** (SE Workflow-tool no-CLI-bypass; containment git-diff+tracked+orphan-scan G-015). **REVIEW (B2 dogfood) bắt 2 lỗi IMPLEMENT-self-assess sót** (hmw.js:52 schema-stale + sleep-cmd auto-check un-wired overclaim) → fixed (auto-check **WIRED thật**: budget.json `+last_sleep_at` + session-start:78 + session-end:48, grep-verified). em-main containment-check tự bắt 1 reviewer residual-write (raw-Workflow KHÔNG hmw.js writeGuard → reverse-finding #4) → revert. **B3 self-correct:** S71 report path tắt `runs/`+"14" → thật `.claude/workflows/runs`=22. **Sleep `all`=NO-OP** (5/9 empty-archive + 4/9 đã-gisted → 0 compressed; `last_sleep_at`=2026-06-18). **0 production code, state THẬT GIỮ NGUYÊN.** adap-report `2026-06-18-Governance-harness-10-flat-refine-checklist-v2` + email ai_infra (`5f511fe5c0f2`). ⚠️ **restart CLI** activate FLAT-runtime hmw.js + wired sleep-check + sleep-recovery skill. 🔴 **NEXT (em):** curate investigator-codebase L1 **28973 OVER** (audit-trail) + watch frontend-designer/test-specialist near-cap. → session log `2026-06-18-S72-harness-10-flat-refine.md`. **Prev S71 — Harness-10 adopt: tracked run-trace folder convention + checklist 9-10 self-verify** — em main + 3 Workflow (invest `wf_9c2cd2cd-2e7` → implement `wf_e4e46725-231` → review `wf_636bc95b-939`) theo mandate Harness-9 PART 2. **0 production code** (governance/workflow only). Migrate `.claude/workflows/wave-*/` gitignored → `runs//` **git-TRACKED** (run.md + sub-md/ + harvest/) + `_ledger.md` 2-nhịp + 3-layer anti-miss (L1 em-main@P1 ledger-check / L2 session-start orphan-scan / L3 session-end close-gate **idempotent-VERIFY-not-re-APPEND**) + **containment model shift** (Harness-2 B6 "mọi tracked-change=vi-phạm" → Harness-10 "tracked-change NGOÀI run-folder + code-disjoint=vi-phạm"; run-folder TRACKED → HIỆN git-diff = audit trực-tiếp). hmw.js wave→run-trace (accept `args.run`, alias `wave`; path `sub-md/`; `node --check` PARSE-OK). **Review độc-lập (R2+R3) bắt C5 L1 over-claim** (doc nói hmw.js prompt-builder emit L1 reminder nhưng grep engine=0 → engine no-fs → fixed path-a: L1 = em-main @P1 convention) — dogfood mandate B2 đúng (1-workflow-tự-chấm sẽ bỏ sót). **checklist 9-10:** Part A (Harness-9 memory) + Part B (adap 2-workflow) ĐÃ done S70; Part C (Harness-10) MỚI 8/8. dogfood: 3 run-trace folder TRACKED đầu + 3 entry ledger. adap-report `2026-06-18-Governance-checklist-harness-9-10` + email ai_infra. **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** + `CLAUDE.md` test-flush 263→306 (pre-existing uncommitted, resolve H1 stale-flag). ⚠️ restart CLI activate hmw.js RUN-TRACE runtime + (carry S66/S70) §2.1.2 budget-audit/reviewer-Cat-6/H8-inherit. ✅ **curate-debt CLOSED S71** (FINALIZE double-check `wf_73de399d-753` + curate `wf_f32987b8-03f`): reviewer 36.7→24.8KB + investigator 29.8→23.2KB (both <25600 cap, archive +N -0 0-byte-loss) + reviewer-gist gen:2 + 3 user-memory G2/G3 + budget.json re-measure. Race root-cause fixed cấu-trúc (hmw.js RUN-TRACE writeGuard). → session log `2026-06-18-S71-harness-10-run-trace.md` (pending). **Prev S70** — **Harness-9 adopt: L2 archive dark-matter recovery + adap 2-workflow mandate** — em main + 3 Workflow (investigate `wf_be952f3c-97f` → implement `wf_a58e0d15-beb` → audit `wf_9520d8cd-4fe`) + 2 monitor bootstrap. **0 production code** (governance/memory only, commit `f36aab8` pushed). 4 over-cap sub-agent (cicd-monitor/investigator-codebase/reviewer/implementer-backend) curate L1→L2 + `archive/_INDEX.md` (mục-lục con-trỏ **substring sha-keyed**, Ctrl-F fallback) + `.gist.md` (nén 4-field distill-gen:1, verbatim FROZEN) → **cả 4 < 25KB auto-inject cap** (P1 curate-debt CLOSED; ~240KB archive hết RAG-dark). PART 2/3 process-mandate codify (adap-apply + agents/README Upgrade S70 + session-start §2.1.2 budget-audit). **0-byte-loss git+sha verified** (Stage C audit + em-main self-gate khi 2 reviewer no-StructuredOutput). +`memory-budget.json` (seed-by-measure) + `scripts/measure-agent-memory.ps1` + `.ragignore` + doc-drift 4-cite flush. adap-report + email-back ai_infra (body-hash `7c07b716e775`). **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** ⚠️ restart CLI để activate session-start §2.1.2 + pending H8 inherit + reviewer Cat-6. → session log `2026-06-17-S70-harness-9-l2-recovery.md`. **Prev S69** — **Văn phòng số (E-Office) port + golive + PE cờ gấp/ngưỡng CCM — 4 deploy prod-verified Run #305→#308, HMW-mode ON, 2 workflow fan-out + ~14 spawn**: foundation PURO (shared PageHeader/KpiCard/WidgetCard + Dashboard 2-cột + sync fe-admin index.css đóng drift S66-S68) #305 → **re-skin TRỌN 10 page** PURO layout + CSS Hồ sơ NS, phẫu-thuật-giữ-100%-logic (reviewer verify api/queryKey byte-identical) #306 → **Office golive public** `SeedAllRolesOfficeModulePermissionsAsync` read+create 16-key allow-list mọi role (mirror S65 pattern, chạy SAU revoke; excluded Off_PhongHop_Manage/Off_AttendanceReport/Off_ChamCong giữ ẩn; cicd DB-verify 16/16×13 role) #307 → **PE cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị** Mig 53 (anh Kiệt FDC sau họp sếp) #308. **State THẬT: Mig 53 · 88 bảng · 306 test (45D+261I) · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf` Run #308.** 2 gotcha NEW (**#67** Tailwind accent palette thiếu-stop vỡ-màu-im-lặng · **#68** stale-diagnostic-background-agent). 2 truncation #53 (impl-backend positional-record + impl-frontend) → em main recover-disk + self-gate (cả 2 build PASS sau-cùng). C (sau duyệt → chuyển phiếu đến dự án) chờ anh Kiệt spec form. → session log `2026-06-17-S69-vanphong-golive-pe-urgent-threshold.md`. **Prev S68** — **Hồ sơ NS header chi tiết NV: làm nổi bật + fix tên render đen→trắng** — em main solo, 3 commit (2 FE `6983609`+`37752eb` · 1 docs `11bc96d`), 2 deploy prod-verified Run #303-304 (anh UAT realtime): tên `text-xl extrabold`+drop-shadow · dòng meta `text-[13px] font-medium` trắng-đậm · badge pill **màu theo trạng thái** (#303); anh báo "tên đen nền xanh ko nổi bật" → diagnose **rule `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng `text-white`** (Tailwind v4 unlayered > all layers, **gotcha #66 NEW**) → ép `text-white!` + thu nhỏ `text-lg` (#304, grep dist confirm `!important`). Bootstrap: 2 monitor RE-REPORT CLEAN + 2 doc-drift fix (dep-audit 64→65 · root CLAUDE 263→286, H1 flag). **State THẬT: Mig 52 · 88 bảng · 286 test · 66 gotcha · menu 53 · bundle admin `CNUv1jxY`/user `CpOskeS1` Run #304.** ⚠️ curate-debt P1: cicd-monitor **44.1KB** (worst). **Prev S67:** **buổi sản phẩm LỚN, 6 deploy prod-verified Run #297→#302** (anh + anh Kiệt FDC UAT realtime, HMW-mode ON): fe-user Hồ sơ NS đồng nhất font + chữ đen→**xanh đậm `brand-800`** (#297 `ab4e681`) · **fe-admin mirror master-detail** + accent tokens index.css [đóng pending lớn nhất HRM go-live, page SHA256 ×2] (#298 `292d64d`) · **+23 test-after HRM** [Dept cycle-guard · PE HoSoLink absolute-set · HRM-perm seed] → 263→**286** (#299 `bcd619d`) · **list flex-row gọn** [bảng 3-cột→flex-row, `overflow-x-hidden` → hết tràn ngang rail] + đồng nhất cỡ chữ [18/14/13/11px] ×2 app (#300 `91aaf05`) · **PE Link hồ sơ auto-detect** `http(s)`→hyperlink/`O:\`→Copy (#301 `6df1b2d`) → **render link `file://` bấm-thử** + Copy (#302 `536dd6b`). **Workflow research 3 investigator-api** (auto-mở `O:\` từ web): default browser CHẶN https→file://; **chỉ Edge GPO `IntranetFileLinksEnabled`** (Edge-only, Intranet Zone, 1 GPO domain zero-per-machine) = one-click thật — Chrome không có; .url-download zero-install nhưng 2-click. **State THẬT: Mig 52 · 88 bảng · 286 test (45D+241I) · 65 gotcha · menu 53 · bundle admin `CcrZqfht`/user `DniDFUB_`** (#302). test-specialist truncated return #53 → em main recover-disk (3 file test đủ + 286 verify); 0 production bug. ⚠️ curate-debt: cicd-monitor 39.8KB + inv-codebase 39.4KB over-cap. **Prev S66** — **session-end closeout em-main-solo, 0 product-sub:** adopt **Harness-8 all-inherit** (7 sub demoted `claude-opus-4-8`→`inherit` → cả 11 = inherit, gỡ two-tier Harness-4) + **cicd-monitor L1 curate 86.8→28.9KB** (byte-exact sed → `archive/2026-06.md`, incl #291 forensic) + **ef-core skill doc-flush Mig 50→52** (H1 drift, +Mig 51/52 rows) + check-email AI_INFRA (**0 thư mới se-directed**). ~17 file docs/gov/config, **0 production code** → state THẬT GIỮ NGUYÊN: **Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf`**. ⚠️ **Restart CLI** để H8 runtime (frontmatter no hot-reload) + reviewer Category 6 (S64 pending). adap-report `2026-06-16-Governance-harness-8-all-inherit-workflow-fastest` + email-back ai_infra (hash `fa7f690d` round-trip MATCH). Prev S65 — **HRM go-live: public Hồ sơ Nhân sự + trang master-detail giống NamGroup + Department hierarchy + PE Link hồ sơ**, ~6 deploy prod-verified Run #289→#295, anh + anh Kiệt FDC UAT realtime): (1) **public Hồ sơ Nhân sự mọi role** — `SeedAllRolesHrmProfileReadPermissionsAsync` grant CanRead `Hrm`+`Hrm_HoSo` 13 role chạy SAU revoke S58 (upgrade-only; EmployeesController policy-based `Hrm_HoSo.Read` mở luôn API không hardcode Roles), giữ ẩn Dashboard NS, Run #289; (2) **redesign màu foundation fe-user** — accent palette teal/violet/amberx/greenx + `.app-gradient-brand`/`.card-accent`/`.icon-chip` + heading 700, brand #1F7DC1 + Be Vietnam Pro giữ, Run #290; (3) **Department hierarchy** Mig 51 `AddDepartmentParentId` (ParentId loose-Guid no-FK + `GET /departments/tree` ráp cây in-memory + rollup count theo `User.DepartmentId` + cycle-guard HashSet) + picker "Phòng cha" fe-admin (self-service org chart) + Update cycle-guard, Run #292; (4) **Hồ sơ Nhân sự master-detail giống NamGroup** — `EmployeesListPage` rewrite: 3-panel→**2-cột** (cây tổ chức gốc "SOLUTION COMPANY" + list chồng TRÁI · chi tiết 5 tab PHẢI) + tô màu accent, giữ 100% 5 satellite CRUD (16 endpoint), Run #293/#294/#295; (5) **PE mục "e. Link hồ sơ"** Mig 52 `AddHoSoLinkToPurchaseEvaluation` (`HoSoLink string?` hyperlink NAS + `` target_blank rel-noopener + null-safe) + rename "Dự trù PRO"→"Ngân sách PRO" (row+badge) ×2 app SHA256-mirror, Run #293. **State THẬT: Mig 52 · 88 bảng · 263 test (45D+218I) · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf`** (Run #295 `456c7a7` Employee-refine — user rotate `CZfo_PFZ→DbVv6rsf`, cicd PASS). **🔥 Workflow fan-out chạy THẬT lần đầu** (`pe-hoso-link-rename-pro` BE∥FE→review) — parallel disjoint-file OK, NHƯNG FE+reviewer return-RỖNG #53 → em main recover-disk + self-gate (bắt badge "DỰ TRÙ PRO" sót rename); **verdict: fan-out cho parallelism nhưng reviewer-stage không tin được trong harness này → verify-heavy task vẫn tự gác = tương đương spawn lẻ** (`feedback_workflow_fanout_reliability`). gotcha **#65** NEW (build csproj con ≠ `dotnet build slnx` gồm tests → miss test-compile khi đổi chữ ký record command → CI CS7036 Run #291 FAIL-gated). **Prev S64** adopt **Harness-7 writing-quality floor** — em main solo, commit `6afde19` docs/gov-only, 0 sub spawn: `rules.md §1.1` outward-VN-full-grammar + reviewer Category 6 + adap-report + email ai_infra; broadcast body-hash `a4580ea9` verified-MATCH **KHÔNG mis-stamp** [false-mismatch = gotcha #61 PS5.1 UTF-8 decode của em]. Prev S63 docs-closeout bù S60/S61/S62 — **State THẬT: Mig 50 · 88 bảng · 263 test (45D+218I) · 64 gotcha · menu 53 · bundle admin `0xKYGhhf`/user `C81ZdG9G` Run #286**; S60-62 = PE ràng buộc gửi-duyệt + bypass drafter (S60) · gỡ "Từ chối" (S60) · Mig 50 ngân sách per-gói-thầu Excel anh Kiệt + XÓA module Budget cũ (S61) · vượt-NS cảnh-báo-mềm cho lưu (S62); + reconcile stray reviewer cwd-misland; session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`). Prev Session 59 ( **10 đợt ship prod-verified: 8 Run PASS + 2 cancelled-supersede-benign #273→#282** (run_number API — dải đếm khác #38x S58, cùng pipeline; 2 cancel = push-đè khi UAT góp ý realtime, ancestor-verified): (1) **wipe transactional testing data** theo anh Kiệt FDC — 10 PE + 7 HĐ [DEMO] + 64 notif + 1 AwV2 cũ inactive = 0, reset PeSeq/CtSeq → phiếu thật đầu tiên team tạo chiều nay = **PE/2026/A/001** ✓, app-recycle KHÔNG resurrect (DemoSeed gate held), uploads orphan dọn (`56882ac` #273); (2+3) **PE tree Panel 1 chốt 4 tầng "📅 Năm > 📁 Dự án > 🧱 Hạng mục > Phiếu"** (anh chốt follow-up sau bản gộp "Dự án (Năm)"; `yearGroups` useMemo, expand-key v3, FE-only — list DTO đã có workItemName S57bis) (`0eafcd3` #274); (4) **dọn 15 mã hạng mục demo tự chế** theo chị Trà Sol "xóa cái đám phần thô phần hoàn thiện… MÀ ANH TỰ ĐẺ RA" — WorkItems 86→**71**, GỠ HẲN block seed demo khỏi DbInitializer, đối chiếu 71/71 khớp bảng PMH từng dòng (`bbd1554` #275, bundle frozen BE-only); (5) **rename 71 mã đúng format PMH anh Kiệt chốt** "MÃ CV gồm chữ MEP-SUB-1 rồi tên 1 MEP Sub MEP (Full) — đúng kiểu vậy" → `MAT-n`/`SUB-n`/`MEP-SUB-n`/`MEP-EQU-n` + Name "STT nhóm tên"; **DB-trước-code-sau** (gotcha **#62** NEW — seed per-code idempotent, sai thứ tự = 142 rows) + sqlcmd `-f 65001` (gotcha **#61** NEW — verify data qua API JSON, KHÔNG tin console mojibake) + FE sort numeric ×3 ×2 app (`c869d26` #276); (6) **UAT 6 vòng 11 điểm**: NEW **`ui/SearchableSelect`** combobox gõ-lọc BỎ DẤU (fold NFD — Hạng mục/Dự án/NCC) + auto Địa điểm từ Project.Location + điều khoản TT Textarea đa dòng (`faed59f` #277) · anh chốt: **ẩn cả Trả lại+Từ chối khi người duyệt = người soạn** (drafterUserId match) + **quick-add NCC ngay form** (SuppliersController POST hạ → any-auth, PUT/DELETE giữ khóa — cicd authz probe live 4/4: 401 unauth/201 nv.test/403 delete/cleanup) + upload multiple files ×2 chỗ (`9c330d2` #278) · vòng 3-6 realtime (`f21c55d` #279-cancelled / `69997da` #280 / `80b64dd` #281-cancelled / `792c030` **#282 FINAL**): **bảng NCC table-fixed** width từng cột (file dài hết vỡ layout) + **bỏ ô "Tên" ngân sách nhập tay** (chỉ còn Số tiền, hasManual detect theo amount) + **GỠ field "Điều khoản thanh toán" khỏi TẤT CẢ form phiếu** (cột per-NCC + display phiếu cũ GIỮ) + **bỏ nút "+ Thêm hạng mục"** (1 phiếu = 1 hạng mục header). Bundle FINAL admin **`B1DtNT9C`**/user **`D6uF3Mln`** (Run #282). Test 240 ×2 local + 8× CI gate. **0/14 spawn truncated** (lần đầu sau nhiều session). → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`. Prev S58 (2026-06-11 — **4 việc prod-verified Run #382/#383/#384**: lock-demo-user fix + tạm ẩn HRM/Office/Cá nhân + Danh mục cuối sidebar + fe-user redesign theo UI/UX guide AI_INFRA. **Việc 1 — lock fix** (Run #382, `5998163` ~3m31s): Run #381 cicd phát hiện S57bis lock = NO-OP (14 email named-person là population Dev-only). Recon dump prod: demo thật = 20 UAT-matrix `{dept}.{nv,pp,tp}@`+`bod.{1,2}@` tạo TAY 05-13; root cause sâu = `DemoUserPassword` 11 ký tự < prod `RequiredLength=12` → `CreateAsync` silent-fail MỌI startup từ trước tới giờ (= root cause "helpdesk inert phòng IT 0 user" S56). Fix: union 20 email + password 12 ký tự. Prod sau deploy: **55 user / 21 active / 34 locked** — 20 UAT + 14 named-person locked ✓, **nv.cao/nv.truong CREATED+ACTIVE (helpdesk S56 RESOLVED)** ✓, 5 real staff created ✓, guard admin/catalog.manager/nv.test/chuong.phan-typo active ✓ (anh chốt 3 quyết định AskUserQuestion). Bundle FROZEN. gotcha **#60** NEW (seed silent-fail vs prod password policy — dump population thật trước khi lock/seed-by-email). +Closeout S57bis residual: gotcha #59 commit, 4 spawn-record on-behalf (H2 4-MISS), H1 5-patch doc-drift, test 240 re-verified local. Prev S57bis (2026-06-11 sáng) — **PE gắn Hạng mục công việc (Mig 49) + mở quyền Pe all-role + menu "Cá nhân" + khóa demo user** (sếp Zalo deadline 15:00): commit `17b23a4` (Harness-4 two-tier runtime-VERIFIED spawn-test 2 chiều) + `dd117b7` (product) → Run #381 PASS ~4m25s. Mig 49 `AddWorkItemToPurchaseEvaluation`: PE.WorkItemId `Guid?` loose-Guid KHÔNG FK vật lý (convention PE — database-agent design) + IX + validator NotEmpty create + FK-guard handler Conflict + UpdateDraft null-safe. FE ×2 app PeWorkspaceCreateView/PeHeaderForm (SHA256 identical)/PeDetailTabs "Dự án – Hạng mục". Pe_* 11 key CanRead+CanCreate mọi role (130 rows/13 role — Pe_* leaf KHÔNG nằm MenuKeys.All, build qua factory). Menu Personal root@30 + Chấm công re-parent + Master write-lock `Admin,CatalogManager` ×3 controller. Test 228→**240** (+12 PeWorkItemGuardTests). Bundle rotate cả 2: admin `CP4CB1ym` / user `BmZ3VHnm`. 2 builder truncated #53 + reviewer die-0-byte ×2 → em main solo vá cross-stack + self-gate. Excel (3) đối chiếu = NO-CHANGE (S55 data identical). Prev S56 — **Pre-golive verify sweep + golive-harden 4 fix — HMW 2-workflow, prod-verified**: commit `a20cde8` → Run #379 PASS ~4m20s. WF1 `pre-golive-verify` 7-stream song song + adversarial → 6 PASS/1 CONCERN/0 blocker = **GO**; key finds = **ops not code** (prod IT-dept 0 active user → helpdesk inert + S43 LeaveBalance lost-update còn nguyên). WF2 `golive-harden` fix 4: **#3** LeaveBalance lost-update→atomic `ExecuteUpdateAsync`+Serializable tx (NO mig, exactly-once nguyên) · **#5** ItTicket authz Forbidden-trước-NotFound (fail-closed) · **#6** DocxRenderer null-guard (2 warn→0) · **#4** Travel/Vehicle ApproveV2 +4 smoke. Test **216→228**. Bundle FROZEN `4SUwDLD8`/`XdKzt9LL` (BE-only). `sys.tables` re-ground **92→93** (cicd ground-truth, Mig 48 col-only). reviewer stage StructuredOutput-fail→em main đỡ cross-stack review (3 diff clean) + bump Serializable đóng MAJOR. gotcha **#58** NEW (EF read-modify-write lost-update→ExecuteUpdate atomic). **2 ops VPS pending** (gán user phòng IT + `tzutil` UTC+7). FE Phase 2 redesign **deferred** (recon ready). Prev S55 — **Nạp master data thật từ Excel + Project +4 cột (Mig 48), HMW-mode ON**: commit `69cb393` → Run #377 PASS ~4m33s, prod-verified. Anh giao file Excel "HẠNG MỤC CÔNG VIỆC DỰ ÁN" → `/ultra-on "workflow làm xong hết"`. Nạp **62 dự án + 71 hạng mục + 3 NCC** vào Project/WorkItem/Supplier qua `SeedRealMasterDataAsync` (per-code idempotent, **UNGATED** → coexist demo, tự lên prod). **Mig 48 `AddProjectMasterFields`**: Project +4 cột nullable (Year/Investor/Location/Package, NO new table). FE ProjectsPage form +4 input ×2 app SHA256 mirror. Test 216 (compile-fix MasterCatalogFilteredUniqueTests +4 null args, no new test). Bundle admin `DmjI8Cmn`→`B-d6893W`/user `YxL_MljK`→`XdKzt9LL` (cả 2 rotate). Prod verify: Mig 48 applied · Projects spot-6/6 · WorkItems VT/TP/MEP/TB=71 · Suppliers 3 · CAL01.Investor="Công ty TNHH Calofic". **2 agent return truncated** (implementer-backend + reviewer, gotcha #53) → em main disk/runtime-recover (build/test/sqlcmd/git truth); cicd verdict-FIRST → PASS clean no-truncate. Data-quality catch: MEP col gộp 2 nhóm + divider "THIẾT BỊ" → split đúng 71/4-category. Provenance `scripts/master-import-data.generated.md`. Prev S54 — **IT staff tự reassign ticket (cross-stack authz, HMW-mode ON)**: 1 code commit `ca4b602` → Run #376 PASS ~4m18s, prod-verified. Cho tổ IT (dept Code=="IT") + Admin reassign ItTicket trên CẢ 2 app. BE: NEW `GetAssignableItStaffQuery` capability endpoint `{canReassign,staff}` + `AssignItTicketHandler` authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict) + controller `/assign` hạ `[Authorize(Roles=Admin)]`→`[Authorize]` (handler fine-grained). FE: fe-admin+fe-user ItTicketsPage **SHA256-identical** (REVERSE S53 divergence) gate nút by `canReassign`, dropdown từ `/assignable-staff` (không `/users`). Test 203→**216** (+13 authz guard test-before-merge). NO migration (DepartmentId reuse). Bundle admin `DfCfHUE9`→`DmjI8Cmn` / user `_3S0BPJ2`→`YxL_MljK` (cả 2 rotate). 6-agent fan-out (BE∥FE→test→reviewer→cicd) + em main reconcile stray-memory residual (3 agent ghi MEMORY nhầm `src/Backend/.claude` → harvest về canonical). reviewer PASS 0 blocker (role-string "Admin" chain-verified). Task 1 Phase 9 Ops KHÔNG làm (anh dừng). flag: cicd `sys.tables=93` vs STATUS 92 → monthly audit re-ground.) Prev S53 (gotcha #57 EXT Master Mig 47 + P11-D reassign-UI fe-admin + P11-E menu + database-agent verified-runtime: `44b9e54` Run #260 + `dbf6648` Run #261, test→203, bundle→`DfCfHUE9`). Prev S52 (Phase 11 P11-D+E+F deployed + database-agent adopt, HMW-mode ON): 3 commit — `e9ee97f` (database-agent DB1–DB11 read-advisory, roster 10→11, executed-file CHỜ restart) + `6a66429` Wave 1 (P11-E AttendanceReport+Excel+OtPolicy multiplier + P11-F MaTicket codegen, migration-free) + `dcf76f8` Wave 2 (P11-D ItTicket round-robin assign dept-IT + SLA timer, Mig 46). Test 186→**200**. Bundle admin `DYfjnpY0`/user `_3S0BPJ2` (cả 2 deploy verified curl độc lập — Wave 1 BE 401 wired + Wave 2 /assign 401 + Mig 46 applied health-200). ⚠️ **Session-limit hit giữa Wave 2** → recovery: BE/test verify-on-disk + em main solo FE redo + curl-self-verify thay cicd-spawn (multi-agent resilience, git/disk/prod = source-of-truth). RAG recovered (chunk 2416 rerank live) nhưng stale 05-29. Prev S51: P11-C Vehicle+Driver.) +**Last updated:** 2026-06-23 (S85 — **buổi UAT anh Kiệt FDC CỰC LỚN: CV PRO 6-fix batch + clear-data + 6 vòng UAT + 2 ROOT-CAUSE + 5 SQL-fix — ~10 deploy prod-verified #334→#341, HMW-mode ON, ~12 spawn** — anh forward Zalo anh Kiệt + Tra Sol + long.chau realtime. **Batch CV PRO (Run #334 `5a61254`):** đọc file `Cần chỉnh sửa CV PRO.xlsx` = **8 ảnh chú-thích nhúng** (không phải bảng công thức) → 6 fix: C1 ẩn "c.Giá chào thầu"+"d.Bảng so sánh" form TẠO · C3 ô8 pre-fill từ row7 (Ngân sách còn lại) · C4a **live-recompute** ô3/8 chưa-Lưu (VndInlineEdit +onLiveChange, draftRow3/8) · C4b So-sánh=0→"Bằng ngân sách"/"—" · C5 hủy/đổi NCC winner (BE `SelectWinnerBody(Guid?)` clear-branch + FE dropdown/toggle) · C7 nút "Toàn màn hình" preview file. **Clear-data (`scripts/s85-wipe-uat-data.sql`, BACKUP-trước):** wipe 43 PE + 28 PeWorkItemBudgets + 1 HĐ + 32 notif + 21 NCC-test (CreatedAt≥06-11, giữ 22 gốc) + reset mã→A/001; AskUserQuestion chốt scope (xóa budgets + NCC-test); SET QUOTED_IDENTIFIER ON (filtered-index). **6 vòng UAT (#335→#338):** R1 D1 ẩn mục 3/4/5 + D5 auto-chọn quy trình (1 option) · R2 D2 drafter tự-gỡ cờ GẤP (nới S77 GỠ=TP→+drafter clear-cả-2, BE restructure SET/UNSET) + D3 ngân-sách-kỳ-này tự-nhảy từ "Ban hành lần đầu" (`proInitialAmount`, FE display + BE/FE submit-guard fallback `budgetPeriodAmount ?? proInitialAmount`) · R3 ràng tạo-phiếu (hint đỏ "thiếu gì") + D4 checklist xanh✓/đỏ✗ trường bắt-buộc · R4 checklist +"Quy trình duyệt". **2 ROOT-CAUSE (whack-a-mole→fix gốc):** **(R5 #339 `1263c0d`)** workflow MẤT khi bấm Sửa = **bug-class S42** — `UpdatePeDraftHandler` absolute-set `ApprovalWorkflowId=null` khi form Sửa KHÔNG gửi field → CLEAR (field SÓT khỏi pattern null-safe mà BudgetPeriodAmount/WorkItemId cạnh đã có) → fix `if (request.X is not null)` (gotcha **#73** NEW, +3 regression test) · **(R6 #341 `49ac086`)** "mới tạo báo 7h trước" = **TZ** — timestamps lưu UTC nhưng EF đọc `DateTimeKind.Unspecified` → System.Text.Json default serialize KHÔNG có 'Z' → FE `new Date(naive)`=local → lệch +7h (VN UTC+7) → **`UtcDateTimeJsonConverter`** global (AddControllers.AddJsonOptions) ép UTC-with-Z (gotcha **#72** NEW) — cicd verify API trả `createdAt:"…3154440Z"`. **5 SQL-fix** (2 đợt 3+2 phiếu workflow-less, gán QT-DN-V2-001 type-1, ssh prod). **Cách chạy:** em-main-led + impl-backend (C5 BE clear) + impl-frontend mirror + test-specialist ×3 (C5 +10 · urgent-authz +5 · workflow-preserve +3) + reviewer ×2 (truncated→em-main self-gate, memory-lesson) + cicd-monitor ×7 (7/7 PASS; ship-proof BE-only = `Application.dll`/`Api.dll` Last-Modified in-window, #69-REFINE). **Test 356→374** (+18). **State THẬT: Mig 57 · 88 bảng · 374 test · gotcha 73 · menu 54 · bundle admin `aKuNip19`/user `BUsL0HeQ` (Run #341, FE frozen #339+#341 BE-only).** **Lesson `feedback_root_cause_over_symptom`:** bug lặp-lại (SQL/tzutil band-aid không dứt) → truy field/case **LỆCH-quy-ước** rồi đưa vào pattern đã-đúng = fix 1 chỗ hết tái-diễn. → log `2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md`.) · **Prev S84** — **bootstrap + flush session-start hot-feed cap-echo v3 + commit S83 cicd harvest-orphan (em-main hygiene, 0 production code)** — anh `/session-start` → 2 monitor INFORM: H1 bắt `session-start.md:114` còn cap CŨ `lead 60K/sub 20K/wf 16K` ≠ canonical budget v3 `220K/60K/50K` (S82 self-shrink chưa flush khi S83 owner-set lại); H2 bắt `cicd-monitor/MEMORY.md` = harvest S83 hợp-lệ (Run #333 + gotcha **#69-REFINE**: hash giữ-nguyên khi 0 `fe-*/src` đổi → ship-proof THẬT = `Last-Modified` in-window, KHÔNG hash-delta) sót khỏi closeout `f71654f`. Anh "Sao ko add luôn?" → em flush `session-start.md:114` echo cap → **220K/60K/50K + canonical-pointer "đọc số sống ở budget.json"** chống tái-drift (detector C2 KHÔNG track cap-number → echo-trần lệch âm-thầm lần đổi cap sau) + commit cicd harvest-orphan. **Lesson (`feedback_derived_flush_execution`):** monitor INFORM-only proposal về **derived→canonical flush** = em-main **EXECUTION** (B3 VERIFY→APPEND = verify-rồi-LÀM), KHÔNG gate user-confirm; chỉ **ĐỔI-con-số** mới = quyền anh (chủ-dự-án). archive-gate A7 GATE PASS 217/217 · 2 WATCH strike-1 (FD/test-spec, no-action). **State GIỮ NGUYÊN: Mig 57 · 88 bảng · 356 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** ⚠️ restart CLI (command `.md` no hot-reload — runtime %-print mới ăn cap đúng). → log `2026-06-22-S84-session-start-cap-flush.md`.) · **Prev S83** — **(1) adopt H-15 v3 memory-budget full-parity (anh owner-directive) + (2) fix PE require-workflow create+submit (đóng lỗ hổng "quy trình cũ") prod-verified Run #333** — anh `/session-start` → directive budget Tầng-1 **220K**/mem-sub **60K**/wf-sub **50K** "nạp đầy cho đủ" → diagnose phiếu A/040 "quy trình cũ" → "(B) vá guard BE + test-before → deploy" → `/session-end`. **Part 1 H-15 v3 (commit `2c7fd63` docs-only CI-skip):** `token_governor` lead 200K→**220K**/mem-sub 20K→**60K**/wf-sub 16K→**50K** full AI_INFRA parity (sửa self-shrink S82 = AI tự-co-nhỏ, mark `RC-…01-58-01` cấm) + NEW `spawn_fill_directive` (nạp sub tới budget bằng prompt GIÀU — byte-cap MEMORY.md = 1 lát, prompt nạp phần còn lại; retire `≤8K-brief`) + engine **§G.5** + ACTIVE-MARKS H-15 **v3-delta** `RC-pqhuy1987-22-06-2026-16-35-37` (anh-directed, report-before-stamp). **Part 2 PE fix (commit `fc1f19d`, cicd Run #333 PASS ~4m59s):** validator `NotEmpty(ApprovalWorkflowId)` + submit-guard (SAU Section-3, TRƯỚC mutate phase) → phiếu null-workflow KHÔNG gửi-duyệt được (trước: kẹt nhánh V1-legacy = banner "quy trình cũ", không Bước/Cấp, "Lịch sử duyệt 0"). **Diagnose:** banner ⟺ `approvalFlow` rỗng ⟺ `ApprovalWorkflowId` null; A/040 **tự-khỏi-khi-reload ⟹ cache** (data-hỏng reload không khỏi — em KHÔNG đụng prod). **test-before RED→GREEN**, full-suite bắt **9 đỏ** → triage: 2 genuine-spec-conflict (V1-submit deprecated, data wipe S59) rewrite + 6 collateral giữ (dời guard sau Section-3) + 1 validator fix. **Test 354→356** (+2 validator). **#69-REFINE (cicd):** bundle KHÔNG rotate vì 0 fe-src change (Vite deterministic) — ship-signal THẬT = Last-Modified in-window KHÔNG hash-delta; bundle GIỮ admin `CsJetgZH`/user `BVS0ApIm` Run #333. State THẬT: **Mig 57 · 88 bảng · 356 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`**. ⚠️ restart CLI activate budget v3 runtime. → log `2026-06-22-S83-h15v3-pe-require-workflow.md`.) · **Prev S82** — **adopt Harness-15-v2 (Tầng-1 hot-feed-lớn + L2/L3 bỏ-trần + %-print 2-đầu-phiên + ranh-giới vai-trò), 0 production code** — `/check-email AI_INFRA` (1 thư mới H15-v2-notify verify ✓✓ whole-file+body) + `/adap-apply all` (fan-out 29 broadcast vs 22 report → CHỈ H15-v2 MỚI; 7 còn lại verify = đã-phủ S72/S75/S79). em-main IMPLEMENT single-writer D9 (6 edit: `token_governor` L1 12K→per-role **lead 60K/sub 20K/wf 16K** · L2/L3 6K/4K→**NO-CAP** · engine §G.4 · session-start §2.1.6 + session-end §L.b(c) %-print · mark H-15 What-cell refine) + **REVIEW Workflow `wf_04667b25-5fa` 3-lane 3/3 PASS** (bắt 3 MINOR → fixed: volume "~42K" stale · mark pending-confirm flag · _index STAGE-2). **Ranh-giới vai-trò:** con-số = quyền CHỦ-DỰ-ÁN/anh, AI thực-thi + báo-% — sửa framing S81 "lead-authority" gộp nhầm AI-lead↔owner. mark H-15 **v2-delta anh-confirm** `RC-pqhuy1987-21-06-2026-01-58-01` (report-before-stamp). commit `aa3f0fe` push (docs-only CI-skip) + email AI_INFRA `a749bb6bd1be`. **State THẬT GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** ⚠️ restart CLI (session-start §2.1.6 + session-end §L.b(c) %-print runtime). → log `2026-06-21-S82-harness-15-v2-adopt.md`.) · **Prev S81** — **adopt Harness-15 memory-budget per-agent (token-governor + value-gate + work-state block)** — em main single-writer + 1 REVIEW Workflow (`wf_b7f3c8ac-b53` 3-lane: Part-A PASS · Part-B PASS · Honesty HONEST), **0 production code**. `/check-email AI_INFRA` STAGE 1 = **0 new directed** (outbox/se 4 file processed S79); fan-out diff → CHỈ **H15** unapplied (H14/v2.0/checklist-9-10/11 đã phủ S72/S75/S79). **8/8 🔴 floor:** A1 đo-SÀN persona-direct `Get-ChildItem` 4.3-13.3KB + harness-injected SE-ước-riêng 21K→**30K cap-riêng-SE** · A2 `token_governor` L1 12K/L2 6K/L3 4K (lead hard-cap) · A3 tách-nhà · B(a) nạp-đầy-no-token-saving · B(b) **value-gate** `value_protect` 10-pattern + gate-script FLAG **runtime-fired** (test-specialist gotcha#/guard) ⟂ keep-floor recency = mark `RC-…11` áp tầng-bộ-nhớ · B(c) **work-state block** `session-start §2.1.5` · B(d) 3-tệp-chốt verified (`hmw.js:124` MEMORY-PACK) · B(e) **2-governor** byte⟂token. **5/6 sàn = convention, chỉ (e)+đo-SÀN = mechanized (honest no-overclaim).** Review bắt **2 CONCERN** (anchoring + tool-attribution) → **fixed** (review→fix loop) + refresh stale `measured` block S71→S81. Artifacts: `memory-budget.json` + engine `§G` + `session-start §2.1.5` + `rules §6.6` + gate-FLAG + adap-report `2026-06-20-Governance-harness-15-memory-budget.md`. A7 217/217 · detector 26-flag baseline (0 new). ⚠️ **restart CLI** (session-start §2.1.5). **✅ mark H-15 stamped Active-High** (`RC-…23-07-37`, anh-confirm S81). **State GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** → log `2026-06-20-S81-harness-15-adopt.md`. · **Prev S80** — **curate L1 over-cap reviewer/inv-codebase/cicd → L2 archive** — em-main single-writer, archive-gate keep-floor-hit→manual condense-with-archive: 31 entries byte-exact (`sed`) +N−0 → `archive/2026-06.md` + 31 `_INDEX` substring pointer → **A7 GATE PASS 217/217**; stale foundation counts flushed (130/263→354 · 55→71 · Mig 40/55→57 · 84→88 · bundle→#330). **0 production code, state GIỮ NGUYÊN: Mig 57 · 88 bảng · 354 test · gotcha 71 · bundle `CsJetgZH`/`BVS0ApIm`.** WATCH (A6 strike-1): frontend-designer 26KB + test-specialist 28KB. Lesson: `_INDEX` substring **quote-free** (A7 quote-parser bắt escaped-quote PURO pointer self-grep miss). 9 agent-memory file, docs-only commit (CI skip). → log `2026-06-20-S80-curate-l1-overcap.md`. · **Prev S79** — **adopt User-Mark (H-12/13) canonical §P + Harness-14 (Eval/Budget/Outcome) + chữ-ký RC** — em main + 4 Workflow (invest `wf_82337f7f-95c` → review `wf_a7cbe93e-912` → align-re-review `wf_9d3beebb-a95` → H14-review `wf_4d4eba6f-8a0`), **0 production code**. Anh gõ `/user-mark-active-high` "áp đầy-đủ chính-xác nhất theo AI_INFRA" → áp **canonical §P đầy-đủ** (P1-P10): 4 lệnh `/user-mark-*` + ledger `.claude/governance/ACTIVE-MARKS.md` (Active-High/Active/Medium/Disable) + `harness-11-engine.md §E`+**§F** + `rules.md §6.6` objective-criteria. **3 mark Active-High stamped** anh-confirm (`RC-pqhuy1987-20-06-2026-10-29-09/10/11`). completeness-gate H-6→H-13 **ĐẠT** (H-8 11/11 inherit no-`[1m]`). §F floor 6/6 + maturity HONEST. 3 adap-report + email ai_infra (`7b8615b3`). Bài học: broadcast cô-đọng→canonical-command/§P là spec THẬT (bản đầu MUST/TRACK→align lại) · report-before-stamp dogfood · investigator residual-diary OK. State GIỮ NGUYÊN Mig 57·88 bảng·354 test·gotcha 71·bundle `CsJetgZH`/`BVS0ApIm`. ⚠️ restart CLI. → log `2026-06-20-S79-user-mark-harness-14-adopt.md`). · **Prev S78** — **PE: đính kèm file khi DUYỆT (UAT Tra Sol / 5 tester)** — người duyệt tải file của mình lên ngay lúc Duyệt thay vì Trả lại phiếu (tình huống thay đổi nhỏ). Reuse hệ attachment + enum `ApprovalAttachment=5` **MIGRATION-FREE** (int-stored, 0 schema change); endpoint `POST {id}/attachments` + authz có sẵn (handler không guard drafter-only → approver upload được). FE 2 app SHA-identical: `PeWorkflowPanel` picker multi-file + upload-TRƯỚC-chuyển-phase (file lỗi=không duyệt) + mục "📎 File đính kèm khi duyệt" (download/preview) + 2 filter fix loại purpose=5 khỏi "Bảng so sánh" (gotcha **#71** proxy-predicate pollution). commit `7886fd0` → **Run #330 PASS** ~4m56s (test gate **354**, bundle admin **`CsJetgZH`**/user **`BVS0ApIm`**, NO migration, smoke 4×200 + attachments 401-wired). **3 lỗi em tự bắt review-trước-deploy** (authz-verify handler · filter-pollution #71 · Dialog mirror-truncate fe-admin). em-main-led + self-gate (grep no-leak thay reviewer over-cap) + cicd-monitor verify. → log `2026-06-19-S78-pe-attach-file-on-approve.md`. · **Prev S77** — **buổi sản phẩm RẤT LỚN: 10 deploy prod-verified #320→#329 (anh Kiệt FDC + Tra Sol + Bích Phượng UAT realtime, HMW-mode ON)** — bundle cuối admin **`BqKD3Y23`** / user **`Cn-i349D`** (Run #329). **Mig 56→57** `AddPeSuggestedPriceNotes` · test 344→**354** (+10) · gotcha **70** (tái dùng #70). 10 việc PE: (1) cờ GẤP **pill** 🔴PRO/🟢CCM đồng bộ MỌI danh sách + inbox (#320, NEW `PeUrgentChips` ×2 app); (2) **focus mode** bấm phiếu→overlay (#321) → **revert** list về layout gốc bám-trái lấp-đầy (#322); (3) **Mig 57** ô ghi chú giá đề xuất PRO/CCM (2 cột nvarchar(1000)) + **số phân cách VND** (`VndInlineEdit`/`BudgetCell`) + sửa chính tả "Bảng so sánh giá" + **guard #70** stale-echo (#323); (4) số âm → **đỏ + ngoặc** `(…)` hàng 7/8/9 (#324); (5) mục con **thụt dòng + gạch đầu dòng** phân biệt có-số/không-số (#325); (6) cờ gấp authz **BẤT ĐỐI XỨNG** GẮN=NV chức năng / GỠ=chỉ Trưởng phòng (DeptManager) (#326, asymmetric handler + button-by-state); (7) **tách chọn-phiếu (inline 3-panel) khỏi mở-rộng (overlay)** + nút "Xem mở rộng" mỗi dòng (`?expand=1`) (#327); (8) **chuông báo người duyệt** khi phiếu vào cấp họ — submit + mỗi approve-advance (#328, `LogTransitionAsync` notify current-level approvers); (9) banner phiếu **Trả lại** hướng dẫn gửi lại (#329). **3 lỗi em tự bắt khi review TRƯỚC deploy** (guard #70 stale-echo cho ô ghi chú · luật cờ-gấp bất-đối-xứng Tra Sol clarify giữa-chừng · double-mount PeDetailTabs Task H — intent-comment có nhưng code sót). Cách chạy: em-main + frontend-designer ×3 (focus/revert/decouple, FD2 stub-verify do backend-down #3) + implementer-frontend (pill/notes/sep/spelling) + implementer-backend ×2 (Mig 57 · approver-notify) + test-specialist ×3 (notes +7 · urgent symmetric→asymmetric REDO do clarify-after-dispatch) + cicd-monitor ×10 (10/10 PASS). **frontend-designer process-death giữa Task H → recover-disk** (edit hoàn-chỉnh trên disk, em-main build-verify + mirror). **🔴 NEXT (em): curate L1 over-cap GẤP** — reviewer **45KB** + cicd-monitor 37.6KB + inv-codebase 35.6KB (keep-floor-hit → manual SPLIT/condense; archive-gate A7 GATE PASS 186/186 integrity OK) + FD 26KB/test-spec 27.7KB WATCH strike-1. → log `2026-06-19-S77-pe-ux-batch-10-deploy.md`. · **Prev S76** — **PE ngân sách MA TRẬN 3 cột (Dự án|PRO|CCM) + bảng lưới `
` viền-ô + badge quyền-NS theo role** — anh Kiệt FDC + chị Trà Sol, go-live; anh giao `/ultra-on` "step-by-step + workflow-review-per-step, hoàn chỉnh rồi deploy". **3 commit prod-verified:** `e33481e` (feature Run #318 — Mig 56 + ma-trận-3-cột + badge designer/flow, `BhFDF9IJ`/`BAkuRl3C`) → `21d1f4e` (bảng lưới `
` theo phản hồi anh, Run #319 **`jOqxW4-p`**/**`DbsznVvR`**, smoke 3×200). **Part 1:** PRO sửa cột PRO (canEditPro), CCM sửa cột CCM (canEditCcm), Dự án FE hiển-thị-only; Mig 56 +ProInitial/ProAdjust additive + data-migrate ProEstimate→ProInitial (4 rows prod). **Part 2+3:** badge "✎ NS PRO/CCM" cạnh approver (suy từ role, display-only no-authz) ở Workflow Designer + flow Duyệt NCC. Test 339→**344** (+5). **2 workflow review** (Part 1 PASS + Part 2/3 PASS) — reviewer bắt **race mất-dữ-liệu** Part 1 (impl self-review sót) → vá `useIsFetching` 2 app, **gotcha #70 NEW**. Lessons: flex+gap KHÔNG ra "bảng" → phải `
` viền-ô · workflow-review-flaky (2-3 lane empty #53) → em-main self-gate lane rỗng. **NEXT:** 🔴 curate L1 over-cap (reviewer **45KB** + inv-codebase 35KB keep-floor-hit manual-condense; cicd 29KB + test-spec 28KB strike-1). → log `2026-06-19-S76-pe-budget-matrix-table-grid.md`. · **Prev S75 (2026-06-18)** — **Harness-11 adopt: engine bộ-nhớ-và-governance TỰ-BẢO-TRÌ + 2 double-check** — anh giao `/check-email AI_INFRA` + `/adap-apply` (mỗi stage workflow-review) + double-check ×2 + finalize report + push + session-end. em main + **5 Workflow** (audit `wf_7fdc3bd5-930` → implement `wf_c5e5844e-7c1` → review `wf_d7ca1ff8-942` → double-check `wf_a0b68d2f-30e` → checklist-verify `wf_39cd4cbe-f07`). **0 production code.** Built `scripts/governance-detectors.ps1` (C1 broken-pointer + C2/B3 staleness + C3 vocab-fork + C4 self-exclusion + C5 resolve, NO-API DÒ+FLAG, runtime **26 flag** bắt drift thật, C4 0-self-match) + `scripts/memory-archive-gate.ps1` (PHẦN A hysteresis 0.85/keep-floor 5/2-strike/A7 NO-API 186/186) + `docs/governance/harness-11-engine.md` canonical (3-tier D5/D6/D7 EXPLICIT + one-direction-lock D8) + **B1 ×11 count→pointer `docs/STATUS.md`** (drift mig53→55/test306→339/gotcha68→69/table93→88 RESOLVED) + cadence-wire session-start §2.1.3 (D1) + session-end §L.b(c) (D2) + agents/README Upgrade S75. **completeness-gate FORMAL ĐẠT** (B 4/4 + C 5/5 + D 11/11 đủ-trọn, A 🟡 tailored — A6 runtime cần 2×-Apply legit-by-design). **gotcha #30 reinforced** (box-glyph ├└─ KHÔNG vào .ps1 — PS5.1 -File ANSI mojibake, KỂ CẢ qua Edit render-normalize; detector pure-ASCII verified). 3 commit `e70c046`+`ae957c4`+`aa09e99` pushed + adap-report + email ai_infra (`2316773229f2`). **State THẬT GIỮ NGUYÊN: Mig 55 · 88 bảng · 339 test · gotcha 69 · menu 54 · bundle `BYF5vIMJ`/`CB-tiRxd`.** ⚠️ restart CLI (cadence §2.1.3/§L.b + ef-core skill). 🔴 curate-debt: reviewer 38.8KB + inv-codebase 31.5KB + cicd 26.8KB over-cap (archive-gate confirm; reviewer+inv keep-floor hit → manual split). → log `2026-06-18-S75-harness-11-adopt.md`. **Prev S74** — **PE ô "Ghi chú từ CCM" ngân sách gói thầu (Mig 55)** — anh forward 2 luồng Zalo (Trà Sol + Kiệt FDC) "CCM cũng giống PRO cho nhập + ghi chú, hiện 0 hết" → em-main BE+Mig55 ∥ implementer-frontend FE 2 app SHA-mirror ∥ test-specialist (chết rate-limit → recover-disk). 2 fork anh chốt qua AskUserQuestion: **thêm CcmNote (Mig 55)** + **GIỮ phân vai CCM** (CostControl/Admin). Entity `PeWorkItemBudget +CcmNote` mirror ProNote · `UpdatePeBudgetCcmCommand +CcmNote` absolute-set role-gate fail-closed · DTO+controller+mapping · FE dòng "Ghi chú từ CCM" gate `canEditCcm` (sau V0/hiệu chỉnh, absolute-set đủ 3 field). Mig 55 additive-nullable sạch (no #63). Test 334→**339** (+5 CcmNote). **Chẩn đoán "0 hết không nhập":** tài khoản thiếu role CostControl (KHÔNG bug) → UAT bằng CCM/Admin. commit `8655ebf` push main (cicd **Run #315 PASS** ~4m54s — Mig 55 applied prod, bundle admin `BYF5vIMJ`/user `CB-tiRxd`, smoke 4×200). Lessons: controller call-site thiếu arg sau +param record (grep+vá, #65 bắt) · agent-kill-529 recover-disk no-re-spawn · PS here-string commit-msg trong if-block mis-parse → `git commit -F`. → session log `2026-06-18-S74-pe-ccm-note.md`. **Prev S73** — **Mig 54 PE giá đề xuất PRO/CCM + CEO chọn giá chốt + CCM duyệt-done ô-tích (anh Kiệt FDC — go-live so-sánh-giá thứ Hai 22/06)** — em main + 6 sub + 2 review-workflow. **2 commit prod-verified:** `1d86abc` (feature, cicd Run #313 PASS — Mig 54 + bundle admin `OlNyG9OD`/user `DSzSLVtL`) + `6aa4dcb` (FE empty-candidates guard fix). **BE:** Mig 54 `AddPeSuggestedAndApprovedPrice` 5 cột additive-nullable (ProSuggestedMin/Max·CcmSuggested·ApprovedPriceAmount·Source) + 2 setter role-gate PRO/CCM (Forbidden fail-closed mirror budget) + ApproveV2 **③ AUTO→OPT-IN** (`finalizeByCcmDelegation` ô-tích, gỡ auto-threshold S69) + **① bind giá chốt** mọi nhánh DaDuyet (human bắt-buộc-chọn, isSystem-miễn) + DTO +7 field/capability. **FE 2 app SHA-mirror:** PeWorkflowPanel (bộ chọn giá + ô tích CCM + fix empty-candidates) + PeDetailTabs `SuggestedPriceRows` + types +7. **Test 306→334** (+28). **2 workflow review (bài học):** R1 schema-force CHỈ **1/4** lane returned (flaky no-StructuredOutput) → R2 **free-text 2/3 PASS** — rủi ro #1 FE empty-candidates = **UNREACHABLE** (submit-guard `:194` chặn gửi-duyệt khi winnerQuoteTotal≤0). → review fan-out dùng **free-text / hmw RUN-TRACE**, KHÔNG ép-schema inline. **Governance honest:** em lệch mandate auto-Workflow (mode-ON) + chỉ khai khi anh hỏi → **cam kết báo-TRƯỚC-khi-lệch**. Run-trace `runs/2026-06-18-mig54-pe-review/` (custom-inline, bù post-hoc). → session log `2026-06-18-S73-pe-gia-de-xuat-ccm-done.md` pending. · **Prev S72** — **Harness-10 flat-refine + checklist-v2 adopt (re-audit 3-workflow) + sleep NO-OP** — em main + 9 sub qua 3 Workflow (audit `wf_13868efb-ea7` → implement `wf_ac43b5ff-7d1` → review `wf_d482e10d-5dd`, mandate Harness-9 B1+B2). Anh chỉ "sisters làm tốt mỗi SE thiếu" → re-audit đo vs canonical: **SE BEHIND Harness-10 flat** (run-trace còn SUBFOLDER, canonical=FLAT) → migrate `hmw.js` (`:103` sub-md/→flat + `:52` schema + **H4.5→H8 doc-drift**) + `workflows/README` full-rewrite + `runs/README` + session-start/end + `agents/README` Upgrade S72 + `_ledger`; **5 run cũ S71 GIỮ subfolder** (C8 dual-accept). +2 broadcast 06-18 adopt (checklist-v2 + h10-flat-detector-refine). +`/sleep-recovery-memory-l2` port (A8, §J2-tailored SE-only, floor intact, live skill). **detector refine-b TAILORED-OUT** (SE Workflow-tool no-CLI-bypass; containment git-diff+tracked+orphan-scan G-015). **REVIEW (B2 dogfood) bắt 2 lỗi IMPLEMENT-self-assess sót** (hmw.js:52 schema-stale + sleep-cmd auto-check un-wired overclaim) → fixed (auto-check **WIRED thật**: budget.json `+last_sleep_at` + session-start:78 + session-end:48, grep-verified). em-main containment-check tự bắt 1 reviewer residual-write (raw-Workflow KHÔNG hmw.js writeGuard → reverse-finding #4) → revert. **B3 self-correct:** S71 report path tắt `runs/`+"14" → thật `.claude/workflows/runs`=22. **Sleep `all`=NO-OP** (5/9 empty-archive + 4/9 đã-gisted → 0 compressed; `last_sleep_at`=2026-06-18). **0 production code, state THẬT GIỮ NGUYÊN.** adap-report `2026-06-18-Governance-harness-10-flat-refine-checklist-v2` + email ai_infra (`5f511fe5c0f2`). ⚠️ **restart CLI** activate FLAT-runtime hmw.js + wired sleep-check + sleep-recovery skill. 🔴 **NEXT (em):** curate investigator-codebase L1 **28973 OVER** (audit-trail) + watch frontend-designer/test-specialist near-cap. → session log `2026-06-18-S72-harness-10-flat-refine.md`. **Prev S71 — Harness-10 adopt: tracked run-trace folder convention + checklist 9-10 self-verify** — em main + 3 Workflow (invest `wf_9c2cd2cd-2e7` → implement `wf_e4e46725-231` → review `wf_636bc95b-939`) theo mandate Harness-9 PART 2. **0 production code** (governance/workflow only). Migrate `.claude/workflows/wave-*/` gitignored → `runs//` **git-TRACKED** (run.md + sub-md/ + harvest/) + `_ledger.md` 2-nhịp + 3-layer anti-miss (L1 em-main@P1 ledger-check / L2 session-start orphan-scan / L3 session-end close-gate **idempotent-VERIFY-not-re-APPEND**) + **containment model shift** (Harness-2 B6 "mọi tracked-change=vi-phạm" → Harness-10 "tracked-change NGOÀI run-folder + code-disjoint=vi-phạm"; run-folder TRACKED → HIỆN git-diff = audit trực-tiếp). hmw.js wave→run-trace (accept `args.run`, alias `wave`; path `sub-md/`; `node --check` PARSE-OK). **Review độc-lập (R2+R3) bắt C5 L1 over-claim** (doc nói hmw.js prompt-builder emit L1 reminder nhưng grep engine=0 → engine no-fs → fixed path-a: L1 = em-main @P1 convention) — dogfood mandate B2 đúng (1-workflow-tự-chấm sẽ bỏ sót). **checklist 9-10:** Part A (Harness-9 memory) + Part B (adap 2-workflow) ĐÃ done S70; Part C (Harness-10) MỚI 8/8. dogfood: 3 run-trace folder TRACKED đầu + 3 entry ledger. adap-report `2026-06-18-Governance-checklist-harness-9-10` + email ai_infra. **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** + `CLAUDE.md` test-flush 263→306 (pre-existing uncommitted, resolve H1 stale-flag). ⚠️ restart CLI activate hmw.js RUN-TRACE runtime + (carry S66/S70) §2.1.2 budget-audit/reviewer-Cat-6/H8-inherit. ✅ **curate-debt CLOSED S71** (FINALIZE double-check `wf_73de399d-753` + curate `wf_f32987b8-03f`): reviewer 36.7→24.8KB + investigator 29.8→23.2KB (both <25600 cap, archive +N -0 0-byte-loss) + reviewer-gist gen:2 + 3 user-memory G2/G3 + budget.json re-measure. Race root-cause fixed cấu-trúc (hmw.js RUN-TRACE writeGuard). → session log `2026-06-18-S71-harness-10-run-trace.md` (pending). **Prev S70** — **Harness-9 adopt: L2 archive dark-matter recovery + adap 2-workflow mandate** — em main + 3 Workflow (investigate `wf_be952f3c-97f` → implement `wf_a58e0d15-beb` → audit `wf_9520d8cd-4fe`) + 2 monitor bootstrap. **0 production code** (governance/memory only, commit `f36aab8` pushed). 4 over-cap sub-agent (cicd-monitor/investigator-codebase/reviewer/implementer-backend) curate L1→L2 + `archive/_INDEX.md` (mục-lục con-trỏ **substring sha-keyed**, Ctrl-F fallback) + `.gist.md` (nén 4-field distill-gen:1, verbatim FROZEN) → **cả 4 < 25KB auto-inject cap** (P1 curate-debt CLOSED; ~240KB archive hết RAG-dark). PART 2/3 process-mandate codify (adap-apply + agents/README Upgrade S70 + session-start §2.1.2 budget-audit). **0-byte-loss git+sha verified** (Stage C audit + em-main self-gate khi 2 reviewer no-StructuredOutput). +`memory-budget.json` (seed-by-measure) + `scripts/measure-agent-memory.ps1` + `.ragignore` + doc-drift 4-cite flush. adap-report + email-back ai_infra (body-hash `7c07b716e775`). **State THẬT GIỮ NGUYÊN: Mig 53 · 88 bảng · 306 test · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf`.** ⚠️ restart CLI để activate session-start §2.1.2 + pending H8 inherit + reviewer Cat-6. → session log `2026-06-17-S70-harness-9-l2-recovery.md`. **Prev S69** — **Văn phòng số (E-Office) port + golive + PE cờ gấp/ngưỡng CCM — 4 deploy prod-verified Run #305→#308, HMW-mode ON, 2 workflow fan-out + ~14 spawn**: foundation PURO (shared PageHeader/KpiCard/WidgetCard + Dashboard 2-cột + sync fe-admin index.css đóng drift S66-S68) #305 → **re-skin TRỌN 10 page** PURO layout + CSS Hồ sơ NS, phẫu-thuật-giữ-100%-logic (reviewer verify api/queryKey byte-identical) #306 → **Office golive public** `SeedAllRolesOfficeModulePermissionsAsync` read+create 16-key allow-list mọi role (mirror S65 pattern, chạy SAU revoke; excluded Off_PhongHop_Manage/Off_AttendanceReport/Off_ChamCong giữ ẩn; cicd DB-verify 16/16×13 role) #307 → **PE cờ gấp PRO/CCM + CCM duyệt-final theo ngưỡng giá trị** Mig 53 (anh Kiệt FDC sau họp sếp) #308. **State THẬT: Mig 53 · 88 bảng · 306 test (45D+261I) · 68 gotcha · menu 54 · bundle admin `BgNCjwsG`/user `CBvh0vtf` Run #308.** 2 gotcha NEW (**#67** Tailwind accent palette thiếu-stop vỡ-màu-im-lặng · **#68** stale-diagnostic-background-agent). 2 truncation #53 (impl-backend positional-record + impl-frontend) → em main recover-disk + self-gate (cả 2 build PASS sau-cùng). C (sau duyệt → chuyển phiếu đến dự án) chờ anh Kiệt spec form. → session log `2026-06-17-S69-vanphong-golive-pe-urgent-threshold.md`. **Prev S68** — **Hồ sơ NS header chi tiết NV: làm nổi bật + fix tên render đen→trắng** — em main solo, 3 commit (2 FE `6983609`+`37752eb` · 1 docs `11bc96d`), 2 deploy prod-verified Run #303-304 (anh UAT realtime): tên `text-xl extrabold`+drop-shadow · dòng meta `text-[13px] font-medium` trắng-đậm · badge pill **màu theo trạng thái** (#303); anh báo "tên đen nền xanh ko nổi bật" → diagnose **rule `h1-h4{color:#0b1220}` viết NGOÀI `@layer` thắng `text-white`** (Tailwind v4 unlayered > all layers, **gotcha #66 NEW**) → ép `text-white!` + thu nhỏ `text-lg` (#304, grep dist confirm `!important`). Bootstrap: 2 monitor RE-REPORT CLEAN + 2 doc-drift fix (dep-audit 64→65 · root CLAUDE 263→286, H1 flag). **State THẬT: Mig 52 · 88 bảng · 286 test · 66 gotcha · menu 53 · bundle admin `CNUv1jxY`/user `CpOskeS1` Run #304.** ⚠️ curate-debt P1: cicd-monitor **44.1KB** (worst). **Prev S67:** **buổi sản phẩm LỚN, 6 deploy prod-verified Run #297→#302** (anh + anh Kiệt FDC UAT realtime, HMW-mode ON): fe-user Hồ sơ NS đồng nhất font + chữ đen→**xanh đậm `brand-800`** (#297 `ab4e681`) · **fe-admin mirror master-detail** + accent tokens index.css [đóng pending lớn nhất HRM go-live, page SHA256 ×2] (#298 `292d64d`) · **+23 test-after HRM** [Dept cycle-guard · PE HoSoLink absolute-set · HRM-perm seed] → 263→**286** (#299 `bcd619d`) · **list flex-row gọn** [bảng 3-cột→flex-row, `overflow-x-hidden` → hết tràn ngang rail] + đồng nhất cỡ chữ [18/14/13/11px] ×2 app (#300 `91aaf05`) · **PE Link hồ sơ auto-detect** `http(s)`→hyperlink/`O:\`→Copy (#301 `6df1b2d`) → **render link `file://` bấm-thử** + Copy (#302 `536dd6b`). **Workflow research 3 investigator-api** (auto-mở `O:\` từ web): default browser CHẶN https→file://; **chỉ Edge GPO `IntranetFileLinksEnabled`** (Edge-only, Intranet Zone, 1 GPO domain zero-per-machine) = one-click thật — Chrome không có; .url-download zero-install nhưng 2-click. **State THẬT: Mig 52 · 88 bảng · 286 test (45D+241I) · 65 gotcha · menu 53 · bundle admin `CcrZqfht`/user `DniDFUB_`** (#302). test-specialist truncated return #53 → em main recover-disk (3 file test đủ + 286 verify); 0 production bug. ⚠️ curate-debt: cicd-monitor 39.8KB + inv-codebase 39.4KB over-cap. **Prev S66** — **session-end closeout em-main-solo, 0 product-sub:** adopt **Harness-8 all-inherit** (7 sub demoted `claude-opus-4-8`→`inherit` → cả 11 = inherit, gỡ two-tier Harness-4) + **cicd-monitor L1 curate 86.8→28.9KB** (byte-exact sed → `archive/2026-06.md`, incl #291 forensic) + **ef-core skill doc-flush Mig 50→52** (H1 drift, +Mig 51/52 rows) + check-email AI_INFRA (**0 thư mới se-directed**). ~17 file docs/gov/config, **0 production code** → state THẬT GIỮ NGUYÊN: **Mig 52 · 88 bảng · 263 test · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf`**. ⚠️ **Restart CLI** để H8 runtime (frontmatter no hot-reload) + reviewer Category 6 (S64 pending). adap-report `2026-06-16-Governance-harness-8-all-inherit-workflow-fastest` + email-back ai_infra (hash `fa7f690d` round-trip MATCH). Prev S65 — **HRM go-live: public Hồ sơ Nhân sự + trang master-detail giống NamGroup + Department hierarchy + PE Link hồ sơ**, ~6 deploy prod-verified Run #289→#295, anh + anh Kiệt FDC UAT realtime): (1) **public Hồ sơ Nhân sự mọi role** — `SeedAllRolesHrmProfileReadPermissionsAsync` grant CanRead `Hrm`+`Hrm_HoSo` 13 role chạy SAU revoke S58 (upgrade-only; EmployeesController policy-based `Hrm_HoSo.Read` mở luôn API không hardcode Roles), giữ ẩn Dashboard NS, Run #289; (2) **redesign màu foundation fe-user** — accent palette teal/violet/amberx/greenx + `.app-gradient-brand`/`.card-accent`/`.icon-chip` + heading 700, brand #1F7DC1 + Be Vietnam Pro giữ, Run #290; (3) **Department hierarchy** Mig 51 `AddDepartmentParentId` (ParentId loose-Guid no-FK + `GET /departments/tree` ráp cây in-memory + rollup count theo `User.DepartmentId` + cycle-guard HashSet) + picker "Phòng cha" fe-admin (self-service org chart) + Update cycle-guard, Run #292; (4) **Hồ sơ Nhân sự master-detail giống NamGroup** — `EmployeesListPage` rewrite: 3-panel→**2-cột** (cây tổ chức gốc "SOLUTION COMPANY" + list chồng TRÁI · chi tiết 5 tab PHẢI) + tô màu accent, giữ 100% 5 satellite CRUD (16 endpoint), Run #293/#294/#295; (5) **PE mục "e. Link hồ sơ"** Mig 52 `AddHoSoLinkToPurchaseEvaluation` (`HoSoLink string?` hyperlink NAS + `` target_blank rel-noopener + null-safe) + rename "Dự trù PRO"→"Ngân sách PRO" (row+badge) ×2 app SHA256-mirror, Run #293. **State THẬT: Mig 52 · 88 bảng · 263 test (45D+218I) · 65 gotcha · menu 53 · bundle admin `BDwV5d0X`/user `DbVv6rsf`** (Run #295 `456c7a7` Employee-refine — user rotate `CZfo_PFZ→DbVv6rsf`, cicd PASS). **🔥 Workflow fan-out chạy THẬT lần đầu** (`pe-hoso-link-rename-pro` BE∥FE→review) — parallel disjoint-file OK, NHƯNG FE+reviewer return-RỖNG #53 → em main recover-disk + self-gate (bắt badge "DỰ TRÙ PRO" sót rename); **verdict: fan-out cho parallelism nhưng reviewer-stage không tin được trong harness này → verify-heavy task vẫn tự gác = tương đương spawn lẻ** (`feedback_workflow_fanout_reliability`). gotcha **#65** NEW (build csproj con ≠ `dotnet build slnx` gồm tests → miss test-compile khi đổi chữ ký record command → CI CS7036 Run #291 FAIL-gated). **Prev S64** adopt **Harness-7 writing-quality floor** — em main solo, commit `6afde19` docs/gov-only, 0 sub spawn: `rules.md §1.1` outward-VN-full-grammar + reviewer Category 6 + adap-report + email ai_infra; broadcast body-hash `a4580ea9` verified-MATCH **KHÔNG mis-stamp** [false-mismatch = gotcha #61 PS5.1 UTF-8 decode của em]. Prev S63 docs-closeout bù S60/S61/S62 — **State THẬT: Mig 50 · 88 bảng · 263 test (45D+218I) · 64 gotcha · menu 53 · bundle admin `0xKYGhhf`/user `C81ZdG9G` Run #286**; S60-62 = PE ràng buộc gửi-duyệt + bypass drafter (S60) · gỡ "Từ chối" (S60) · Mig 50 ngân sách per-gói-thầu Excel anh Kiệt + XÓA module Budget cũ (S61) · vượt-NS cảnh-báo-mềm cho lưu (S62); + reconcile stray reviewer cwd-misland; session log `2026-06-12-S60-S62-pe-budget-workitem-softwarning.md`). Prev Session 59 ( **10 đợt ship prod-verified: 8 Run PASS + 2 cancelled-supersede-benign #273→#282** (run_number API — dải đếm khác #38x S58, cùng pipeline; 2 cancel = push-đè khi UAT góp ý realtime, ancestor-verified): (1) **wipe transactional testing data** theo anh Kiệt FDC — 10 PE + 7 HĐ [DEMO] + 64 notif + 1 AwV2 cũ inactive = 0, reset PeSeq/CtSeq → phiếu thật đầu tiên team tạo chiều nay = **PE/2026/A/001** ✓, app-recycle KHÔNG resurrect (DemoSeed gate held), uploads orphan dọn (`56882ac` #273); (2+3) **PE tree Panel 1 chốt 4 tầng "📅 Năm > 📁 Dự án > 🧱 Hạng mục > Phiếu"** (anh chốt follow-up sau bản gộp "Dự án (Năm)"; `yearGroups` useMemo, expand-key v3, FE-only — list DTO đã có workItemName S57bis) (`0eafcd3` #274); (4) **dọn 15 mã hạng mục demo tự chế** theo chị Trà Sol "xóa cái đám phần thô phần hoàn thiện… MÀ ANH TỰ ĐẺ RA" — WorkItems 86→**71**, GỠ HẲN block seed demo khỏi DbInitializer, đối chiếu 71/71 khớp bảng PMH từng dòng (`bbd1554` #275, bundle frozen BE-only); (5) **rename 71 mã đúng format PMH anh Kiệt chốt** "MÃ CV gồm chữ MEP-SUB-1 rồi tên 1 MEP Sub MEP (Full) — đúng kiểu vậy" → `MAT-n`/`SUB-n`/`MEP-SUB-n`/`MEP-EQU-n` + Name "STT nhóm tên"; **DB-trước-code-sau** (gotcha **#62** NEW — seed per-code idempotent, sai thứ tự = 142 rows) + sqlcmd `-f 65001` (gotcha **#61** NEW — verify data qua API JSON, KHÔNG tin console mojibake) + FE sort numeric ×3 ×2 app (`c869d26` #276); (6) **UAT 6 vòng 11 điểm**: NEW **`ui/SearchableSelect`** combobox gõ-lọc BỎ DẤU (fold NFD — Hạng mục/Dự án/NCC) + auto Địa điểm từ Project.Location + điều khoản TT Textarea đa dòng (`faed59f` #277) · anh chốt: **ẩn cả Trả lại+Từ chối khi người duyệt = người soạn** (drafterUserId match) + **quick-add NCC ngay form** (SuppliersController POST hạ → any-auth, PUT/DELETE giữ khóa — cicd authz probe live 4/4: 401 unauth/201 nv.test/403 delete/cleanup) + upload multiple files ×2 chỗ (`9c330d2` #278) · vòng 3-6 realtime (`f21c55d` #279-cancelled / `69997da` #280 / `80b64dd` #281-cancelled / `792c030` **#282 FINAL**): **bảng NCC table-fixed** width từng cột (file dài hết vỡ layout) + **bỏ ô "Tên" ngân sách nhập tay** (chỉ còn Số tiền, hasManual detect theo amount) + **GỠ field "Điều khoản thanh toán" khỏi TẤT CẢ form phiếu** (cột per-NCC + display phiếu cũ GIỮ) + **bỏ nút "+ Thêm hạng mục"** (1 phiếu = 1 hạng mục header). Bundle FINAL admin **`B1DtNT9C`**/user **`D6uF3Mln`** (Run #282). Test 240 ×2 local + 8× CI gate. **0/14 spawn truncated** (lần đầu sau nhiều session). → session log `2026-06-11-S59-wipe-tree-pmh-uat-batch.md`. Prev S58 (2026-06-11 — **4 việc prod-verified Run #382/#383/#384**: lock-demo-user fix + tạm ẩn HRM/Office/Cá nhân + Danh mục cuối sidebar + fe-user redesign theo UI/UX guide AI_INFRA. **Việc 1 — lock fix** (Run #382, `5998163` ~3m31s): Run #381 cicd phát hiện S57bis lock = NO-OP (14 email named-person là population Dev-only). Recon dump prod: demo thật = 20 UAT-matrix `{dept}.{nv,pp,tp}@`+`bod.{1,2}@` tạo TAY 05-13; root cause sâu = `DemoUserPassword` 11 ký tự < prod `RequiredLength=12` → `CreateAsync` silent-fail MỌI startup từ trước tới giờ (= root cause "helpdesk inert phòng IT 0 user" S56). Fix: union 20 email + password 12 ký tự. Prod sau deploy: **55 user / 21 active / 34 locked** — 20 UAT + 14 named-person locked ✓, **nv.cao/nv.truong CREATED+ACTIVE (helpdesk S56 RESOLVED)** ✓, 5 real staff created ✓, guard admin/catalog.manager/nv.test/chuong.phan-typo active ✓ (anh chốt 3 quyết định AskUserQuestion). Bundle FROZEN. gotcha **#60** NEW (seed silent-fail vs prod password policy — dump population thật trước khi lock/seed-by-email). +Closeout S57bis residual: gotcha #59 commit, 4 spawn-record on-behalf (H2 4-MISS), H1 5-patch doc-drift, test 240 re-verified local. Prev S57bis (2026-06-11 sáng) — **PE gắn Hạng mục công việc (Mig 49) + mở quyền Pe all-role + menu "Cá nhân" + khóa demo user** (sếp Zalo deadline 15:00): commit `17b23a4` (Harness-4 two-tier runtime-VERIFIED spawn-test 2 chiều) + `dd117b7` (product) → Run #381 PASS ~4m25s. Mig 49 `AddWorkItemToPurchaseEvaluation`: PE.WorkItemId `Guid?` loose-Guid KHÔNG FK vật lý (convention PE — database-agent design) + IX + validator NotEmpty create + FK-guard handler Conflict + UpdateDraft null-safe. FE ×2 app PeWorkspaceCreateView/PeHeaderForm (SHA256 identical)/PeDetailTabs "Dự án – Hạng mục". Pe_* 11 key CanRead+CanCreate mọi role (130 rows/13 role — Pe_* leaf KHÔNG nằm MenuKeys.All, build qua factory). Menu Personal root@30 + Chấm công re-parent + Master write-lock `Admin,CatalogManager` ×3 controller. Test 228→**240** (+12 PeWorkItemGuardTests). Bundle rotate cả 2: admin `CP4CB1ym` / user `BmZ3VHnm`. 2 builder truncated #53 + reviewer die-0-byte ×2 → em main solo vá cross-stack + self-gate. Excel (3) đối chiếu = NO-CHANGE (S55 data identical). Prev S56 — **Pre-golive verify sweep + golive-harden 4 fix — HMW 2-workflow, prod-verified**: commit `a20cde8` → Run #379 PASS ~4m20s. WF1 `pre-golive-verify` 7-stream song song + adversarial → 6 PASS/1 CONCERN/0 blocker = **GO**; key finds = **ops not code** (prod IT-dept 0 active user → helpdesk inert + S43 LeaveBalance lost-update còn nguyên). WF2 `golive-harden` fix 4: **#3** LeaveBalance lost-update→atomic `ExecuteUpdateAsync`+Serializable tx (NO mig, exactly-once nguyên) · **#5** ItTicket authz Forbidden-trước-NotFound (fail-closed) · **#6** DocxRenderer null-guard (2 warn→0) · **#4** Travel/Vehicle ApproveV2 +4 smoke. Test **216→228**. Bundle FROZEN `4SUwDLD8`/`XdKzt9LL` (BE-only). `sys.tables` re-ground **92→93** (cicd ground-truth, Mig 48 col-only). reviewer stage StructuredOutput-fail→em main đỡ cross-stack review (3 diff clean) + bump Serializable đóng MAJOR. gotcha **#58** NEW (EF read-modify-write lost-update→ExecuteUpdate atomic). **2 ops VPS pending** (gán user phòng IT + `tzutil` UTC+7). FE Phase 2 redesign **deferred** (recon ready). Prev S55 — **Nạp master data thật từ Excel + Project +4 cột (Mig 48), HMW-mode ON**: commit `69cb393` → Run #377 PASS ~4m33s, prod-verified. Anh giao file Excel "HẠNG MỤC CÔNG VIỆC DỰ ÁN" → `/ultra-on "workflow làm xong hết"`. Nạp **62 dự án + 71 hạng mục + 3 NCC** vào Project/WorkItem/Supplier qua `SeedRealMasterDataAsync` (per-code idempotent, **UNGATED** → coexist demo, tự lên prod). **Mig 48 `AddProjectMasterFields`**: Project +4 cột nullable (Year/Investor/Location/Package, NO new table). FE ProjectsPage form +4 input ×2 app SHA256 mirror. Test 216 (compile-fix MasterCatalogFilteredUniqueTests +4 null args, no new test). Bundle admin `DmjI8Cmn`→`B-d6893W`/user `YxL_MljK`→`XdKzt9LL` (cả 2 rotate). Prod verify: Mig 48 applied · Projects spot-6/6 · WorkItems VT/TP/MEP/TB=71 · Suppliers 3 · CAL01.Investor="Công ty TNHH Calofic". **2 agent return truncated** (implementer-backend + reviewer, gotcha #53) → em main disk/runtime-recover (build/test/sqlcmd/git truth); cicd verdict-FIRST → PASS clean no-truncate. Data-quality catch: MEP col gộp 2 nhóm + divider "THIẾT BỊ" → split đúng 71/4-category. Provenance `scripts/master-import-data.generated.md`. Prev S54 — **IT staff tự reassign ticket (cross-stack authz, HMW-mode ON)**: 1 code commit `ca4b602` → Run #376 PASS ~4m18s, prod-verified. Cho tổ IT (dept Code=="IT") + Admin reassign ItTicket trên CẢ 2 app. BE: NEW `GetAssignableItStaffQuery` capability endpoint `{canReassign,staff}` + `AssignItTicketHandler` authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict) + controller `/assign` hạ `[Authorize(Roles=Admin)]`→`[Authorize]` (handler fine-grained). FE: fe-admin+fe-user ItTicketsPage **SHA256-identical** (REVERSE S53 divergence) gate nút by `canReassign`, dropdown từ `/assignable-staff` (không `/users`). Test 203→**216** (+13 authz guard test-before-merge). NO migration (DepartmentId reuse). Bundle admin `DfCfHUE9`→`DmjI8Cmn` / user `_3S0BPJ2`→`YxL_MljK` (cả 2 rotate). 6-agent fan-out (BE∥FE→test→reviewer→cicd) + em main reconcile stray-memory residual (3 agent ghi MEMORY nhầm `src/Backend/.claude` → harvest về canonical). reviewer PASS 0 blocker (role-string "Admin" chain-verified). Task 1 Phase 9 Ops KHÔNG làm (anh dừng). flag: cicd `sys.tables=93` vs STATUS 92 → monthly audit re-ground.) Prev S53 (gotcha #57 EXT Master Mig 47 + P11-D reassign-UI fe-admin + P11-E menu + database-agent verified-runtime: `44b9e54` Run #260 + `dbf6648` Run #261, test→203, bundle→`DfCfHUE9`). Prev S52 (Phase 11 P11-D+E+F deployed + database-agent adopt, HMW-mode ON): 3 commit — `e9ee97f` (database-agent DB1–DB11 read-advisory, roster 10→11, executed-file CHỜ restart) + `6a66429` Wave 1 (P11-E AttendanceReport+Excel+OtPolicy multiplier + P11-F MaTicket codegen, migration-free) + `dcf76f8` Wave 2 (P11-D ItTicket round-robin assign dept-IT + SLA timer, Mig 46). Test 186→**200**. Bundle admin `DYfjnpY0`/user `_3S0BPJ2` (cả 2 deploy verified curl độc lập — Wave 1 BE 401 wired + Wave 2 /assign 401 + Mig 46 applied health-200). ⚠️ **Session-limit hit giữa Wave 2** → recovery: BE/test verify-on-disk + em main solo FE redo + curl-self-verify thay cicd-spawn (multi-agent resilience, git/disk/prod = source-of-truth). RAG recovered (chunk 2416 rerank live) nhưng stale 05-29. Prev S51: P11-C Vehicle+Driver.) --- diff --git a/docs/changelog/sessions/2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md b/docs/changelog/sessions/2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md new file mode 100644 index 0000000..43460cd --- /dev/null +++ b/docs/changelog/sessions/2026-06-23-S85-pe-uat-cvpro-rootcause-tz.md @@ -0,0 +1,73 @@ +# Session 85 — 2026-06-23 — PE UAT anh Kiệt FDC CỰC LỚN: CV PRO 6-fix + clear-data + 6 vòng UAT + 2 ROOT-CAUSE + 5 SQL-fix + +> **~10 deploy prod-verified #334→#341 (anh Kiệt FDC + Tra Sol + long.chau UAT realtime, HMW-mode ON, ~12 spawn).** Anh `/session-start` → forward Zalo + file Excel `Cần chỉnh sửa CV PRO.xlsx` liên-tục realtime → `/session-end`. +> State THẬT cuối: **Mig 57 · 88 bảng · 374 test · gotcha 73 · menu 54 · bundle admin `aKuNip19`/user `BUsL0HeQ` (Run #341, FE frozen #339+#341 BE-only).** + +## Đợt 1 — Batch CV PRO 6-fix (Run #334 `5a61254`) + +File `Cần chỉnh sửa CV PRO.xlsx` = **8 ảnh chú-thích nhúng** (zip xl/media/, KHÔNG phải bảng công thức) — đọc qua skill xlsx + giải-nén + Read ảnh. 6 fix → AskUserQuestion chốt 3 nhóm mơ-hồ: +- **C1** ẩn "c.Giá chào thầu" + "d.Bảng so sánh giá" khỏi form TẠO (giữ ở Detail). +- **C3** ô8 "Giá trị TH dự kiến còn lại" pre-fill từ dòng7 (Ngân sách còn lại). +- **C4a** **live-recompute** — `VndInlineEdit +onLiveChange`, `PeBudgetSummaryTable draftRow3/draftRow8` → dòng 5/6/7/9 + % nhảy NGAY khi gõ ô3/8 (chưa cần Lưu). +- **C4b** So-sánh=0 → "Bằng ngân sách"/"—" (chỉ khi base>0). +- **C5** hủy/đổi NCC winner — BE `SelectWinnerBody(Guid?)` + Command/Handler clear-branch (null=clear bỏ-validate-list, no-migration vì SelectedSupplierId đã Guid?) + FE dropdown ""→null + nút ✓ toggle. +- **C7** nút "Toàn màn hình" preview file báo giá (overlay inset-0 + Esc). + +Test +10 (`PeSelectWinnerClearTests`) → 356→366. FE 3 file ×2 app SHA-identical (diff-confirm rồi cp). + +## Đợt 2 — Clear sạch UAT data (`scripts/s85-wipe-uat-data.sql`) + +anh Kiệt "Clear sạch giúp anh nhé. Clear truoc em, xong anh check." Quy-trình destructive-prod chuẩn S59: recon → AskUserQuestion chốt scope → script → chạy → verify exact-count. +- **Recon prod:** 43 PE + 28 PeWorkItemBudgets + 1 HĐ + 32 notif + 43 Suppliers (22 gốc ≤06-09 + 21 test ≥06-11). +- anh chốt: **xóa budgets (28)** + **xóa 21 NCC-test** (CreatedAt≥06-11, mốc cắt sạch 06-10 trống). +- Script: **BACKUP bước 0** (registry backup-dir vì D:\ không tồn-tại VPS) + `SET QUOTED_IDENTIFIER ON` (filtered-index Mig19/20) + `SET XACT_ABORT ON` + `-b` (backup-fail→abort-trước-wipe). Verify exact: PE/budgets/contracts/notif=0, Suppliers=22, reset mã→A/001. DemoSeed:Disabled gate → app-recycle KHÔNG resurrect. +- Orphan upload files **defer** (path CWD-relative chưa pin, vô-hình UAT). + +## Đợt 3-6 — 6 vòng UAT (#335→#338) + +- **R1 #335 `24f0083`:** D1 ẩn mục 3/4/5 (gỡ FormRow/LockedHint/Lock unused) + D5 auto-chọn quy trình khi 1 option (prod PE type-1 có đúng 1 selectable WF). +- **R2 #336 `a5e936f`:** D2 drafter tự-gỡ cờ GẤP — BE restructure SET/UNSET (GẮN role-only; GỠ +drafter clear-CẢ-2) + FE `isDrafter` canToggle. D3 ngân-sách-kỳ-này tự-nhảy từ "Ban hành lần đầu" (`proInitialAmount`) — FE display + FE/BE submit-guard fallback `budgetPeriodAmount ?? proInitialAmount`. test +5 (`PeUrgentToggleAuthzTests` drafter-self-unset) → 366→371. +- **R3 #337 `e3e40ae`:** ràng tạo-phiếu (hint đỏ "thiếu: Quy trình/Hạng mục/Dự án", anh "không chọn quy trình thì ko cho tạo phiếu") + D4 checklist xanh✓/đỏ✗ trường bắt-buộc gửi-duyệt (mirror missingForApproval). [JSX fragment fix: chèn nhầm conditional trùng → bọc `<>`.] +- **R4 #338 `34218f0`:** checklist +"Quy trình duyệt" (sót → toàn-xanh-nhưng-submit-chặn misleading). [R4 auto-assign-at-submit thử → REVERT vì phá 2 test S83 + nới block ngược "ràng".] + +## Đợt 7-8 — 2 ROOT-CAUSE (whack-a-mole → fix gốc) + +**(R5 #339 `1263c0d`) Workflow MẤT khi bấm Sửa = bug-class S42** — gotcha #73. +- long.chau + anh Kiệt vẫn kẹt "chưa chọn quy trình" DÙ SQL-fix 5 phiếu. Query prod: 2 phiếu workflow-less MỚI (A/005 14:54, A/010 15:08) tạo SAU SQL-fix → KHÔNG phải point-in-time, là systemic. +- Truy: form Sửa header → `PUT /purchase-evaluations/{id}` (PeHeaderForm:112) KHÔNG gửi `approvalWorkflowId` → `UpdatePeDraftHandler:282` absolute-set `= null` = CLEAR. Field SÓT khỏi pattern null-safe mà BudgetPeriodAmount/WorkItemId cạnh đã có (S42). +- Fix: `if (request.ApprovalWorkflowId is not null) entity.ApprovalWorkflowId = ...`. Test +3 (`PeUpdateDraftWorkflowPreserveTests`) → 371→374. + +**(R6 #341 `49ac086`) "Mới tạo báo 7h trước" = TZ +7h** — gotcha #72. +- timestamps UTC nhưng EF đọc `DateTimeKind.Unspecified` → System.Text.Json serialize KHÔNG 'Z' → FE `new Date(naive)`=local → lệch +7h. +- Fix: global `UtcDateTimeJsonConverter` (AddControllers.AddJsonOptions) ép UTC-with-Z `.ToString("O")`. cicd verify API trả `createdAt:"…3154440Z"`. (= ops "tzutil UTC+7" pending S58, fix tầng-serialize chuẩn hơn đổi giờ máy-chủ.) + +**5 SQL-fix** (2 đợt 3+2 phiếu workflow-less): `UPDATE PurchaseEvaluations SET ApprovalWorkflowId='E08E3DA6…' WHERE ApprovalWorkflowId IS NULL AND Type=1` (QT-DN-V2-001). Bridge tới khi R5 deploy. + +## Cách chạy + spawn-record (§L.b(d) — ~12 spawn) + +| Sub | Task | Nấc | Evidence | +|---|---|---|---| +| tooling-auditor (H1) | session-start RE-REPORT 4-mặt | verified | 0 new-alloc, ef-core/skills-README stale-cite defer-monthly | +| harvest-curator (H2) | (skip — em-main proxy harvest closeout) | n-a | — | +| implementer-backend | C5 BE select-winner Guid? clear | verified | build slnx 0-err, Run #334 | +| implementer-frontend | (em-main did mirror) | n-a | — | +| test-specialist ×3 | C5 +10 · urgent-authz +5 · workflow-preserve +3 | verified | 356→374, 0 fail | +| reviewer ×2 | R2-batch + R5-batch | partial | truncated #53 → em-main self-gate (memory-lesson) | +| cicd-monitor ×7 | #334/#335/#336/#337/#338/#339/#341 | verified | 7/7 PASS, ship-proof Last-Modified BE-only | +| investigator-codebase | recon D2-GẤP-authz + D5-WF + validators | verified | found create-validator + IsUserSelectable prod=1 | + +⚠️ **Residual-write reconcile (B3):** investigator-codebase + test-specialist ×2 tự ghi MEMORY (residual) — em-main review git-diff = legit findings, KEEP. + +## §L closeout + +- **§L.a RCA:** 2 production-bug = lỗi-KÉP → 2-fix mỗi cái: R5 (code null-safe + test regression #73) · R6 (code converter + gotcha-guard #72). AS-* không thêm class mới. +- **§L.b(c)** archive-gate A7 GATE PASS 217/217 · test-specialist 28.4KB WATCH strike-1 (value-protect gotcha#/guard KEEP) · sleep-check 5d<7 skip. +- **§L.b(h)** User-Mark: 4 Active-High hiển-thị, 0 governance-decision MỚI (product session) → n-a. +- **Lesson NEW `feedback_root_cause_over_symptom`:** bug lặp-lại + band-aid (SQL/tzutil) không dứt → truy field/case LỆCH-quy-ước, đưa vào pattern đã-đúng = fix 1 chỗ hết tái-diễn. + +## 🔴 NEXT + +- **Anh:** ⚠️ restart CLI (carry budget v3 runtime + lệnh `/user-mark-*` + cadence). Báo anh Kiệt/long.chau Ctrl+F5. +- **Em (carry):** curate test-specialist 28.4KB WATCH (value-protect KEEP) · monthly 2026-07-01 (doc-cite ef-core/skills-README Mig→57 · STATUS/HANDOFF re-tier · **SignalR TZ-check** nếu realtime-push lệch · **edit-form workflow-selector** defer = đóng dead-end "mở Sửa chọn quy trình" mà form chưa có ô · fix L1-essentials `vrapp` password prefix-thừa per cicd-flag). +- **Pending product:** Ngưỡng giá CEO (Mig 54) Designer UAT · "C" chuyển phiếu→dự án chờ spec. +- **Ops:** email typo anh Chương · 5 real-staff pw · gán CNTT. diff --git a/docs/gotchas.md b/docs/gotchas.md index ecdb631..09a60de 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -1246,6 +1246,30 @@ for h in resp.points: # ← .points không phải iterable trực tiếp --- +### 72. DateTime serialize KHÔNG có 'Z' (EF đọc `Unspecified` kind) → FE `new Date()` hiểu là local → lệch +7h (Session 85) + +**Triệu chứng:** anh Kiệt "mới tạo phiếu mà báo cách 7h trước" — relative-time thông-báo (`Date.now() - new Date(createdAt).getTime()`) lệch đúng +7h (VN UTC+7). + +**Cơ chế:** timestamps lưu UTC (`DateTime.UtcNow`) nhưng EF Core đọc SQL Server `datetime2` về `DateTimeKind.Unspecified`. `AddControllers()` mặc-định (KHÔNG JSON config) → System.Text.Json serialize DateTime Unspecified-kind **KHÔNG có hậu-tố 'Z'** (`"2026-06-23T08:20:00"`). FE `new Date(naive)` hiểu chuỗi-không-TZ là **giờ LOCAL** → nhưng giá-trị là UTC → lệch +7h. Build PASS + test xanh (serialization không unit-test) → CÂM. + +**Guard:** global `JsonConverter` ép UTC-with-Z: `Kind==Unspecified ? SpecifyKind(Utc) : ToUniversalTime()` → `.ToString("O")`. Đăng-ký `AddControllers().AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new UtcDateTimeJsonConverter()))`. System.Text.Json tự áp cho `DateTime?` (Nullable non-null). **Verify:** curl authed endpoint → field `createdAt` JSON CÓ 'Z'. Lưu-UTC + convert-on-display (FE) là CHUẨN — KHÔNG band-aid `tzutil` đổi giờ máy-chủ (ảnh-hưởng GETUTCDATE + lệch khác). SignalR realtime-push dùng serializer RIÊNG (`AddJsonProtocol`) → nếu giờ realtime còn lệch thì áp converter tương-tự. + +**References:** `src/Backend/SolutionErp.Api/Serialization/UtcDateTimeJsonConverter.cs` · `Program.cs` AddControllers · `fe-user/src/components/NotificationBell.tsx:23`. + +--- + +### 73. UPDATE-handler absolute-set field → CLEAR khi FE KHÔNG gửi field (bug-class S42 recurrence) (Session 85) + +**Triệu chứng:** phiếu tạo CÓ Quy trình duyệt → bấm "Sửa" (đổi tên/dự án) → MẤT workflow → kẹt submit "chưa chọn quy trình duyệt" (**whack-a-mole**: SQL-fix vá xong, ai bấm Sửa lại rụng tiếp). long.chau + anh Kiệt + nhiều account. + +**Cơ chế:** `UpdatePeDraftHandler` absolute-set `entity.ApprovalWorkflowId = request.ApprovalWorkflowId`. Form Sửa (PeHeaderForm) KHÔNG gửi `approvalWorkflowId` → command bind `null` (default `Guid? = null`) → handler set `= null` = **CLEAR**. Field SÓT khỏi pattern null-safe (`if (request.X is not null)`) mà `BudgetPeriodAmount`/`ExpectedRemainingAmount`/`WorkItemId` NGAY DƯỚI đã có (comment "client không gửi → GIỮ giá trị cũ" — bug-class S42). 1 field lọt khỏi quy-ước đã-thiết-lập. + +**Guard:** MỌI field optional trong UPDATE-handler PHẢI null-safe `if (request.X is not null) entity.X = request.X` (preserve khi không gửi); CHỈ field text-clearable CỐ-Ý (TenGoiThau/DiaDiem/MoTa) mới absolute-set. Khi thêm field vào UPDATE command → **đối-chiếu pattern null-safe của field cạnh**. Triệu-chứng "vá-điểm xong TÁI-DIỄN" = nghi field-clear-on-omit, truy root KHÔNG vá-data lặp (root-cause-over-symptom). + +**References:** `src/Backend/SolutionErp.Application/PurchaseEvaluations/PurchaseEvaluationFeatures.cs:~282` (UpdatePeDraftHandler) · `fe-user/src/components/pe/PeHeaderForm.tsx:112` (PUT no-workflow) · bug-class S42 (BudgetPeriodAmount null-safe S61) · `tests/.../PeUpdateDraftWorkflowPreserveTests.cs`. + +--- + ## Checklist debug bug mới 1. Build pass không? → fail → check using + package version compat diff --git a/scripts/s85-wipe-uat-data.sql b/scripts/s85-wipe-uat-data.sql new file mode 100644 index 0000000..d4eb46c --- /dev/null +++ b/scripts/s85-wipe-uat-data.sql @@ -0,0 +1,102 @@ +-- ============================================================================ +-- S85 (2026-06-23) — Wipe UAT testing data ("clear sạch") trước UAT anh Kiệt FDC sáng nay +-- Chỉ đạo: anh Kiệt FDC (Zalo "Clear sạch giúp anh nhé" + "Clear truoc em. Xong anh +-- check một sáng nay em"). Quy trình destructive-prod chuẩn S59: +-- recon -> AskUserQuestion chốt scope -> script committed -> chạy -> verify exact. +-- +-- Anh chốt (AskUserQuestion S85): +-- - PeWorkItemBudgets (28) -> XÓA (UAT sạch hoàn toàn, ô ngân sách trống lại). +-- - Suppliers test thêm sau S59 -> XÓA 21 (CreatedAt >= 2026-06-11); GIỮ 22 gốc +-- (CreatedAt < 2026-06-11: 19 demo 04/21-23 + 3 real S55 06-09). Mốc cắt SẠCH +-- (06-10 trống — không nhập nhằng). +-- +-- XÓA: 43 PurchaseEvaluations (cascade child ~700: Suppliers/Details/Quotes/Approvals/ +-- Changelogs/Attachments/LevelOpinions/DeptOpinions) · 28 PeWorkItemBudgets +-- (loose-Guid per Dự-án×Hạng-mục — KHÔNG cascade theo PE -> DELETE riêng) · 1 +-- Contract (cascade) · 32 Notifications · 21 Suppliers test (CreatedAt >= 06-11) +-- · PeSeq + CtSeq (reset -> generator INSERT lại LastSeq=1 -> phiếu thật đầu = .../001). +-- GIỮ: 22 Suppliers gốc · Projects 70 · WorkItems 71 · Users 55 · Permissions/MenuItems/ +-- Roles · Workflows (7 active + Steps/Levels/Approvers — KHÔNG đụng config) · +-- ContractTemplates 9 · HRM/Office master (EmployeeProfiles/MeetingRooms/Vehicles/ +-- Drivers/LeaveTypes/Holidays/ShiftPatterns/OtPolicies) · EmployeeCodeSequences. +-- FK: PE child ALL CASCADE (Quotes NO_ACTION dọn qua Details->Quotes, proven S59). +-- Suppliers xóa SAU PE+Contracts (đã giải phóng SelectedSupplierId/Quotes/Contract). +-- Safety: SET XACT_ABORT ON (lỗi -> rollback toàn bộ) + BACKUP bước 0 ngoài tran + +-- chạy sqlcmd -b (backup fail -> abort TRƯỚC wipe). Resurrect-safe: DemoSeed:Disabled. +-- Run: scp -> VPS C:\temp\s85.sql ; sqlcmd -S .\SQLEXPRESS -d SolutionErp -i C:\temp\s85.sql -f 65001 -b +-- ============================================================================ +SET QUOTED_IDENTIFIER ON; +SET ANSI_NULLS ON; +SET NOCOUNT ON; +SET XACT_ABORT ON; +GO + +-- ===== 0. BACKUP insurance (NGOÀI transaction; -b -> fail thì abort trước wipe) ===== +-- Lấy backup dir từ registry (SQL service account chắc chắn ghi được; D:\ KHÔNG tồn tại +-- trên VPS này — chỉ ổ C:). xp_instance_regread auto-resolve path theo instance. +DECLARE @bkdir nvarchar(512), @bkfile nvarchar(600); +EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @bkdir OUTPUT; +SET @bkfile = @bkdir + N'\SolutionErp_S85_prewipe.bak'; +PRINT 'Backup device -> ' + @bkfile; +BACKUP DATABASE [SolutionErp] TO DISK = @bkfile WITH INIT, CHECKSUM, NAME = N'SolutionErp-S85-pre-wipe'; +GO + +PRINT '=== BEFORE ==='; +SELECT 'PE' AS T, COUNT(*) AS C FROM PurchaseEvaluations +UNION ALL SELECT 'PeWorkItemBudgets', COUNT(*) FROM PeWorkItemBudgets +UNION ALL SELECT 'Contracts', COUNT(*) FROM Contracts +UNION ALL SELECT 'Notifications', COUNT(*) FROM Notifications +UNION ALL SELECT 'Suppliers_total', COUNT(*) FROM Suppliers +UNION ALL SELECT 'Suppliers_test(>=06-11)', COUNT(*) FROM Suppliers WHERE CreatedAt >= '2026-06-11' +UNION ALL SELECT 'PeSeq', COUNT(*) FROM PurchaseEvaluationCodeSequences +UNION ALL SELECT 'CtSeq', COUNT(*) FROM ContractCodeSequences; +GO + +BEGIN TRANSACTION; + +-- 1. Phiếu PE (cascade child) +DELETE FROM PurchaseEvaluations; +PRINT ' PurchaseEvaluations deleted : ' + CAST(@@ROWCOUNT AS varchar); + +-- 2. Ngân sách per-gói-thầu (loose-Guid, KHÔNG cascade theo PE) +DELETE FROM PeWorkItemBudgets; +PRINT ' PeWorkItemBudgets deleted : ' + CAST(@@ROWCOUNT AS varchar); + +-- 3. Hợp đồng (cascade child) +DELETE FROM Contracts; +PRINT ' Contracts deleted : ' + CAST(@@ROWCOUNT AS varchar); + +-- 4. Thông báo +DELETE FROM Notifications; +PRINT ' Notifications deleted : ' + CAST(@@ROWCOUNT AS varchar); + +-- 5. NCC test thêm sau S59 (giữ 22 gốc CreatedAt < 2026-06-11) +DELETE FROM Suppliers WHERE CreatedAt >= '2026-06-11'; +PRINT ' Suppliers test deleted : ' + CAST(@@ROWCOUNT AS varchar); + +-- 6. Reset bộ đếm mã (DELETE row -> generator INSERT lại LastSeq=1 -> .../001) +DELETE FROM PurchaseEvaluationCodeSequences; +DELETE FROM ContractCodeSequences; +PRINT ' Code sequences reset (Pe+Ct)'; + +PRINT '=== AFTER (expect transactional=0, Suppliers=22, master giữ) ==='; +SELECT 'PE' AS T, COUNT(*) AS C FROM PurchaseEvaluations +UNION ALL SELECT 'PeWorkItemBudgets', COUNT(*) FROM PeWorkItemBudgets +UNION ALL SELECT 'PeSuppliers', COUNT(*) FROM PurchaseEvaluationSuppliers +UNION ALL SELECT 'PeQuotes', COUNT(*) FROM PurchaseEvaluationQuotes +UNION ALL SELECT 'PeAttachments', COUNT(*) FROM PurchaseEvaluationAttachments +UNION ALL SELECT 'PeChangelogs', COUNT(*) FROM PurchaseEvaluationChangelogs +UNION ALL SELECT 'Contracts', COUNT(*) FROM Contracts +UNION ALL SELECT 'Notifications', COUNT(*) FROM Notifications +UNION ALL SELECT 'Suppliers_keep', COUNT(*) FROM Suppliers +UNION ALL SELECT 'PeSeq', COUNT(*) FROM PurchaseEvaluationCodeSequences +UNION ALL SELECT 'CtSeq', COUNT(*) FROM ContractCodeSequences +UNION ALL SELECT 'KEEP_Projects', COUNT(*) FROM Projects +UNION ALL SELECT 'KEEP_WorkItems', COUNT(*) FROM WorkItems +UNION ALL SELECT 'KEEP_Users', COUNT(*) FROM Users +UNION ALL SELECT 'KEEP_Workflows', COUNT(*) FROM ApprovalWorkflows +UNION ALL SELECT 'KEEP_Templates', COUNT(*) FROM ContractTemplates; + +COMMIT TRANSACTION; +PRINT 'S85 wipe COMMITTED.'; +GO