Every command so far asked an addition question — what to add, what to move, what it costs. Nothing asked what is no longer earning its always-loaded rent. This adds that axis as a fourth lensCheck on the existing hybrid motor rather than a new scanner or a 22nd command: the measured payoff (~18% of one file) justifies a mode, not machinery. It is the only lens that proposes REMOVING config, so it carries a guarantee the others don't need: a load-bearing block is never a candidate. Precision is asymmetric — a missed dead line costs a few tokens per turn, a deleted one costs a wrong remote or a broken script — so the floor is decided in code (lib/floor-exclusion.mjs) before the opus judge sees anything, never in prose. Granularity is the leaf block, with two structural exceptions: a paragraph ending in ':' merges with the list it introduces, and an ordered list is a contract whose steps inherit floor from any sibling. Unordered lists deliberately do not inherit — a load-bearing bullet and a disposable one routinely share a list, and container-reasoning is the error the hand-built ground truth exists to catch. Verified against that ground truth (built before any classifier existed), with the comparison machine-checked rather than read by eye: zero load-bearing blocks proposed, 11/18 deletable groups surfaced, ~756 tok ~ 18% of a ~4300 token file — inside the pre-registered band. The first run found five floor violations the synthesized fixture missed; each got a structural rule and a fixture shape so it cannot regress. Three real bugs the dogfood run exposed, all now covered: - JS \b is ASCII-only, so /\bunngå\b/ never matches — every Norwegian keyword ending in æ/ø/å was silently dead. - A bare word/word is not a path; "pros/cons" vetoed the largest deletable block until PATH_RE was tightened to rooted paths and globs. - "Mid-sentence" must key on a preceding lowercase letter; the loose version read **bold labels:** and quoted openers as entities, costing 4 of 11 groups. BP-SUB-001 is grounded entirely in the Anthropic steering blog already cited by BP-MECH-001..004 and asserts nothing from the talk that motivated the feature — no "80%", no ablation figure. Suite 1365 -> 1382/0. Frozen v5.0.0 snapshots untouched; plain optimize output byte-identical on identical input (--subtract adds keys only when passed). knowledge-refresh-cli's reference date moved to 2026-08-01: its premise that every seed entry was verified 2026-06-20 expired when BP-SUB-001 got a genuine verification date, and backdating the entry to fit the test would have been a lie about when its source was checked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RW2haJXbxZpKivKHseSXNh
153 lines
9.1 KiB
JSON
153 lines
9.1 KiB
JSON
{
|
|
"version": 1,
|
|
"note": "Machine-readable best-practices register. SOURCE OF TRUTH for the optimization lens (v5.7 CA-OPT). Human-readable mirror lives in knowledge/*.md. Every entry is provenance-stamped (source.url + source.verified) and carries a confidence; only CONFIRMED claims are consumed user-facing (Verifiseringsplikt). Curated manually + by /config-audit knowledge-refresh (human-approved). Seeded from docs/v5.5-steering-model-plan.md V-rows + the Anthropic 'Steering Claude Code' blog.",
|
|
"entries": [
|
|
{
|
|
"id": "BP-MECH-001",
|
|
"claim": "Lifecycle automation phrased as an instruction in CLAUDE.md (\"every time\", \"before each\", \"always run X after Y\") should be a hook — a behavior the model chooses to follow is not deterministic.",
|
|
"mechanism": "hook",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Move the behavior to a PreToolUse/PostToolUse/Stop hook so it runs deterministically, outside the model's discretion.",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "mechanism-fit",
|
|
"lensCheck": "claude-md-lifecycle-phrasing",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-MECH-002",
|
|
"claim": "A file- or path-specific constraint placed in root CLAUDE.md or an unscoped rule should be a path-scoped rule (paths: frontmatter), so it loads only when a matching file is touched.",
|
|
"mechanism": "rule",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Move it to .claude/rules/ with a paths: frontmatter; unscoped instructions cost tokens every turn whether relevant or not.",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "mechanism-fit",
|
|
"lensCheck": "unscoped-path-specific-instruction",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-MECH-003",
|
|
"claim": "A multi-step procedure (deploy/release checklist) in CLAUDE.md should be a skill — CLAUDE.md is for facts Claude should hold all the time; procedures belong in skills.",
|
|
"mechanism": "skill",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Extract the procedure into .claude/skills/; its body then loads only on invoke instead of every turn.",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "mechanism-fit",
|
|
"lensCheck": "procedure-in-claude-md",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-MECH-004",
|
|
"claim": "An absolute prohibition phrased as a \"never do X\" instruction is the wrong tool; for something that absolutely must not happen, use permissions or a PreToolUse hook.",
|
|
"mechanism": "permission",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Enforce hard prohibitions via permission deny rules or a PreToolUse hook (exit code 2 denies the call), not prose instructions.",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "mechanism-fit",
|
|
"lensCheck": "never-instruction",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-MECH-005",
|
|
"claim": "A custom output style without keep-coding-instructions: true removes Claude Code's built-in software-engineering instructions when active.",
|
|
"mechanism": "output-style",
|
|
"appliesTo": "output-style",
|
|
"recommendation": "Set keep-coding-instructions: true, or prefer a built-in style (Explanatory / Learning / Proactive) before writing a custom one.",
|
|
"confidence": "confirmed",
|
|
"severity": "medium",
|
|
"category": "mechanism-fit",
|
|
"lensCheck": "CA-OST-001",
|
|
"source": { "url": "https://code.claude.com/docs/en/output-styles", "title": "Output styles", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-001",
|
|
"claim": "Project-root CLAUDE.md and unscoped rules are re-injected from disk after compaction (they survive a /compact).",
|
|
"appliesTo": "claude-md",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/context-window", "title": "Context window — what survives compaction", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-002",
|
|
"claim": "Path-scoped rules are lost after compaction until a matching file is read again, and they trigger on Read of a matching file (not on every tool use).",
|
|
"appliesTo": "rule",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/memory", "title": "Memory — path-specific rules", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-003",
|
|
"claim": "A nested (non-root) CLAUDE.md is lost after compaction until a file in its directory is read again.",
|
|
"appliesTo": "claude-md",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/context-window", "title": "Context window — what survives compaction", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-004",
|
|
"claim": "A skill's name + description load every turn; its body loads only on invoke.",
|
|
"appliesTo": "skill",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/skills", "title": "Skills", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-005",
|
|
"claim": "Hook scripts run outside the model context, but any additionalContext they inject is saved to the transcript and is therefore subject to compaction.",
|
|
"appliesTo": "hook",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/hooks", "title": "Hooks", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-LOAD-006",
|
|
"claim": "A subagent runs in an isolated, fresh context window; only its final summary returns to the main session (parent instructions are not auto-injected).",
|
|
"appliesTo": "agent",
|
|
"confidence": "confirmed",
|
|
"category": "loading-model",
|
|
"lensCheck": null,
|
|
"source": { "url": "https://code.claude.com/docs/en/sub-agents", "title": "Subagents", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-SIZE-001",
|
|
"claim": "Keep CLAUDE.md under 200 lines; give it an owner and review changes to it like code. Every line costs tokens whether relevant or not.",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Trim CLAUDE.md to facts; move procedures to skills and path-specific rules to .claude/rules/.",
|
|
"confidence": "confirmed",
|
|
"severity": "medium",
|
|
"category": "size-budget",
|
|
"lensCheck": "CA-CML-001",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-SIZE-002",
|
|
"claim": "The skill-listing description cap is 1,536 characters (maxSkillDescriptionChars, configurable, v2.1.105+); the name + description load every turn.",
|
|
"appliesTo": "skill",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "size-budget",
|
|
"lensCheck": "CA-SKL-002",
|
|
"source": { "url": "https://code.claude.com/docs/en/skills", "title": "Skills", "verified": "2026-06-20" }
|
|
},
|
|
{
|
|
"id": "BP-SUB-001",
|
|
"claim": "Every line of CLAUDE.md loads into every session whether or not it is relevant, which consumes tokens and dilutes adherence. A line that states a local fact the model cannot derive (build commands, directory layout, conventions, team norms) earns that cost; a line that only restates general engineering behaviour pays it without being the kind of content CLAUDE.md is for, and is a candidate for removal.",
|
|
"mechanism": "deletion",
|
|
"appliesTo": "claude-md",
|
|
"recommendation": "Review the block for removal, then re-add it only if the model actually stumbles on it repeatedly. Local facts (remotes, versions, paths, conventions) and policy invariants are the floor and are never removal candidates.",
|
|
"confidence": "confirmed",
|
|
"severity": "low",
|
|
"category": "subtraction",
|
|
"lensCheck": "compensatory-instruction",
|
|
"source": { "url": "https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more", "title": "Steering Claude Code: skills, hooks, rules, subagents and more", "verified": "2026-07-31" }
|
|
}
|
|
]
|
|
}
|