Files
solution-erp/docs/rules.md
pqhuy1987 7dc0233f08 [CLAUDE] Docs+Skill: audit định kỳ 2026-05 — 6 file patch + 1 log page
Combined audit (skill staleness + doc drift) theo §6.4 + §9.4. Cron 2026-05-01 trễ 4 ngày (cron empty), chạy manual 2026-05-04 sau Session 9 close Chunk E-bis.

Drift patched (Phase 1 — count cross-check):
- docs/CLAUDE.md:70    52 bảng → 55 bảng (+§14 DepartmentApprovals Mig 16)
- docs/rules.md:368    Phase 8 active — 77 test → Phase 9 — 83 test
- docs/architecture.md:329, 365   77 test → 83 test (2 chỗ)
- .claude/skills/ef-core-migration/SKILL.md:52    77 test → 83 test + ghi 6 PE 2-stage S9
- .claude/skills/dependency-audit-erp/SKILL.md:153    26+ bẫy → 41 bẫy

Skill content patch (Phase 2 — staleness):
- contract-workflow: thêm "Phase 9 cross-ref (Mig 16)" block + section "Phase 9 done" (2-stage dept approval + smart reject + lock edit + CanBypassReview)
  → KHÔNG tạo skill 2-stage riêng (§9.5 anti-pattern "viết skill chỉ để có thêm")

KEEP per §6.5 (không cắt narrative):
- docs/rules.md:328 "52 bảng" example minh họa rule §6.5
- docs/changelog/migration-todos.md:152, 196 historical session record
- 9 session log mention 77/52 — snapshot lịch sử

Total patches: 6 file ~+30 / ~12 lines, KHÔNG rewrite, đáp ứng 3 câu validation §6.5.

Audit log: docs/changelog/skill-audit-2026-05.md (1 page max per cadence).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:53:51 +07:00

24 KiB

Rules — Coding Conventions SOLUTION_ERP

Nguồn duy nhất cho rules. Bất cứ commit nào vi phạm cần justify trong message.

1. Ngôn ngữ

Thành phần Ngôn ngữ
UI FE 100% tiếng Việt
Code (.cs/.ts) English (tên biến/hàm/class)
Comment code Tiếng Anh hoặc Việt — miễn rõ
Tên DB table + column English PascalCase (Contracts, SupplierId)
Business label Tiếng Việt (vd "Đang soạn thảo" cho phase 2)
Commit message English hoặc Việt — preferred English
Doc MD (docs/) Tiếng Việt (audience là người Việt)

2. Backend — .NET 10

2.1 Clean Architecture dependency rule

Api → Application ← Domain
      ↑
Infrastructure ──┘
  • Domain: pure, chỉ dùng Microsoft.Extensions.Identity.Stores (cần cho IdentityUser) — không depend ASP.NET Core framework
  • Application: depend Domain; CQRS handlers + interfaces + DTOs + validators
  • Infrastructure: depend Application + Domain; impl interfaces (EF, JWT, rendering, services)
  • Api: depend Application + Infrastructure; Controllers + middleware + composition root

2.2 CQRS + MediatR pattern

  • 1 feature = 1 file {Verb}{Entity}Command.cs / {Verb}{Entity}Query.cs
  • File chứa: Command record + Validator + Handler (cùng 1 file cho compact)
  • Dài thì tách: {Feature}/Commands/{Create}/...

Command naming:

Create{Entity}Command      // tạo mới
Update{Entity}Command      // update full
Patch{Entity}FieldCommand  // update 1 field
Delete{Entity}Command      // soft delete (default)
{Action}{Entity}Command    // action domain-specific (vd TransitionContract)

Query naming:

Get{Entity}Query            // single by Id
List{Entity}sQuery          // list với paging
{Entity}{Purpose}Query      // custom query (vd GetMyInboxQuery)

2.3 Validation

  • FluentValidation (KHÔNG dùng DataAnnotation)
  • Validator = class trong cùng file command: {Command}Validator : AbstractValidator<{Command}>
  • Pipeline: ValidationBehavior auto-chạy trước Handler — throw ValidationException → 400 ProblemDetails

2.4 Error handling

  • KHÔNG try-catch ở Controller
  • Throw domain exception: NotFoundException, ForbiddenException, UnauthorizedException, ConflictException, ValidationException
  • GlobalExceptionMiddleware map exception → HTTP status + ProblemDetails JSON
  • Logging: Serilog structured, không Console.WriteLine

