feat: sg-md-writing và sg-prompt-sharpening v0.2.0 — gọn hơn, có eval

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
This commit is contained in:
2026-10-08 11:45:44 +07:00
parent b1217e1846
commit add66c25bd
32 changed files with 311 additions and 157 deletions
+70 -130
View File
@@ -1,157 +1,97 @@
---
name: sg-md-writing
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.
---
# Writing AGENTS.md / CLAUDE.md
# Maintaining project knowledge (CLAUDE.md, AGENTS.md, rules, skills, subagents)
## Overview
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 extension point, 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:
- **backend** — service/repo/controller paths (e.g. `app/Repositories/Widget/WidgetRepository.php`)
- **frontend/UI** — screens/components that expose it
- **database** — tables, enums, migrations (e.g. `widgets` table, `WidgetKind` enum)
- **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.
## Fact vs constraint — the test for every line
| ❌ Fact (model reads from code → delete) | ✅ Constraint + intent (keep) |
|---|---|
| "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.