wal: flush 20260717T1446
This commit is contained in:
@ -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]`
|
||||
|
||||
@ -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 = <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.
|
||||
|
||||
@ -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).
|
||||
@ -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 cũ CŨ 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user