wal: flush 20260712T1435

This commit is contained in:
pqhuy1987
2026-07-12 14:35:10 +07:00
parent 06e846ad73
commit 264ca2e8fe
4 changed files with 58 additions and 13 deletions

View File

@ -1,19 +1,18 @@
# WAL — auto-generated, không sửa tay
updated: 2026-07-12 | session: S112 | branch: main
goal: 2 mạch song song — (A) Supplier Excel-import BUILD + close-spec · (B) PE sign-off save-advance INVESTIGATE
goal: 2 mạch song song — (A) Supplier Excel-import BUILDclose→deploy · (B) PE sign-off change review→implement→DEPLOY (anh-directed "deploy luôn")
chain A (Supplier import):
[x] investigate wf_e2f23a84-933 + anh chốt 5 decision
[x] BE DONE (a4cde85): entity+Mig63(3-file)+SupplierExcelImportService+2 endpoint preview/confirm+DTO+DI; `dotnet build` EXIT-0 ✅; case-fix verified (OrdinalIgnoreCase preview+confirm) + fill-nulls + all-or-nothing + Type→NCC OK
[!] test-specialist (BG aac55f3d) test-before case-collation+fill-nulls+all-or-nothing+parser
[ ] FE fe-admin upload/preview/confirm (admin-only)
[ ] /fable-clone review đóng-spec (Opus MAX) → adjust (⚠️ #1 = ExpectedHeaderTokens best-guess → 30 real token đã extract từ Excel, bake vào; header hiện reject file thật) → ĐÓNG SPEC + commit + cicd + harvest
[x] BE DONE build EXIT-0 ✅ + case-fix (OrdinalIgnoreCase) verified
[x] test-specialist DONE (aac55f3d): SupplierExcelImportServiceTests 10 test → dotnet test 450 PASS (440→450), 0 prod-bug; case-collation test có RĂNG (SQLite BINARY → dedup ở service không dựa DB)
[!] FE fe-admin (BG) Import-Excel button→dialog upload→preview-table→confirm
[ ] /fable-clone review đóng-spec → adjust (⚠️ bake ExpectedHeaderTokens 30 real-token đã-extract; Case-9 auto-flip LayoutValid=true, 0-test-edit) → ĐÓNG SPEC + commit + cicd
chain B (PE sign-off):
[x] ensemble wf_fd8f2bfe-9f6 PASS_WITH_CONCERNS 4/4 — root=ApplyDrafterBypassOnSubmitAsync (S60 feature) auto-ký-hộ ô creator+comment-canned; fix=gỡ/gate bypass 1-chỗ, 0-đổi-ApproveV2Async, FE~0, giữ 1-nút; reject=Assignee-mode-đã-gần-đủ; +EDGE-5 mở-lại-DaDuyet MAJOR pre-existing reachable
[x] anh Kiệt chốt 4/5/6: (4)1-nút ✓ · (5)giữ+cho-sửa-cập-nhật+LƯU-HISTORY ⚠️[cần cơ-chế history opinion — hiện UPSERT-overwrite mất bản cũ → thêm version-stamp/history-log] · (6)chỉ-phiếu-mới ✓
[!] CÒN CHỜ anh Kiệt: (1)A1/A2 gỡ-bypass [= còn muốn skip-NV S60 không] · (2)guard-B2 self-finalize · (3)EDGE-5-fix mở-lại-DaDuyet → KHÔNG code PE tới khi chốt đủ 3
chain B (PE sign-off change):
[x] investigate wf_fd8f2bfe-9f6 + anh Kiệt chốt 6 decision: (1)A1-bypass-subordinate-only+creator-ký-tay (2)no-hard-guard-single-person (3)EDGE-5-hard-lock-DaDuyet (4)1-nút (5)opinion-history (6)phiếu-mới-only
[!] /fable-clone review close-review (BG wf) 3-lane Opus — validate cách-làm + điều-chỉnh + history-mechanism a/b/c + DEPLOY GO/NO-GO
[ ] fan-out Opus implement (BE A1+EDGE-5+history + FE mirror + test) → reviewer pre-commit → commit+push → cicd DEPLOY (gates PHẢI pass — KHÔNG deploy nếu review NO-GO/test fail)
next: chờ test-specialist(aac55f3d) land → FE Supplier → close-review; PE chờ anh chốt 6 decision. KHÔNG deploy/code-PE tới khi review+anh-chốt
verify: Supplier build EXIT-0 (DONE) + test PASS + header-token-baked ; PE run-folder spec+4sub+synthesis non-zero (DONE)
next: chờ FE-Supplier(BG) + PE-close-review(BG wf) land → synthesize; PE: review GO → fan-out implement → deploy. Supplier: FE → close-review → deploy
verify: Supplier build+450test PASS(DONE)+header-baked ; PE review GO-GATE + implement build+test PASS + cicd prod-verify TRƯỚC khi coi deploy xong
side: harness_floor 30K→100K + measured 21K→55K (S112)

View File

@ -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: 440 tests = 440 PASS (45 Domain + 395 Infra) as of S97
## 📊 Baseline: 450 tests = 450 PASS (45 Domain + 405 Infra) as of D3
- 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.
@ -56,6 +56,7 @@ Test theo CODE (single source truth), document mismatch header comment + report.
## 📅 Recent activity (one-line FIFO — verbose in [archive/baseline-history.md](archive/baseline-history.md))
- **D3 (2026-07-12) Supplier Excel-import BE (Phase B) TEST-BEFORE-MERGE (CRITICAL-ALGO + case-collation bug-class) — 440→450 PASS (+10 Infra), no-red, NO prod bug:** new `Services/SupplierExcelImportServiceTests.cs` (10 [Fact]). **Case-collation (THE bug):** ConfirmAsync lowercase `truonggiang` vs DB `TRUONGGIANG` → Inserted=0/Updated=1/count=1 (dedup ở SERVICE `OrdinalIgnoreCase`, KHÔNG dựa DB — SQLite fixture BINARY collation KHÔNG bắt CI-dup, prod SQL Server CI thì có → nếu Ordinal = 500 batch); Preview classify Update. **Fill-nulls SAFE** (non-null giữ / null điền). **All-or-nothing** (1 hard-error→Committed=false + DB unchanged). MapType unknown→NhaCungCap+warning · emoji-strip status → DangHoatDong · valid-layout absolute-index parse (LinkGuq RAW backslash) · no-column-drift (col9 empty→col12 vẫn TaxCode) · #REF! literal→null. **Pattern (reuse):** header xlsx dựng từ `ExpectedHeaderTokens` qua REFLECTION (`GetField(NonPublic|Static)`) → valid-layout test tự đồng bộ khi tokens sửa; ClosedXML in-mem `XLWorkbook.AddWorksheet`+`ws.Cell(r,c).Value=string` GIỮ TEXT (0.105 no numeric-coercion → leading-zero safe). **Spec-drift FLAGGED (không phải bug):** `ExpectedHeaderTokens` = BEST-GUESS ≠ 30 real row-4 token → Case 9 dynamic `LayoutValid==(NormalizeJoin(real)==NormalizeJoin(reflected))` robust 2-chiều, hiện LayoutValid=false; close-review sẽ sửa tokens → test tự flip true.
- **S97 (2026-07-01) PE EndsBeforeCeo CONFIG→RUNTIME (bug anh Kiệt FDC, spec-change test) — 440 PASS no-red, NET +0 [Fact] (extend in-place):** em-main BE thêm `PurchaseEvaluation.EndedByLevelFinalize` (Mig 60) set true DUY NHẤT nhánh level-finalize `ApproveV2Async`. ListApproved (DaDuyet-only) đọc THẲNG field (`CreateContractFromEvaluationFeatures.cs:196`); List/Inbox ternary `Phase==DaDuyet ? field : subquery`. **Spec-change RED handled:** `PeFinalizeProjectionTests` seed-helper +param `endedByLevelFinalize` → case cũ `peFin` set true; **REPRO case mới `peFinButWentCeo`**: CÙNG wfFin config-có-finalize NHƯNG field=FALSE → EndsBeforeCeo=FALSE (bug: config-true nhưng lên CEO thật). FinalizeStep/LevelName VẪN từ config-subquery (nhãn cấp, không phải cờ). **EF-translate OK** (ListApproved handler no-throw). Service `PeApproverFinalizeTests` +3 assert: #1 finalize→true / #2 advance-CEO→false / #6 opt-out→false (khớp projection repro). No prod bug.
- **S92 (2026-06-29) +3 admin-only-modules revoke (test-before-merge SECURITY) — 431→434 PASS, no red:** anh chốt 5 nhóm menu (NHÂN SỰ/VĂN PHÒNG SỐ/CÁ NHÂN/HỢP ĐỒNG/DANH MỤC) CHỈ Admin thấy. Em-main mở rộng `RevokeTemporarilyHiddenModulesAsync` predicate +Contracts/Ct_*/Master/Suppliers/Projects/Departments/Catalog* (cộng dồn S58 Hrm*/Off*/Personal) + TẮT 2 re-grant S65/S69 + narrow `InReviewScope→Pe_*`. `AdminOnlyModulesRevokeTests.cs` (3): NonAdmin-S92Modules-4cờ-false LOAD-BEARING + Admin-untouched + Pe-module-NOT-revoked invariant (root `PurchaseEvaluations` + `Pe_DuyetNcc` không match predicate → giữ user). Reflection harness mirror Office/Hrm seed test. **Gotcha:** OfficeModulePermissionSeedTests + HrmProfilePermissionSeedTests VẪN PASS dù prod đã TẮT 2 call grant — vì test invoke method-CÔ-LẬP qua reflection (private static giữ cho reversibility), KHÔNG chạy SeedAsync chain; thêm 1 dòng header note mỗi file. (ChangePassword S91 10-test ĐÃ merge → trong baseline 431.)
- **S87** +7 PE Mig 59 CCM-budget-period setter authz (`PeCcmBudgetPeriodSetterAuthzTests.cs`, role-gate Admin|CostControl, null=clear gotcha #73). → 402.

View File

@ -0,0 +1,20 @@
# RUN — PE sign-off close-review (review cách-làm + điều chỉnh trước implement+deploy)
- **folder:** `2026-07-12-S112-pe-signoff-close-review` · session S112 · lead Opus 4.8 MAX
- **command:** `/fable-clone review kỹ lại cách làm và điều chỉnh` (anh-directed) → sau đó fan-out Opus implement + deploy
- **mode:** HMW RUN-TRACE · engine fable-clone review-ensemble (3 reviewer lanes) · model=opus
- **base:** investigation `wf_fd8f2bfe-9f6` + 6 decision anh Kiệt chốt
- **spec:** `spec-pe-signoff-implement-12-07-2026.md`
## taskList
| Stage | Role | Lane | Lens |
|---|---|---|---|
| Review | reviewer | L1 | State-machine (A1 pointer · EDGE-5 lock · no-stuck · 5-state) |
| Review | reviewer | L2 | Security/governance (EDGE-5 kín · câu-2 no-CEO-skip · finalize) |
| Review | reviewer | L3 | Schema/history (câu-5 cơ-chế a/b/c · no-migrate · 1-nút+history) |
## deliverable
Validated plan + điều-chỉnh + file:line + test-list + DEPLOY-risk + GO/NO-GO → em synthesize → fan-out implement → reviewer → deploy.
## synthesis
_(pending)_

View File

@ -0,0 +1,25 @@
# SPEC — PE sign-off IMPLEMENT (6 decision chốt) + close-review — 12-07-2026
> `/fable-clone review` (H21 LỆNH-B) anh-directed S112: "review kỹ lại cách làm + điều chỉnh" TRƯỚC khi fan-out implement + deploy. Opus 4.8 MAX. Base = investigation `wf_fd8f2bfe-9f6` (PASS_WITH_CONCERNS).
## ① Đề-bài — 6 decision anh Kiệt ĐÃ CHỐT (lock)
1. **A1** — sửa `ApplyDrafterBypassOnSubmitAsync` (SVC:571-681): bypass CHỈ NV *cấp dưới* creator (order < drafterSlots.Min); creator TAY ô cấp mình (comment thật, SignedByUserId=creator). Giữ skip-NV-dưới của S60. Creator Cấp-1 0 subordinate pointer đứng (0,1) creator tự .
2. **Không guard cứng self-approve** "cấp chỉ 1 người tạo duyệt luôn được". Creator duyệt cấp single-person của mình hợp lệ (KHÔNG thêm Forbidden guard B2).
3. **Fix EDGE-5 (hard-lock)** DaDuyet (+ TuChoi) = terminal khóa cứng: guard `fromPhase∈{DaDuyet,TuChoi}→throw` reject-branch (SVC:92) + `EnsureCanRejectV2Async` early-return `:321` + handler `FEAT:510-539` + controller. "Đã duyệt rồi cứng không trả lại hay thao tác được."
4. **1 nút** (save=advance) giữ nguyên, không tách.
5. **Opinion history** giữ ô ý-kiến + cho sửa/cập-nhật + **LƯU HISTORY bản cũ** (hiện UPSERT overwrite = mất bản ). Cần cơ-chế mới: version-stamp col / bảng `PurchaseEvaluationLevelOpinionHistory` / log vào `PurchaseEvaluationChangelog`.
6. **Chỉ phiếu MỚI** không migrate phiếu (anh Kiệt: "phiếu user đã chỉnh rồi").
## ② Cách implement (từ investigation, verify lại)
- **B1 (A1):** `SVC:571-681` đổi `k`/`bypassedOrders` chỉ bypass `order < drafterSlots.Min`; set pointer = creator min-own-order (thay advance-qua `:647-680`). Update test `PeSubmitGuardAndBypassTests.cs` (spec-change §7).
- **B2 (câu 2):** KHÔNG thêm hard guard. review xác-nhận: interaction với `AllowApproverFinalize`/`SkipToFinal` (SVC:805/:867) creator single-person-level bật finalize tự lên DaDuyet bỏ CEO. anh Kiệt "tạo duyệt luôn được" = chấp-nhận? hay CHỈ áp cho cấp không-phải-terminal? (review chốt: no-guard tạo CEO-skip NGOÀI Ý không).
- **B3 (EDGE-5):** guard terminal-lock. Xác-nhận ĐỦ kín: 4 return-mode + controller `:130-143` + handler fromPhase.
- **B5 (history):** review CHỌN cơ-chế (a) bảng history append-only, (b) version/round col trên LevelOpinion, (c) log Changelog + Mig tối-thiểu. 1-nút mỗi lần lại log bản trước.
- **FE:** happy-path ~0 (banner+nút Duyệt đúng khi pointer đứng creator); F1 cosmetic label. Mirror 2-app byte-identical (903 dòng).
- **Test:** bypass-test update + EDGE-5-lock test + history test.
## ③ Checklist review (mỗi lane 1 lăng-kính, đối kháng)
- [ ] **State-machine:** A1 pointer đúng (subordinate-only, creator tay, 0 kẹt phiếu, 5-state nguyên); reject-return sau A1 không vỡ.
- [ ] **Security/governance:** EDGE-5 fix ĐỦ KÍN mọi đường tới terminal (4 mode + controller + handler); câu-2 no-guard KHÔNG tạo CEO-skip ngoài ý (finalize-flag interaction) nếu cảnh-báo owner.
- [ ] **Schema/history:** chọn cơ-chế history (a/b/c) tối-thiểu-schema + reversible; 1-nút+history log đúng mỗi lần lại; câu-6 no-migrate an-toàn (phiếu canned-comment).
- [ ] Output: bảng file:line cần đổi + test cần update + **risk DEPLOY** (đây prod ERP live UAT anh Kiệt) + GO/NO-GO cho fan-out.