Files
solution-erp/docs/changelog/sessions/2026-06-25-S88-pe-stability-audit-d1-d2.md

9.2 KiB
Raw Blame History

S88 (2026-06-25) — PE stability audit → fix patchwork (D1) + complete multi-winner (D2)

Anh: /session-start/sleep-recovery-memory-l2 all → "Plan review test, unittest... review invest lại 1 lần nữa xem có vấn đề gì đang làm chấp vá thì xử lý, tính năng đã ổn định rồi nhé. workflow chạy cho nhah ultra-on, mỗi bước đều phải có invest, review testing cẩn thận" → (sau audit + AskUserQuestion) "viết unittest... review/invest kỹ và workflow hoàn chỉnh các thứ luôn đi nhé, xong thì session-end".

HMW-mode ON. Frozen CEO-approved PE (Duyệt NCC) spec, testers signed off — hardening audit, NOT feature change (but anh chốt completing the multi-winner feature).


Sleep-recovery (early) — 1 gist, NOT NO-OP

/sleep-recovery-memory-l2 all: 18/19 L2 verbatim SKIP (14× 2026-05-qN.md/runs.md already in aggregate 2026-05.gist.md gen:1 — verified by reading source-decl; 4× 2026-06.md double-distill guard gen 1-2; 5 subs empty). 1 distilled: test-specialist/activity-s51-s52.md (gen-0 orphan, no gist) → activity-s51-s52.gist.md (distill-gen:1), 4 records → 3 clusters (C-A merges 2 gotcha#57 episodes). harvest-curator Phase-1 propose → reviewer Fidelity-gate FAIL v1 (merge mis-attributed Mig 45 to Master half; canonical = Mig 47) → re-distill split per-episode → PASS. commit e939fab. last_sleep_at → 2026-06-25.

Audit — Workflow wf_c15da996-be5 (6 area × invest→review pipeline + full-suite test, 13 agent, ~7min)

Core verified SOLID (both reviewers read real code): winnerQuoteTotal 3 canonical sites · SelectWinner multi-toggle/clear · urgent fail-closed asymmetric authz · drafter-exclusion notify · both finalize mechanisms · finalize tests. Test baseline GREEN 402/402.

Findings split safe-vs-behavior-affecting → AskUserQuestion ×4 → anh chốt max scope (fix-all-safe + complete-joint-winner + activate-CEO-notify + create-contract = 1 HĐ/winner).

D1 (73cce1f Run #347 PASS, test 402→413) — the fixes

Fix Detail
Block B financials currentProposalTotal (:846) + prevSelected rollup (:832) re-key SelectedSupplierId→IsWinner — reported 0 / excluded peers for ≥2 joint winners; now match winnerQuoteTotal. Behavior-affecting (approved).
CEO-notify reactivated PurchaseEvaluationUrgentFeatures.cs — notify block ran AFTER the only SaveChanges → Director notification never persisted. +SaveChanges after NotifyManyAsync (in try, best-effort).
HoSoLink preserve UpdatePeDraftHandler HoSoLink absolute-set → null-safe + clear-via-empty (null=preserve, ""=clear). Header forms omit=preserve (auto-fix); HoSoLinkRow sends hoSoLink.trim() to clear. Bug-class S42/#73.
#70 guard PRO budget row3/row8 saving={adjustMut.isPending}|| peFetching.
Relocate SetPeCcmBudgetPeriodCommand PeSuggestedPriceFeatures → PeWorkItemBudgetFeatures (byte-identical).
Comments WinnerQuoteTotal DTO + AddItemDialog + type comments.

Tests +11 (PeHoSoLinkTests spec-change update + PeWorkItemBudgetTests joint-winner + PeUrgentNotifyDirectorTests 6× real-notify-fixture persistence).

D2 (1aa3bdb Run success, test 413→419) — complete multi-winner outward

  • create-contract 1→N: CreateContractFromEvaluationCommandList<Guid>, one draft HĐ per IsWinner supplier (was 409 dead-end for ≥2). Key design: ContractCodeGenerator.GenerateAsync runs its OWN Serializable transaction + SaveChanges + commit per call (self-commits the sequence) → so gen ALL N codes first (contracts built in a LOCAL list, NOT db.Contracts.Add) so the codegen's internal SaveChanges only flushes the sequence row (never a half-built contract), THEN loop-2 adds all + pe.ContractId=first + ONE final SaveChanges = atomic (no partial-create; failure wastes only seq numbers). GiaTri: single = details ThanhTienNganSach sum (legacy preserved); ≥2 = per-winner quote total (DangSoanThao draft, editable — anh Kiệt UAT). Controller → {contractIds}.
  • list-card winner names: PurchaseEvaluationListItemDto +WinnerSupplierNames List<string> via EF collection-subquery over IsWinner suppliers (3 projection sites). Verified: translates + runs on SQLite (test-specialist translation-smoke — no 2-pass fallback needed). FE PeListPanel joins names for ≥2 (was blank).
  • FE: dialog already showed winners + gated on isWinner; only response {contractId}→{contractIds} + toast "Đã tạo N HĐ" + navigate to first.

Tests +6 (CreateContractFromEvaluationMultiWinnerTests 5 [≥2-winner per-winner GiaTri 140/260 vs single legacy 800, idempotency, 0-winner, not-DaDuyet] + PeListWinnerNamesProjectionTests EF-translate smoke). reviewer PASS (codegen-sequencing + positional-record arg-order + no-partial-create all independently verified).

State THẬT

Mig 59 · 88 bảng · 419 test (45D+374I) · gotcha 73 · menu 54 · bundle admin BQq2eTP6 / user dHa64I59.

Cách chạy + #53

em-main-led BE core (financial/coupled/design-heavy = create-contract multi + Block B financials, em-main wrote directly per agent-boundary "schema/cross-stack design = em-main solo") + delegate impl-backend (relocate) ∥ impl-frontend (FE 2-app SHA-mirror) ∥ test-specialist (test-before bug + test-after feature) + reviewer adversarial + cicd-monitor. #53 truncation ×3 (test-specialist 34.8KB / reviewer 27KB / cicd-monitor — returns rớt ở MEMORY-over-budget step) → em-main recover-disk (work landed) + self-gate (read the tests + own suite run) + curl-self-verify deploy (Gitea run status=success + bundle rotation, when cicd-monitor verdict truncated).

Lessons

  1. Multi-entity create with a self-committing sequence-generator = gen ALL codes first (entities local, un-tracked) → atomic final SaveChanges. → feedback_multi_entity_create_self_committing_codegen.
  2. Cardinality single→multi = grep MỌI consumer (reinforced feedback_cardinality_change_grep_consumers): the S87 FE-only sweep (8 sites) missed 2 BE financial read-sites (Block B) — the audit caught them.
  3. Frozen-module workflow: audit → AskUserQuestion to split safe-vs-behavior-affecting → user picks scope → fix with test+review per change. Behavior-affecting fixes need explicit user OK even when they're "more correct".

§L closeout

  • §L.a: 0 production-bug RCA. #53 ×3 = known curate-debt pattern (recover-disk held; no new code-fault).
  • §L.b(c): test-specialist 34.8KB OVER-SOFT (root #53) + reviewer 27.1KB + FD 26.1KB over-autoinject — archive-gate strike-1 (DRY-RUN); curate deferred to next session as #1 NEXT-em (proper byte-exact L1→L2 + _INDEX, not rushed). sleep-check skip (ran today). Hot-feed %-print → REPORT.
  • §L.b(d)(f): 6 sub spawned + flushed own MEMORY (committed). harvest landed (BE/FE/test/reviewer/cicd/inv deltas).
  • §L.b(g): tooling — no new skill/plugin/roster change.
  • §L.b(h): User-Mark — 0 new governance decision (product session) → display-only (4 Active-High).
  • infra-adoption: N/A (no infra adoption — product work).

🔴 NEXT

  • Anh: ⚠️ restart CLI (carry budget v3 + /user-mark-* + cadence). UAT anh Kiệt Ctrl+F5: ① ≥2-winner Block B số đúng · ② GẤP→Director chuông · ③ Link hồ sơ giữ khi sửa header · ④ ≥2-winner "Tạo HĐ" → N HĐ (xác nhận GiaTri per-winner = giá NCC chào).
  • Em: curate test-specialist L1 (GẤP) · monthly 2026-07-01 (STATUS/HANDOFF re-tier mega-line bloat — line không Read được · detector test-count regex anchor · vocab-fork alias-map · ef-core Mig→59).
  • Pending product: Section B cột Dự-án wire · Ngưỡng giá CEO Designer UAT · "C" chuyển phiếu→dự án.

Post-closeout addenda (cùng phiên S88)

  • 🔥 White-screen incident (eoffice/fe-user) — KHÔNG phải code bug: anh báo màn-hình-trắng-tinh sau D2 deploy. Diagnose: deploy KHỎE — fresh load eoffice boot OK (login render, 0 console error qua Chrome MCP), BE all 200, MỌI asset 200 (old+new, KHÔNG 404), changes PE-only + landing /dashboard (em không đụng). ⟹ client-side transient/stale-cache (tab mở trong lúc IIS app-pool recycle khi deploy). Fix: anh hard-refresh Ctrl+Shift+R → khỏi. KHÔNG revert (code lành). 🔴 Robustness finding (NEXT/ops): IIS serve index.html KHÔNG Cache-Control: no-cache (chỉ ETag/Last-Modified) → tab cũ có thể kẹt index stale qua deploy. Repo KHÔNG có web.config (SPA routing + headers = server-side VPS). Đề-xuất: add web.config vào fe-user/public + fe-admin/public (index.html→no-cache + assets/*→immutable 1y) SAU khi inspect server config (đừng vỡ SPA rewrite) — iis-deploy-runbook task, cẩn-thận-prod. (Lesson: build+deploy PASS ≠ runtime-render OK; nhưng white-screen ≠ luôn-là-code — verify deploy-health TRƯỚC khi revert.)
  • PE Block B table-align (3f9dc32): 2 bảng "TỔNG HỢP NGÂN SÁCH TRÌNH KÝ" (A NGÂN SÁCH / B THỰC HIỆN) lệch cột Dự án/PRO/CCM (A w-40 vs B w-44, auto-layout). Fix: cả 2 table-fixed + đồng-nhất w-20/w-44/w-44 → thẳng hàng 1 lưới. FE-only 2-app SHA 93a4e8a1, build PASS.