Claude Code auto-loads everything matching .claude/rules/*.md into every <system-reminder>. At 40,000 chars CC emits a yellow runtime warning — by then context burn is already material. The hq-ext platform recent-decisions.md ballooned to 53.8k chars (1.3× cliff) before anyone noticed.
SessionStart async hook scans .claude/rules/ + .claude/plugins/ and emits operator-facing stderr warnings:
[orchestkit] WARN: .claude/rules/foo.md is 36.2 KiB (37,123 chars) — auto-loaded into every prompt. CC warns at 40k. Consider splitting via index-per-entry pattern (see src/skills/CONTRIBUTING-SKILLS.md#storage-patterns or skill-evolution/references/storage-patterns.md).
Thresholds:
New doc at src/skills/skill-evolution/references/storage-patterns.md with trade-off table, decision matrix, migration script. Pointer added to src/skills/CONTRIBUTING-SKILLS.md so future skill authors hit it during the authoring flow.
| Pattern | Best for | Failure mode |
|---|---|---|
| Rolling logbook | Bounded growth, < 30k chars total, chronological narrative | Crosses 40k cliff silently |
| Index-per-entry | Unbounded growth, lookups by-key or by-date | Two-step writes, more PR diff noise |
Default to index-per-entry if unsure — bounded by construction.
rules-size-check.test.ts — 12 tests: thresholds, silent paths, severity escalation, sort order, *.md filter, ctx.projectDir fallback, defensive on null input, warning text shapesplit-bundles.test.ts + hooks-json-wiring.test.ts — count bumps 228→229, 196→197Total: 196 → 197 (one new lifecycle/ hook, SessionStart async).
Closes #1815. Closes #1816.