[CLAUDE] Docs: S107 office-document VERIFIED-RUNTIME cùng-phiên (registry hot-reload agent MỚI + spawn-test PASS OD1/OD4/OD5 template thật — finding wwwroot 0-placeholder) + cicd Run #489 PASS record + S27 lesson thu hẹp EDIT-agent-only
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -22,7 +22,7 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve
|
||||
- **Bundle hash unchanged = ship FAIL** — push+action success nhưng prod không đổi. Verify via INDEX.HTML ref (`curl -s https://admin.solutions.com.vn/ | grep -oE '/assets/index-[A-Za-z0-9_-]+\.(js|css)'`), NOT by GETting a hash-named asset directly. ⚠️ verify MUST sau status=success (Run #242 false-positive: check khi "running" → stale hash).
|
||||
- **🔴 #69 (S72 Run #312) — FE bundle hash NON-DETERMINISTIC per rebuild.** `deploy.yml` `Remove-Item fe-*\* -Exclude web.config` + `Copy-Item dist\*` runs UNCONDITIONALLY every run (path-filter gates whole-workflow trigger, NOT per-step). Identical FE source ⟹ DIFFERENT hash each deploy (Vite/rolldown non-reproducible chunk-id). PROVEN: governance-only `18fced6` (0 files in fe-*/src) rotated BOTH bundles. ⟹ "BE-only/governance ⟹ bundle frozen" is FALSE; rotation EXPECTED every deploy. **To detect REAL FE change, diff `fe-*/src` in commit/range, NOT hash delta.**
|
||||
- **⚠️ SPA-fallback 200 trap (S72):** server rewrites `/*`→`/index.html` so GET `/assets/index-<ANYTHING>.js` returns **200** even for fake hash (control `ZZdoesnotexist0.js`→200, size~919b text/html). Old-hash-still-200 MEANINGLESS. RELIABLE signal = parse index.html `<script src>`, GET that exact path + check `size_download` LARGE (real ~1.6MB vs fake ~919b) + `Last-Modified` in deploy window + 2nd-fetch byte-stable (no mid-deploy transient).
|
||||
- **🟢 #69-REFINE (S83 Run #333) — hash can stay IDENTICAL across deploy when fe-*/src 0-change.** #69 said "rotates EVERY deploy" — NOT absolute. Run #333 (BE+tests+governance, ZERO `fe-*/src` diff) shipped FE (Last-Modified 17:10:35/17:11:27 BOTH in run-window 17:06→17:11) but hash UNCHANGED (admin `CsJetgZH`/user `BVS0ApIm` = #330 baseline). ⟹ identical Vite source ⟹ byte-identical output ⟹ same content-hash. Rolldown chunk-id apparently MORE deterministic than #69 feared (or only rotates on real src delta). **MOST RELIABLE ship-proof = `Last-Modified` header on the real bundle file IN deploy-window, NOT hash-delta** (hash-delta has false-NEGATIVE when src unchanged + false-POSITIVE risk noted in #69). Always cross-ref `git diff fe-*/src` scope: 0-FE-change ⟹ expect SAME hash + fresh Last-Modified.
|
||||
- **🟢 #69-REFINE (S83 Run #333) — hash can stay IDENTICAL across deploy when fe-*/src 0-change.** #69 said "rotates EVERY deploy" — NOT absolute. Run #333 (BE+tests+governance, ZERO `fe-*/src` diff) shipped FE (Last-Modified 17:10:35/17:11:27 BOTH in run-window 17:06→17:11) but hash UNCHANGED (admin `CsJetgZH`/user `BVS0ApIm` = #330 baseline). ⟹ identical Vite source ⟹ byte-identical output ⟹ same content-hash. Rolldown chunk-id apparently MORE deterministic than #69 feared (or only rotates on real src delta). **MOST RELIABLE ship-proof = `Last-Modified` header on the real bundle file IN deploy-window, NOT hash-delta** (hash-delta has false-NEGATIVE when src unchanged + false-POSITIVE risk noted in #69). Cross-ref `git diff fe-*/src` scope: 0-FE-change ⟹ hash EITHER same (#333/#485-487) OR rotated (#312/#489 S107) — both benign; ship-proof = fresh LM-in-window + real-size.
|
||||
- **Migration drift prod vs repo** — compare `ls .../Persistence/Migrations/*.cs` vs `sqlcmd __EFMigrationsHistory`. Fix: check `Program.cs`/DbInitializer `app.MigrateDatabase()` + app pool recycle. Mig-applied proof = `__EFMigrationsHistory` top==repo-HEAD; stuck-old ⟹ pool didn't recycle ⟹ FAIL even if status=success+bundle-rotated.
|
||||
|
||||
---
|
||||
@ -52,7 +52,7 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve
|
||||
- **SSH→PS quoting (S42):** nested bash→ssh→powershell mangles `$var`/`\"` → use `iconv UTF-16LE | base64` → `powershell -EncodedCommand $B64`; OR write ps1-file + `powershell -File $(cygpath -w)`. sqlcmd over SSH direct `-W -h -1` pw-inline. sys-catalog string-concat → `COLLATE DATABASE_DEFAULT` (collation conflict).
|
||||
- **Tests baseline:** **440 PASS** (45 Domain + 395 Infra · 0 fail/skip; S96 Run #480 sha 0c2f9f6 — 436 + new `PeSuggestedPriceSetterAuthzTests`; prior S96 #479 436, S96/S95 434, S90 #465 421). Phase 9 UAT skip per chunk OK.
|
||||
- **Mig latest repo:** **Mig 62 `20260706084342_ExpandSupplierFields`** (S104 #488; AddColumn ×18 on `Suppliers` [17 nullable string + `Status` int] + guarded `Sql()` UPDATE `Note=NULL WHERE Code IN (4 NCC) AND Note LIKE N'Loại:%'` — un-cram legacy concat Note; NO CreateTable ⟹ sys.tables stays 89 — VERIFIED-APPLIED-PROD history-HEAD + 18-cols-present + Suppliers-total-35-cols + 4-row Note=NULL/Pkg/Bank/LegalRep-populated/Status=1 + Note-still-Loại-count=0). Prev Mig 61 `BackfillEndedByLevelFinalizeFromChangelog` (S97, data-only). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/`. Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5`. ⚠️ **`sys.tables` (is_ms_shipped=0) = 89** (S104 LIVE-verified post-#488 — AddColumn/data-only migs don't change count → commit touches no new table ⟹ 89 correct don't FAIL. Cross-ref COMMIT scope vs ambient count). enum-additive (e.g. `ApprovalAttachment=5`) = int-stored NO-mig → history NOT-advance + empty `git diff -- '*Migrations*'`.
|
||||
- **Bundle hash live (S104 #488 verified 2026-07-06):** admin js **`ChSNAJBK`**/css `Bbtesa6B` · user js **`Bn2w1znH`**/css `BmuPz_Dy` — JS ROTATED (real fe-src diff: SuppliersPage+PathLink+types) từ #487 `mEGqlNWc`/`Dnrp4PU1`; CSS frozen (0 style change). Last-Modified in-window 16:10:04/16:10:57+07 + real-size 1.64/1.55MB + marker `officeAddress`/`legalRepresentative` PRESENT in bundle = REAL-ship proof. ⚠️ **id ≠ run_number; head_sha-keyed.** ⚠️ **PER #69: hash MAY rotate (real src-diff, e.g. #488) OR frozen (0 fe-src diff, e.g. #485-487) — SNAPSHOT per-run, NOT baseline; ALWAYS re-snapshot LIVE pre-deploy.** Real FE ship = diff `fe-*/src` in range + real-size-vs-fake (1.64/1.55MB vs ~919b SPA-trap 200-text/html) + Last-Modified-in-window + content-marker-grep, NOT hash delta alone.
|
||||
- **Bundle hash live (S107 #489 verified 2026-07-10):** admin js **`BVyH-FY7`**/css `Bbtesa6B` · user js **`EDsZebvn`**/css `BmuPz_Dy` — JS ROTATED-benign (0 fe-src governance-only, Vite non-determinism #69) từ #488 `ChSNAJBK`/`Bn2w1znH`; CSS frozen. LM-in-window 09:32:12/09:33:07+07 + real-size 1.64/1.55MB = ship-proof. ⚠️ **id ≠ run_number; head_sha-keyed.** ⚠️ **PER #69 TWO-MODE: hash MAY rotate (real src-diff #488, HOẶC 0-fe-src #489/#312) OR freeze (0 fe-src #485-487) — SNAPSHOT per-run, NOT baseline; ALWAYS re-snapshot LIVE pre-deploy.** Real FE ship = diff `fe-*/src` in range + real-size-vs-fake (1.64/1.55MB vs ~919b SPA-trap 200-text/html) + Last-Modified-in-window + content-marker-grep, NOT hash delta alone.
|
||||
- **Bearer:** admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM, gotcha #44 check).
|
||||
|
||||
## 🔑 Critical config (flag commit nếu tái xuất)
|
||||
@ -70,6 +70,7 @@ BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code /
|
||||
|
||||
## 📅 Recent runs (compressed — full verbatim → `archive/2026-06.md` via `archive/_INDEX.md`)
|
||||
|
||||
- **🟢 S107 #489 (rn 375, id 489) `21387cd` GO 5m33s (09:28:08→09:33:41+07, poll iter8) — GOVERNANCE-ONLY 14-file (+office-document 12th sub agent+skill+roster wiring; `hmw.js`+`memory-budget.json` non-ignored → #41 CI-run; prior `1eea51b` .md-only NO-run đúng filter):** status=success (gate 440, conclusion=null quirk) · 0 BE/FE src ⟹ **Mig FROZEN 62** `ExpandSupplierFields` history-top + **sys.tables=89** ✓ · smoke health/admin/eoffice **3×200** · **bundle JS ROTATED-benign** admin `ChSNAJBK`→`BVyH-FY7` / user `Bn2w1znH`→`EDsZebvn`, CSS frozen ×2 + real-size 1.64/1.55MB application/javascript + LM-in-window 09:32:12/09:33:07+07 vs fake-control 919b-text/html = REAL-ship. 🔑 **#69 TWO-MODE CONFIRMED: governance 0-fe-src có thể ROTATE (#312+#489) hoặc FROZEN (#333/#485-487) — cả 2 benign; ship-proof duy nhất = LM-in-window + real-size; hash-delta chỉ là chỉ báo phụ, KHÔNG flag rotation-on-0-src làm anomaly.**
|
||||
- **🟢 S104 #488 (rn 374, id 488) `778fc98` GO ~4m (poll iter4→success, updated_at 16:11:25+07) — FULL-STACK Supplier 9→27 field + Mig 62 `ExpandSupplierFields` (BE+FE 2-app, NCC/TP Excel-import anh Kiệt FDC):** status=success (test gate 440 passed, `conclusion=None` tasks-quirk = trust success) · **Mig 62 APPLIED-PROD** `__EFMigrationsHistory` top==repo-HEAD, present=1 · **AddColumn ×18** (17 nullable str + `Status` int) VERIFIED sys.columns=18 + Suppliers-total-35-cols · **sys.tables=89 UNCHANGED** (Mig source 0 CreateTable/DropTable — schema-add-only, count-invariant ✓) · **🔑 UN-CRAM DATA-OUTCOME EXACT:** 4 NCC (TRUONGGIANG/TANPHU/TGN/DONGDUONG) all Note=NULL (guarded `Sql()` ran) + Note-still-Loại-count=**0** + PackageCategory/BankAccount/LegalRepresentative populated + Status=1 + LinkGuq populated for DONGDUONG+TRUONGGIANG (TANPHU/TGN legit no-GUQ in source) · smoke health 3×200 + auth accessToken-len468 + **GET /api/suppliers 200 (22 items) DTO carries 18 new keys** (packageCategory/bankAccount/legalRepresentative/linkGuq/officeAddress/contactPhone/status/note) w/ proper VN-diacritics · SignalR bodyless-411=wired · **bundle JS ROTATED** admin `ChSNAJBK`/user `Bn2w1znH` (real fe-src diff SuppliersPage+PathLink+types) CSS-frozen + LM-in-window 16:10 + real-size 1.64/1.55MB + marker `officeAddress`/`legalRepresentative` grep-HIT vs SPA-trap-919b-control = REAL-ship (#69: rotation HERE meaningful, real src-diff). ship-proof BE Infra.dll 16:07 + w3wp recycle 16:11:50. 🔑 **FULL-STACK-SCHEMA-ADD + DATA-UN-CRAM PASS = CI-success + Mig-top==HEAD + AddColumn-count-EXACT + sys.tables-invariant + target-rows-outcome-EXACT (Note-cleared/new-cols-populated/marker-count-0) + DTO-new-keys-in-API + bundle-real-ship-marker-grep + dll/w3wp-in-window.**
|
||||
- _(**S103 #487 `f0874dd` + S100 #486 `5ee32c0`** GOVERNANCE/SCRIPTS-ONLY [.ps1/.json non-ignored → #41] GO — bundle FROZEN #69-REFINE ×4 (0 fe-src ⟹ byte-identical + LM-in-window = ship-proof) · GOVERNANCE-PASS stable ×4 [#476/#485/#486/#487] · 🔧 python `time.sleep` foreground-OK (chỉ bash-sleep-block) · full verbatim → `archive/2026-07.md` via `_INDEX`)_
|
||||
- _(S98 #485 (rn 371) `8a249c5` GO 5m18s GOVERNANCE-ONLY [22 .md + `memory-budget.json` non-ignored → #41] — Mig61 frozen · hash FROZEN + LM-in-window 11:01:48/11:02:42 + real-size = ship-proof · #69-REFINE lần 2 · verbatim git `c112be9`)_
|
||||
|
||||
@ -15,4 +15,4 @@
|
||||
- **Guard #53:** return VERDICT + path output + số-đo (page/sheet/row) — KHÔNG dump nội dung dài / transcript-slice.
|
||||
|
||||
## Entries (append-only, newest last)
|
||||
_(trống — spawn đầu tiên PENDING CLI-restart; spawn-test OD1/OD5: đọc 1 file Office thật + round-trip verify)_
|
||||
- **[S107 spawn-test]** Task: verified-runtime lần đầu — READ 2 template thật + WRITE round-trip. Verdict: **PASS** (OD1 skill docx+xlsx invoked · OD4 extract honest · OD5 round-trip 3/3 para + bảng 2×2 khớp nguyên văn, 37,043 bytes, VN có dấu + em-dash sống qua write→read). Learned: (a) pipeline local = python-docx/openpyxl + `PYTHONIOENCODING=utf-8` khi print VN ra console; (b) openpyxl `read_only=True` trả `EmptyCell` KHÔNG có `.coordinate` → tự build ref bằng `get_column_letter(max_c)+str(max_r)`; (c) scan placeholder docx = paragraph.text (đã merge run, bắt split-run) + raw-XML strip-tag toàn part (bắt textbox) — 2 lớp mới đủ. **SURPRISE:** cả 2 template `wwwroot/templates` (FO-002.05 Giao khoán docx 249 para/10 table · FO-002.07 Đơn đặt hàng xlsx 3 sheet `(F.01)_SS GIA`/`PO`/`Po01 NLT (sua)`) đều **0 placeholder `{{field}}`** (raw-XML 0 hit mọi syntax) — mẫu gốc dạng blank chấm-chấm "Số: …………..", CHƯA placeholder-hóa; đừng assume `{{}}` có sẵn trong file template — form-engine mapping nằm ngoài file hoặc là việc chưa làm → hỏi em main trước khi đụng. Registry hot-reload giữa phiên ĂN THẬT (không cần CLI-restart như dự kiến S107).
|
||||
|
||||
@ -14,7 +14,7 @@ H1 tooling-freshness auditor **SOLUTION_ERP-self**. Read-only + **propose-only**
|
||||
- ❌ NOT: harvest-memory/5-trục → **harvest-curator** (H2) · corpus/RAG/deploy → cicd-monitor · code/SQL audit → investigator-codebase · write/decide → em main
|
||||
|
||||
## 📋 Baseline state (re-ground 2026-07-02 S99 — VERIFY mỗi session, đừng tin số cũ)
|
||||
- **Roster:** 12 sub (S107 +office-document 📄 Office WRITE, anh giao), **12/12 `model: inherit`** (Harness-8 all-inherit, runtime-verified S98 — Fable 5 RESTORED, inherit-chain self-report `claude-fable-5`). 10 product/quality (investigator-codebase/api · implementer-backend/frontend · test-specialist · reviewer · cicd-monitor · frontend-designer · database-agent read-advisory · office-document Office S107 ⚠️ spawn-test pending CLI-restart) + 2 monitor INFORM-only (tooling-auditor · harvest-curator). VALID_ROLES hmw.js = 10 product-only by-design.
|
||||
- **Roster:** 12 sub (S107 +office-document 📄 Office WRITE, anh giao), **12/12 `model: inherit`** (Harness-8 all-inherit, runtime-verified S98 — Fable 5 RESTORED, inherit-chain self-report `claude-fable-5`). 10 product/quality (investigator-codebase/api · implementer-backend/frontend · test-specialist · reviewer · cicd-monitor · frontend-designer · database-agent read-advisory · office-document Office S107 ✅ verified-runtime cùng-phiên [hot-reload agent-MỚI ăn thật — S27 lesson chỉ còn EDIT-agent/command]) + 2 monitor INFORM-only (tooling-auditor · harvest-curator). VALID_ROLES hmw.js = 10 product-only by-design.
|
||||
- **Skills:** 6 project (`.claude/skills/`) + 23 standalone (`~/.claude/skills/`) + 14 command-file (`.claude/commands/` — hmw = script `workflows/hmw.js`, KHÔNG phải slash-command).
|
||||
- **Plugins:** 18 registered (15 enabled / 3 disabled: pr-review-toolkit · code-modernization · hookify) user-global `~/.claude/settings.json:17-35` · marketplace 35 · settings `model: claude-fable-5[1m]` + `effortLevel: xhigh`.
|
||||
- **Docs canonical:** `CLAUDE.md` (root+docs) · `docs/STATUS.md` (số canonical B1) · `docs/HANDOFF.md` · `.claude/agents/README.md` · `docs/governance/`.
|
||||
|
||||
Reference in New Issue
Block a user