From 1b8b065cab2e3246d75108b48df9877ca0e7a2ee Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Tue, 14 Jul 2026 11:55:28 +0700 Subject: [PATCH] [CLAUDE] Docs: S117 monitor-gate reconcile (H1 ef-core range + H2 diary nits) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H1 tooling-auditor: ef-core SKILL §16+ pending-range 27-64/27-61 → 27-66 (internal consistency; 2 STALE-rows Tests/bundle đã fix ở d08f2a3). H2 harvest-curator PASS 5/5: 3 benign diary-reconcile (0 data-loss) — inv-cb S118→S117 (mis-tag header+tag, task-2 của S117) · test-spec baseline 500→501 (+1 em-main-solo luyke fix nó không đếm) · cicd S117 garble→resume self-record (was under-reported "×3 clean"). Docs/.claude-only → CI-skip. Co-Authored-By: Claude Opus 4.8 --- .claude/agent-memory/cicd-monitor/MEMORY.md | 2 +- .claude/agent-memory/investigator-codebase/MEMORY.md | 4 ++-- .claude/agent-memory/test-specialist/MEMORY.md | 2 +- .claude/skills/ef-core-migration/SKILL.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.claude/agent-memory/cicd-monitor/MEMORY.md b/.claude/agent-memory/cicd-monitor/MEMORY.md index 284c600..93b8eda 100644 --- a/.claude/agent-memory/cicd-monitor/MEMORY.md +++ b/.claude/agent-memory/cicd-monitor/MEMORY.md @@ -14,7 +14,7 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve ## ⚠️ cicd-lane return-garble tracker (#53) -cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay verdict (×5/6 qua S114; cumulative ×18 all-agents → [[feedback_agent_return_garble_recover]], root-cause = curate-at-return). Recover: em-main-solo curl-verify. **S115 (#385)+S116 (#386)+S117 (#387) cicd-lane CLEAN-return no-garble ×3 — verdict delivered OK.** +cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay verdict (×5/6 qua S114; cumulative ×18 all-agents → [[feedback_agent_return_garble_recover]], root-cause = curate-at-return). Recover: em-main-solo curl-verify. **S115 (#385)+S116 (#386) cicd-lane CLEAN-return no-garble ×2; S117 (#387) garble→SendMessage-resume (em-main curl cross-verify khớp, verdict disk-true) — return-mechanics garbled NHƯNG verdict-substance OK.** --- diff --git a/.claude/agent-memory/investigator-codebase/MEMORY.md b/.claude/agent-memory/investigator-codebase/MEMORY.md index beb142d..487de15 100644 --- a/.claude/agent-memory/investigator-codebase/MEMORY.md +++ b/.claude/agent-memory/investigator-codebase/MEMORY.md @@ -101,8 +101,8 @@ Bearer từ `POST api.solutions.com.vn/api/auth/login` → status matrix expecte --- -## S118 — PE giá-chốt RANGE Min+Max invest (fable-real single, 07-14) -- ApprovedPrice WRITE = 1 site duy nhất `ApplyApprovedPriceOnFinalize` (`PurchaseEvaluationWorkflowService.cs:951-966`, allow-list :950) gọi tại 3 nhánh DaDuyet :858 level-finalize / :896 ccm-delegation / :928 all-steps-done (skipToFinal :820 chỉ dời pointer, KHÔNG finalize-site thứ 4). READ prod = detail-DTO ONLY (`PurchaseEvaluationFeatures.cs:1230` → `PurchaseEvaluationDtos.cs:285`) + FE display `PeDetailTabs.tsx:1712/:1850-1863`. ⭐ **HĐ-gen KHÔNG đọc ApprovedPrice** — GiaTri=SUM Quote.IsSelected per-winner (`CreateContractFromEvaluationFeatures.cs:88-100` LOCKED A1/D4) → range 0-impact contract/lũy-kế/list. Rec model A: +1 col nullable `ApprovedPriceMaxAmount` + source token `ProMinMax` = radio thứ-5 (chỉ khi cả Min+Max present), no backfill, phiếu cũ nguyên. PRO-entry đã enforce Min≤Max (`PeSuggestedPriceFeatures.cs:38-40`). Panel+DetailTabs SHA-mirror 2-app NHƯNG `types/purchaseEvaluation.ts` KHÔNG mirror (SHA differ) — edit riêng từng app. Latent edge: winnerQuoteTotal subset-selected có thể ÂM (S116) vs validator `ApprovedPriceAmount>=0` `:501` → transition reject khó hiểu. WIP S117 uncommitted CÙNG file PurchaseEvaluationFeatures.cs (endsBeforeCeo pointer-aware :642/:768/:1157) — vùng khác, merge-safe. `[s118, pe-approved-price-range, prominmax]` +## S117 — PE giá-chốt RANGE Min+Max invest (fable-real single, 07-14) +- ApprovedPrice WRITE = 1 site duy nhất `ApplyApprovedPriceOnFinalize` (`PurchaseEvaluationWorkflowService.cs:951-966`, allow-list :950) gọi tại 3 nhánh DaDuyet :858 level-finalize / :896 ccm-delegation / :928 all-steps-done (skipToFinal :820 chỉ dời pointer, KHÔNG finalize-site thứ 4). READ prod = detail-DTO ONLY (`PurchaseEvaluationFeatures.cs:1230` → `PurchaseEvaluationDtos.cs:285`) + FE display `PeDetailTabs.tsx:1712/:1850-1863`. ⭐ **HĐ-gen KHÔNG đọc ApprovedPrice** — GiaTri=SUM Quote.IsSelected per-winner (`CreateContractFromEvaluationFeatures.cs:88-100` LOCKED A1/D4) → range 0-impact contract/lũy-kế/list. Rec model A: +1 col nullable `ApprovedPriceMaxAmount` + source token `ProMinMax` = radio thứ-5 (chỉ khi cả Min+Max present), no backfill, phiếu cũ nguyên. PRO-entry đã enforce Min≤Max (`PeSuggestedPriceFeatures.cs:38-40`). Panel+DetailTabs SHA-mirror 2-app NHƯNG `types/purchaseEvaluation.ts` KHÔNG mirror (SHA differ) — edit riêng từng app. Latent edge: winnerQuoteTotal subset-selected có thể ÂM (S116) vs validator `ApprovedPriceAmount>=0` `:501` → transition reject khó hiểu. WIP S117 uncommitted CÙNG file PurchaseEvaluationFeatures.cs (endsBeforeCeo pointer-aware :642/:768/:1157) — vùng khác, merge-safe. `[s117, pe-approved-price-range, prominmax]` ## S117 — PE lũy-kế "không bắt sau duyệt" RCA (fable-real single deep-pass) - **2026-07-14** VERDICT: phiếu nguồn A/018 KHÔNG hề DaDuyet — Chương (Bước2 Cấp2 `AllowApproverFinalize`, badge "Duyệt thay CEO" = CONFIG-display `PeWorkflowPanel.tsx:364`) duyệt KHÔNG tick ô OPT-IN "Cấp này KẾT THÚC" (S97 Part1 đảo default UNCHECKED `PeWorkflowPanel.tsx:57` useState(false); FE gửi tường minh :203) → advance thường lên Bước3 CEO, Phase=10 ChoDuyet. Prod ground-truth: StepIdx=2 LvlOrd=1 EndedFin=0; changelog 13/07 12:23Z "Hoàn tất Bước 2/3, sang Bước 3 (Cấp 1)" no-finalize-marker; IsWinner=1 SelQ=1 (749.564M) → RC-2 refuted. Lũy-kế Row2 filter `Phase==DaDuyet` (`PeFeatures.cs:906`) ĐÚNG nguyên tắc Kenny "duyệt rồi mới bắc"; tính LIVE :886-918 no-store → xóa+tạo-lại phiếu-XEM vô ích. ⭐ Residual = DISPLAY-LIE nửa-còn-lại gotcha #78: non-DaDuyet `endsBeforeCeo`=config TRUE bất chấp pointer (detail `:1152-1154` literal `: true`; list `:647-651` subquery `.Any()`) → Bước3 mờ "Kết thúc tại Cấp 2" + chip list "⚑ Kết thúc·CCM" NGAY KHI phiếu nằm inbox CEO → user tưởng xong. 3 cơ chế chồng phân biệt: AllowApproverFinalize (Mig58 + opt-in S97) ≠ finalizeByCcmDelegation (Mig53/54 threshold — v04 CeoThresh=NULL không dùng) ≠ skipToFinal (Mig31 pointer-jump giữ ChoDuyet). Fix rec: vận-hành CEO-duyệt hoặc trả-lại→Chương tick; code = pointer-aware endsBeforeCeo (detail in-memory trivial, list EF-subquery kềnh), KHÔNG nới filter lũy kế. `[engine: fable-real-single · Fable-S117]` diff --git a/.claude/agent-memory/test-specialist/MEMORY.md b/.claude/agent-memory/test-specialist/MEMORY.md index 04d15a7..cace3ae 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: 500 tests = 500 PASS (45 Domain + 455 Infra) as of S117 (was 495@S116; +5 PE ProMinMax, filtered-run 15/15) +## 📊 Baseline: 501 tests = 501 PASS (45 Domain + 456 Infra) as of S117 (was 495@S116; +5 PE ProMinMax [own] +1 endsBeforeCeo-pointer-aware [em-main-solo, PeFinalizeProjectionTests], filtered-run 15/15) - Count history + verbose per-session test-design notes (S54→D2): [archive/baseline-history.md](archive/baseline-history.md) (L2, on-demand). - Latest (D2): +6 PE Mig 58 multi-winner — `CreateContractFromEvaluationMultiWinnerTests.cs` (5, 1→N HĐ per IsWinner, GiaTri per-winner=quote-total / single=legacy-budget-sum) + `PeListWinnerNamesProjectionTests.cs` (1, EF collection-projection translation-smoke). No prod bug. > 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. diff --git a/.claude/skills/ef-core-migration/SKILL.md b/.claude/skills/ef-core-migration/SKILL.md index 3fc65e6..0f6be6e 100644 --- a/.claude/skills/ef-core-migration/SKILL.md +++ b/.claude/skills/ef-core-migration/SKILL.md @@ -87,7 +87,7 @@ when-to-use: | **65** | **`BackfillPeQuoteIsSelectedAndWinnerInvariant`** | **🎯 S114 — DATA-ONLY no-schema (multi-NCC per hạng mục anh Kiệt): backfill **2-CHIỀU** thiết lập bất-biến `Supplier.IsWinner == Any(Quote.IsSelected)`. CHIỀU-1 `IsWinner→IsSelected` (phiếu cũ whole-supplier winner Mig58 → set IsSelected mọi quote NCC, **preserve tổng** winnerQuoteTotal) + CHIỀU-2 `IsSelected→IsWinner` (dormant/seed EXISTS). Idempotent (`WHERE ...=0`), SQL-Server-only (SQLite EnsureCreated bỏ qua migration), Down **no-op** (data backfill không reversible, mirror Mig 61). **No new table (89 giữ)** — snapshot UNCHANGED (0 CreateColumn). Prod-verified bundle rotate ×2 `D51OYyGV`/`BVdssm5S`; commit `d436af2`. Kèm **gotcha #81** (delete-writer sót re-derive IsWinner → phantom HĐ giaTri=0 — verify-bắt).** | | **66** | **`AddPeApprovedPriceRange`** | **🎯 S117 — PE +`ApprovedPriceMaxAmount decimal(18,2)?` (feature "duyệt theo khoảng Min–Max" anh Kiệt FDC "chọn cả 2 min và max"): source `"ProMinMax"` = Amount(Min)+MaxAmount(Max), bất-biến `MaxAmount != null ⟺ Source=="ProMinMax"` + Min≤Max (guard service `ApplyApprovedPriceOnFinalize` + FluentValidation). 1 AddColumn nullable, **no backfill** (phiếu cũ Source-đơn Max=null nguyên vẹn), **no new table (89 giữ)**, reversible Down (DropColumn). HĐ.GiaTri KHÔNG đọc giá chốt (=SUM báo giá NCC được chọn) → 0 tác động HĐ (range = record-of-decision hiển thị). Prod-verified Run #387 (`ApprovedPriceMaxAmount` col decimal(18,2) + `__EFMigrationsHistory` top); commit `316a82f`.** | -Total: **89 bảng** `sys.tables` (= 88 dbo-app + `__EFMigrationsHistory`; re-ground S97 cicd Run #482 LIVE — số canonical → `docs/STATUS.md`; last schema-changing Mig 50 net 93→88-app, Mig 51-66 đều AddColumn/index/data-only/schema-expand không đổi số bảng). Xem `docs/database/schema-diagram.md` migration table + §11-15 module ERD (§16+ Mig 27-64 chi tiết pending). +Total: **89 bảng** `sys.tables` (= 88 dbo-app + `__EFMigrationsHistory`; re-ground S97 cicd Run #482 LIVE — số canonical → `docs/STATUS.md`; last schema-changing Mig 50 net 93→88-app, Mig 51-66 đều AddColumn/index/data-only/schema-expand không đổi số bảng). Xem `docs/database/schema-diagram.md` migration table + §11-15 module ERD (§16+ Mig 27-66 chi tiết pending). ## N-stage workflow pattern (Mig 18-20 — Session 12-13) @@ -304,5 +304,5 @@ sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P -i migrate.sql ## Related - `docs/database/database-guide.md` — conventions + migration workflow chi tiết -- `docs/database/schema-diagram.md` — **ERD** (số bảng → `docs/STATUS.md`) + §11 PE + §12 ~~Budget~~ (REMOVED Mig 50) + §13 PEDeptOpinions (Mig 15) + §14 ApprovalWorkflow V2 (Mig 22-25) + §15 PE Level Opinions V2 (Mig 26); §16+ Mig 27-61 detail pending (xem migration table) +- `docs/database/schema-diagram.md` — **ERD** (số bảng → `docs/STATUS.md`) + §11 PE + §12 ~~Budget~~ (REMOVED Mig 50) + §13 PEDeptOpinions (Mig 15) + §14 ApprovalWorkflow V2 (Mig 22-25) + §15 PE Level Opinions V2 (Mig 26); §16+ Mig 27-66 detail pending (xem migration table) - `docs/gotchas.md` #7, #17, #38 — migration pitfalls + Identity 4-field rename