2.5 Async/await

  • Tất cả I/O (DB, HTTP, file) PHẢI async
  • Truyền CancellationToken mọi async call
  • Tên method async: suffix Async (trừ ASP.NET action signature)

2.6 Entity rules

  • Mọi entity mới extend BaseEntity (Id Guid + audit) hoặc AuditableEntity (+ soft delete)
  • PK: Id type Guid, default Guid.NewGuid() trong constructor
  • FK: {Entity}Id type Guid
  • Enum: HasConversion<int>() trong EF config
  • String: luôn HasMaxLength(n) trong EF config — không để nvarchar(max) trừ khi là JSON/rich text
  • Money: decimal + HasPrecision(18, 2)
  • DateTime: luôn UTC, lấy từ IDateTime.UtcNow (không DateTime.Now)
  • Query filter soft delete: HasQueryFilter(x => !x.IsDeleted) cho AuditableEntity

2.7 DI registration

  • Singleton: stateless services (DateTimeService, FormRenderer)
  • Scoped: per-request services (JwtTokenService, ContractWorkflowService, DbContext)
  • Transient: lightweight utility (hiếm dùng)

2.8 Package version pinning

  • KHÔNG dùng * hoặc latest — luôn pin version cụ thể
  • Check compatibility với .NET 10 trước khi add. Gotchas đã biết:
    • MediatR 14 → lỗi IMediator DI, pin 12.4.1
    • Swashbuckle 10 → conflict OpenApi 2, pin 6.9.0
  • Xem gotchas.md cho full list

3. Frontend — React 19 + Vite 8 + TS 6

3.1 Named export, không default export

// ✅
export function SuppliersPage() { }
export const MyConstant = 1

// ❌
export default function SuppliersPage() { }

// Exception: App.tsx dùng default export (Vite convention)

3.2 erasableSyntaxOnly (Vite 8)

KHÔNG dùng enum — dùng const-object pattern:

// ❌
export enum SupplierType { NhaCungCap = 1 }

// ✅
export const SupplierType = { NhaCungCap: 1, NhaThauPhu: 2 } as const
export type SupplierType = typeof SupplierType[keyof typeof SupplierType]

3.3 Path alias

  • Dùng @/ cho absolute import: import { api } from '@/lib/api'
  • Config ở vite.config.ts + tsconfig.app.json (chỉ paths, không baseUrl)

3.4 Data fetching

  • TanStack Query cho mọi API call (KHÔNG useState + useEffect thủ công)
  • useQuery cho GET, useMutation cho POST/PUT/DELETE
  • invalidateQueries sau mutation thành công

3.5 API calls

  • Qua api instance (src/lib/api.ts) — đã wire axios interceptor JWT + 401 redirect
  • Base URL: /api (Vite proxy → :5443)

3.6 Permission guard

<PermissionGuard menuKey="Contracts" action="Update">
  <Button>Sửa</Button>
</PermissionGuard>

// Hook
const { can } = usePermission()
if (!can('Contracts', 'Update')) return null

Nhớ: FE guard chỉ là UX. BE policy [Authorize(Policy = "Contracts.Update")] là source of truth.

3.7 Component naming

  • PascalCase cho file: SuppliersPage.tsx, DataTable.tsx
  • kebab-case cho utility: api.ts, cn.ts
  • React component = PascalCase
  • Hook: prefix use, ví dụ usePermission

3.8 Toast + error

  • Dùng sonner (đã wire <Toaster> ở App)
  • toast.success('...'), toast.error(getErrorMessage(err))
  • Error helper: src/lib/apiError.ts extract từ ProblemDetails

3.9 Duplicate giữa 2 FE

CÓ CHỦ ĐÍCH. Mỗi app (fe-admin + fe-user) là standalone — copy shared code giữa 2 app thay vì extract ra package chung. Lý do: 2 app có UX rất khác (admin mission-critical, user workflow-heavy), evolution độc lập.

Khi share code: cp file từ app này sang app kia. Đồng bộ tay khi có breaking change.

4. Database

4.1 Convention

Item Rule
Schema 1 schema duy nhất: dbo
Table PascalCase tiếng Anh, plural: Contracts, Suppliers
Column PascalCase: FullName, CreatedAt
PK Iduniqueidentifier
FK {Entity}Iduniqueidentifier
Index IX_{Table}_{Col}
Unique UX_{Table}_{Col}

Full: xem database/database-guide.md.

