|
| 1 | +# Rule compression |
| 2 | + |
| 3 | +Read when the Not yet codified dimension flags rule volume, or before compressing or splitting `AGENTS.md` |
| 4 | +or a `.claude/rules` file for any reason. Proven on 2026-10-17, when this guide went from 89.7 KB to 30.5 KB by moving area |
| 5 | +sections into path rules. |
| 6 | + |
| 7 | +## When |
| 8 | + |
| 9 | +A file is a candidate when it is more than 20% larger than the size recorded after its last compression |
| 10 | +in `docs/weekly-audit.md` (record the size the same day you compress). Reporting a size is not enough: |
| 11 | +a file reported in two runs without a Phase 4 item stayed as it was. Compression is a Phase 4 item like any other: it needs the maintainer's approval of the batch. |
| 12 | + |
| 13 | +## Contract |
| 14 | + |
| 15 | +The header of `AGENTS.md` is the contract: keep each rule's invariant, scope and why, plus failure |
| 16 | +mechanism, measured numbers, counterexamples, locked test names, rejected alternatives, maintainer |
| 17 | +decisions with their dates and every failure-recovery step. Remove narration, timelines and repeated |
| 18 | +receipts. Per-case detail (one app, one tool, one incident) may move to the matching `.claude/references` |
| 19 | +file with a one-line pointer; moving is not deleting. Never delete a rule because a personal global file |
| 20 | +says the same: the repo's guides are the complete contract. Keep `paths:` frontmatter byte-identical. |
| 21 | + |
| 22 | +## Steps |
| 23 | + |
| 24 | +1. Save each original to the scratchpad with `git show HEAD:<path>` and record `wc -w` / `wc -c`. |
| 25 | +2. One agent per file, each told to touch only its file and the reference file it moves detail to, and to |
| 26 | + stop if `git diff --stat -- <file>` is not empty before its final write (other sessions share the tree). |
| 27 | +3. Mechanical gates, all from the agents and rerun by the main session: |
| 28 | + no lock checker exists here: grep every test name the original names after "Locked by" in `tests/` and `cmd/`; |
| 29 | + every backticked token of the original still appears in the file or its reference destination; no |
| 30 | + U+2014; the size before and after. |
| 31 | +4. Independent meaning review, mandatory: a different agent diffs `git show <commit>^:<path>` against the |
| 32 | + new file and reports dropped or changed constraints, each refuted once by searching the file, its |
| 33 | + references, `AGENTS.md` and sibling rules. On 2026-10-17 every mechanical gate passed and this review |
| 34 | + still found 73 real losses across the four rule sets compressed that day, none dangerous, many medium. The recurring |
| 35 | + shapes, to look for first: |
| 36 | + - a "why" deleted where it was the only thing stopping a plausible wrong fix; |
| 37 | + - a list of conditions cut to its first item; |
| 38 | + - scope widened or narrowed; |
| 39 | + - the maintainer's name and date removed, so a settled decision reads as reopenable; |
| 40 | + - a claim the compressor invented: a rounded number, a generalisation from one incident, or a |
| 41 | + narrowing the code does not make (the split here wrote that the installer pins `SCRIPT_DIR=`, which |
| 42 | + it rewrites). |
| 43 | +5. Restore each surviving loss by putting the original wording back, then rerun the gates. |
| 44 | +6. Before syncing a shared checkout, compare the originals with `origin/main`: a session that edited the same |
| 45 | + rule while you compressed it leaves a sync conflict. Take its added words with |
| 46 | + `git diff --word-diff=plain HEAD origin/main -- <file>`, apply them to the compressed text, restore the file |
| 47 | + to HEAD, sync, then write the merged text back. |
| 48 | + |
| 49 | +## Splitting a guide into path rules |
| 50 | + |
| 51 | +- Every glob in `paths:` must match a real file: test each against `git ls-files`. A rule whose globs match |
| 52 | + nothing never loads. |
| 53 | +- A rule that must apply before any file is edited (triage, PR review, release, announcements, replies) stays |
| 54 | + in `AGENTS.md` or gets an explicit "read X before ..." line there naming every trigger; the CLI split first |
| 55 | + loaded `github.md` only at reply time, after a fix already existed. |
| 56 | +- A contract between two files (an app shape the uninstall inventory accepts must also pass Clean's scan) |
| 57 | + goes into the rules of both sides, and a rule follows the file that holds its code, not the feature name. |
| 58 | +- The routing table in `AGENTS.md` names every rule file for runtimes that do not load `.claude/rules`. |
0 commit comments