wal: flush 20260717T1446

This commit is contained in:
pqhuy1987
2026-07-17 14:46:51 +07:00
parent 1e799eed3d
commit 169b0dc42f
4 changed files with 164 additions and 0 deletions

View File

@ -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 -- <file> | 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]`

View File

@ -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 84=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 = <biến>` 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.

View File

@ -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).

View File

@ -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<this. TestApplicationDbContext KHÔNG wire audit interceptor set CreatedAt thủ công (peers earlier, current later).
- V1 legacy: PurchaseEvaluationWorkflowDefinition + Steps + Approvers(Kind=User AssignmentValue=userId). Match qua userManager.FindByIdAsync cần user THẬT (fix.CreateUserAsync).
## T1-T9 danh sách (tên test = scenario_expected)
- T1 `LevelFinalize_SnapshotsAll11Columns_FromPairAndAccumulator` (:861) 6 pair cột + notes + 2 peer (PrevSubmitted 150tr/2, PrevSelected 90tr/1) + SnapshotAt.
- T2 `CcmThresholdFinalize_SetsBudgetSnapshot` (:900) CCM delegation below-threshold snapshot pair cols + SnapshotAt.
- T3 `AllStepsDoneFinalize_SetsBudgetSnapshot` (:933) 1 Bước 1 Cấp no-finalize-flag, approve last slot snapshot + DaDuyet.
- T4 `V1LegacyFinalize_SetsBudgetSnapshot_WithoutApprovedPrice` (:1108) def+step+user-approver snapshot set + ApprovedPriceAmount==null.
- T5 `SetCcmBudgetPeriodGuard_BlocksDaDuyet_ForCcmAndAdmin_AllowsChoDuyet`.
- T6 `AdjustBudgetGuard_BlocksDaDuyetAndTuChoi_ForAdmin`.
- T7 `BudgetSummary_LiveVsFrozen_FlagsAndEditability`.
- T8 `Finalize_NullSafe_NoWorkItemAndNoPairRecord`.
- T9 `ReFinalize_AlwaysOverwritesStaleSnapshot_RefreshesSnapshotAt`.
## Kết quả chạy — ✅ ALL GREEN (T1-T9 phủ đủ, 0 RED phase vì BE đã land)
**Filtered:** `dotnet test SolutionErp.slnx --filter "FullyQualifiedName~PeBudgetFreeze" --nologo -p:BuildInParallel=false -maxcpucount:1`
`Passed! - Failed: 0, Passed: 10, Skipped: 0, Total: 10` (T0 + T1-T9).
**FULL:** `dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1`
Domain `Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45`
Infra `Passed! - Failed: 0, Passed: 474, Skipped: 0, Total: 474`
**Tổng 519 PASS / 0 fail / 0 skip** = baseline 510 (509 + T0) + 9 (T1-T9).
## Bảng T1-T9 (verdict)
| Test | Nhánh/guard/edge | Verdict |
|---|---|---|
| T1 `LevelFinalize_SnapshotsAll11Columns_FromPairAndAccumulator` | :861 level-finalize 11 cột | PASS |
| T2 `CcmThresholdFinalize_SetsBudgetSnapshot` | :900 CCM-delegation | PASS |
| T3 `AllStepsDoneFinalize_SetsBudgetSnapshot` | :933 all-steps | PASS |
| T4 `V1LegacyFinalize_SetsBudgetSnapshot_WithoutApprovedPrice` | :1108 V1 + giá null | PASS |
| T5 `SetCcmBudgetPeriodGuard_BlocksDaDuyet_ForCcmAndAdmin_AllowsChoDuyet` | guard 7a | PASS |
| T6 `AdjustBudgetGuard_BlocksDaDuyetAndTuChoi_ForAdmin` | guard 7b | PASS |
| T7 `BudgetSummary_LiveVsFrozen_FlagsAndEditability` | display live/frozen | PASS |
| T8 `Finalize_NullSafe_NoWorkItemAndNoPairRecord` | null-safe (a)+(b) | PASS |
| T9 `ReFinalize_AlwaysOverwritesStaleSnapshot_RefreshesSnapshotAt` | overwrite semantics | PASS |
## Surprise / bẫy đã xử
- **UNIQUE(ApprovalWorkflows.Code, Version)**: T8 gọi `SeedAndFinalizeAsync` 2 lần/1 db helper `SeedFinalizeWorkflowAsync` Code cố định "QT-BF-V2" v1 SQLite Error 19 (RED lần 1). Fix: thêm param optional `code="QT-BF-V2"` (T0 call-site 2-arg GIỮ NGUYÊN, hành-vi T0 bất biến) + `SeedAndFinalizeAsync` truyền `$"QT-BF-V2-{suffix}"`. Không đụng T0-logic.
- KHÔNG chạm src/ production. KHÔNG sửa T0. Test 0 regression (509 baseline vẫn xanh). KHÔNG REGRESSION-FOUND.
**Verdict:** INV-C COMPLETE 9 test mới GREEN, phủ 4 nhánh snapshot + 2 guard + 2 edge + display live/frozen. Tổng 519/519.