4.2 Migration

  • Một commit = 1 migration (trừ khi nhiều change nhỏ trong cùng feature)
  • Naming PascalCase: AddMasterData, AddContractsWorkflow
  • Commit đủ 3 file: {Name}.cs, {Name}.Designer.cs, ApplicationDbContextModelSnapshot.cs

5. Git & commits

5.1 Branch

  • main — deploy branch
  • Feature branch (nếu nhiều người): feature/phase{N}-{feature}

5.2 Commit format

[CLAUDE] <scope>: <imperative message>

<body optional — chi tiết what + why>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Scope: Contract · Form · Workflow · Supplier · Auth · Admin · Api · App · Domain · Infra · FE-Admin · FE-User · Docs · CICD · Scripts · Report · Dashboard

5.3 Một commit nên

  • Build pass (BE + FE)
  • Không leave WIP nửa chừng (trừ khi commit message nói rõ)
  • Test E2E với endpoint mới (curl trong session log)

5.4 Không commit

  • .env, appsettings.*.Local.json
  • node_modules/, bin/, obj/
  • wwwroot/uploads/ (user files)
  • SolutionErp_Design database (tạm cho EF CLI)

6. Docs

6.1 Khi nào viết session log

  • Session có commit thay đổi code → PHẢI tạo docs/changelog/sessions/YYYY-MM-DD-HHMM-{topic}.md
  • Session chỉ Q&A, không đụng file → không cần

6.2 Session log format

# Session YYYY-MM-DD HH:MM — <topic>

**Dev:** Claude / Copilot / <name>
**Duration:** ~Nh
**Base commit:** <sha>

## Làm được

### Chunk X — <name>
- bullet list deliverable

## E2E verified

<curl output hoặc screenshot>

## Bug gặp + fix

| Bug | Fix |

## Docs updates

## Handoff

## Thông số cumulative

6.3 Update khi thêm feature

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.

6.5 Consolidate MD đúng cách — KEEP vs CUT

Bài học session 6 (2026-04-30): Compact -288 dòng nhanh, paraphrase + cắt narrative để "rõ đẹp" → user phản hồi "viết MD gọn lại tý là mất mẹ luôn tính cách cũ". Docs đọc 6 tháng sau như machine output, không hiểu tại sao chọn approach. Rule §6.5 này chốt để KHÔNG TÁI PHẠM.

Mục tiêu consolidate: Giảm độ dài để session sau đọc context không mệt. KHÔNG = cắt thông tin / paraphrase / "đẹp hóa".

KEEP — CẤM CẮT (asset không tái tạo được)

Loại Vì sao bắt buộc giữ NGUYÊN VĂN Ví dụ
Narrative tích lũy qua sessions Không tái tạo. Là tài sản chỉ ra "đã đi qua đâu, đã đổi hướng ra sao" "Ban đầu chọn MediatR 14, fail DI runtime, downgrade 12.4.1"
Rationale (lý do quyết định) Quan trọng hơn quyết định. Mất rationale → agent mới revert vì không biết tại sao "Pin Swashbuckle 6.9.0 vì 10.x conflict OpenApi 2", "Skip E2E Playwright vì brittle cho solo dev"
Gotcha context (incident bối cảnh) Gotcha = fix + bối cảnh đau. Mất context → instructions khô không apply được G-084 "Next.js bind 0.0.0.0 → Gitea fallback IPv6 → IIS ARR resolve IPv4 first → leak homepage"
Anecdote / bài học Nuance không có trong code/git, chỉ có trong docs "Bài học NamGroup: Node latest fail CI Windows"
Decision why over decision what Code chỉ có "what", docs phải bù "why" "PE workflow tách enum riêng vì Phase ≠ ContractPhase"

CUT — XÓA hoặc CHUYỂN CHỖ được

Loại Cách xử lý Ví dụ
Số liệu lặp giữa nhiều file Giữ 1 chỗ canonical, các file khác cross-ref "52 bảng" canonical ở PROJECT-MAP, STATUS/HANDOFF cross-ref
Section duplicate copy-paste Cross-ref thay vì copy nguyên văn "Versioned WF quick ref" → cross-ref workflow-contract.md §7bis
List Recently Done > 30 row Archive sang file riêng recently-done-archive-{YYYY-MM}.md (CHUYỂN CHỖ, KHÔNG xóa) Phase 0-7 cũ
Phase đã đóng > 1 tháng Collapse thành 1 paragraph + link session log đầy đủ Phase 0-5 → "Phase 0-5 done, session logs"
Stats lặp Cumulative table giữ ở STATUS, file khác chỉ con số mới nhất LOC / endpoint / migration count

