From 169b0dc42f06747f16a4c0b7481805c6893a1e4c Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 17 Jul 2026 14:46:51 +0700 Subject: [PATCH] wal: flush 20260717T1446 --- .../investigator-codebase/archive/2026-07.md | 14 ++++ .../agent-memory/reviewer/archive/2026-07.md | 14 ++++ .../sub-cicd-monitor-0.md | 79 +++++++++++++++++++ .../sub-test-specialist-0.md | 57 +++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 .claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-cicd-monitor-0.md diff --git a/.claude/agent-memory/investigator-codebase/archive/2026-07.md b/.claude/agent-memory/investigator-codebase/archive/2026-07.md index 00c1ff0..3b448ac 100644 --- a/.claude/agent-memory/investigator-codebase/archive/2026-07.md +++ b/.claude/agent-memory/investigator-codebase/archive/2026-07.md @@ -47,3 +47,17 @@ ## @S126 hook-curate batch (2026-07-16, em-main single-writer, moved-not-cut verbatim từ L1) - **S116 — PE negative-quote invest (fable-clone ensemble, 07-13):** Hội-tụ **FE-ONLY**: BE/DB nhận âm sẵn (no validator/CHECK); NS giữ-nguyên architectural; 3 chốt FE parseVnd/format/gate; sign-aware `VndInlineEdit:1003` tái dùng; chỉ submit-guard `:206` hard-reject. ⚠️ Lesson: quote sống `details[].quotes` KHÔNG `suppliers[].quotes`. **Detail:** `.claude/workflows/runs/2026-07-13-pe-negative-quote/` + session-log S116 + archive/2026-07.md 2×LENS. `[Opus-S116]` + +--- + +## [S134 curate 2026-07-17 — hook-triggered @20.8KB, investigator-codebase self-curate] Verbatim các entry L1 bị thay stub + +- **S114 (07-12) PE multi-winner PER-HANG-MUC (fable-clone):** Mig58/59 multi-winner = WHOLE-SUPPLIER (`PurchaseEvaluationSupplier.IsWinner`); `Quote.IsSelected` per hang-muc×NCC = latent-hook Mig12 nay LIVE (Mig65 backfill re-key winner-truth IsWinner→IsSelected = CARDINALITY-CHANGE #2). winnerQuoteTotal=SUM(Quote WHERE IsSelected) `PeFeatures.cs:1188`. #1 open: N-win 1 hang-muc split KHOI-LUONG hay full-price (schema thieu per-winner volume). Tag `[s114, pe-multiwinner-per-hangmuc, quote-isselected-live]`. +- **S113 (07-12) Supplier import v2 (5-lane ensemble):** selection consumers qua ListSuppliersQuery (`PeDetailTabs:2222`+`ContractCreatePage:321`+dashboard); chot IsPublic-bool + dedup-MST+Code + fail-closed default. Prod 37 NCC. 1 lane #53-garble→em-main recover. Tag `[s113, supplier-import-v2, ma-ncc=code]`. +- **S112 (07-12) Supplier Excel-import + PE sign-off (fable-clone):** Supplier 27/27 bijective (Mig62 SHIPPED prod); dedup Code CI-collation → normalize-case TRUOC store; PE bypass = go/gate `ApplyDrafterBypassOnSubmitAsync`; EDGE-5 drafter-forge-Reject REACHABLE. Tag `[s112, supplier-mapping, pe-bypass-a1, edge5-reachable]`. +- **[→ archive/2026-07.md] 2026-07-13 PE negative-quote 2× LENS (Budget-consumers + edge/precedent/test)** — key giữ: budget-not-mutated-by-quote (architectural) · submit-guard `Sum()<=0` `:206` duy-nhất reject · no-quote-validator · parseVnd strip-minus · giaTri-âm bypass validator · gotcha #81 orthogonal-dấu. Executed S116; anchors sống trong S116/S117 entries. +- **[→ git 07-12 · superseded by S115 entry above] PE per-HANGMUC multi-winner LENS BE-consumer-audit:** 3 cardinality axes — `SelectedSupplierId` single (legacy) · Mig58 `IsWinner`=WHOLE-SUPPLIER liên-danh · `Quote.IsSelected` per hangmuc×supplier (S114 made LIVE). 5 money consumers keyed off IsSelected now (winnerQuoteTotal/submit-guard/ccm-threshold/giaTri/budget-block-B). ~6 test files. Tag `[pe-multiwinner, per-hangmuc, quote-isselected, cardinality]`. +- **[→ git 07-12] Supplier-import-v2 LENS-3 FE-dialog-UX:** SupplierImportDialog+SuppliersPage SHA-identical 2-app; dialog 2-step preview→confirm round-trips `preview.rows` → per-row edit feasible; `ExpectedHeaderTokens` 30-token baked `SupplierExcelImportService.cs:35-68` = template single-source; Mã NCC=Code; import authz-mismatch BE `[Roles=Admin,CatalogManager]` vs FE `Suppliers/Create` open. Tag `[s112, supplier-import-v2, fe-lens3, import-authz-mismatch]`. +- **[→ git 07-12 · Mig64 IsPublic shipped since] Supplier import-v2 LENS-4 public/visibility recon:** 3 SELECTION consumers ALL hit `GET /suppliers` ListSuppliersQuery (SuppliersPage:83 · PeDetailTabs:2222 · ContractCreatePage:321); DISPLAY-of-existing joins by stored SupplierId MUST NOT filter (ContractFeatures/PeFeatures/Dashboard); write-guard backstops `ContractFeatures.cs:64`+`PurchaseEvaluationSupplierFeatures.cs:49`. Rec fail-closed default + stored `IsPublic bit`. Tag `[s112b, supplier-visibility, fail-closed-default]`. +- **[all verbatim → archive/2026-07.md] S98 verify-lane (detector 28→25, 8 derived-stale=FP vs canonical 61/89/440/79; grep exact misses README variant) · S97 feedback-audit (#77/#78/#79 `gotchas.md:1301/1317/1325`; #53-garble×6=cicd MEMORY-self-target ~17.5KB; Mig60 wrong-table Approvals→Mig61 Changelogs) · 07-01 Supplier-predecessor SUPERSEDED by 07-06 · S93 MFE denom=marks/AS/guards dedup-AS-xref=29, coverage exact-id OR ≥2-content-word.** +- **S129 (07-16 đêm) adap 2 errata EOL 3-lane `wf_3fccd7d1`:** T0 sweep = SE **0 defect-site** (counter duy-nhất `agent-frontmatter-eol-check.ps1` byte-level pre-satisfy fix①③; pattern hỏng chỉ ở mention-site). T1: 19 `i/-text` đều declared-binary 0-suspect — **filter mẫu erratum thiếu docx/xlsx = 13 dương-giả trên SE** (tailor-per-class!); generator-drift thật duy-nhất `mfe-eval.ps1:204` Set-Content UTF8 = **BOM+CRLF** (blob mang BOM 3-byte); W0.6 = EOL-only A/B, trục-quote UNDETERMINED — đừng over-read. T2: nấc thật = **4 gated + 3 discipline** (đừng kê "7/7" phẳng — R1 MAJOR). 2 bẫy tự-mắc đáng nhớ: `git log -- | tail -1` = **first-touch KHÔNG phải policy-landing** (.gitattributes 08c7036 06-15 vs 92de58f 07-15) · story "40 = +1 agent mới" BỊA — số scoped=39, delta=`skills/README.md` ngoài glob SKILL.md (meta-count class). #53 WRITE-lane 2/3 lane — journal cứu trọn, em-main scribe. Tag `[s129, adap-errata-eol, byte-counter-pre-satisfy, bom-in-blob, tail1-first-touch-trap]` diff --git a/.claude/agent-memory/reviewer/archive/2026-07.md b/.claude/agent-memory/reviewer/archive/2026-07.md index fd93da9..b48c2e7 100644 --- a/.claude/agent-memory/reviewer/archive/2026-07.md +++ b/.claude/agent-memory/reviewer/archive/2026-07.md @@ -59,3 +59,17 @@ - **S124 L2 fidelity-to-source review, adap-wave plan — PWF (0 misread/1 MAJOR/3m):** 5/6 broadcast-reading traps read-faithful (NOT-adopt→method/spirit · h17 4-floors-KEEP · r6 abs-path). MAJOR = **push-guard "REFINEMENT ahead-of-broadcast" (spec:58) = OVERCLAIM**: SE trailing-K is LOOSER than broadcast ahead-range-all-count, keeps sandwiched wal:→leak; NO dimension strictly ahead. run.md:15 + mark cl.4 already carry honest "noise-accepted no-rewrite" ⇒ spec contradicts own run.md+mark. **Lesson: "ahead/refinement" = verify vs broadcast's ACTUAL requirement (looser≠ahead); spec+adap-report = shipped artifact → reconcile before hub-send.** Verified: adap-reports at `docs/governance/` not `.claude/` (path-trap false-empty). → `archive/2026-07.md`. - **S112 fable-real-single close-reviews+FINAL — GO 0-must:** Import btn reuses sibling-menu guard but endpoint=Admin ⇒ derive guard from ENDPOINT authz; EDGE-5 gác FROM-state ở ĐỈNH method KHÔNG per-branch; self-flip token-test = internal NOT external-accept. → [topic](project_s112_supplier_import_review.md). - **S126 (2026-07-16) A1-H23-probe + email-H23-gate [opus ×2, em-main VERIFY+APPEND] — gate FAIL bắt 3 lỗi thật trước stamp:** (1) 🎯 "Audit 2/2/0" NON-REPRODUCIBLE — audit COUNTS = **session-cumulative**, chính 2 lane review đẩy 2→4. **Lesson: số AGGREGATE cumulative KHÔNG vào outward artifact mời-reproduce — evidence bền = per-lane theo run-id.** (2) "Ba việc nêu ở thư" thực = **2 ASK** — MỞ thư đếm ask thật, đừng gộp courtesy-expectation. (3) "hub 17/17" = SE-self-obs R1-open → hedge+quy-thuộc. Lõi verified độc-lập: lead=Fable **116/116** records · A1 fable · A2 opus. Fixed → stamp `945cf3ad` selftest+stamp_verify+_index CÙNG lượt. Evidence: `runs/2026-07-16-S126-adap-spec-execute/`. + +--- + +## [BATCH S134-curate 2026-07-17 — moved verbatim từ L1 MEMORY.md (hook 21.3KB→<17.1KB), move-not-cut] + +- **S131b (07-17) GATE#2 outward email-hub closure-cadence follow-up (owner-direction narrate, KHÔNG claim đo mới) — PASS_WITH_FIXES (0C/1M/3m):** owner-fidelity vs 2-lượt-chat: "owner tự chỉ ra trade-off" phương-án-A = ĐÚNG (turn-1 owner nói CẢ pro 'giảm nặng start/end' + con 'khó theo dõi hơn' — reviewer NGHI bịa nhưng thật-sự faithful, KHÔNG manufacture) · 4 tiêu-chí trực-tiếp turn-2. 🎯 **M1: "nghi-thức chạy tắt HÀNG LOẠT" inflate source chính-xác "3 closeout liên tiếp"/3-session** (morning e46863c8 GAP-2) — re-introduce đúng overclaim-class mà morning-gate ĐÃ gỡ (2 fencepost/overclaim); follow-up outward tới bounded-source phải GIỮ con-số của source, "hàng loạt" undo kỷ-luật source đã trả-giá. m2: title quote "không **sót**" nhưng owner viết "ko **xót**" (x) — silent spelling-normalize + gloss "im lặng phải khác sạch" commit 1 reading của homophone mập-mờ; interpret probably-correct NHƯNG gate-prompt CŨNG lặp "sót" ⇒ divergence sót upstream = independent-catch. m3: paren-gloss 4 tiêu-chí trộn framework-lead vào section "Owner nhận-định" (hedged caveat-3). Số verify sạch: 250-300K=(ước lượng vận hành)✓ · 6/15 owner-decisions-file+memory-budget:122-123 ⇒ 'số owner đặt' ĐÚNG · eval~0 memory-budget:44 'deterministic NO-API analyzer' ✓. Caveat-block 3-điểm mạnh (chưa-chốt/est-spawn/SE-diễn-giải). Lesson: **verbatim-quote owner = so TỪNG CHỮ kể cả homophone x/s; "đã đo" outward chỉ pass khi trỏ disk-measure thật (morning email có).** +- **S131 (07-17) GATE outward email-hub + adap-report §6 báo 3 op-gap H24×H22×H1/H2 — PASS_WITH_FIXES (0C/2M-shared-root/3m):** → [topic](project_s131_h24_h22_3gap_outward_gate.md). MỌI số atomic reproduce (counter=7·S124=3·S128/129/130 no-tick·tick chỉ session-start §2.1.8 [session-end §L.b(j) chỉ ĐỌC]·12 measured·9+4+1 flag·§5(a) flip đúng). 🎯 **Bắt fencepost khi số atomic ĐÚNG HẾT:** "8 nhãn/+4 (3→7)" ghép lệch cột-mốc (8 nhãn↔+5 baseline post-S123=2; +4↔7 nhãn baseline S124=3) → đọc 8−4=4-miss SAI (thật 3) → đẻ "gấp-đôi" 2× overclaim (đo thật 8:5=1.6×). Lesson: hero-ratio phái-sinh re-derive từ raw, đừng tin phép-nhân tác-giả; fencepost = liệt-kê từng nhãn + đếm tay. +- **S129 (07-16 đêm) REVIEW adap-errata-EOL 2-lane `wf_8a0249f6` — GO-WITH-FIXES ×2:** R0 re-verify **byte-exact** T0/T1 + bắt P1 writer-only = **NỬA-VÁ** (reader `mfe-eval.ps1:193` là read duy-nhất thiếu `-Encoding UTF8`, đang BOM-sniff; blob mang BOM thật `ef bb bf` — S87 consumer-sweep áp cho cả ĐỀ-XUẤT-VÁ, không chỉ code) + 2 presentation-gap (blob-mutation không khai · lợi-ích thổi khi porcelain vốn rỗng — S81 class). R1 adversarial: 4/4 cite exact + 2 quick-test **tự chạy lại = chứng không-bịa rẻ nhất**; tally "7/7 ADOPTED" = rung-flatten 4-gated/3-discipline (S122 memory≠enforcement); story T0 "+1 agent mới" BỊA (delta thật = `skills/README.md` ngoài glob, số scoped=39); on-behalf verbatim 0-miss (22/22+41/41). Cả 2 lane #53 khai-path-không-ghi → em-main scribe từ journal. Tag `[s129, review-adap-errata, half-fix-writer-only, rung-flatten, byte-exact-rerun]` +- **S128 (2026-07-16) D-review 2-lane adap 16-07 [hmw reviewer opus-max ×2 · R1 tự-ghi sub-md, R2 return-only→lead scribe; em-main VERIFY+APPEND] — GO-COMMIT 2/2, 0 BLOCKER, owner-gated 0-diff CONFIRMED:** R1: 5 acceptance re-run PASS paste-thật · hash 7/7 recompute · 0 self-claim "verified" · M1 evidence-paste "tô-điểm" (`contextual_retrieval = False` khi lệnh chỉ in `False`) — soi literal-fidelity CẢ KHI giá-trị đúng. R2: email fact-check 7/7 · counter cumulative AN-TOÀN khi neo file persisted reproducible (≠ S126 self-mutating) · lineage "05-26" → git nói 05-22 `bf93abd` — lệch CONSERVATIVE ⇒ minor không blocker (**direction-of-error quyết mức lỗi outward**) · brute-force canonical-variant với known-good TRƯỚC khi phán tamper (recipe strip-1 vs strip-ALL: 2 biến-thể sống chung theo phía phát-hành — SE-set khớp strip-1, hub-set khớp strip-ALL). Lead fold M1+lineage 3-chỗ-cùng-lớp + re-stamp `c0ac7486447e`. Trace: `runs/2026-07-16-S127-adap-dot-16-07/{sub-reviewer-0,sub-reviewer-1,review-synthesis}.md`. Tag `[s128, d-review, direction-of-error, sha-variant-per-publisher]` +- **S128 fable-real #2 re-review spec-execute adap 16-07 [0-garble ghi-đĩa-tăng-dần; em-main VERIFY+APPEND] — GO-WITH-FIXES 4 SHOULD-FIX/0 BLOCKER (cả 4 = lỗi verify-lệnh/scope-rơi):** F1 count-quên-README · F2 so `_index` bằng Get-FileHash = SAI-LOẠI-HASH (body-sha ≠ whole-file, đo `181a6d19`≠`f29247cf`) · F3 nén draft→spec RƠI item gated cả 2 lane · F4 future-claim S108. **Lesson:** lệnh verify trong spec = CODE chạy thử trước (2/4 sai thật) · bệnh encoding S125 ở CMDLET không ở shell (`Select-String -Path` đúng, `Get-Content` bệnh) · fold = disposition TỪNG DÒNG (S119). Full: `runs/2026-07-16-S127-adap-dot-16-07/sub-reviewer-3-verdict.md`. +- **S127 fable-real #1 gate đầu-vào adap 16-07 [Fable ~62K tok 0-garble; em-main VERIFY 3/3 + APPEND] — GO-ADAP, BÁC claim hub "bản 2 duy nhất":** rag.json:26 override ACTIVE ⇒ bản 5 việc THẬT + bản 3 ≥2 hằng-số sống-bằng-nhãn. **Lesson:** hedge broadcast phải test bằng MỞ config THẬT · "already-aligned" tinh-thần ≠ luật · SE GIỮ counter đúng (điều-kiện gỡ không áp: 3 tick/2 ngày). Full + AC 8/8: `runs/2026-07-16-S127-adap-dot-16-07/sub-reviewer-1-verdict.md`. + +- **S133 (07-17) pre-commit review pe-budget-freeze [wf_f9c0b939-181, return sạch]:** VERDICT **PASS_WITH_FIXES** — 0 MUST / 2 SHOULD (CÙNG root #81 indirect-writer) / 2 NIT. ⭐ Catch giá trị nhất: literal-grep 4-site (`= PurchaseEvaluationPhase.DaDuyet`) PASS hết, nhưng grep `.Phase = ` lòi **2 đường gián tiếp bypass helper snapshot**: `WorkflowService:308` admin-override catch-all (`= targetPhase`) + `DbInitializer:1323` seeder (`= current`; fresh-DB migrate-trước-seed → backfill Mig 67 no-op trên bảng rỗng). **Bài: RULE "mọi nhánh set X" phải grep CẢ assignment-qua-BIẾN, không chỉ token enum — #81 mở rộng lên lớp indirect-assignment.** 10/10 mục PASS: 3-bản predicate khớp từng điều kiện (kể cả chi tiết Suppliers/Quotes = BaseEntity → SQL đúng khi KHÔNG có IsDeleted trên s/q) · 18-field frozen mapping chỉ rò đúng 2 field cố-ý (pairRec.Id + CurrentProposalTotal live) · R2-hold ✓ · guards đúng vị trí + T5/T6 ✓ · EDGE-5 snapshot-dormant + T9 overwrite ✓ · FE fallback `?? bs.*` nằm TRONG nhánh editable đã đóng ✓ · Mig: UNIQUE(ProjectId,WorkItemId) chống row-multiplication LEFT JOIN backfill ✓. Lead áp 2 SHOULD ngay trong phiên: site-5 helper-call + test `AdminOverride_DirectToDaDuyet_SetsBudgetSnapshot` + seeder demo snapshot + comment gate → suite 520/0. Tag `[s133, review-budget-freeze, indirect-assignment-grep, 81-class]` +- **S123 governance 4-change review (backtick-guard + H24-3 + retire dạng-3 + mark) — PWF (3 must/1 MAJOR/3m):** → [topic](project_s123_governance_4change_review.md). 🔴 **#53 garble tại TAO; đĩa KHÔNG cứu vì chưa ghi diary ⇒ ghi diary TRƯỚC return.** Vá-1-lớp⇒grep MỌI matcher cùng-lớp TRONG diff · đổi-format-cho-trượt-mẫu = Goodhart rời-tập-đo. diff --git a/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-cicd-monitor-0.md b/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-cicd-monitor-0.md new file mode 100644 index 0000000..524589d --- /dev/null +++ b/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-cicd-monitor-0.md @@ -0,0 +1,79 @@ +# sub-cicd-monitor-0 — S133 pe-budget-freeze deploy verify (commit d4fbced) + +> Read-only CI/CD verifier. Evidence dồn dần (anti-#53). VERDICT ở cuối khi đủ 5 mục. +> Target commit: `d4fbced02f6a24df7177c33adc21b8ca89140a0c` +> Subject: `[CLAUDE] PurchaseEvaluation: freeze ngân sách phiếu DaDuyet — Mig 67 snapshot 11 cột + display-gate budgetFrozen + 2 terminal-guard (UAT anh Kiệt 07-16)` + +## Stage 1 — Push + path-filter (DONE) +- `git rev-parse origin/main` = `d4fbced02f6a24df7177c33adc21b8ca89140a0c` → d4fbced IS on origin/main. PASS. +- `git branch -r --contains d4fbced` → `origin/main`. PASS. +- Local HEAD = `bf79842 wal: flush 20260717T1116` (1 commit ahead, unpushed docs/WAL — NOT the target, irrelevant). +- Files changed `9e874ca..d4fbced` (28 files): FULL-STACK + - BE: PeBudgetAccumulator.cs, PeWorkItemBudgetFeatures.cs, PurchaseEvaluationFeatures.cs, PurchaseEvaluationDtos.cs, Domain/PurchaseEvaluation.cs, PurchaseEvaluationConfiguration.cs, DbInitializer.cs, PurchaseEvaluationWorkflowService.cs + - Mig 67: `20260717032812_AddPeApprovedBudgetSnapshot.cs` + .Designer.cs + ApplicationDbContextModelSnapshot.cs + - FE: fe-admin/{PeDetailTabs.tsx, types/purchaseEvaluation.ts}, fe-user/{PeDetailTabs.tsx, types/purchaseEvaluation.ts} → 4 real fe-src files → bundle MUST rotate ×2 + - Tests: PeBudgetFreezeTests.cs + - Governance/memory/run-trace: .claude/WAL.md, agent-memory×4, run.md, spec + 4 sub-*.md +- Non-docs code present → CI MUST trigger (NOT docs-skip). CONFIRMED triggered (run #398 exists). + +## Stage 1b — Migration file review (Mig 67, DONE) +- `20260717032812_AddPeApprovedBudgetSnapshot.cs`: 11 AddColumn on PurchaseEvaluations, 0 CreateTable: + 1. ApprovedBudgetProInitialAmount decimal(18,2) null + 2. ApprovedBudgetProAdjustmentAmount decimal(18,2) null + 3. ApprovedBudgetProNote nvarchar(1000) null + 4. ApprovedBudgetCcmInitialAmount decimal(18,2) null + 5. ApprovedBudgetCcmAdjustmentAmount decimal(18,2) null + 6. ApprovedBudgetCcmNote nvarchar(1000) null + 7. ApprovedBudgetPrevSubmittedTotal decimal(18,2) null + 8. ApprovedBudgetPrevSubmittedCount int null + 9. ApprovedBudgetPrevSelectedTotal decimal(18,2) null + 10. ApprovedBudgetPrevSelectedCount int null + 11. ApprovedBudgetSnapshotAt datetime2 null +- Backfill `Sql()`: `UPDATE ... SET ... SnapshotAt=SYSUTCDATETIME() WHERE pe.Phase=7 AND pe.ApprovedBudgetSnapshotAt IS NULL AND pe.IsDeleted=0`. Idempotent. → post-apply ALL Phase=7 rows have SnapshotAt NOT NULL → expected chua=0. +- NO CreateTable → sys.tables invariant 89 should hold. + +## Stage 2 — Gitea CI poll (IN PROGRESS) +- API: `/api/v1/repos/vietreport-admin/solution-erp/actions/tasks?limit=8` (anon, GITEA_TOKEN empty — public repo OK). NOT /runs (404, gotcha #46). +- Run #398 | head_sha d4fbced02f | status=running | conclusion=None (prev #397 72f68d1 success — matches SPEC baseline). +- Polling until terminal status... (conclusion stays None even on success per memory — trust `status`). + +### Stage 2 RESULT — CI PASS +- Run #398 (d4fbced02f) → `status=success` @ updated_at `2026-07-17T11:20:02+07:00` (conclusion=None = Gitea tasks-API norm, trust status). Prev #397 success — baseline OK. +- Poll note: python subprocess `capture_output=True` (text) crashed cp1252 on Vietnamese titles ×14 iters; re-fetch with `text=False`(bytes)+`json.loads(bytes)` → clean. Elapsed ~6min covered the run. +- Test gate (web-UI log `runs/398/jobs/0/logs`, 17936 bytes, NO /api/v1): + - `Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45` — SolutionErp.Domain.Tests + - `Passed! - Failed: 0, Passed: 475, Skipped: 0, Total: 475` — SolutionErp.Infrastructure.Tests + - 45 + 475 = **520**, 0 fail/skip → matches SPEC baseline. **PASS.** + +## Item 2 — Mig prod (ssh vietreport-vps sqlcmd, DONE) +- `__EFMigrationsHistory` TOP3: `20260717032812_AddPeApprovedBudgetSnapshot` (top) · `20260714035636_AddPeApprovedPriceRange` · `20260712142652_Backfill...` → top == SPEC target. **PASS.** +- sys.columns ApprovedBudget* on PurchaseEvaluations = **11** (all 11 names present, exact match to Mig 67 file). **PASS.** +- Backfill `WHERE Phase=7 AND IsDeleted=0`: total=**18**, chua(SnapshotAt IS NULL)=**0** → all 18 DaDuyet phiếu snapshotted. **PASS.** +- sys.tables is_ms_shipped=0 = **89** (no new table — AddColumn-only). **PASS.** + +## Item 3 — Bundle FE rotate + byte-verify #77 (DONE) +- ADMIN index.html: js `/assets/index-3NCdyODe.js` css `/assets/index-B--dUHcm.css` (was S129 js `yCkX-2Bp` css `CXD7q9xH`) → JS+CSS ROTATED. +- EOFFICE index.html: js `/assets/index-CKsoiNCI.js` css `/assets/index-BuntB63r.css` (was S129 js `DKSD4p9k` css `CjwZwYJo`) → JS+CSS ROTATED. +- Real-size + LM: admin.js 1,657,025 B, LM `Fri 17 Jul 2026 04:18:42 GMT` (11:18:42 +07) · eoffice.js 1,563,373 B, LM `04:19:36 GMT` (11:19:36 +07) — both application/javascript, LM in CI window (run done 11:20:02 +07). NOT SPA-trap. +- Byte-verify markers (python bytes-search): admin.js `budgetFrozen`=1, `Ngân sách chốt tại thời điểm duyệt`=1 · eoffice.js both=1. +- CONTROL old admin `yCkX-2Bp` → 900 B text/html (SPA-fallback trap), markers=0 → confirms markers are NEW not fallback. **PASS.** + +## Item 4 — Smoke (DONE) +- api/health/live=200 · api/health/ready=200 (body "Healthy") · admin=200 · eoffice=200 · GET /api/purchase-evaluations no-token=**401** (secured). **PASS.** + +## Item 5 — Traps handled +- S116: polled CI to `success` BEFORE bundle snapshot ✓ · #69: rotate benign (4 real fe-src changed → rotate expected) ✓ · #77: curl byte-level + old-hash control (900b SPA-trap) not browser ✓. + +--- + +## VERDICT | GO (5/5 PASS) +| # | Item | Verdict | Key evidence | +|---|------|---------|--------------| +| 1 | CI run #398 + gate 520 | PASS | status=success; Domain 45/45 + Infra 475/475, 0 fail | +| 2 | Mig 67 prod applied | PASS | history top=AddPeApprovedBudgetSnapshot; 11 cols; backfill 18/18 chua=0; 89 tables | +| 3 | Bundle rotate ×2 + byte-verify | PASS | admin js 3NCdyODe / eoffice js CKsoiNCI; markers present; old-control 0; real-size+LM-in-window | +| 4 | Smoke 5-probe | PASS | live/ready 200, admin/eoffice 200, PE no-token 401 | +| 5 | Traps (S116/#69/#77) | PASS | poll-then-snapshot; benign rotate; byte-level+control | + +Run URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/398 +Token cost: ~90K. No production file modified (only this run-trace sub-file). diff --git a/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-test-specialist-0.md b/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-test-specialist-0.md index 287a9f2..da899f8 100644 --- a/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-test-specialist-0.md +++ b/.claude/workflows/runs/2026-07-17-S133-pe-budget-freeze-daduyet/sub-test-specialist-0.md @@ -60,3 +60,60 @@ Failed! - Failed: 1, Passed: 0, Skipped: 0, Total: 1, Duration: **Verdict:** T0 RED PASS-as-designed. KHÔNG PREMISE-FAIL (không GREEN bất ngờ). KHÔNG chạm production. Sẽ GREEN sau khi implementer thêm snapshot ngân sách tại 4 site DaDuyet + display-gate đọc cột snapshot. **Baseline:** 509 → 510 test (test này RED tới khi fix land — test-before đúng quy trình bug-fix docs/rules.md §7). + +--- + +# STAGE C — INV-C T1-T9 (BE ĐÃ LAND, T0 ĐÃ GREEN → phủ nhánh/guard/edge còn lại) + +Role: test-specialist. KHÔNG đụng src/ · KHÔNG sửa T0/test cũ. Thêm T1-T9 vào cùng file `PeBudgetFreezeTests.cs`. + +## Anchors verified (đọc code truth — BE post-fix) +- Domain `PurchaseEvaluation.cs:122-132` — 11 cột snapshot: ApprovedBudgetProInitialAmount/ProAdjustmentAmount/ProNote · CcmInitialAmount/CcmAdjustmentAmount/CcmNote · PrevSubmittedTotal/Count · PrevSelectedTotal/Count · SnapshotAt. +- Service helper `ApplyBudgetSnapshotOnFinalizeAsync` def :994; gọi 4 site: :861 (level-finalize AllowApproverFinalize) · :900 (CCM-threshold delegation) · :933 (all-steps-done) · :1108 (V1 legacy — CHỈ snapshot, KHÔNG ApplyApprovedPrice). Helper: WorkItemId null → 10 cột null + SnapshotAt set; pair thiếu → 6 pair cols null; 4 lũy kế qua PeBudgetAccumulator; LUÔN overwrite + LUÔN SnapshotAt=dateTime.UtcNow. +- Helper NAMING: pair.InitialAmount/AdjustmentAmount = CCM; pair.ProInitialAmount/ProAdjustmentAmount = PRO. +- Display-gate `PurchaseEvaluationFeatures.cs:928` `frozen = Phase==DaDuyet && ApprovedBudgetSnapshotAt!=null`. Frozen branch :929-954 → CanEditPro/Ccm HARDCODE false,false (KỂ CẢ Admin) + BudgetFrozen=true + lũy kế từ snapshot + CurrentProposalTotal VẪN live-own-quotes. Live branch :956-984 → accumulator + canEditPro/Ccm theo role + BudgetFrozen=false. +- Guard 7a `SetPeCcmBudgetPeriodCommandHandler` PeWorkItemBudgetFeatures.cs:235 — `Phase is DaDuyet or TuChoi` → Conflict TRƯỚC role-gate (chặn CẢ Admin lẫn CCM). +- Guard 7b `AdjustPurchaseEvaluationBudgetCommandHandler` PurchaseEvaluationFeatures.cs:365 — cùng message, TRƯỚC isAdmin block. +- Accumulator: peers cùng (ProjectId,WorkItemId), Id!=this, CreatedAt