From 6ab6cfd9b4d7299b971a68697e4a802b776319eb Mon Sep 17 00:00:00 2001 From: haelyra <49814733+haelyra@users.noreply.github.com> Date: Sun, 9 Aug 2026 17:32:15 -0400 Subject: [PATCH] fix: route context checks to native meters --- .../commands/context-budget.md | 6 +- skills/context-budget/SKILL.md | 162 ++++++------------ tests/skills/context-budget.test.js | 70 ++++++++ 3 files changed, 125 insertions(+), 113 deletions(-) create mode 100644 tests/skills/context-budget.test.js diff --git a/legacy-command-shims/commands/context-budget.md b/legacy-command-shims/commands/context-budget.md index 871b7d580..09a82c2a9 100644 --- a/legacy-command-shims/commands/context-budget.md +++ b/legacy-command-shims/commands/context-budget.md @@ -18,6 +18,6 @@ $ARGUMENTS ## Delegation Apply the `context-budget` skill. -- Pass through `--verbose` if the user supplied it. -- Assume a 200K context window unless the user specified otherwise. -- Return the skill's inventory, issue detection, and prioritized savings report without re-implementing the scan here. +- Without an explicit `--audit`, return the harness's native live-context command and do not scan files or call tools. +- Pass through `--audit` and `--verbose` only when the user supplied them. +- Keep any explicit audit bounded to the scope and safety rules in the canonical skill. diff --git a/skills/context-budget/SKILL.md b/skills/context-budget/SKILL.md index 16f3bd29c..b5da5b2c6 100644 --- a/skills/context-budget/SKILL.md +++ b/skills/context-budget/SKILL.md @@ -1,136 +1,78 @@ --- name: context-budget -description: Audits Claude Code context window consumption across agents, skills, MCP servers, and rules. Identifies bloat, redundant components, and produces prioritized token-savings recommendations. +description: Routes live context checks to the native Codex or Claude Code meter without scanning files, and performs a bounded static component audit only when explicitly requested. metadata: origin: ECC --- # Context Budget -Analyze token overhead across every loaded component in a Claude Code session and surface actionable optimizations to reclaim context space. +Use the provider's native meter for live session usage. Keep the separate, +estimated installation audit behind an explicit opt-in. -## When to Use +## Default: Live Context -- Session performance feels sluggish or output quality is degrading -- You've recently added many skills, agents, or MCP servers -- You want to know how much context headroom you actually have -- Planning to add more components and need to know if there's room -- Running `/context-budget` command (this skill backs it) +Treat an invocation with no audit request as a live-context request. This +includes requests for the current window, remaining capacity, headroom, token +usage, or a context breakdown. -## How It Works +For this default path: -### Phase 1: Inventory +- Do not call or use tools. +- Do not scan or read files. +- Do not run shell commands, provider CLIs, debug logging, or MCP discovery. +- Reply with only the native command and one short explanation. -Scan all component directories and estimate token consumption: +Route by the active harness: -**Agents** (`agents/*.md`) -- Count lines and tokens per file (words × 1.3) -- Extract `description` frontmatter length -- Flag: files >200 lines (heavy), description >30 words (bloated frontmatter) +| Harness | Native command | Guidance | +| --- | --- | --- | +| Codex CLI | `/status` | Shows current token usage and remaining context capacity. Use `/statusline` and enable **Context stats** plus **Token counters** for a persistent footer meter. | +| Claude Code | `/context` | Shows the live context breakdown. Use `/context all` for expanded items. | +| Other or unknown | None verified | State that ECC cannot read live provider state and ask which harness is active. | -**Skills** (`skills/*/SKILL.md`) -- Count tokens per SKILL.md -- Flag: files >400 lines -- Check for duplicate copies in `.agents/skills/` — skip identical copies to avoid double-counting +A skill cannot invoke a TUI slash command on the user's behalf. Never replace +the native command with an estimated scan and never infer an audit request from +phrases such as “context is heavy” or “how much is left.” -**Rules** (`rules/**/*.md`) -- Count tokens per file -- Flag: files >100 lines -- Detect content overlap between rule files in the same language module +## Explicit Static Audit -**MCP Servers** (`.mcp.json` or active MCP config) -- Count configured servers and total tool count -- Estimate schema overhead at ~500 tokens per tool -- Flag: servers with >20 tools, servers that wrap simple CLI commands (`gh`, `git`, `npm`, `supabase`, `vercel`) +Run an installation/configuration audit only when the user explicitly says +`--audit`, “audit installed components,” or equivalent unambiguous wording. +`--verbose` changes report detail; it does not opt into an audit by itself. -**CLAUDE.md** (project + user-level) -- Count tokens per file in the CLAUDE.md chain -- Flag: combined total >300 lines +If the audit scope is ambiguous, ask for the harness and installation root +before reading anything. Keep every audit bounded and read-only: -### Phase 2: Classify +1. Inspect only the named plugin/install root and the named harness's known + configuration files. +2. Never recursively enumerate the workspace root, home directory, provider + cache, transcripts, debug logs, or unrelated worktrees. +3. Never launch a provider CLI, MCP server, or debug session to count tools. +4. Cap inventory output at 50 entries per component class. Summarize the rest. +5. Do not write temporary logs or copy configuration content into the report. -Sort every component into a bucket: +Audit only the component metadata relevant to eager discovery: -| Bucket | Criteria | Action | -|--------|----------|--------| -| **Always needed** | Referenced in CLAUDE.md, backs an active command, or matches current project type | Keep | -| **Sometimes needed** | Domain-specific (e.g. language patterns), not referenced in CLAUDE.md | Consider on-demand activation | -| **Rarely needed** | No command reference, overlapping content, or no obvious project match | Remove or lazy-load | +- agent and skill descriptions; +- command descriptions when the harness discovers them eagerly; +- always-loaded instruction files in the explicitly named scope; +- configured MCP tool schemas when an existing bounded manifest exposes them. -### Phase 3: Detect Issues +Full skill, agent, command, and rule bodies are generally on-demand content. +Report their disk size separately from estimated eager overhead instead of +adding every body to the session baseline. -Identify the following problem patterns: +## Audit Output -- **Bloated agent descriptions** — description >30 words in frontmatter loads into every Task tool invocation -- **Heavy agents** — files >200 lines inflate Task tool context on every spawn -- **Redundant components** — skills that duplicate agent logic, rules that duplicate CLAUDE.md -- **MCP over-subscription** — >10 servers, or servers wrapping CLI tools available for free -- **CLAUDE.md bloat** — verbose explanations, outdated sections, instructions that should be rules +Return a compact report containing: -### Phase 4: Report +- harness and exact paths inspected; +- estimated eager/discovery overhead by component class; +- installed counts and the heaviest metadata entries; +- assumptions, unavailable measurements, and up to three optimizations. -Produce the context budget report: - -``` -Context Budget Report -═══════════════════════════════════════ - -Total estimated overhead: ~XX,XXX tokens -Context model: Claude Sonnet (200K window) -Effective available context: ~XXX,XXX tokens (XX%) - -Component Breakdown: -┌─────────────────┬────────┬───────────┐ -│ Component │ Count │ Tokens │ -├─────────────────┼────────┼───────────┤ -│ Agents │ N │ ~X,XXX │ -│ Skills │ N │ ~X,XXX │ -│ Rules │ N │ ~X,XXX │ -│ MCP tools │ N │ ~XX,XXX │ -│ CLAUDE.md │ N │ ~X,XXX │ -└─────────────────┴────────┴───────────┘ - -WARNING: Issues Found (N): -[ranked by token savings] - -Top 3 Optimizations: -1. [action] → save ~X,XXX tokens -2. [action] → save ~X,XXX tokens -3. [action] → save ~X,XXX tokens - -Potential savings: ~XX,XXX tokens (XX% of current overhead) -``` - -In verbose mode, additionally output per-file token counts, line-by-line breakdown of the heaviest files, specific redundant lines between overlapping components, and MCP tool list with per-tool schema size estimates. - -## Examples - -**Basic audit** -``` -User: /context-budget -Skill: Scans setup → 16 agents (12,400 tokens), 28 skills (6,200), 87 MCP tools (43,500), 2 CLAUDE.md (1,200) - Flags: 3 heavy agents, 14 MCP servers (3 CLI-replaceable) - Top saving: remove 3 MCP servers → -27,500 tokens (47% overhead reduction) -``` - -**Verbose mode** -``` -User: /context-budget --verbose -Skill: Full report + per-file breakdown showing planner.md (213 lines, 1,840 tokens), - MCP tool list with per-tool sizes, duplicated rule lines side by side -``` - -**Pre-expansion check** -``` -User: I want to add 5 more MCP servers, do I have room? -Skill: Current overhead 33% → adding 5 servers (~50 tools) would add ~25,000 tokens → pushes to 45% overhead - Recommendation: remove 2 CLI-replaceable servers first to stay under 40% -``` - -## Best Practices - -- **Token estimation**: use `words × 1.3` for prose, `chars / 4` for code-heavy files -- **MCP is the biggest lever**: each tool schema costs ~500 tokens; a 30-tool server costs more than all your skills combined -- **Agent descriptions are loaded always**: even if the agent is never invoked, its description field is present in every Task tool context -- **Verbose mode for debugging**: use when you need to pinpoint the exact files driving overhead, not for regular audits -- **Audit after changes**: run after adding any agent, skill, or MCP server to catch creep early +Every calculated token number is an estimate of static configuration overhead, +not live session context. Do not claim that an estimate is provider-reported, +current, exact, or evidence of realized savings. Direct the user back to the +native live-context command for current usage. diff --git a/tests/skills/context-budget.test.js b/tests/skills/context-budget.test.js new file mode 100644 index 000000000..186c532df --- /dev/null +++ b/tests/skills/context-budget.test.js @@ -0,0 +1,70 @@ +'use strict'; + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +const repoRoot = path.resolve(__dirname, '..', '..'); +const skillPath = path.join(repoRoot, 'skills', 'context-budget', 'SKILL.md'); +const legacyShimPath = path.join(repoRoot, 'legacy-command-shims', 'commands', 'context-budget.md'); + +const skill = fs.readFileSync(skillPath, 'utf8'); +const legacyShim = fs.readFileSync(legacyShimPath, 'utf8'); + +let passed = 0; +let failed = 0; + +function test(name, fn) { + try { + fn(); + console.log(` ✓ ${name}`); + passed += 1; + } catch (error) { + console.log(` ✗ ${name}`); + console.log(` Error: ${error.message}`); + failed += 1; + } +} + +console.log('\n=== Context budget skill tests ===\n'); + +test('describes a cross-harness live-context router instead of a Claude-only audit', () => { + const frontmatter = skill.match(/^---\n([\s\S]*?)\n---/); + assert.ok(frontmatter, 'SKILL.md frontmatter is missing'); + assert.match(frontmatter[1], /description:.*live context/i); + assert.match(frontmatter[1], /Codex/i); + assert.doesNotMatch(frontmatter[1], /Audits Claude Code/i); +}); + +test('routes Codex live context requests to native status surfaces without tools', () => { + assert.match(skill, /Codex[\s\S]*`\/status`/i); + assert.match(skill, /Codex[\s\S]*`\/statusline`/i); + assert.match(skill, /do not (?:call|use).*tools/i); + assert.match(skill, /do not (?:scan|read).*files/i); +}); + +test('routes Claude Code live context requests to its native context command', () => { + assert.match(skill, /Claude Code[\s\S]*`\/context`/i); +}); + +test('requires explicit audit intent before inventorying installed components', () => { + assert.match(skill, /only.*(?:`--audit`|explicit).*audit/is); + assert.match(skill, /never infer.*audit/is); + assert.match(skill, /bounded/i); +}); + +test('keeps estimated static overhead distinct from live provider usage', () => { + assert.match(skill, /estimate/i); + assert.match(skill, /not.*live (?:session|context)/i); + assert.match(skill, /do not claim/i); +}); + +test('keeps the legacy slash shim on the same safe default', () => { + assert.match(legacyShim, /native live-context command/i); + assert.match(legacyShim, /explicit.*`--audit`/i); + assert.doesNotMatch(legacyShim, /Assume a 200K context window/i); +}); + +console.log(`\nPassed: ${passed}`); +console.log(`Failed: ${failed}`); +process.exit(failed > 0 ? 1 : 0);