CẤM TUYỆT ĐỐI

  • Paraphrase câu chữ original — dù "rõ ràng hơn", KHÔNG paraphrase. Giữ y nguyên văn cũ.
  • Summary đoạn đã có narrative — không tóm tắt 5 dòng kể chuyện thành 1 dòng "X done". Mất context.
  • "Đẹp hóa" bằng cách cắt — đẹp đạt qua format (bảng, anchor link, heading), KHÔNG qua cắt nội dung.
  • Compact với mindset machine-first — viết cho agent mới đọc 6 tháng sau hiểu, KHÔNG phải tổng hợp ngắn nhất.

Decision tree khi gặp đoạn dài

Đoạn này có narrative / rationale / gotcha context / anecdote / "tại sao"?
├─ Có → GIỮ NGUYÊN VĂN, kể cả dài (lossless)
└─ Không → kiểm tra:
    ├─ Duplicate file khác?      → cross-ref
    ├─ Số liệu cũ stale?         → archive sang file riêng
    ├─ Phase đã đóng > 1 tháng?  → collapse + link session log
    └─ KHÔNG match gì            → GIỮ NGUYÊN (default lossless)

Validation sau consolidate (BẮT BUỘC chạy)

Đọc lại file đã compact, tự hỏi 3 câu:

  1. Agent mới đọc 6 tháng sau có biết "tại sao chọn approach này" không?
  2. Có còn cảm giác "kể chuyện" tích lũy không, hay chỉ là instructions khô?
  3. Gotcha context vẫn còn ý nghĩa khi đọc rời rạc không?

→ Nếu "không" cho bất kỳ câu nào → revert đoạn đó về nguyên văn cũ.

Trigger áp §6.5

  • Audit định kỳ §6.4 (cron đầu tháng)
  • User nói "consolidate", "compact", "gọn lại MD", "rõ ràng MD"
  • Cuối phase đóng (>1 tháng) khi compact STATUS/HANDOFF/migration-todos

7. Testing (Phase 9 active — 83 test pass + CI gate live)

Stack đã apply

  • xUnit 2.9.3 + FluentAssertions 7.2 (pin trước v8 commercial license)
  • Microsoft.EntityFrameworkCore.Sqlite 10 (in-memory testing — supports transactions, không như InMemory provider)
  • Custom TestApplicationDbContext override nvarchar(max) → TEXT cho SQLite compat (xem tests/.../Common/SqliteDbFixture.cs)
  • NO mock framework (tránh mock-heavy, prefer EF in-memory hoặc fake data)

Test pyramid (bottom-heavy, KHÔNG E2E)

✅ Phase 1: Domain policy            54 test  (pure functions, no DB)
✅ Phase 2: Infra code generator     17 test  (SQLite in-mem)
✅ Phase 3 mini: Application versioning  6 test  (SQLite, no UserManager)
⏸️ Phase 3 full: Application handlers w/ Identity (cần UserManager DI helper)
⏸️ Phase 4: API smoke (WebApplicationFactory)
⏸️ Phase 5: FE Vitest cho lib utility
❌ E2E (Playwright) — KHÔNG làm (brittle cho solo dev)

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). Pattern Phase 1-8 đã làm.
Bug fix Test-before BẮT BUỘC: reproduce bug bằng test failing → fix → green. "1 bug = 1 regression test before merge".
Critical algorithm (code generator atomic, workflow guard, financial calc, security check) Test-before merge — edge case nhiều, race condition đắt nếu break prod.
Spec change (không phải bug) Update test cũ + code, commit chung. KHÔNG xóa, KHÔNG skip test cũ. Coverage chỉ tăng.
Skip test DTO mapping, CRUD master đơn giản, FE component snapshot, wrapper passthrough, migration backfill idempotent.

Quy tắc bổ sung mỗi feature mới

  • Domain entity / enum → 0 test (compile check đủ)
  • Domain policy method → 2-3 test (positive + negative + edge case)
  • CQRS handler có guard logic → 1 test mỗi guard branch
  • Migration mới → smoke test "DbInitializer chạy được + seed không lỗi"
  • API endpoint mới → 1 happy path smoke (cho endpoint critical)
  • Bug found in production / staging → 1 regression test BEFORE merge fix

Pattern: "1 bug found → 1 regression test added".

Workflow user end-of-task

# Sau mỗi task code (BẮT BUỘC trước commit code):
dotnet test SolutionErp.slnx        # local verify ~3s
git add -A && git commit -m "..."
git push                             # CI tự run test gate trước build/deploy

