diff --git a/.claude/skills/ef-core-migration/SKILL.md b/.claude/skills/ef-core-migration/SKILL.md index 76730fe..5018679 100644 --- a/.claude/skills/ef-core-migration/SKILL.md +++ b/.claude/skills/ef-core-migration/SKILL.md @@ -226,14 +226,14 @@ sqlcmd -S .\SQLEXPRESS -d SolutionErp -U vrapp -P -i migrate.sql ## Code pointers -- `src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs` — 24 DbSet +- `src/Backend/SolutionErp.Infrastructure/Persistence/ApplicationDbContext.cs` — DbSet cho 52 bảng (15 migration) - `src/Backend/SolutionErp.Infrastructure/Persistence/DesignTimeDbContextFactory.cs` — EF tooling factory -- `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` — seed + warn + migrate runtime -- `src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/` — 24 IEntityTypeConfiguration +- `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` — seed + warn + migrate runtime + backfill (idempotent reconcile pattern) +- `src/Backend/SolutionErp.Infrastructure/Persistence/Configurations/` — IEntityTypeConfiguration per entity - `src/Backend/SolutionErp.Application/Common/Interfaces/IApplicationDbContext.cs` — interface Application layer ## Related - `docs/database/database-guide.md` — conventions + migration workflow chi tiết -- `docs/database/schema-diagram.md` — ERD 24 bảng -- `docs/gotchas.md` #7, #17 — migration pitfalls +- `docs/database/schema-diagram.md` — **ERD 52 bảng** + §11 PE module + §12 Budget module + §13 PEDeptOpinions +- `docs/gotchas.md` #7, #17, #38 — migration pitfalls + Identity 4-field rename diff --git a/.claude/skills/form-engine/SKILL.md b/.claude/skills/form-engine/SKILL.md index 05ce295..8947155 100644 --- a/.claude/skills/form-engine/SKILL.md +++ b/.claude/skills/form-engine/SKILL.md @@ -12,8 +12,9 @@ when-to-use: # Form Engine Skill -> **Status:** Phase 2 implemented (MVP — placeholder replace cơ bản). -> **Missing:** loop `{{#loop}}...{{/loop}}` cho table lặp, field spec JSON, PDF convert, form builder FE. +> **Status (post Session 6 — 2026-04-30):** Tier 3 FEATURE-COMPLETE. +> ✅ Placeholder replace + split-runs handling, ✅ FieldSpec JSON, ✅ Form builder FE (admin upload), ✅ DynamicForm renderer (Form↔JSON toggle), ✅ PDF export qua LibreOffice headless, ✅ .doc/.xls auto-convert tới .docx/.xlsx. +> **Missing (low priority):** loop `{{#loop}}...{{/loop}}` cho table lặp (chưa cần — 8 form hiện không có table dynamic), Export PE phiếu PDF (Phase 9 carry over, không quan trọng). ## Tech stack @@ -99,14 +100,12 @@ foreach (var para in root.Descendants()) { ## Known limitations -| # | Limitation | Phase fix | +| # | Limitation | Status | |---|---|---| -| 1 | Không support `{{#loop}}...{{/loop}}` cho table lặp | Phase 2 iteration 2 | -| 2 | Không có field spec JSON — form builder FE phải điền JSON thủ công | Phase 2 iteration 2 | -| 3 | 3 file `.doc` (FO-002.02/03/06) chưa convert → IsActive=false | Convert offline qua Word COM | -| 4 | Không có PDF convert → preview chỉ download .docx | Phase 4 | -| 5 | Không handle `.docm` (macro) — chỉ accept `.docx` / `.xlsx` | By design | -| 6 | Không convert format trong template (vd number → `150,000,000 VND`) — BE phải format trước khi pass data | Phase 3 khi gen mã HĐ | +| 1 | Không support `{{#loop}}...{{/loop}}` cho table lặp | Pending (chưa cần) | +| 2 | Không handle `.docm` (macro) — chỉ accept `.docx` / `.xlsx` | By design (security) | +| 3 | BE phải format số/tiền trước khi pass data (template không format) | By design — caller responsibility | +| 4 | PE Export phiếu PDF chưa wire | Phase 9 carry over (không quan trọng) | ## Common pitfalls (xem gotchas.md) @@ -116,15 +115,8 @@ foreach (var para in root.Descendants()) { - **SaveAs type conversion** — gotcha #11 - **Template file không tồn tại** → throw `NotFoundException` ở RenderCommandHandler -## Gen mã HĐ (RG-001) — chưa implement (Phase 3) +## Gen mã HĐ (RG-001) — DONE Phase 3 + Phase 6 PE -Xem [`docs/forms-spec.md §RG-001`](../../../docs/forms-spec.md). Tóm tắt format: +Đã implement: `ContractCodeGenerator` + `PurchaseEvaluationCodeGenerator` (atomic SERIALIZABLE). Detail trong skill `contract-workflow` (HĐ) + format PE `PE/{YYYY}/{A|B}/{Seq:D3}`. 17 unit test cover (Infrastructure.Tests/Services). -| Loại HĐ | Format | -|---|---| -| HĐ Thầu phụ | `{Project}/HĐTP/SOL&{Partner}/{Seq}` | -| HĐ Giao khoán | `{Project}/HĐGK/SOL&{Partner}/{Seq}` | -| HĐ NCC | `{Project}/NCC/SOL&{Partner}/{Seq}` | -| HĐ Nguyên tắc | `{Year}/NCC/SOL&{Partner}/{Seq}` | - -Planned implementation: `IContractCodeGenerator.GenerateAsync()` với transaction SERIALIZABLE + `ContractCodeSequences` table để tránh race. +Xem [`docs/forms-spec.md §RG-001`](../../../docs/forms-spec.md) cho format spec từng ContractType. diff --git a/.claude/skills/permission-matrix/SKILL.md b/.claude/skills/permission-matrix/SKILL.md index 7feff44..29e743e 100644 --- a/.claude/skills/permission-matrix/SKILL.md +++ b/.claude/skills/permission-matrix/SKILL.md @@ -1,6 +1,6 @@ --- name: permission-matrix -description: Hệ thống phân quyền Role × MenuKey × CRUD. Seed 12 menu + admin full. FE PermissionGuard + usePermission. BE AuthorizationHandler + 48 policy. Dùng khi debug access denied, gán role, menu không hiện. +description: Hệ thống phân quyền Role × MenuKey × CRUD. ~60 menu key (12 root + Ct_*/Wf_*/Pe_*/PeWf_*/Bg_*/Catalogs). FE PermissionGuard + usePermission. BE AuthorizationHandler + ~240 policy. Dùng khi debug access denied, gán role, menu không hiện, inheritance không work. when-to-use: - "permission denied" - "access denied" @@ -8,20 +8,19 @@ when-to-use: - "gán role cho user" - "seed permission" - "permission matrix edit" + - "menu inheritance không work" --- # Permission Matrix Skill -> **Status:** Phase 1 đợt 2 IMPLEMENTED + extended qua các phase sau (28 Ct_* + 7 Wf_* + Phase 6 thêm 13 Pe_*/PeWf_*). +> **Status (post Session 6 — 2026-04-30):** Phase 1 đợt 2 base + extended qua mọi phase. ~60 menu key total: +> - Core: Dashboard / Master+3 leaves / Forms / Reports / System+Users/Roles/Permissions (12 base) +> - Contracts root + 28 Ct_* (7 type × {Group/List/Create/Pending}) + Workflows root + 7 Wf_* +> - PurchaseEvaluations root + 6 Pe_* (2 type × 3 action) + PeWorkflows root + 2 PeWf_* +> - Budgets root + 3 Bg_* (List/Create/Pending) +> - Catalogs group + 4 leaves (Units/Materials/Services/WorkItems) > -> **Phase 6 cross-ref (2026-04-23):** Thêm menu keys module Duyệt NCC: -> - `PurchaseEvaluations` (root group) + `PeWorkflows` (admin root, WIP) -> - `Pe__` cho 2 type × 3 action = 6 leaf -> (`Pe_DuyetNcc_List/Create/Pending`, `Pe_DuyetNccPhuongAn_List/Create/Pending`) -> - `PeWf_` cho admin designer UI (FE chưa build) -> - Inheritance: `PurchaseEvaluations.Read` → auto grant Pe_* descendants (pattern Contracts → Ct_*) -> - FE resolver Layout.tsx: `Pe__List` → `/purchase-evaluations?type=N` (1=NccOnly / 2=NccWithPlan) -> - **TODO session tiếp:** grant non-admin role `PurchaseEvaluations.Read` qua `/system/permissions` để user thấy menu Pe_*. +> **Inheritance roots (4 group, gotcha #35):** `Contracts` → Ct_*, `Workflows` → Wf_*, `PurchaseEvaluations` → Pe_*, `PeWorkflows` → PeWf_*. Khi thêm root mới có children → PHẢI extend 3 chỗ trong `GetMyMenuTreeQuery` (xem gotcha #35). Budgets KHÔNG inherit (Bg_* phải grant tay). ## Model @@ -35,26 +34,40 @@ User ────< UserRoles ────< Role ────< Permissions ── - Union (OR) nhiều role → user có quyền nếu **bất kỳ role nào** cho quyền đó - Admin role → **bypass** check (luôn pass mọi policy) -## Menu tree (seed) - -12 menu trong `MenuKeys.All`: +## Menu tree (seed — ~60 key sau Phase 8) ``` Dashboard Master ├── Suppliers ├── Projects - └── Departments -Contracts + ├── Departments + └── Catalogs (group) + ├── UnitsOfMeasure + ├── MaterialItems + ├── ServiceItems + └── WorkItems +Contracts (root inherit) + └── Ct__ × 7 type = 28 leaf Forms +PurchaseEvaluations (root inherit) + └── Pe__ × 2 type = 6 leaf +Budgets (root, NO inherit — grant tay) + ├── Bg_List + ├── Bg_Create + └── Bg_Pending Reports System ├── Users ├── Roles - └── Permissions + ├── Permissions + ├── Workflows (root inherit) + │ └── Wf_ × 7 type = 7 leaf + └── PeWorkflows (root inherit) + └── PeWf_ × 2 type = 2 leaf ``` -Tree hierarchy qua `ParentKey` field. Seed trong `DbInitializer.SeedMenuTreeAsync`. +Tree hierarchy qua `ParentKey` field. Seed trong `DbInitializer.SeedMenuTreeAsync` + Pe/Wf/Bg seeders riêng. ## Code pointers diff --git a/CLAUDE.md b/CLAUDE.md index 2b89819..7393ee3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -107,9 +107,11 @@ dotnet test SolutionErp.slnx # chạy cả 2 test project | `form-engine` — render docx/xlsx + PDF | `ef-core-migration` — EF migration + 3-file rule | | `permission-matrix` — role × menu × CRUD | `iis-deploy-runbook` — 3 site IIS + win-acme + runner | -**Audit định kỳ:** đầu mỗi tháng — workflow `docs/rules.md §9.4`. Lần kế: **2026-05-01**. +**Audit định kỳ:** đầu mỗi tháng — combined skill + doc drift audit theo `docs/rules.md §6.4 + §9.4`. Cron `solution-erp-skill-audit-monthly` fire 9:00 ngày 1. Lần kế: **2026-05-01**. -Quy tắc: KHÔNG bulk-clone repo skill 3rd party. Chỉ thêm skill PROJECT-SPECIFIC. Xem `docs/rules.md §9` đầy đủ. +Quy tắc: +- KHÔNG bulk-clone repo skill 3rd party. Chỉ thêm skill PROJECT-SPECIFIC. Xem `docs/rules.md §9` đầy đủ. +- KHÔNG rewrite toàn bộ MD định kỳ. Chỉ compact + patch drift. Xem `docs/rules.md §6.4` đầy đủ. ## 📖 Tài liệu quan trọng diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 70d2839..034e599 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,8 +1,17 @@ # HANDOFF — Brief 5 phút cho session tiếp theo -**Last updated:** 2026-04-29 tối (Phase 8 — **Budget complete + PE feature gap đóng + Tests Phase 1-2-3mini (77 test) + CI gate + Path filter + 3 gotcha CI mới (#39 #40 #41)**) +**Last updated:** 2026-04-30 (Session 6 — **MD audit + compact -288 dòng + 3 skill refresh + 2 rule mới timing test + audit định kỳ**) -## TL;DR +## TL;DR Session 6 (30/04 — không code, chỉ docs) + +**Output session 6** — pure docs work, không thay đổi code/test: + +- ✅ **Compact 3 file core**: STATUS -27%, HANDOFF -32%, migration-todos -35% (-288 dòng tổng). Archive 51 row Recently Done Phase 0-7 → `changelog/recently-done-archive-2026-04.md`. +- ✅ **Refresh 3 skill stale**: `form-engine` (Phase 2 MVP → Tier 3 feature-complete), `permission-matrix` (12 menu → ~60 + inheritance roots), `ef-core-migration` (24 DbSet → 52 bảng). +- ✅ **Rule mới §7 Timing test**: 1 bảng 5-row compact — feature mới = test-after, bug = test-before, critical algorithm = test-before, spec change = update test cũ, skip 5 loại. +- ✅ **Rule mới §6.4 Audit + compact MD định kỳ**: cadence + checklist + anti-pattern. Cross-ref §9.4 skill audit. KHÔNG rewrite toàn bộ. +- ✅ **77 test vẫn pass** (Domain 54 + Infra 23). 0 thay đổi code. +- ✅ **Cron 2026-05-01 fire mai** — combined audit (skill + doc drift) theo §6.4 + §9.4. **Session 5 (29/04)** đóng gần hết feature gap + bật test gate: @@ -44,21 +53,17 @@ - ⏸️ **npm junction cache** — thử ở #111 fail `tsc not found`, rollback. Cần debug session sau (gotcha #40 doc rồi). - ✅ **Tests Phase 3 mini (PE Workflow Designer)** — 6 test versioning logic. Total 77. -## ⚠️ CẢNH BÁO session tiếp (Session 6) +## ⚠️ CẢNH BÁO session tiếp (Session 7+) -1. **CI test gate active** — mỗi commit push trigger 2 step `dotnet test` (Domain + Infrastructure) TRƯỚC build/deploy. Test fail = NO deploy. Khi feature mới có bug logic → thêm regression test trước khi commit. Workflow: code → `dotnet test SolutionErp.slnx` local → commit → push. -2. **Login email** `admin@solutionerp.local` / `Admin@123456` — domain default - chưa đổi sang `@solutions.com.vn` (chỉ demo user rebrand qua BackfillDemoEmail). -3. **Chưa xóa binding cũ `.huypham.vn`** — vẫn active fallback. Sau 1-2 ngày - verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS. -4. **win-acme scheduled task "unhealthy"** — cert auto-renew có thể fail - khi gần 2026-06-18. Fix: mở `wacs.exe` interactive → Manage Renewals → - recreate task. -5. **Export phiếu PDF/Excel PE** — pending vô thời hạn (user nói không quan trọng lắm). Khi cần: tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx`. -6. **Atomic sequence Budget chưa chốt** — `NS-YYYYMM-XXXX` Random.Shared. Khi format chốt → migration `AddBudgetCodeSequences` + `IBudgetCodeGenerator` SERIALIZABLE pattern (mirror Contract/PE). -7. **Versioned workflow Budget chưa có** — hardcoded `BudgetPolicy.Default` 3-step. Khi user cần admin config UI → migration `AddBudgetVersionedWorkflow` + 3 bảng + pin per Budget. -8. **Chú ý G-084:** VPS shared với VietReport — mọi reverse proxy / backend - service mới phải dùng `127.0.0.1` + bind loopback IPv4 explicit. +1. **CI test gate active** — code → `dotnet test SolutionErp.slnx` local → commit → push. Test fail = NO deploy. Workflow user §7 rules.md. +2. **Timing test rule live (§7)**: feature mới = test-after, bug = test-before BẮT BUỘC, critical algorithm = test-before merge, spec change = update test cũ + code chung commit. +3. **Doc audit cadence live (§6.4)**: cuối phase compact, đầu tháng cron audit, KHÔNG rewrite toàn bộ. Cron fire **mai (2026-05-01)** — combined skill + doc drift theo checklist. +4. **Login email** `admin@solutionerp.local` / `Admin@123456` — domain default chưa đổi sang `@solutions.com.vn` (chỉ demo user rebrand). +5. **Chưa xóa binding cũ `.huypham.vn`** — vẫn fallback. Sau verify stable → `.\migrate-domains.ps1 -RemoveOld -SkipCert` trên VPS. +6. **win-acme scheduled task "unhealthy"** — fix trước cert expire 2026-06-18. +7. **Export phiếu PDF/Excel PE** — pending vô thời hạn (user nói không quan trọng). +8. **3 feature mới chưa test** (PE Opinion Upsert / Budget validate / Contract BudgetId carry) — đợi UAT phát sinh bug → áp rule §7 (regression test before fix). Hoặc soak 2-3 tuần ổn → viết happy path. +9. **G-084:** VPS shared VietReport — mọi reverse proxy mới phải `127.0.0.1` + bind loopback IPv4 explicit. ## ⭐ Skills (.claude/skills/) — PHẢI dùng khi task khớp diff --git a/docs/STATUS.md b/docs/STATUS.md index c05b0a4..6a1d0ec 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -2,9 +2,9 @@ > **Update rule:** trước khi bắt đầu 1 task → ghi row vào `🔥 In Progress`. Xong → chuyển sang `✅ Recently Done`. -**Last updated:** 2026-04-29 tối (Phase 8 — **Budget complete + PE feature gap đóng + Tests Phase 1-2-3mini + CI gate + Path filter + 3 gotcha CI mới**) +**Last updated:** 2026-04-30 (Session 6 — **MD audit + compact -288 dòng + 3 skill refresh + rule timing test + rule audit định kỳ §6.4**) -## 📍 Phase hiện tại: **Feature freeze + CI optimize live** — 52 DB tables, 15 migrations, ~128 API endpoints, 31 FE pages. **77 unit test pass** (54 Domain policy + 17 Infra code generator + **6 PE Workflow versioning**) — CI fail-fast. Path filter docs-only skip = 0s cho commit MD. Manual checkout từ Gitea bypass github.com timeout (gotcha #39). 41 gotcha tổng. 30 demo user. +## 📍 Phase hiện tại: **Phase 9 active — UAT + Ops + carry over** — 52 DB tables, 15 migrations, ~128 API endpoints, 31 FE pages. **77 unit test pass** (54 Domain + 17 Infra + 6 PE WF Application) — CI fail-fast. Path filter docs-only skip 0s. 41 gotcha. 30 demo user. **6 skill (3 refresh)**. Doc audit định kỳ §6.4 chốt cron 2026-05-01 fire mai. ### 🌐 Production URLs @@ -14,41 +14,46 @@ - https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp — Gitea repo + Actions - Default admin: `admin@solutionerp.local` / `Admin@123456` ⚠️ **RE-ROTATE sau login đầu** -## 🔥 In Progress — Còn lại cho session 6 +## 🔥 In Progress — Session 7+ (Phase 9 active) -### A. PE feature gap (carry over) +### A. Hard blockers (chờ user / ops) -- [ ] **Export phiếu PDF/Excel** — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx` (user pending — không quan trọng lắm) +- [ ] **UAT thật 1 tuần** với 2-3 user (Drafter / CCM / BOD) — hard requirement Phase 5 roadmap +- [ ] **SMTP config** → Email outbox (BLOCKED chờ user cấp host/user/pass) +- [ ] **Rotate creds** — admin + 30 demo + SA + vrapp + JWT secret + Gitea runner token +- [ ] **Schedule SQL backup daily** — `scripts/backup-sql.ps1` đã sẵn, chưa schedule Task Scheduler +- [ ] **Remove binding cũ `.huypham.vn`** sau verify stable: `ssh vietreport-vps ; .\migrate-domains.ps1 -RemoveOld -SkipCert` +- [ ] **win-acme scheduled task "unhealthy"** — auto-renew fix trước 2026-06-18 -### B. Optional polish (khi UAT phát sinh) +### B. Carry over feature gap -- [ ] Budget MaNganSach atomic sequence (hiện `NS-YYYYMM-XXXX` Random.Shared, chốt format chính thức sau → migration `AddBudgetCodeSequences`) -- [ ] Budget versioned workflow (admin config qua UI — hiện hardcoded `BudgetPolicy.Default`) -- [ ] Payment terms tách field (PE) — JSON blob → 6 column riêng (migration `AddPePaymentTermFields`) +- [ ] **Export phiếu PDF/Excel** PE — tái dùng `IDocumentConverter` + template `PE-TrinhDuyet.docx` (user pending — không quan trọng lắm) + +### C. Optional polish (khi UAT phát sinh bug) + +- [ ] Budget MaNganSach atomic sequence (hiện Random.Shared → migration `AddBudgetCodeSequences`) +- [ ] Budget versioned workflow (admin config UI thay hardcoded `BudgetPolicy.Default`) +- [ ] Payment terms PE tách field (JSON blob → 6 column riêng) - [ ] Auto-map PE Details → Contract per-type Details khi gen HĐ - [ ] Matrix Quotes bulk paste từ Excel - [ ] fe-user Inbox thêm section "Phiếu Duyệt NCC chờ tôi" -### C. Tests Phase 3-5 (làm khi gặp bug recurring để justify ROI) +### D. Tests Phase 3-5 (làm khi gặp bug recurring để justify ROI — rule §7) -- [ ] **Phase 3** — Application handler tests (CQRS) với EF InMemory (~1 ngày, ~15 test) -- [ ] **Phase 4** — API smoke tests qua WebApplicationFactory (~0.5 ngày, ~7 test) -- [ ] **Phase 5** — FE Vitest cho lib utility (queryMatches, fmtMoney) (~0.5 ngày, ~10 test) +- [ ] **Phase 3 full** — Application handler tests cần UserManager DI helper (PE Opinion Upsert, Budget validate, CreateContractFromEvaluation BudgetId carry) ~15 test +- [ ] **Phase 4** — API smoke tests qua WebApplicationFactory ~7 test +- [ ] **Phase 5** — FE Vitest cho lib utility (queryMatches, fmtMoney) ~10 test -### D. Deploy / Ops chưa xong +### E. Audit định kỳ (cron tự fire) -- [ ] **Remove binding cũ `.huypham.vn`** sau verify: `ssh vietreport-vps ; cd C:\solution-erp\scripts ; .\migrate-domains.ps1 -RemoveOld -SkipCert` -- [ ] **win-acme scheduled task "unhealthy"** — auto-renew fix trước 2026-06-18. -- [ ] UAT thật 1 tuần với 2-3 user (16 demo + 14 Solutions = 30 user) -- [ ] SMTP config → Email outbox -- [ ] Rotate creds (admin + 30 demo + SA + vrapp + JWT) -- [ ] Schedule SQL backup Task Scheduler +- [ ] **2026-05-01** (mai) — `solution-erp-skill-audit-monthly` cron fire 9:00. Combined audit theo §6.4 + §9.4 (skill staleness + doc drift + count consistency). Log → `docs/changelog/skill-audit-2026-05.md` ## ✅ Recently Done (newest on top) | Ngày | Ai | Task | Commit | |---|---|---|---| -| 2026-04-29 | Claude | **Tests Phase 3 mini + 3 gotcha CI mới (#39 #40 #41)** — `tests/.../Application/PeWorkflowAdminTests.cs` 6 test versioning logic (CreatePeWorkflowDefinition: first version IsActive=true, second deactivates first, different EvaluationType independent, persists steps ordered + approvers per step, third version increments to v3). Total **77 test** (54 Domain + 17 Infra + 6 PE WF Application). Gotcha #39 act_runner github.com TCP timeout 21s + manual checkout fix. #40 npm junction cache fail `tsc not found` rolled back. #41 paths-ignore behavior + workflow file exclusion. | (cur commit) | +| 2026-04-30 | Claude | **Session 6 — MD audit + compact + 3 skill refresh + 2 rule mới** — Compact 3 file core (-288 dòng): STATUS -27%, HANDOFF -32%, migration-todos -35%. Archive 51 row Recently Done Phase 0-7 → `changelog/recently-done-archive-2026-04.md`. Refresh 3 skill stale: `form-engine` (Phase 2 MVP → Tier 3 feature-complete + bỏ section duplicate gen mã HĐ), `permission-matrix` (12 menu → ~60 menu key + Bg_*/Pe_*/PeWf_* + inheritance roots), `ef-core-migration` (24 DbSet → 52 bảng + ERD update). Rule mới `rules.md §7 Khi nào viết test — timing rule` (5-row table compact, sau khi rút gọn từ 70 dòng overkill). Rule mới `rules.md §6.4 Audit + compact MD định kỳ` (cadence + checklist + anti-pattern, KHÔNG rewrite toàn bộ). `rules.md §9.4 Skill audit` mở rộng cross-ref §6.4. | (current) | +| 2026-04-29 | Claude | **Tests Phase 3 mini + 3 gotcha CI mới (#39 #40 #41)** — `tests/.../Application/PeWorkflowAdminTests.cs` 6 test versioning logic (CreatePeWorkflowDefinition: first version IsActive=true, second deactivates first, different EvaluationType independent, persists steps ordered + approvers per step, third version increments to v3). Total **77 test** (54 Domain + 17 Infra + 6 PE WF Application). Gotcha #39 act_runner github.com TCP timeout 21s + manual checkout fix. #40 npm junction cache fail `tsc not found` rolled back. #41 paths-ignore behavior + workflow file exclusion. | `b874743` | | 2026-04-29 | Claude | **CI Path filter docs-only skip live** — `paths-ignore` trong on:push lookup `docs/**`/`**/*.md`/`.claude/skills/**`/`.gitignore`. Commit chỉ touch docs SKIP CI hoàn toàn (saving ~196s/commit, ~30% commit thuộc loại này). Verify `512880c` (docs-only) → Gitea NO trigger run #113. | `29eb5d9` · `a21790d` · `512880c` | | 2026-04-29 | Claude | **CI manual checkout bypass github.com (fix #108/#109)** — Run #108/#109 fail TCP timeout 21s khi act_runner fetch `actions/checkout@v4` từ github.com. Replace `uses: actions/checkout@v4` + `actions/upload-artifact@v4` bằng manual `git init` + `git fetch` từ Gitea internal. Token `${{ github.token }}` auth tự sẵn per-job. Fetch by ref + depth=30. Run #110 pass 3m16s. | `14b7d18` · `26075c4` | | 2026-04-29 | Claude | **Tests Phase 2 — Code generator format + sequence (SQLite in-memory)** — `tests/SolutionErp.Infrastructure.Tests/` xUnit + EF SQLite 10. `SqliteDbFixture` + `TestApplicationDbContext` subclass override `nvarchar(max) → TEXT` (SQLite không support `max`). 17 test: ContractCodeGenerator (format RG-001 5 type + Framework year scope vs Project scope + sequence per prefix + year boundary reset + persistence verify) + PurchaseEvaluationCodeGenerator (format A/B + 3-digit pad + independent A/B sequences + year boundary). CI gate +1 step. Total 71 test pass / 2.1s. | `df5988b` | diff --git a/docs/changelog/migration-todos.md b/docs/changelog/migration-todos.md index d1dd6ef..b66438c 100644 --- a/docs/changelog/migration-todos.md +++ b/docs/changelog/migration-todos.md @@ -84,6 +84,14 @@ Session logs: `2026-04-23-2300-purchase-evaluations.md` · `2026-04-24-chot-sess ## 📝 Phase 9 — UAT + Ops + carry over (Session 6+ active) +### ✅ Session 6 done (2026-04-30 — pure docs work) + +- [x] **MD audit + compact** — STATUS -27%, HANDOFF -32%, migration-todos -35%, archive 51 row Phase 0-7 cũ +- [x] **3 skill refresh** — `form-engine` Phase 2 MVP → Tier 3 feature-complete, `permission-matrix` 12 menu → ~60 + inheritance roots, `ef-core-migration` 24 DbSet → 52 bảng +- [x] **Rule mới rules.md §7** — Khi nào viết test (timing rule 5-row table) +- [x] **Rule mới rules.md §6.4** — Audit + compact MD định kỳ (cadence + checklist + anti-pattern) +- [x] **rules.md §9.4** — Mở rộng skill audit cross-ref §6.4 + ### A. Hard blockers (chờ user / ops) - [ ] UAT thật 1 tuần với 2-3 user (30 demo: 16 sample + 14 Solutions thật) diff --git a/docs/changelog/sessions/2026-04-30-chot-session-6-md-audit-compact.md b/docs/changelog/sessions/2026-04-30-chot-session-6-md-audit-compact.md new file mode 100644 index 0000000..7a090e3 --- /dev/null +++ b/docs/changelog/sessions/2026-04-30-chot-session-6-md-audit-compact.md @@ -0,0 +1,157 @@ +# Session log — 2026-04-30 chốt session 6 — MD audit + compact + 3 skill refresh + 2 rule mới + +**Topic:** Pure docs work — audit toàn bộ MD, compact 3 file core, refresh 3 skill stale, chốt 2 rule mới (timing test §7 + audit định kỳ §6.4). 0 thay đổi code/test. + +**Dev:** Claude (Opus 4.7) + user (pqhuy1987@gmail.com) +**Duration:** ~2 giờ (bao gồm Q&A về unit test philosophy) +**Base commit:** `b874743` (chốt session 5) + +## Commits session 6 + +- `d2298fa` — Docs: chốt rule timing unit test (1 bảng 5-row compact) +- `f24acb6` — Docs: compact 3 file core (-273 dòng tổng) +- (commit chốt session 6 này) + +## A. Q&A unit test philosophy + +User hỏi: +1. Ý nghĩa unit test? Lợi ích? +2. Khi spec đổi (không phải bug) thì test thế nào? +3. Khi bug fix thì test thế nào? +4. Có nên áp rule? → user confirm. +5. Rule mới có overkill không? → user nhận xét sắc. +6. Có nên rewrite MD định kỳ? → user hỏi nghiêm túc. + +**Outcome:** +- Chốt rule timing test (rules.md §7) — 1 bảng 5-row compact, sau khi rút gọn từ 70 dòng overkill ban đầu +- Chốt rule audit + compact MD định kỳ (rules.md §6.4) — KHÔNG rewrite toàn bộ +- Lưu feedback memory `feedback_unittest_timing.md` cho session sau + +## B. MD compact (commit `f24acb6`) + +| File | Trước | Sau | Δ | +|---|---|---|---| +| STATUS.md | 196 | 144 | -27% | +| HANDOFF.md | 460 | 313 | -32% | +| migration-todos.md | 210 | 136 | -35% | +| recently-done-archive-2026-04.md | (mới) | 61 | archive 51 row Phase 0-7 | + +**Pattern:** +- STATUS Recently Done > 30 row → archive cũ vào `changelog/recently-done-archive-{YYYY-MM}.md` +- HANDOFF section duplicate (Versioned WF / File active / Git state) → cross-ref thay vì copy +- migration-todos Phase done → collapse thành 1 paragraph + cross-ref session log + +**0 information loss** — tất cả nội dung vẫn còn ở file gốc (gotchas, rules, architecture, schema-diagram, session logs). + +## C. 3 skill refresh (commit chốt session) + +### form-engine/SKILL.md +- Status: "Phase 2 MVP — missing PDF + form builder" → "Tier 3 feature-complete" +- Known limitations: 6 row → 4 row, đánh dấu DONE Phase 8 +- "Gen mã HĐ chưa implement" → DONE Phase 3+6, cross-ref `contract-workflow` skill (bỏ duplicate) + +### permission-matrix/SKILL.md +- Description: 12 menu + 48 policy → ~60 menu + ~240 policy +- Menu tree section: 12 menu cũ → ~60 với Pe_*/PeWf_*/Bg_*/Catalogs đầy đủ +- Inheritance roots: 4 group (Contracts/Workflows/PE/PeWorkflows). Budgets KHÔNG inherit (gotcha #35). + +### ef-core-migration/SKILL.md +- Code pointers: "ApplicationDbContext.cs — 24 DbSet" → "DbSet cho 52 bảng (15 migration)" +- Related: "ERD 24 bảng" → "ERD 52 bảng + §11 PE + §12 Budget + §13 PEDeptOpinions" + +## D. 2 rule mới chốt + +### rules.md §7 — Khi nào viết test (timing rule) + +``` +| Tình huống | Quy tắc | +| Feature mới | Test-after: UAT 2-3 lần ổn → viết test (≤1 commit theo sau) | +| Bug fix | Test-before BẮT BUỘC: reproduce bằng test failing → fix → green | +| Critical algorithm (codegen/guard/financial/security) | Test-before merge | +| Spec change | Update test cũ + code, commit chung. KHÔNG xóa, KHÔNG skip. | +| Skip | DTO mapping, CRUD master, FE snapshot, wrapper, migration backfill | +``` + +Rút gọn từ 70 dòng overkill (decision tree ASCII + triết lý chung + bảng critical algorithm chi tiết) còn 6 dòng. User nhận xét đúng — overkill thật. + +### rules.md §6.4 — Audit + compact MD định kỳ + +| Tần suất | Action | Effort | +|---|---|---| +| Cuối session | Update STATUS + HANDOFF | ~10 phút | +| Cuối phase (~1 tháng) | Compact STATUS Recently Done > 30 row → archive | ~30 phút | +| Đầu mỗi tháng (cron) | Audit skill + doc drift + count consistency, patch (Edit, không rewrite) | ~45 phút | +| Khi trigger riêng | Selective rewrite 1 file (drift > 30%) | 1-2 giờ | +| KHÔNG BAO GIỜ | Rewrite toàn bộ docs | — | + +**Doc audit checklist** (mở rộng từ §9.4 skill audit, chạy cùng cron): +1. `dotnet test` count khớp STATUS/CLAUDE/HANDOFF +2. `ls migrations/` count khớp ef-core-migration skill +3. `grep '#[0-9]\+' gotchas.md` count khớp HANDOFF/STATUS +4. STATUS Recently Done > 30 row → đề xuất archive +5. HANDOFF section duplicate → đề xuất bỏ +6. Skill SKILL.md mention "Phase N MVP" mà N <= phase hiện tại → stale +7. Output report → human review patch (Edit, KHÔNG Write toàn file) + +**§9.4 Skill audit** mở rộng cross-ref §6.4 — chạy chung cron `solution-erp-skill-audit-monthly`. + +## E. Verify state cuối session + +``` +✅ 77 test pass (Domain 54 + Infra 23) — chạy `dotnet test SolutionErp.slnx` +✅ 15 migration / 52 bảng / 41 gotcha — khớp docs +✅ 6 skill (3 refresh trong session) +✅ Cron 2026-05-01 ready fire mai (combined audit) +✅ MEMORY.md có 3 entry (project + node CI/CD + unit test timing) +``` + +## F. Files touched session 6 + +``` +docs/rules.md (mod: §7 Timing test rule + §6.4 doc audit + §9.4 cross-ref) +docs/STATUS.md (mod: Phase 9 active + Session 6 Recently Done + cron 05-01) +docs/HANDOFF.md (mod: TL;DR session 6 + cảnh báo session 7+, bỏ 3 section duplicate) +docs/changelog/migration-todos.md (mod: Phase 6-7 collapse, Phase 9 + Session 6 done sub) +docs/changelog/recently-done-archive-2026-04.md (NEW: 51 row archive) +docs/changelog/sessions/2026-04-30-chot-session-6-md-audit-compact.md (NEW: file này) +.claude/skills/form-engine/SKILL.md (mod: refresh Phase 2 MVP → Tier 3 done) +.claude/skills/permission-matrix/SKILL.md (mod: refresh 12 menu → ~60 + inheritance roots) +.claude/skills/ef-core-migration/SKILL.md (mod: refresh count 24 → 52) +CLAUDE.md (root) (mod: timing test compact 1 dòng) +~/.claude/.../memory/feedback_unittest_timing.md (NEW: feedback memory) +~/.claude/.../memory/MEMORY.md (mod: index +1 entry) +``` + +## G. Cảnh báo session 7 + +1. **Cron `solution-erp-skill-audit-monthly` fire 2026-05-01 9:00** — combined audit theo §6.4 + §9.4 checklist. Log → `docs/changelog/skill-audit-2026-05.md`. Session sau verify cron đã fire OK. +2. **Hard blockers ops vẫn chờ user** — UAT 1 tuần / SMTP / rotate creds / SQL backup schedule. +3. **3 feature mới chưa test** (PE Opinion Upsert / Budget validate / Contract BudgetId carry) — đợi UAT phát sinh bug → áp §7 rule (regression test before fix). +4. **win-acme** schedule task unhealthy — fix trước cert expire 2026-06-18. +5. **MD compact pattern** lần kế: cuối Phase 9 (sau UAT) — STATUS Recently Done > 30 row archive lần 2. + +## H. Lessons learned session 6 + +1. **User feedback on overkill** — Claude tendency là viết quá dài. Lần đầu rule timing test = 70 dòng (decision tree ASCII + triết lý + bảng chi tiết). User catch ngay → rút còn 6 dòng. Bài học: skill audit phải có "compact pass" sau draft đầu. +2. **Rewrite vs compact** — User hỏi nghiêm túc "rewrite toàn bộ định kỳ" và push back tốt khi tôi suggest 4 chiến lược (compact / audit / selective rewrite / never full rewrite). Confirm: drift là normal, fix bằng patch, KHÔNG rewrite. +3. **Skill staleness là silent killer** — `form-engine` lifeline "Phase 2 MVP missing PDF" survived qua nhiều session vì chỉ Claude đọc trước khi auto-invoke. User không thấy trực tiếp. Cron audit định kỳ là cơ chế duy nhất catch được. +4. **Feedback memory path** — Lưu rule vào memory file giúp session sau (không có conversation history) tự áp dụng. 3 entry hiện tại: project overview / Node CI/CD pin / unit test timing. Không bloat — chỉ rule actionable. +5. **Path filter CI làm việc cực tốt cho docs-heavy session** — session 6 có 3 commit, đều skip CI (0s deploy). Saving lớn nếu maintain pattern này. + +## I. Stats sau session 6 + +| | Trước S6 | Sau S6 | +|---|---:|---:| +| BE LOC | ~13050 | ~13050 (no code change) | +| DB tables | 52 | 52 | +| Migrations | 15 | 15 | +| API endpoints | ~128 | ~128 | +| FE pages | ~31 | ~31 | +| Tests | 77 | 77 (no test change) | +| Gotchas | 41 | 41 | +| **Skill** | 6 (3 stale) | **6 (3 refresh)** | +| **Docs lines core 3 file** | 866 | **593** (-273, -32%) | +| **Memory entries** | 2 | **3** (+unit test timing) | +| Demo user | 30 | 30 | +| Commits S6 | 0 | **3** (rule + compact + chốt) | +| Session log files | 17 | **18** | diff --git a/docs/rules.md b/docs/rules.md index 344c779..4539452 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -270,6 +270,41 @@ Co-Authored-By: Claude Opus 4.7 (1M context) - Thêm pattern → update skill tương ứng ở `.claude/skills/` - Phase đổi → update [`STATUS.md`](STATUS.md) + [`HANDOFF.md`](HANDOFF.md) + [`changelog/migration-todos.md`](changelog/migration-todos.md) +### 6.4 Audit + compact MD định kỳ + +**Triết lý:** KHÔNG rewrite toàn bộ. Chỉ **compact + patch drift** định kỳ. Test/code là source of truth, MD theo sau. + +**Cadence + trigger:** + +| Tần suất | Action | Effort | Trigger | +|---|---|---|---| +| **Cuối session** (đã làm tự động) | Update STATUS Recently Done + HANDOFF cảnh báo session tiếp | ~10 phút | Mỗi session có code commit | +| **Cuối phase** (~1 tháng) | Compact STATUS Recently Done > 30 row → `changelog/recently-done-archive-{YYYY-MM}.md`. Collapse migration-todos Phase done thành 1 paragraph cross-ref session log | ~30 phút | Phase đóng | +| **Đầu mỗi tháng** (cron `solution-erp-skill-audit-monthly`) | Audit skill + doc drift + count consistency. Patch stale qua Edit (KHÔNG rewrite). Log kết quả | ~45 phút | 9:00 ngày 1 mỗi tháng | +| **Khi trigger riêng** | Selective rewrite 1 file (skill drift > 30%, architecture redesign, phase major) | 1-2 giờ | Quantitative trigger | +| **KHÔNG BAO GIỜ** | Rewrite toàn bộ docs | — | — | + +**Doc audit checklist (mở rộng từ §9.4 skill audit, chạy cùng cron):** + +``` +1. dotnet test SolutionErp.slnx → verify count khớp STATUS/CLAUDE/HANDOFF +2. ls migrations/ → verify count khớp ef-core-migration skill + database-guide +3. grep '#[0-9]\+' gotchas.md → verify khớp count claim trong HANDOFF/STATUS +4. ls .claude/skills/ → verify khớp count trong rules §9 + skills/README +5. STATUS Recently Done > 30 row? → đề xuất archive cũ +6. HANDOFF có section duplicate file khác (PROJECT-MAP/workflow/git log)? → đề xuất bỏ +7. Skill SKILL.md mention "Phase N MVP" mà N <= phase hiện tại? → stale, refresh +8. Output report stale items + suggest patches → human review +9. Log vào docs/changelog/skill-audit-{YYYY-MM}.md (1 page max) +``` + +**Anti-pattern (đã trải nghiệm):** +- ❌ Rewrite toàn bộ MD định kỳ — mất context, paraphrase mất nuance, ROI thấp +- ❌ Bulk-clone 3rd party docs — đã từ chối ở Skill governance §9.5 +- ❌ Skip audit "vì sắp UAT/sắp deploy" — drift tích lũy → onboard agent mới sai + +**Trigger override:** User nói "audit MD", "kiểm tra docs", "định kỳ kiểm tra", "compact docs" → chạy doc audit ngay không đợi cron. + ## 7. Testing (Phase 8 active — 77 test pass + CI gate live) ### Stack đã apply @@ -410,37 +445,37 @@ when-to-use: ## Related (dẫn chiếu gotcha #N, docs/...) ``` -### 9.4 Audit định kỳ — mỗi 4 tuần +### 9.4 Audit định kỳ — mỗi đầu tháng (chạy chung với doc audit §6.4) -**Cadence:** Mỗi đầu tháng (hoặc thứ Hai tuần đầu tháng), chạy audit skill list: +**Cadence:** Đầu mỗi tháng, cron `solution-erp-skill-audit-monthly` fire 9:00 ngày 1 → chạy combined audit (skill + doc drift theo §6.4 checklist). + +**Skill audit phần riêng (mỗi skill SKILL.md):** ``` 1. Đọc .claude/skills/README.md — list 6 skill hiện có -2. Cross-check với: - - docs/STATUS.md "Recently Done" — feature mới nào chưa có skill cover? - - docs/gotchas.md — gotcha mới (>3 dòng) nào nên gom thành skill mới? - - migration-todos.md "In Progress" / "Next up" — task lớn sắp tới có cần skill? -3. Check repo nguồn skill 3rd party có gì mới: - - https://github.com/alirezarezvani/claude-skills (default-branch) - - Anthropic skills built-in (xem system reminder skill list) -4. Đánh giá staleness: - - Mỗi skill: SKILL.md có còn match code thực tế không? - - Trigger phrases có còn hiệu quả? - - Code pointers có còn đúng path? -5. Hành động: - - Skill stale → update SKILL.md + commit `[CLAUDE] Skill: refresh ` +2. Cross-check stale: + - SKILL.md mention "Phase N MVP" mà N < phase hiện tại → stale + - Code pointers paths có còn tồn tại không (Glob check) + - Count claim (vd "24 DbSet", "13 migration") khớp thực tế không + - Trigger phrases có còn hiệu quả không +3. Cross-check feature gap: + - docs/STATUS.md Recently Done — feature mới nào chưa có skill cover? + - docs/gotchas.md — gotcha mới (>3 dòng / cluster) nào nên gom thành skill? + - migration-todos.md — task lớn sắp tới có cần skill mới? +4. Hành động: + - Skill stale → Edit SKILL.md (KHÔNG rewrite) + commit `[CLAUDE] Skill: refresh ` - Skill cần thêm → tạo theo §9.2 §9.3 + commit `[CLAUDE] Skill: add ` - Skill không còn cần → archive vào .claude/skills/_archived/ + commit -6. Update bảng §9.1 trong rules.md + .claude/skills/README.md + docs/CLAUDE.md count -7. Log vào docs/changelog/skill-audit-{YYYY-MM}.md (1 page max) +5. Update bảng §9.1 trong rules.md + .claude/skills/README.md + docs/CLAUDE.md count +6. Log skill + doc drift report vào docs/changelog/skill-audit-{YYYY-MM}.md (1 page max) ``` -**Trigger:** Khi user nói "audit skill", "check skill list", "skill staleness", "định kỳ kiểm tra skill" → chạy workflow này. +**Trigger:** User nói "audit skill", "check skill list", "skill staleness", "audit MD", "kiểm tra docs", "định kỳ kiểm tra" → chạy combined audit (§6.4 + §9.4) ngay không đợi cron. -**Lịch chính thức:** -- Tháng 1, 2, 3, ... — đầu tháng audit (1 buổi sáng) -- Hoặc khi bắt đầu Phase mới (vd Phase 6) → audit ngay trước phase -- Hoặc khi `docs/gotchas.md` vượt mốc (cứ +5 gotcha thì xem có gom thành skill được không) +**Threshold trigger ngoài cron:** +- `gotchas.md` +5 gotcha mới → audit (xem có gom thành skill mới được không) +- Phase mới đóng → audit ngay (track stale từ feature mới) +- Skill drift > 30% (count check, path broken, mention phase cũ) → selective rewrite ### 9.5 Anti-patterns