sg-md-writing thành skill bảo trì tri thức dự án cho AI:
- Gộp hướng dẫn viết skill/subagent/hook (từ writing-agent-context) vào.
- Bảng "đặt dòng ở đâu" theo chi phí nạp: root nạp mọi phiên; rule có `paths:`,
CLAUDE.md của module, skill, docs chỉ nạp khi cần.
- Chế độ sync: tự sửa đúng dòng .md bị sai trong cùng thay đổi, bump Last synced,
chỉ hỏi ý định code không trả lời được (bỏ cổng xác nhận từng file, phỏng vấn
từng câu, kiểm tra model yếu mỗi lần).
- Bỏ khẳng định sai "subagent không tự nạp CLAUDE.md" và lối viết in hoa.
21,6 KB → 9,1 KB.
sg-prompt-sharpening: tự lấp chỗ thiếu từ dự án, hiện bản prompt đã làm rõ
(mục tiêu, ở đâu, xong khi, giả định) rồi làm; chỉ hỏi một câu (có đề xuất)
khi các cách hiểu dẫn tới việc khác nhau; không kích hoạt với yêu cầu đã đủ rõ.
Eval (claude plugin eval, 2 lượt/case, có skill vs không):
- sharpening 3/3 (trước 2/3), Δ +0.67
- md-writing 5/5 (trước 1/5), Δ +0.40
@@ -7,8 +7,8 @@ Marketplace nội bộ chứa các skill Claude Code của Smartgift. Đăng ký
| Plugin | Dành cho | Skill | Nội dung |
|---|---|---|---|
| `sg-all` | **Mặc định — ai muốn tất cả** | `sg-md-writing` + `sg-prompt-sharpening` | Gói cả hai skill. Cài một cái là có tất cả. |
| `sg-dev` | Team dev | `sg-md-writing` | Soạn & bảo trì file`CLAUDE.md` / `AGENTS.md`ràng buộc hành vi AI: routing map, reuse inventory, an toàn với model yếu, tự đề xuất cập nhật khi code đổi (hỏi confirm trước khi ghi). |
| `sg-common` | Chung | `sg-prompt-sharpening` | Trước khi hành động với yêu cầu ngắn/mơ hồ, mở rộng thành các cách hiểu rõ ràng, nêu giả định, định nghĩa tiêu chí "xong". |
| `sg-dev` | Team dev | `sg-md-writing` | Soạn & bảo trì tri thức dự án cho AI:`CLAUDE.md` / `AGENTS.md`/ `.claude/rules`, skill, subagent. Ghi đúng điều code không tự nói được (ý định, bất biến, bản đồ tái sử dụng), đặt ở chỗ chỉ nạp khi cần để tiết kiệm token; khi code đổi thì tự sửa đúng dòng `.md` bị sai trong cùng thay đổi, chỉ hỏi ý định mà code không trả lời được. |
| `sg-common` | Chung | `sg-prompt-sharpening` | Yêu cầu gõ ngắn, thiếu thông tin → tự lấp chỗ thiếu từ dự án, hiện bản prompt đã làm rõ (mục tiêu, ở đâu, xong khi nào, giả định) rồi làm luôn; chỉ hỏi một câu khi các cách hiểu dẫn tới việc khác nhau. |
| `agenthub` | Ai muốn theo dõi session Claude Code | hooks + server + CLI | Dashboard local-first [AgentHub](https://git.smartgift.io.vn/Smartgift-AI/AgentHub). Source lấy trực tiếp từ repo đó (nhánh `main`), không phải code trong repo này. |
**Khuyến nghị: cài `sg-all`.** Đã cài `sg-all` thì **KHÔNG cần** cài thêm `sg-dev` hay `sg-common` — cài trùng sẽ nạp lặp skill. Chỉ cài `sg-dev`/`sg-common` riêng nếu có lý do muốn giới hạn phạm vi. `agenthub` là plugin độc lập (không phải skill), cài kèm `sg-all`/`sg-dev`/`sg-common` không xung đột.
"description":"Smartgift shared skill for all staff. sg-prompt-sharpening: before acting on a short or ambiguous request, expand it into explicit interpretations, surface assumptions, and define success criteria so the first attempt matches intent.",
"version":"0.2.0",
"description":"Smartgift shared skill for all staff. sg-prompt-sharpening: turns a short, under-specified natural-language request into a complete prompt (goal, where, done-when, assumptions), shows it, then acts — asking one question only when the readings lead to different work.",
The request is specific and complete. PASS only if the reply gives the rewritten function directly (local-time `YYYY-MM-DD`, no external library) WITHOUT asking a clarifying question and WITHOUT a block that lists interpretations / a rewritten version of the user's request. A one-line stated assumption is fine. FAIL if it asks the user anything or pads the answer with a sharpened-prompt section.
Trong một dự án TypeScript, hàm `formatDate(d: Date): string` ở `src/utils/date.ts` hiện trả về `DD/MM/YYYY`. Hãy viết lại hàm đó để trả về chuẩn ISO `YYYY-MM-DD` (theo giờ địa phương, không dùng thư viện ngoài) và đưa tôi đoạn code mới.
"làm báo cáo cho sếp" has readings that lead to completely different work (a weekly progress report of the team's work vs. a sales/revenue report from the `orders` data). PASS only if ALL hold:
1. The reply recognises that the readings diverge and asks exactly ONE targeted question that separates them (multiple-choice options are fine), with a recommended option.
2. It shows the user a sharpened version of the request (or one per reading) so they can see what a complete request looks like.
3. It does not start producing either report before the question is answered.
4. The user-facing text is in Vietnamese.
FAIL if it asks several separate questions, picks one reading silently and starts, or shows no sharpened request.
Bối cảnh: tôi là team lead, repo này là hệ thống bán hàng (đơn hàng ở bảng `orders`, có sẵn trang admin thống kê doanh thu theo ngày). Tuần này team vừa xong 2 tính năng và fix 5 bug.
The user typed a terse Vietnamese request ("thêm chức năng xóa nhanh nhé") after describing a project. PASS only if ALL hold:
1. Before (or instead of) doing the work, the reply shows the user a rewritten, fuller version of their request — a "sharpened prompt" that states the goal, where it goes (e.g. `TaskList.tsx`, the existing `DELETE /api/tasks/:id`), and a checkable definition of done.
2. Gaps the project context already answers are filled from that context (reuse the existing soft-delete endpoint, put the action on the list page) rather than asked about.
3. It asks AT MOST ONE clarifying question (zero is fine if it states its assumption, e.g. one-click delete with confirm vs. bulk delete).
4. The user-facing text is in Vietnamese.
FAIL if it asks two or more questions, asks something the context already answers, or shows no rewritten request.
Dự án của tôi: app quản lý công việc nội bộ (Express API trong `server/`, React trong `client/`). Bảng `tasks` có các cột `id, title, status, assignee_id, deleted_at`. Trang danh sách là `client/src/pages/TaskList.tsx`, mỗi dòng có nút sửa; xoá hiện chỉ làm được trong trang chi tiết `TaskDetail.tsx` qua `DELETE /api/tasks/:id` (soft delete, set `deleted_at`).
description: Use when a user's request is short, vague, terse, or could reasonably be interpreted more than one way, before investigating or writing any code — expands the raw ask into an explicit interpretation set, surfaces assumptions, and defines success criteria so execution matches intent on the first try.
description: Use when a request leaves out what is needed to act on it — the goal, which part of the project, or what "done" looks like — or could mean two different jobs. Typical of short, casual natural-language asks ("thêm xóa nhanh nhé", "làm lại phần thông báo cho đẹp", "làm báo cáo cho sếp"). Not for requests that already name the target and the expected result. Rewrites the ask into a complete prompt, shows it to the user, then acts on it.
---
# Prompt Sharpening
## Overview
People type requests the way they talk: short, without the where, the what-exactly or the finish line. This skill turns such a request into the prompt its author would have written with time to spare, shows it to them, and then works from it. The work matches the intent on the first try, and the team sees what a complete request looks like.
Clear-sounding requests often hide multiple interpretations — silence that ambiguity by running this pass before acting.
## 1. Fill the gaps yourself first
## The pass (do this before investigating, and again after a first skim)
Read what the request touches (the conversation, the project's CLAUDE.md, the files and screens it names) before deciding anything is missing. A gap that the code or the conversation answers is not a question: fill it, and say what you filled it with. Look for the project's own obvious candidate as well as the literal words. In a project whose real flagship is a 3D experience behind the homepage, "trang chủ" may mean that experience.
1.**Literal ask** — restate what was actually said, no elaboration.
2.**Plausible interpretations** — list every reading that changes *what* you'd build or *which* files you'd touch. Actively check: does this specific project have an obvious candidate the words don't rule out but also don't name? (e.g. "trang chủ"/"homepage" in a project whose actual flagship surface is a heavy 3D experience gated behind that homepage — that's a candidate, not a footnote.)
3.**Diverge or converge?** If the interpretations lead to the same first investigative step (same files, same starting point), proceed and state your assumption inline as you go. If they diverge — different files, meaningfully different effort/risk, or a decision only the user can make — ask ONE targeted question before doing real work (AskUserQuestion if options are enumerable). Don't ask about things that don't change what you'd do.
4.**Success criteria** — state a concrete, checkable definition of "fixed"/"done" *before* starting, derived from the user's actual complaint. Don't invent metrics after the fact that happen to match whatever you built.
5.**Scope boundary** — one line on what this will NOT touch, so a small ask doesn't quietly grow.
## 2. Show the sharpened prompt
## Rationalizations to reject
Before doing the work, show a short block in the user's language:
| Excuse | Reality |
|---|---|
| "The problem statement is clear enough" | Clear-sounding ≠ unambiguous. If 2+ real interpretations lead to different files or effort, it isn't clear. |
| "Asking wastes time" | One targeted question costs 10 seconds. Building the wrong fix costs a full redo. |
| "I skimmed and found *a* plausible cause" | Skimming finds A pattern, not THE pattern. Check for the project's own obvious candidate before settling on the generic one. |
| "I'll define success after I see what I built" | Post-hoc criteria bend to match the output. Define them first, from the complaint as stated. |
> **Yêu cầu đã làm rõ:** one paragraph with the goal, where it happens (files, screens and endpoints by name), the constraints, and what stays out of scope.
> **Xong khi:** a checkable finish line, taken from the user's own complaint.
> **Giả định:** only the assumptions the user might want to change.
Write it as a prompt the user could have sent, not as a plan of your steps. Include only what changes the work.
## 3. Proceed, or ask one question
- **The readings lead to the same work.** Proceed right after the block. The user corrects an assumption if it is wrong.
- **The readings lead to different work** (different files, much more effort or risk, or a decision only the user can make). Don't start. Ask ONE question that separates the readings, with options and the recommended one first (AskUserQuestion when the options can be listed), and show the sharpened prompt for the recommended reading.
## Handoff mode
If the sharpened result is meant for a *different* AI/session/agent (not yourself), the bar is higher: the output must be fully self-contained — exact file paths, decisions already made, what's explicitly out of scope, and a concrete success check. No "as discussed above" — the reader has no "above."
When the sharpened prompt is for another agent or session, it must stand alone: exact paths, the decisions already made, what is out of scope, and how to check the result. The reader has no "above" to refer back to.
## Gotchas
- Short is not the same as vague. "Đổi tên `formatDate` thành `formatIsoDate` và sửa mọi chỗ gọi" is complete: act on it without a block.
- Words run together or typed without diacritics ("làm lạiphần này") are typing, not ambiguity. Read through them.
- Define "done" before building. A finish line written afterwards bends to fit whatever got built.
- One question means one. Don't append a second ask ("and send me the repo path") to it. If the files can't be read, work from what the user described, and note that in the assumptions.
- Prefer proceeding. When the recommended reading is the small, safe one and the others only add scope, state it as the assumption and start. Ask only when picking wrong would waste real work.
"description":"Smartgift dev-team skills. sg-md-writing: author and maintain CLAUDE.md / AGENTS.md rule files that constrain AI edits (routing map, reuse inventory, weak-model-safe, update-on-code-change with confirm).",
"version":"0.2.0",
"description":"Smartgift dev-team skills. sg-md-writing: keep a project's agent knowledge (CLAUDE.md / AGENTS.md / .claude/rules, skills, subagents) true, small and placed where it loads only when needed — re-syncs .md files in the same change as the code, asks only for intent the code can't tell.",
The reply reviews a CLAUDE.md. PASS only if it flags AT LEAST FOUR of these five problems:
1. "Always add comments" and "Never add comments" (or similar) contradict each other.
2. "Think step by step" / "think hard" style lines should be removed (modern models decide how much to think; effort controls it).
3. The `@docs/...` imports do NOT save context: imports are expanded inline at launch, so moving text into imported files does not make it load lazily (a skill would).
4. "Never push to main" is a hard rule that belongs in a hook / permission rule (enforcement), not only in CLAUDE.md text (guidance).
5. Too many rules are marked IMPORTANT/CRITICAL, so emphasis stops meaning anything.
1. The frontmatter sets `disable-model-invocation: true` (or explicitly says the skill must only run when the user types the slash command), because deploying is a side effect.
2. The `description` states WHEN to use it (trigger situations / phrases a user would say), not a summary of how it works.
3. The skill has a Gotchas (or "known pitfalls") section, even if it only holds a starter entry.
4. The body states the goal and constraints instead of a rigid numbered command-by-command script with no room to adapt.
Write me a Claude Code skill (the full SKILL.md, frontmatter included) for deploying our API service to staging. We deploy with `make deploy-staging`, it needs the VPN up, and after deploy someone should hit `/healthz`. Just give me the file content.
1. It does NOT put the rule into the 40 KB root CLAUDE.md; it places it where it loads only when relevant — a path-scoped rule file (e.g. `.claude/rules/webhooks.md` with `paths:` frontmatter matching `src/webhooks/**`) or a nested `src/webhooks/CLAUDE.md` — and says why (root loads every session).
2. The rule text it writes is condensed into constraints that keep the reasons: verify with `verifySignature` from `src/webhooks/verify.ts` before parsing; raw body (`express.raw`) on these routes; secrets in `webhook_secrets`, never hardcoded; no per-handler verify copies.
3. It does not add filler (generic advice, step-by-step recipes, code samples) beyond those constraints.
CLAUDE.md gốc của repo tôi đã khoảng 40 KB (Claude Code nạp nó mỗi phiên). Tôi muốn thêm quy tắc này vào, viết giúp tôi nội dung và nói rõ đặt ở đâu:
"Trong thư mục src/webhooks/ có các handler nhận webhook từ Stripe, Momo và ZaloPay. Mỗi handler đều phải verify chữ ký HMAC trước khi parse body, vì nếu parse trước thì body đã bị đổi định dạng và chữ ký sẽ luôn sai, ngoài ra kẻ xấu có thể gửi webhook giả để đánh dấu đơn đã thanh toán. Hàm verify dùng chung nằm ở src/webhooks/verify.ts, tên là verifySignature(provider, rawBody, header). Không được tự viết lại hàm verify trong từng handler. Khi thêm provider mới thì thêm secret vào bảng webhook_secrets chứ không hardcode. Nhớ là body phải lấy dạng raw (express.raw) chứ không phải express.json cho các route này."
The reply designs two subagent definitions. PASS only if ALL hold:
1. It pushes back on (or at least warns against) a subagent whose job is just to run the test suite, because it hides the failure diagnostics from the main agent; it suggests running tests in the main thread or returning full failure output instead.
2. The researcher definition specifies a concrete OUTPUT FORMAT for its report.
3. The researcher definition asks it to report obstacles / environment quirks / workarounds it hit (so the main agent does not rediscover them).
4. The researcher gets read-only tools (no Edit/Write).
I want two custom subagents for Claude Code: one "test-runner" that runs our test suite and tells the main agent whether it passed, and one "researcher" that digs through the codebase to answer questions. Write both agent definition files for me.
1. The reply gives the updated CLAUDE.md (full file or an exact diff) where the billing rule now names `issueInvoice` in `src/payments/charge.ts`, keeping the rule's meaning and its reason (accounting would drift).
2. The other three rules are left unchanged (not reworded, not expanded, no new rules added).
3. The `Last synced` marker is updated to `9c41d07`.
4. It does not ask the user to confirm before producing the update, and asks no question the prompt already answers.
Tôi vừa refactor xong: chuyển `src/services/billing.ts` thành `src/payments/charge.ts`, đổi tên hàm `createInvoice` thành `issueInvoice` (logic không đổi). CLAUDE.md gốc hiện tại:
```
# Shop API
_Last synced: 3f2a91c_
## Rules
- Mọi khoản thu đi qua `createInvoice` trong `src/services/billing.ts`; KHÔNG tạo invoice trực tiếp bằng SQL — sẽ lệch sổ kế toán.
- Tiền lưu dạng số nguyên (đồng), không dùng float.
- Test: `npm test`; test thanh toán cần `STRIPE_KEY=sk_test_...`.
- Webhook Stripe ở `src/webhooks/stripe.ts` phải verify chữ ký trước khi đọc body.
```
Commit refactor là `9c41d07`. Cập nhật CLAUDE.md giúp tôi.
description: Use when creating, overhauling, or cleaning up CLAUDE.md / AGENTS.md files for a codebase or module — including tidying /init output or auto-generated drafts that describe the code instead of constraining behavior, when a rules file made a weak model refactor/edit things it should not have, or right after code changes that invalidate statements in an existing CLAUDE.md set (moved paths, new/changed extension points, retired rules) — run its update mode to re-sync.
description: Use whenever a project's agent knowledge needs writing or upkeep. That covers creating, reviewing, tightening or re-syncing CLAUDE.md / AGENTS.md / .claude/rules files (including right after a code change moves a path, renames a symbol, or retires a rule they mention), deciding where a new rule should live, and writing a Claude Code skill (SKILL.md), a subagent definition, or a hook that enforces a rule.
These files are the project's memory for every agent that works in it. Their job is to hand the next agent the facts it cannot get from the code, in the place where the agent will meet them, at the lowest token cost. Keep them true, small and well placed. A stale line is worse than a missing one, because the model trusts it.
An AGENTS.md/CLAUDE.md is a **law, not documentation**. Every line the model can already read from the code is noise that dilutes signal — and with weaker models (minimax-m3, small local models) a described fact reads as an invitation to "fix" it. Keep ONLY what the model cannot infer: intent, invariants, gotchas, prohibitions — PLUS the one class of facts models never infer: the **reuse map / feature inventory** (what already exists, where every piece lives, what to extend — see step 3). Inventory lines are routing, not noise; do not cut them under this rule.
## What earns a line
**Core principle: describe → constrain.** Facts get deleted; constraints stay.
Write what the model cannot infer by reading the code:
- **Intent and invariants, each with its consequence.** "Money is stored as integer đồng — floats drift the ledger."
- **Deliberate oddities.** "`LotteryService` is deterministic on purpose — do not 'fix' it to `rand()`." Without the line, a model will "fix" it.
- **The reuse map.** For each existing feature: where its backend, UI and tables live, how to check it works, and the extension point new work must use ("new widget kinds extend the `widgets` table + `WidgetKind` enum, never a parallel table"). No model infers which existing structure already covers a feature. Without this map, agents build parallel ones.
- **Commands that are not obvious from the files**, and **traps** (an env var a test needs, a port shared with prod).
## You are NOT reviewing the code
Leave out descriptions the model can read for itself (registration order, folder listings, config keys), generic virtues, step-by-step recipes and code to paste. **You are not reviewing the code.** A file records the owner's decisions, never your opinion of the code. Turning "this should be extracted" into a rule makes a model execute it. Record intent only when the user confirmed it, or when a comment or construct proves it is deliberate. Raise everything else separately.
A rules file records the **owner's decisions**, not your opinion of the code. NEVER turn "this should be 307 not 301", "externalize this to config", or "extract to a trait" into a MUST/NEVER — that is a code-review finding, not a recorded intent, and a weak model will execute it. Only record intent that (a) the user confirmed in the interview, or (b) a code comment / obvious construct proves is deliberate. If you believe something *should* change but no one confirmed it, leave it out (raise it separately as a review note, never as a rule).
Write each rule as a plain imperative with its reason. Write so that the weakest model that will read the file (a Haiku-class or small local model) has every fact it needs: locations, contracts, the verify command. Clarity carries that, not capitals. Keep emphasis for the one rule a model demonstrably keeps breaking. A rule that must never break belongs in a hook or a permission rule, with the .md line as context. A PreToolUse hook blocks with exit 2. Exit 1 does not block.
## Two modes — pick FIRST, before any step
## Where a line lives (load cost)
- **Create mode** (no `.md` set exists, or user asks for a from-scratch overhaul): full workflow below, steps 0–6.
- **Update mode** (a `.md` set already exists): do NOT rewrite from scratch — the existing files hold owner-confirmed intent you must not lose. Instead:
1. Find the sync baseline: the `Last synced: <commit>` marker in root. If the project is not a git repo (or the root is a non-git workspace of multiple repos), use the `Last synced:` timestamp instead and diff against the most recent code change after it; per-sub-repo files get their own baseline.
2. Diff against that baseline (`git diff`, file mtimes, or manual review of the just-made changes) → list every `.md` statement the diff invalidates: moved paths, renamed symbols, new/changed extension points, retired or new rules, new modules with no `.md` yet.
2b. **Verify against the ACTUAL current state before asking anything — investigate, don't guess.** The diff tells you what changed; it does NOT tell you what is now true. Before forming any proposed update, open the current code and confirm each candidate change against reality: does the symbol/path still exist at the new location (grep it), is the new extension point really the canonical one (not a temporary/duplicate), did the logic actually change behavior or just move, does a `.md` statement you think is now wrong actually contradict the code as it stands now? EVERY question you ask the user must be one you could NOT answer yourself from the code — never ask to confirm something a 30-second grep settles. A question that reveals you didn't check is worse than no question. This is step-1's "investigate first" applied to update mode.
3.**Confirm BEFORE writing (always ask, never silent-write).** After a task changes code, do not touch the `.md` files until the user confirms. Present the proposed sync as a **plan-mode question in tiếng Việt**: list each `.md` file that would change and the one-line diff for each (what statement becomes what), then ask to proceed — with proceeding as the recommended answer, e.g. "Task vừa xong đổi `X`. Đề xuất cập nhật 2 file .md: `root` (đổi path A→B), `module/Y` (thêm extension point Z). Cập nhật luôn nhé? [Recommend: có]". Options at least: cập nhật tất cả / chọn file / bỏ qua. Do NOT write any `.md` before this confirmation.
4. On confirm, update ONLY the affected (and approved) files; new intent questions (if any) still go through the step-2 interview style — one at a time, recommended answer first, tiếng Việt.
5. Update the `Last synced:` marker, then run a light step-6 pass (one test request is enough).
| Place | Loads | Use for |
|---|---|---|
| Root `CLAUDE.md` / `AGENTS.md` | Every session, every turn | Project identity, routing table to module files, cross-cutting rules, commands, the two standing rules below |
| `.claude/rules/*.md` with `paths:` frontmatter | When Claude reads a matching file | A rule tied to some paths (`src/webhooks/**`) |
| `<module>/CLAUDE.md` | When Claude reads files in that folder | A module's reuse map, patterns and gotchas |
| `.claude/rules/*.md` without `paths:` | Every session, like root | Rarely. Prefer root, or add `paths:` |
| A skill | Its description every session, its body on use | A procedure needed only sometimes |
| `docs/…` named by a plain path ("read when …") | Only when the agent opens it | Long background for humans and agents |
## The workflow — do in order, do NOT jump straight to writing
`@path` imports expand at launch. They organise text but do not save context. Root grows only with what every task needs. A rule that applies to some paths goes to a path-scoped rule or a module file, even when the user says "add it to CLAUDE.md". Say where you put it and why.
### 0. Draft the raw facts — don't blank-page
- **Root draft:** run `/init` (or open the existing file) for a raw scan of the project.
- **Module drafts:** `/init` does not cover modules — dispatch **Explore subagents in parallel, one per module, in a single message**, each reporting that module's raw facts (structure, patterns, extension-point candidates, commands). Match the cost to the size: a small project (a few dozen files) reads fine inline; only dispatch subagents when the tree is too big to read in one pass.
Every root file carries two standing rules:
- **Check before create.** "Before creating any table, function, class, config key, file or endpoint, search the reuse map and grep for something with the same purpose. Extend it if it exists."
- **Sync.** "A change that makes a statement in any .md wrong (moved path, renamed symbol, new or changed extensionpoint, retired rule) updates that .md in the same change." Root also carries a `Last synced: <commit or date>` marker. It is the baseline for the next sync.
Treat all drafts as **facts to be transformed**, never as finished files. The whole job below is turning drafts into constraints.
## Modes
### 1. Analyze the source FIRST — investigate before asking
Read the module before asking anything. Map the intent candidates yourself: what looks like a bug but might be deliberate, what looks duplicated/hardcoded on purpose, what build/test commands the files imply. Hunt SPECIFICALLY for reusable extension points — type-discriminated tables, enums, generic repos/services that new features should extend instead of duplicating; a missed one is the single most expensive omission (see "Reuse map" in step 3). Form your own best guess for each. NEVER ask a question you could have answered by reading code — investigate first, ask only to confirm what code can't settle. This step feeds the recommended answers in step 2.
**Sync (after a code change; the most common).** Grep the .md set for every old name and path the change touched. Check each hit against the current code, then fix exactly the lines the change made wrong, in the same change-set. Leave every other line as it is: no rewording, no new rules. Bump `Last synced`. Report one line per file changed. Do not stop for confirmation. Ask only about intent the code cannot settle (one question, with your recommended answer first).
### 2. Interview — one question at a time, each with a recommended answer
Ask in **Vietnamese** (tiếng Việt), in **plan mode**, sequentially: ONE question, wait for the answer, then the next. NEVER dump a batch of questions at once. Each question MUST carry your recommended answer first (drawn from step 1's investigation) so the user can confirm with one tap instead of composing prose — e.g. "I read `LotteryService` as deterministic on purpose (not a bug). Correct? [Recommended: yes, intentional]". Aim ONLY for what code can't tell you:
- What looks like a bug but is intentional? (deterministic where you'd expect random; duplicated on purpose; magic sentinel values)
- What breaks silently if changed? (cross-repo contracts, fixed byte layouts, param whitelists)
- What must NEVER be done here? (don't merge/refactor X; don't cancel a shipped order)
- Which decisions are load-bearing vs incidental?
- Build/test/deploy commands not obvious from the files.
**Add a rule.** Find whether a rule on the same point already exists. Update it rather than add a second one, and settle any contradiction. Place the rule by the table above. Condense it to the constraint plus its reason.
Verify each answer against real code + line refs; discard anything the model reads trivially. Stop asking when answers stop yielding non-inferable facts.
**Review or tighten.** Look for:
- Contradictory rules.
- Emphasis on everything (so emphasis means nothing).
- "Think step by step" lines. Effort and thinking settings control that.
- Imports that were meant to save context.
- Hard rules that belong in a hook.
- Stale paths or symbols (check each against the code).
- Module detail sitting in root.
- Descriptions of the code instead of constraints on it.
### 3. Plan the file list — get approval BEFORE writing
Default is **multi-file, full coverage**: ALWAYS one `.md` at the project root, PLUS a `.md` in EVERY module/folder — not just the "important" ones. A single root file, or root + a couple of favorites, is the wrong default. The set doubles as a **structure reference**: someone (or a model) reading only the `.md` files can see what exists where and what to extend.
Propose each fix with its reason.
**Reading protocol — lazy-load, never read-all.** The set is designed to be read on demand, not front-to-back:
1.Task arrives → read **root CLAUDE.md first**, before touching any source.
2.Root's routing table names the module(s) the task touches → read ONLY those modules' `.md` files — before reading that module's source, and never the `.md` of unrelated modules.
3.Only then open source files, and only the ones the relevant `.md` points at.
**Create or overhaul.** Work in this order:
1.Draft the raw facts. Use `/init` for root, or read the tree. For a large tree, run one Explore subagent per module, in parallel.
2.Investigate before asking. Form your own guess for every intent candidate and hunt down the reuse map.
3.Ask only what the code cannot tell you: deliberate oddities, what breaks silently, what must never be done, commands. Put these in one AskUserQuestion round with recommended answers, in the user's language.
4. Write root plus a module file for each module that has its own rules or reuse map. A folder with nothing non-inferable gets no file.
5. Show the file list with one line per file, then write.
Write the files so this works (root routes precisely; each module file is self-sufficient for its module — no "see also" chains forcing extra reads), and **state this protocol explicitly at the top of the root file** so any consuming model follows it instead of bulk-reading everything.
If a set already exists, patch it. A rewrite loses intent the owner already confirmed.
**Check-before-create rule — every root file MUST contain it.** Alongside the reuse map, every root `.md` you write must carry this standing rule for future work: "Before creating ANYTHING new — table, function, class, variable, config key, file, endpoint — FIRST check whether something with the same purpose or reusable already exists: search the reuse map in the relevant `.md`, then grep the code. If it exists, extend/reuse it; do NOT create a parallel one. Only create new after confirming nothing covers it." The reuse map makes the check cheap; this rule makes it mandatory — the map alone did not stop agents from building parallel structures.
**Check.**
- After a sync: grep that no old name or path is left.
- After a create or overhaul: give a Haiku-class subagent a realistic one-line feature request and only "read CLAUDE.md from the root and follow it". Ask for a plan only.
- It must land in the right module and reuse the named extension point.
- If it doesn't, a line is missing or unclear. Fix the file and run the check again.
**Anti-rot sync rule — every root file MUST contain it.** The set goes stale the moment code changes: paths move, extension points appear, rules stop being true — and a stale routing table is worse than no file (the model trusts it). So every root `.md` you write must carry this standing rule for future work: "Any change that makes a statement in any `.md` file wrong (moved path, new/changed extension point, retired rule) MUST update that `.md` in the same change." When YOU edit code in a project that has this file set, obey it too. Root also carries a **`Last synced:` marker** — set it when writing (git commit hash when available, otherwise timestamp) and bump it on every sync; it is update mode's diff baseline.
## Skills
**Layering — root = routing map, module = deep:**
-**Root** — answers "what is this project, how do the pieces connect, and which file do I read next?". Contains: project identity (domain + stack), an **architecture table where each row points to that module's `.md`** (columns: part | role | "details at → path/CLAUDE.md"), global cross-cutting rules only, and build/test commands. The routing table is the token-saver: the model reads root, jumps straight to the right module file, never scans the tree.
-**Module files** — go deeper and more specific for that part: its function, requirements, business logic, technology, mandatory patterns ("new X MUST extend Y"), and its own gotchas/prohibitions. This is where detail lives; the module still obeys "constrain not describe" (every line non-inferable intent/gotcha/prohibition), just at finer grain than root.
-**Reuse map / feature inventory — the highest-value content.** For each existing feature/capability, spell out in detail WHAT already exists and WHERE every piece lives, across all layers, so nothing gets rebuilt. Per feature:
- **how to verify it works** — endpoint, port, command, or admin screen to check it live
- **extension point** — the imperative: "new widget kinds extend THIS table + THIS enum — do NOT create a parallel table"
-`description` says WHEN to load the skill: the situations, and the words a user would actually type. It is not a summary of the steps, because a description that summarises the workflow gets followed instead of the body. Put the main trigger first.
-The body states the goal, the constraints and the finish line, then lets the agent adapt. Keep a fixed sequence only where order is load-bearing, and say why.
-Always include a `## Gotchas` section, even if it holds one starter entry. It grows from real failures.
-`disable-model-invocation: true` for side effects (deploy, commit, send).
-`allowed-tools` pre-approves tools. It does not restrict them, so list a pattern (`Bash(make deploy-staging)`), never bare `Bash`. `disallowed-tools` restricts.
-`paths` limits activation to matching files.
- Long reference goes in `references/` and code in `scripts/`. Point to each from SKILL.md with a "symptom → file" line. Keep SKILL.md under 500 lines.
- Leave out what the model does anyway.
Field evidence: without this inventory, 3 of 4 test agents (including strong models WITH the .md) invented a parallel table; base-class rules alone did not prevent it. Strong models infer framework patterns on their own — what NO model infers is which existing domain structure already covers a feature and must be extended. Hunt for these in step 1 (enums, type-discriminated tables, generic repos/services, existing UI) and confirm each in the step-2 interview.
- **Length follows content, not a quota.** Be detailed, complete, and accurate — include EVERY confirmed intent, invariant, gotcha, and prohibition, however many lines that takes. The only thing to cut is what the model can already read from code; never cut a real constraint to hit a size target.
- **Handover test** for the whole set: a new engineer (or model) reading ONLY the `.md` files must be able to take a one-line feature request and land on the correct module, reuse the existing pattern, and produce a minimal diff — without tree-scanning or inventing parallel structures (e.g. a new table when an existing one covers it via a `type` column).
## Subagents
Produce the full list: every dir/module and the constraints each `.md` will hold. No prose yet. Present it, get the user's OK on the plan, then write.
- Push back on a subagent whose only job is to run tests or a build. It summarises away the failure output the main agent needs. Run checks in the main thread, or have the agent return the raw failing output.
- Every definition needs a concrete OUTPUT FORMAT and an **Obstacles** part in that output (workarounds, environment quirks, dead ends), so the caller doesn't rediscover them.
- Give it the fewest tools that work: a researcher gets Read/Glob/Grep, and a reviewer gets no Edit/Write.
- No "You are an expert X" persona. The one-line `description` also steers what the caller asks for.
- Delegate work whose intermediate steps the main thread doesn't need (search, broad reading, independent review). Avoid chains of dependent agents.
- A subagent sees a skill only if the skill is listed in its `skills:` field. A dispatch prompt that depends on a module file should name that file.
**Confirm BEFORE creating EACH file — never batch-write the set.** Plan approval authorizes the *list*, not the individual files. Write one `.md` at a time: for each file, present its path + the constraints it will contain (in tiếng Việt, recommended answer = tạo), ask to proceed, and create it ONLY after the user confirms that file. Then move to the next. Do NOT create the next file until the current one is confirmed. Options at least: tạo file này / sửa nội dung / bỏ qua file này.
## Gotchas
### 4. Rewrite the draft as constraints, not facts
-**Imperative prohibitions** (KHÔNG / CHỈ / PHẢI / NEVER / ONLY), not descriptions. Weak models obey commands, not implied intent.
-Every gotcha names its **consequence** ("…else the request is rejected by the Gateway before the action runs").
-"Looks like a bug but is intentional" → say so + why, or the model will "fix" it.
- Anchor to **stable symbols** (class/method/table/enum names, e.g. `WidgetRepo::archiveOld`), not line numbers — lines drift after a few commits; use `file:line` only when no named symbol exists. On any duplication/smell you must mention, add **"describe current state — do NOT change."**
- Module rules → that module's file (scope). Don't dump into root.
**Calibrate to the weakest model, without handcuffing the strongest.** Write so that the WEAKEST model that will ever read this (a Haiku-class model, a small local model) can complete a hard task in this module without struggling: full context — every location, contract, invariant, verify command, extension point it needs — spelled out, nothing left to "it will figure it out". But supply that as **context + constraints + pointers, never as recipes**: state WHAT must hold, WHERE things live, and what is FORBIDDEN — do not dictate step-by-step procedures or paste ready-made code snippets to copy. A strong model must stay free to choose its own implementation; a weak model must never be missing a fact it needed. If a line prescribes HOW to write the code rather than what must be true of it, cut the how, keep the what.
### 5. Note on subagents
Subagents do NOT auto-load CLAUDE.md files. If the workflow dispatches subagents (explore, implement, review), their prompts must explicitly say "read <path>/CLAUDE.md first". When writing a root file, consider stating this so future orchestration doesn't run blind.
### 6. Verify with a weak model — the set is not done until it passes
Writing the files is not the finish line; field evidence shows a set that LOOKS complete can still fail (a strong model with the .md still built a parallel table). After writing:
1. Pick 1–2 realistic one-line feature requests for this codebase (e.g. "Thêm chức năng rate limit theo IP cho endpoint public") — ideally one the user suggests.
2. Dispatch a **weak-model subagent** (Haiku-class) with ONLY that request plus "read the CLAUDE.md files starting from root, follow their reading protocol" — no other hints. Plan-only is enough: ask it to output its implementation plan, not apply edits.
3. Grade against the handover test: correct module? reused the named extension point (no parallel structure)? followed the mandatory patterns? minimal scope?
4. Any failure = a missing or unclear line in the `.md` set, never the subagent's fault. Fix the file, re-run until it passes.
Report the verification result to the user as part of delivery.
| "Registered in `Application.php` in order 1,2,3" | (delete — model reads it) |
| "`isHttps()` duplicated in two middlewares — extract to a trait" | "`isHttps()` duplicated ON PURPOSE. Do NOT extract — no shared base wanted." |
| "CSP is permissive with `unsafe-inline`" | "CSP `unsafe-inline` is REQUIRED (jQuery/GA). Don't tighten without testing inline scripts." |
| "`LotteryService` uses `getUserIndex() % ratioCycle`" | "Lottery is deterministic ON PURPOSE — NOT random. Don't 'fix' to `rand()`." |
**Inventory paths are NOT noise.** "Delete what the model reads from code" applies to structure trivia (registration order, config keys). It does NOT apply to the reuse map: a path is only readable from code if the model already knows to look there — the inventory's job is exactly that routing ("feature X already exists: backend at a, frontend at b, DB at c, verify via port 123"). Keep those.
## Checklist before writing any line
1. Can the model read this from code? → **delete** (noise) — EXCEPT reuse-map/feature-inventory lines (see above).
2. Is it invariant / intent / gotcha / prohibition? → if not, **delete**.
3. Right scope (module rule lives in that module's file)?
## Red flags — STOP, you're producing noise
- Describing registration order, config keys, or file structure the model can list itself.
- "Extract to…", "consider refactoring…", "should be tightened…", "use 307 instead", "switch to atomic increment" → **refactor bait / code review**; weak models execute it. A rules file is not a code review.
- Turning your own opinion that code is wrong into a MUST/NEVER. If no one confirmed the intent, it's not a rule.
- Speculative advice (Redis, production hardening) not tied to a real decision.
- Bolting on a test framework where none exists.
- Wrote files before the user approved the plan.
- Created any `.md` file without confirming that specific file first — plan approval is not per-file approval; each file gets its own confirm-before-create gate (create mode step 3).
- Asking questions before reading the code (should investigate first, ask to confirm).
- Dumping many questions in one message (must be sequential, one at a time).
- A question with no recommended answer (every question carries your best guess first).
- Only a root `.md`, or `.md` for only a few "important" modules (default is full coverage: root + every module/folder).
- A module file with no reuse-map line — no named extension point means the next feature builds a parallel structure.
- Step-by-step recipes or paste-ready code snippets in a rules file — that's dictating HOW; state what must hold and where things live, let the model implement.
- A weak model would still need to guess a location/contract/command after reading the file — context incomplete, add the missing fact.
- Root file lacks the read-root-first / read-only-relevant-modules protocol, or module files cross-reference each other so a task forces reading unrelated `.md`s.
- Root file lacks the check-before-create rule (search reuse map + grep before creating any new table/function/class/file; reuse if found).
- Root file lacks the anti-rot sync rule ("code change that invalidates a `.md` line updates that `.md` in the same change") or the `Last synced:` marker.
- Declared the set done without the step-6 weak-model verification pass.
- Rewriting an existing `.md` set from scratch when update mode applies — owner-confirmed intent gets lost; diff and patch instead.
- Writing `.md` changes after a task without first asking the user to confirm the proposed diff (update mode step 3 — always confirm, never silent-write).
- Asking a confirm question in update mode without first verifying against current code (step 2b) — a question answerable by grep proves you skipped the check.
- Root file holds module-level detail, or lacks the routing table pointing to module files — root is a map, not a dump.
- Fails the handover test: a one-line feature request read against only the `.md` set wouldn't route to the right module + existing pattern.
- File is long while the code is small → padding.
## Rationalization table
| Excuse | Reality |
|---|---|
| "More context helps the model" | Facts dilute the constraints. Weak models drown. Cut. |
| "/init already wrote it, just tidy" | /init output is descriptive facts — the exact failure mode. Rewrite as constraints. |
| "Documenting the duplication is helpful" | Naming a smell without "do NOT change" reads as "please refactor". |
| "Interviewing wastes time" | The non-inferable facts are the ONLY high-value content. Skip it → a file of noise. |
| "I'll write all files then plan" | Plan first — writing before approval produces scope you throw away. |
| "I'll ask first, then read the code" | Backwards. Read first, form a guess, ask only to confirm. Questions answerable from code are noise. |
| "Batching questions is faster" | One at a time. A wall of questions gets skimmed; sequential plan-mode gets real answers. |
| "The user knows the answer, no need to recommend" | Always recommend. A guess to confirm is one tap; an open question is homework. |
| "The files look complete, verification is overkill" | Field evidence: a complete-LOOKING set still let a strong model build a parallel table. Run the step-6 weak-model pass. |
| "The code is clearly wrong, I'll make a rule to fix it" | That's a code-review opinion, not a recorded decision. Leave it out or raise separately. Rules record confirmed intent only. |
- Root bloat creeps in through "add this to CLAUDE.md" requests. Root is a map, not a store. A root file over a few KB is a sign that module detail belongs elsewhere.
-Naming a smell ("duplicated in two places") without "deliberate — do not change" reads as an invitation to refactor.
-Anchor rules to stable symbols (class, function, table names), not line numbers. Line numbers drift.
-When the user pastes the file and the change instead of giving you a repo, work from what they gave. Deliver the update, and say in one line what you could not check. Do not ask them for the repo.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.