Test fail local → fix trước khi push. Test fail trên CI → no deploy.

CI gate behavior

.gitea/workflows/deploy.yml:

# Path filter: skip CI hoàn toàn cho commit MD-only
on:
  push:
    paths-ignore:
      - 'docs/**'
      - '**/*.md'
      - '.claude/skills/**'

# 2 step test gate trước build/deploy (fail → exit → no deploy)
- name: Run unit tests (Domain)
- name: Run integration tests (Infrastructure)

Pending (Phase 3-5 future)

  • Application handler tests cần Identity UserManager DI setup helper
  • API smoke tests via WebApplicationFactory + SQLite
  • FE Vitest cho lib/queryMatches, lib/cn, money formatter

Detail: docs/architecture.md §11 Testing strategy.

8. Security baseline

  • HTTPS everywhere prod
  • JWT Secret trong user-secrets / env var (không commit appsettings)
  • Password hash: PBKDF2 (Identity default)
  • CORS whitelist chỉ 2 FE origin
  • SQL injection: EF Core parameterized (không raw SQL trừ khi phải)
  • Audit log: mọi ghi phải log qua ContractApproval hoặc AuditLog (future)
  • Rate limit: /api/auth/login 5 req/min/IP (chưa implement — Phase 5)

9. Skills (.claude/skills/)

Project-level skills encode kiến thức SOLUTION_ERP-specific. Claude tự auto-invoke qua Skill tool dựa trên semantic match với description trong SKILL.md. PHẢI dùng skill khi gặp task tương ứng — không tự suy luận lại.

9.1 Skills hiện có (6)

Domain (3) — logic nghiệp vụ:

Skill Trigger khi
contract-workflow Bug chuyển phase, 403, mã HĐ sai, versioned WF, "HĐ cũ giữ cũ"
form-engine Render template docx/xlsx, FieldSpec, PDF export, upload form mới
permission-matrix Permission denied, gán role, menu không hiện, inherit Contracts/Workflows

Ops (3) — devops + security + schema:

Skill Trigger khi
dependency-audit-erp npm audit, dotnet vulnerable, scan CVE, nâng cấp package
ef-core-migration migrations add, schema change, snapshot lỗi, revert migration, DesignTimeDbContextFactory
iis-deploy-runbook Prod 500/502, cert hết hạn, restart app pool, gitea-runner fail, SignalR 401

9.2 Nguyên tắc tạo skill mới

Project-specific, KHÔNG clone generic. User-level skills global đã có sẵn (code-reviewer, sql-database-assistant, focused-fix, senior-frontend, mcp-builder, webapp-testing, review, security-review, ...). Project-level skills chỉ thêm khi:

  • Encode kiến thức SOLUTION_ERP-only (path, version pin, gotcha number, commit convention)
  • Generic skill không thể có (vd: 8 migration history cụ thể của project)
  • Có YAML when-to-use triggers rõ ràng (cả tiếng Việt + Anh)
  • Workflow Vietnamese-first (audience là dev Việt)

9.3 Format bắt buộc SKILL.md

---
name: kebab-case-name
description: 1-3 câu mô tả + stack specificity (cho semantic match đúng)
when-to-use:
  - "trigger english"
  - "trigger tiếng Việt"
---

# Skill Name

## Context
## Workflow / Commands (copy-pastable, không pseudocode)
## Pitfalls
## Code pointers (path đầy đủ src/Backend/...)
## Related (dẫn chiếu gotcha #N, docs/...)

9.4 Audit định kỳ — mỗi đầu tháng (chạy chung với doc audit §6.4)

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 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 <name>`
   - Skill cần thêm → tạo theo §9.2 §9.3 + commit `[CLAUDE] Skill: add <name>`
   - Skill không còn cần → archive vào .claude/skills/_archived/ + commit
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: 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.

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

KHÔNG bulk-clone repo skill 3rd party — phần lớn doc-dump generic, không có when-to-use, dễ trigger sai.

KHÔNG viết skill chỉ để "có thêm" — skill = trigger semantic match, nếu description quá chung sẽ trigger nhầm trong session khác.

KHÔNG copy nội dung skill từ docs/ sang SKILL.md — skill phải ngắn gọn, action-oriented; docs/ là reference dài. Skill dẫn chiếu docs.

KHÔNG bỏ qua skill khi gặp task khớp — tự suy luận lại = lãng phí context + dễ sai.

10. Liên quan