rules-stocktake — Rules Quality Audit
Evaluate every rule file under ~/.claude/rules/ holistically, all in one context,
and assign each a verdict: Keep / Improve / Update / Merge / Demote to skill / Dissolve / Retire. The audit unit is the file; the cost unit is the line — rules
load into every session unconditionally, so each line is a per-session token tax plus
instruction dilution.
Design note: this is skill-stocktake's sibling with the cost model inverted. A skill's cost is trigger pollution (it fires probabilistically and degrades selection); a rule's cost is residency (it loads always, whether or not it changes behavior). So there is no usage axis — nothing measures "rule invocations", and the concept doesn't apply to unconditional loading. The replacements are static: residency density (is each line worth reading every session?) and substrate absorption (does the harness or the conversation already do this without the rule?).
Design note 2: unlike skill-stocktake, this skill does apply approved Improve/Update/ Merge edits itself instead of handing off. There is no improvement-engine skill for rules (skill-creator's counterpart doesn't exist), and rule files average ~60 lines — delegation would be overengineering. The handoff exception is Demote (creating a new skill is skill-creator's job).
Modes ($ARGUMENTS)
| Argument | Behavior |
|---|---|
none / full |
Read and evaluate every rule (default) |
changed |
Re-evaluate only rules whose mtime is newer than results.json's evaluated_at; carry the rest forward from the ledger |
changed detects changes inline (no script):
find ~/.claude/rules -name "*.md" -newermt "$(jq -r .evaluated_at ~/.claude/skills/rules-stocktake/results.json)"
Correction that keeps changed mode honest: cross-reference breakage is invisible to
rule mtimes — retiring a skill silently breaks a See skill: pointer in an unmodified
rule. So the Phase 1 integrity checks always run over the full set (they are grep,
seconds of work), and any rule with a newly broken reference is promoted into the
re-evaluation set even if its mtime is old.
Phase 1 — Inventory + mechanical integrity checks
Enumerate with Glob (no script): ~/.claude/rules/**/*.md. The corpus is small enough
to read every file into one context — no batching, no grep pre-filter. Measure the
corpus size live (find ~/.claude/rules -name '*.md' | xargs wc -l) rather than
trusting a figure written here; per-file line counts become the residency-cost column
in Phase 3 and the lines field in the ledger.
Run the mechanical checks with throwaway bash/grep (detection is structural → code; judgment on what the findings mean → LLM, per the enumerate/decide split):
- Every
See skill:/See skills:target exists under~/.claude/skills/<name>/ - Every relative link between rule files resolves
- Every rule file's line 1 carries
<!-- origin: X --> - Every
rules/common/file carries<!-- rationale: ... -->and<!-- review-when: ... -->within its first 10 lines (ADR-0021; harness_lint checks presence deterministically — read its result instead of re-grepping) -
rules/README.md's tree matches the actual file list (no missing, no phantom entries)
State the scan result up front: files found, total lines, integrity failures. Carry the failures into Stage 1 as pre-computed evidence — do not re-grep there.
Phase 2 — Evaluation (fully inline, holistic)
Read the body of every rule and evaluate them one by one while seeing the whole set.
Stage 1 — binary screen (every rule). Answer each item as an explicit Yes/No per rule. Record answers internally; surface only the No answers:
- No content overlap with other rules? (a rule that declares another as 正本 and points at it is NOT overlap — that is the intended layering. Copied prose is.)
- No overlap with skills / MEMORY.md / CLAUDE.md? (the division "principle in the rule,
detail in the skill,
See skill:bridging them" is NOT overlap — a full procedure residing in the rule body is, and signals Demote) - All cross-references resolve? (read off the Phase 1 results)
- Technical references current? (if CLI flags / APIs / tool names look stale, confirm with WebSearch)
- Not yet absorbed by the substrate or the conversation? (downward: does the harness — system prompt, tool descriptions, native plan/review machinery — now cover this domain natively? inward: is the principle so internalized that behavior no longer depends on the rule? Either absorption → Dissolve candidate. Criteria imported from akc-cycle.md's Scaffold Dissolution two vectors)
- Dense enough to deserve residency? (does each section change behavior often enough to justify being read every session? rarely-needed reference material, long procedures, single-project content → Demote or Improve-by-shortening candidate)
Six questions and no more — the two static questions (absorption, density) replace the lost usage signal; further decomposition degrades holistic judgment (see References).
Stage 2 — verdict pressure-test (non-Keep candidates only). When Stage 1 plus the
holistic read points away from Keep, generate 1–3 rule-specific atomic yes/no questions
that try to refute the draft verdict before finalizing it. If the rule declares a
review-when: comment, its triggers are the first questions — they are the expiry
conditions captured at write time (ADR-0021), which ad-hoc generation cannot recover.
Ask "has trigger X fired — Yes/No" per declared trigger, then supplement with generated
questions only if needed, each answered with one line
of evidence (file read, path check, WebSearch, harness-doc check). For Dissolve
candidates one question is mandatory: "Can the absorbing harness feature be named
concretely — Yes/No" — an absorption claim that cannot name its absorber is refuted.
Keep-bound rules get no dynamic questions.
Evaluation is holistic judgment, not a numeric rubric — binary answers are evidence feeding the verdict, never aggregated into a score. Evaluation is origin-blind (do not branch on ECC / shimo4228 / customized) — though a missing origin header is itself an integrity finding (common/skills.md requires it) and feeds Improve.
Aggregate residency cost (set-level, not per-rule): holding a rule is not free even when the rule is individually fine. Every line loads into every session — the tax is unconditional — and the longer the total corpus, the weaker the compliance pressure each individual rule exerts (instruction dilution). So the Keep bar rises with total line count: when the corpus is large, a merely-adequate rule is a Demote/Merge candidate on dilution grounds alone. This is a judgment input, never a quota; do not cut lines to hit a number.
| Verdict | Meaning |
|---|---|
| Keep | Earns its residency: current, unique, dense |
| Improve | Worth keeping, but needs tightening — for rules, Improve usually means shorten |
| Update | Referenced technology is outdated (verify with WebSearch) |
| Merge into [X] | Substantial overlap with another rule; name the target |
| Demote to skill | Valuable content that doesn't earn per-session residency; move to the probabilistic trigger layer (the inverse of rules-distill), leaving a 1–3 line pointer in the rule (the task-tracking.md pointer pattern) |
| Dissolve | Absorbed by the substrate (harness went native) or the conversation (internalized). Retirement by success, not defect — delete before it becomes a stale shadow overriding newer defaults, and record the why in an ADR |
| Retire | Defect-based removal: low quality, stale, broken beyond repair |
Mandatory-surface rule (the counterpart of skill-stocktake's zero-usage rule): a No on the absorption question MUST surface the rule as a Dissolve candidate (the final call is the user's). An absorbed rule is more urgent than an unused skill — the unused skill sleeps harmlessly; the absorbed rule actively overrides evolving harness defaults.
README.md special case: rules/README.md is an index, not a rule — it gets only the
tree-consistency and currency checks, and a two-value verdict (Keep or Update).
Phase 3 — Summary
Render a table: Rule | Lines | Verdict | Reason. Close with one line reporting the
total line count and its delta since the previous audit (total_lines in the ledger) —
that delta is the input to the aggregate-residency-cost judgment next run.
Phase 4 — Consolidation
Confirm one by one (config-gc's confirm-each design): walk the non-Keep candidates
sequentially — for each rule, show the evidence first, then ask [y/n/skip]. Never batch
the approval ("apply all edits? [y/n]" defeats the design — one rule, one decision; this
matters doubly here because approved edits are applied in-session). The user can stop at
any point; skip records the verdict in the ledger unactioned.
- Improve / Update / Merge: present the concrete edit per rule → ask
[y/n/skip]; after the user approves that rule, apply it directly in this session (see Design note 2 — no improvement engine exists for rules, and the files are small). If an applied edit changes the rule's reason-to-exist or expiry conditions, refresh itsrationale:/review-when:comments in the same diff (ADR-0021). - Demote to skill: hand off skill creation to
skill-creator; then reduce the rule to a 1–3 line principle +See skill:pointer. - Dissolve / Retire: per file, present (1) the absorption evidence or defect, (2) what
covers the need instead (Dissolve: the named harness feature; Retire: the replacement
rule/skill), (3) removal impact — other rules referencing it and the public repo copy.
Act only after the user confirms. For Dissolve, offer to record the why via
adr-writer(akc-cycle.md: "record the why in an ADR, not a standing rule"). - Sync README.md: any file added/renamed/removed → update the tree and its one-line description (pairs with the Phase 1 consistency check).
- Update the ledger: Read
results.json→ merge this run's verdicts → Write it back (evaluated_at= real UTC fromdate -u +%Y-%m-%dT%H:%M:%SZ). Inchangedmode, preserve prior verdicts of rules not re-evaluated. - Public-repo note: retiring or editing an
origin: shimo4228rule leaves the public repo stale — point the user atharness-syncfor the follow-up.
Reason quality (required)
Every reason must be self-contained — decision-enabling on its own. "unchanged"
alone is banned. For non-Keep verdicts, cite the No answers (question + one-line evidence):
- Demote: name what stays and what moves. Bad:
"Too detailed"/ Good:"109 lines of pytest fixture recipes; only the 80%-coverage principle changes per-session behavior. Keep 3 lines + pointer, move recipes to python-patterns skill." - Dissolve: name the absorber. Bad:
"Not needed anymore"/ Good:"Harness plan mode now enforces the plan-file workflow natively (system prompt §Plan Workflow); the rule's manual checklist duplicates and predates it. ADR the why, then delete." - Merge: name the target + what to integrate. Bad:
"Overlaps"/ Good:"§Retry duplicates debugging.md's Retry with Context; only the backoff constants are unique — fold them into debugging.md L40." - Keep (carry-forward in
changedmode): restate the rationale. Bad:"Unchanged"/ Good:"Content unchanged. 42-line fix-chain gate referenced by planning.md's 2-intervention model; no absorber in current harness."
results.json (lean ledger)
{
"evaluated_at": "2026-07-03T00:00:00Z",
"total_lines": 1144,
"rules": {
"common/planning": {
"path": "~/.claude/rules/common/planning.md",
"lines": 209,
"verdict": "Keep",
"reason": "...",
"mtime": "2026-06-28T09:45:00Z"
}
}
}
Keys are directory-qualified stems (common/planning, common/debugging) so the schema
survives nesting.
lines / total_lines let changed mode rebuild the Phase 3 table
and the aggregate judgment from carried-forward entries. Update inline with Read/Write,
not a script. Created on the first run — do not pre-seed an empty file.
Related
skill-stocktake— the same audit for skills; this skill inverts its cost model (trigger pollution → residency).repo-asset-stocktake— the same stocktake pattern for a project repo's non-code assets (configs / workflows / runbooks); rules-stocktake audits~/.claude/rules/.rules-distill— promotes skill patterns into rules; rules-stocktake audits what accumulated and demotes back what stopped earning residency. Inverse directions over the same boundary.skill-comply— measures whether rules are actually followed (dynamic). rules-stocktake stays static: never issue a compliance-based verdict without a skill-comply run; existing skill-comply results may serve as Stage 2 evidence (read, never require).generation-audit— on a model-generation change, collects runtime-layer evidence (conflict / redundancy / drift classification against the live system prompt and tool descriptions) and hands the rules slice here as Stage 2 evidence, same read-never-require contract as skill-comply results.config-gc— whole-config GC across hooks/permissions/MCP; rules-stocktake judges rule quality.skill-creator— handoff target for the skill-creation half of Demote.adr-writer— records the why of a Dissolve.harness-sync— syncs survivingorigin: shimo4228rules to the public repo after edits/retirements.harness-boundary— design-time lens (layer / portability / obsolescence) applied when a mechanism is proposed; when it is applied to an installed rule its Delete / Move become Stage 2 evidence here (read, never require).
References
The two-stage binary-question design (screen → verdict pressure-test, holistic verdict,
no score aggregation) is inherited from skill-stocktake and follows the
checklist-decomposition evaluation line: BinEval "Ask, Don't Judge"
(arXiv:2606.27226), CheckEval (arXiv:2403.18771),
TICK (arXiv:2410.03608) — over-decomposition degrades correlation on holistic quality,
hence six questions and no score. The absorption question and the Dissolve verdict
implement rules/common/akc-cycle.md — the Curate checks (redundancy / staleness /
silence) and Scaffold Dissolution's two vectors (inward internalization, downward
substrate absorption).