From 462bfbc854cbd9c2f6ba497ec2b279116bd48fbc Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Thu, 18 Jun 2026 19:15:45 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Docs:=20S74=20closeout=20=E2=80=94?= =?UTF-8?q?=20Mig=2055=20PE=20"Ghi=20ch=C3=BA=20t=E1=BB=AB=20CCM"=20(STATU?= =?UTF-8?q?S/HANDOFF/session-log=20+=20agent-memory=20harvest)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STATUS + HANDOFF: S74 entry (Mig 55 CcmNote, test 334->339, "0 het CCM"=role-gate khong bug -> UAT bang CostControl/Admin) - cicd Run #315 PASS ~4m54s: Mig 55 applied prod (CcmNote nvarchar 1000 nullable), sys.tables 88, smoke 4x200; bundle admin BYF5vIMJ / user CB-tiRxd - session log 2026-06-18-S74-pe-ccm-note.md (chan doan + 2 fork + lessons) - agent-memory harvest: implementer-frontend (FE mirror) + test-specialist (5 test §4b + L1 curate ->24.6KB + archive activity-s51-s52) + cicd-monitor (Run #315) Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/agent-memory/cicd-monitor/MEMORY.md | 7 ++-- .../implementer-frontend/MEMORY.md | 4 +- .../agent-memory/test-specialist/MEMORY.md | 9 ++-- .../archive/activity-s51-s52.md | 15 +++++++ docs/HANDOFF.md | 25 ++++++++++- docs/STATUS.md | 19 ++++++--- .../sessions/2026-06-18-S74-pe-ccm-note.md | 42 +++++++++++++++++++ 7 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 .claude/agent-memory/test-specialist/archive/activity-s51-s52.md create mode 100644 docs/changelog/sessions/2026-06-18-S74-pe-ccm-note.md diff --git a/.claude/agent-memory/cicd-monitor/MEMORY.md b/.claude/agent-memory/cicd-monitor/MEMORY.md index bc4ce61..86ee344 100644 --- a/.claude/agent-memory/cicd-monitor/MEMORY.md +++ b/.claude/agent-memory/cicd-monitor/MEMORY.md @@ -50,9 +50,9 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve - **Prod:** api/admin/eoffice `.solutions.com.vn` · SSH `ssh vietreport-vps` (Administrator, id_ed25519) · IIS site phys paths (S42 verified): API `C:\inetpub\solution-erp\api` · admin `\fe-admin` · user `\fe-user` (3 sites Started). DB `.\SQLEXPRESS`/`SolutionErp`/`vrapp` SQL-auth. **Conn string key = `ConnectionStrings.Default` (NOT `DefaultConnection`!)** — read pw from prod appsettings.Production.json when `$env:PROD_DB_PASSWORD` empty. - **SSH→PS quoting (S42 lesson):** nested bash→ssh→powershell mangles `$var`/`\"`. Use `iconv UTF-16LE | base64` → `powershell -EncodedCommand $B64`. Single-quote literal paths. - **Tests baseline:** **263 PASS** (S62 Run #286 sha 7926c21 spec; 45 Domain + 218 Infra — em-main supplied; supersedes prev 228/240/256). CI gate runs both test projects BEFORE build/deploy → status=success ⟹ test gate passed (`tasks` endpoint reports terminal as `status:success`, `conclusion` field NOT populated). Local grep undercounts (Theory/InlineData) — trust CI conclusion. Phase 9 UAT mode skip per chunk OK. -- **Mig latest repo:** **Mig 53 `20260617060207_AddPeUrgentAndCeoApprovalThreshold`** (S71 Run#308; PE +IsUrgentByPro/+IsUrgentByCcm bit-default-0 + ApprovalWorkflows +CeoApprovalThreshold decimal(18,2)-nullable, 3 AddColumn no new table — VERIFIED APPLIED PROD). Prev Mig 52 `AddHoSoLinkToPurchaseEvaluation` (S65 PE HoSoLink hyperlink-NAS) + Mig 51 `AddDepartmentParentId` (S65 org-tree loose-Guid) + Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (S61 net-reduce). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (53 mig .cs non-designer total). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5`. ⚠️ Table-count: `sys.tables` (is_ms_shipped=0, excl mighist) = **88** (S62 Run #286 verified — S61 Budget-replace DROPPED tables 93→88). Narrative-93 is STALE pre-S61 — when commit touches no schema, 88 is correct, don't FAIL on 88↔93. Always cross-ref COMMIT scope vs ambient count. +- **Mig latest repo:** **Mig 55 `20260618105426_AddCcmNoteToPeWorkItemBudget`** (S74-bis Run#315 sha 8655ebf; PeWorkItemBudgets +`CcmNote nvarchar(1000) nullable` — 1 AddColumn no new table — VERIFIED APPLIED PROD: history-top==repo, sys.columns `nvarchar maxlen=2000 null=1` [2000=byte-len 1000char×2], tables88). Prev Mig 54 `AddPeSuggestedAndApprovedPrice` (S73 #313, 5 PE price cols) + Mig 53 `20260617060207_AddPeUrgentAndCeoApprovalThreshold` (S71 Run#308; PE +IsUrgentByPro/+IsUrgentByCcm bit-default-0 + ApprovalWorkflows +CeoApprovalThreshold decimal(18,2)-nullable, 3 AddColumn no new table — VERIFIED APPLIED PROD). Prev Mig 52 `AddHoSoLinkToPurchaseEvaluation` (S65 PE HoSoLink hyperlink-NAS) + Mig 51 `AddDepartmentParentId` (S65 org-tree loose-Guid) + Mig 50 `ReplaceBudgetModuleWithPeWorkItemBudgets` (S61 net-reduce). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (53 mig .cs non-designer total). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5`. ⚠️ Table-count: `sys.tables` (is_ms_shipped=0, excl mighist) = **88** (S62 Run #286 verified — S61 Budget-replace DROPPED tables 93→88). Narrative-93 is STALE pre-S61 — when commit touches no schema, 88 is correct, don't FAIL on 88↔93. Always cross-ref COMMIT scope vs ambient count. - **Bearer:** admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM, gotcha #44 check) -- **Bundle hash live S72:** admin `fc_xkNpJ` + css `C2Zvnd2f` · user `DP-tBcg0` + css `1bS4xeUF` (Run #312 sha 18fced6; index.html `Last-Modified` 2026-06-18T07:07:49Z = deploy window). Prev S71 #308: admin `BgNCjwsG`/user `CBvh0vtf`. ⚠️ **PER #69 (S72): bundle hash ROTATES on EVERY deploy regardless of FE change (non-deterministic rebuild). So "live hash" value is only a SNAPSHOT for THIS run — do NOT treat it as a frozen-baseline to compare next run against.** To detect a real FE ship, diff `fe-*/src` in commit/range — NOT hash delta. ASYMMETRIC-deploy "anomaly" framing (S66) is RETIRED by #69: both apps rebuilt+rotated every deploy, asymmetry impossible to read from hashes alone. S50 mid-deploy transient lesson still holds: re-confirm hash AFTER status=success ALWAYS (anti-pattern #3). +- **Bundle hash live S74-bis:** admin `BYF5vIMJ` + css `X_45M1jX` · user `CB-tiRxd` + css `Bbbo0M5H` (Run #315 sha 8655ebf; index.html `Last-Modified` admin 2026-06-18T12:08:53Z + user 12:09:45Z = deploy window; CSS unchanged from #313/#314 = PE-tab logic touched not style). Prev #314: admin `Bv3jUCNo`/user `BWlMBQz6`. Prev #313: admin `OlNyG9OD`/user `DSzSLVtL`. ⚠️ **PER #69 (S72): bundle hash ROTATES on EVERY deploy regardless of FE change (non-deterministic rebuild). So "live hash" value is only a SNAPSHOT for THIS run — do NOT treat it as a frozen-baseline to compare next run against.** To detect a real FE ship, diff `fe-*/src` in commit/range — NOT hash delta. ASYMMETRIC-deploy "anomaly" framing (S66) is RETIRED by #69: both apps rebuilt+rotated every deploy, asymmetry impossible to read from hashes alone. S50 mid-deploy transient lesson still holds: re-confirm hash AFTER status=success ALWAYS (anti-pattern #3). - **DB pw (S42, when `$PROD_DB_PASSWORD` empty):** `vrapp/buKL3TGBkD0wDDbYVw65QeX9` read from `C:\inetpub\solution-erp\api\appsettings.Production.json`→`ConnectionStrings.Default`. ⚠️ Skill-doc path `C:\inetpub\apps\SolutionErp\Api` is STALE → real path `C:\inetpub\solution-erp\api`. sqlcmd over SSH works direct (no UTF-16 encode needed). ⚠️ sys-catalog string-concat queries hit collation conflict (`Latin1_General_CI_AS_KS_WS` vs `SQL_Latin1_General_CP1_CI_AS`) → add `COLLATE DATABASE_DEFAULT` per concatenated column. ## 🔑 Critical config (flag commit nếu tái xuất) @@ -73,7 +73,8 @@ BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code / - _(S72 Run #312 sha=`18fced6` PASS ~5m16s [governance-only 26-md+hmw.js+memory-budget.json triggers-CI, ZERO prod code, Mig53-unchanged-VERIFIED-prod, tables88, health-4x200, test306-inferred, **BUNDLE-BOTH-ROTATE-but-BENIGN fc_xkNpJ/DP-tBcg0** → NEW gotcha #69 (FE-hash NON-deterministic per-rebuild, deploy.yml Remove+Copy fe-* UNCONDITIONAL every run, "frozen-on-BE-only" invariant OVERTURNED, SPA-200-trap control-test, real-FE-change = `git diff fe-*/src` NOT hash-delta), 0-fe-src-diff-confirms-no-accidental-ship] → gotcha #69 promoted to recurring-patterns §top; FIFO-trimmed, full verbatim git `18fced6`+`39d55d4`)_ - _(S71 Run #308 sha=`ebd7e1c` PASS ~4m41s [FULL-STACK PE-urgent+CCM-threshold, **Mig53 AddPeUrgentAndCeoApprovalThreshold VERIFIED-APPLIED-PROD** 3-cols-sys-columns (IsUrgentByPro/Ccm bit0 + CeoApprovalThreshold decimal18-2-null), history-top-advance-53, tables88-addcolumn-only, bundle-BOTH-rotate BgNCjwsG/CBvh0vtf, endpoint-urgent-401-not-404, test306] → 4-axis full-stack pattern (BE+FE-both-rotate · history-top-advance + N-cols sys.columns type-verify · tables-stay-88 · endpoint-401-not-404); FIFO-trimmed, full verbatim git `ebd7e1c`)_ -- **2026-06-18 S74 Run #314 (run_number 314, id=428) sha=`6aa4dcb` PASS ~5m12s (FE-ONLY guard: PE khóa nút "Xác nhận" khi phải chọn giá mà chưa có giá nào — empty-candidates guard, anh Kiệt FDC continuation of Mig 54. 2 files: `fe-admin/src/components/pe/PeWorkflowPanel.tsx` + `fe-user/src/components/pe/PeWorkflowPanel.tsx`, 8 insert / 2 delete. KHÔNG migration KHÔNG BE — Mig stays 54. deploy 15/15 session after #297–#313 all PASS):** Push HEAD=`6aa4dcb` (nothing unpushed). `git diff --name-only HEAD~1 HEAD -- '*Persistence/Migrations*'` = EMPTY ✓ (FE-only, no EF migration). `.tsx` non-ignored → full pipeline RAN. GITEA_TOKEN+PROD_DB_PW both absent env → anon Gitea API (worked, public repo). Run IN-PROGRESS at spawn (running 16:21:42, exact head_sha match #314 deterministic). Pre-poll bundle baseline captured BEFORE poll-loop (anti#3): admin `OlNyG9OD`/css `X_45M1jX` + user `DSzSLVtL`/css `Bbbo0M5H` = still Run #313 live (deploy not yet shipped). Poll-loop iter6 status=success (created 16:21:42 → success 16:26:54 ≈5m12s; iters 1-5 all running). CI gate (both test proj pre-deploy ⟹ status=success ⟹ test **334** baseline FE-only no new test passed; `conclusion` empty — `tasks` terminal=`status:success` doesn't populate conclusion, trust success; 334 INFERRED gate-passes-pre-build NOT log-confirmed numeric). **★ BUNDLE BOTH ROTATE (FE 2-app PE-panel change ⟹ both EXPECTED to rotate per gotcha #69; verified AFTER status=success + STABLE 2nd-fetch no-transient per anti#3): admin JS ROTATE `OlNyG9OD→Bv3jUCNo`** ✓ (css `X_45M1jX` UNCHANGED — guard touched panel logic not CSS) **+ user JS ROTATE `DSzSLVtL→BWlMBQz6`** ✓ (css `Bbbo0M5H` UNCHANGED). Asset reachable 200 + LARGE: admin js 1,599,110b + user js 1,503,769b (control fake `/assets/index-ZZfakehash0.js`→200 size=919b SPA-fallback ⟹ real JS shipped, gotcha #69 SPA-200-trap distinguished by size). index.html `Last-Modified` admin 09:25:23Z + user 09:26:17Z (=16:25-16:26VN deploy window) ✓ — matches deploy.yml Remove+Copy fe-* runs. Smoke **4×200** health: api `/health/ready`+`/health/live` + admin root + eoffice root. **NO migration check needed** (FE-only per spec; Mig stays 54 from #313 — not re-queried). 0 regression. NO prod-data mutation (read-only curls; FE-copy = expected deploy side-effect). Behavioral empty-candidates guard (nút Xác nhận disabled khi list giá rỗng) = anh Kiệt UAT (em confirm bundles shipped per spec). **VERDICT PASS: green CI + test 334 (FE-only, no new test) + bundle BOTH JS rotate (CSS unchanged — guard = panel logic) + asset 200-large 1.5MB vs fake-919b + health 4×200. LESSON: FE-only guard verify = lightweight — bundle JS rotate (per-rebuild non-deterministic gotcha #69, but here REAL FE change so rotate expected AND confirms ship) + CSS-may-stay-frozen if no style touched (partial rotation OK, JS is the signal) + asset-size SPA-200-trap distinguishes real-JS-1.5MB from fallback-919b + skip Mig/DB-query entirely when 0 migration files in diff (FE-only). #314 fastest-confirm: no SSH/sqlcmd needed. TOOLING: bash POSIX → write PS to `$LOCALAPPDATA/Temp/x.ps1` + `powershell.exe -File $(cygpath -w ...)`; Gitea `tasks` via Invoke-RestMethod `-Body @{limit=N}` hashtable (NOT query-string); poll-loop backgrounded + grep-until FINAL; index.html `