# Action: Diagnose Token Consumption Analyze target skill for token consumption inefficiencies and output optimization opportunities. ## Purpose Detect patterns that cause excessive token usage: - Verbose prompts without compression - Large state objects with unnecessary fields - Full content passing instead of references - Unbounded arrays without sliding windows - Redundant file I/O (write-then-read patterns) ## Detection Patterns | Pattern ID | Name | Detection Logic | Severity | |------------|------|-----------------|----------| | TKN-001 | Verbose Prompts | Prompt files > 4KB or high static/variable ratio | medium | | TKN-002 | Excessive State Fields | State schema > 15 top-level keys | medium | | TKN-003 | Full Content Passing | `Read()` result embedded directly in prompt | high | | TKN-004 | Unbounded Arrays | `.push`/`concat` without `.slice(-N)` | high | | TKN-005 | Redundant Write→Read | `Write(file)` followed by `Read(file)` | medium | ## Execution Steps ```javascript async function diagnoseTokenConsumption(state, workDir) { const issues = []; const evidence = []; const skillPath = state.target_skill.path; // 1. Scan for verbose prompts (TKN-001) const mdFiles = Glob(`${skillPath}/**/*.md`); for (const file of mdFiles) { const content = Read(file); if (content.length > 4000) { evidence.push({ file: file, pattern: 'TKN-001', severity: 'medium', context: `File size: ${content.length} chars (threshold: 4000)` }); } } // 2. Check state schema field count (TKN-002) const stateSchema = Glob(`${skillPath}/**/state-schema.md`)[0]; if (stateSchema) { const schemaContent = Read(stateSchema); const fieldMatches = schemaContent.match(/^\s*\w+:/gm) || []; if (fieldMatches.length > 15) { evidence.push({ file: stateSchema, pattern: 'TKN-002', severity: 'medium', context: `State has ${fieldMatches.length} fields (threshold: 15)` }); } } // 3. Detect full content passing (TKN-003) const fullContentPattern = /Read\([^)]+\)\s*[\+,]|`\$\{.*Read\(/g; for (const file of mdFiles) { const content = Read(file); const matches = content.match(fullContentPattern); if (matches) { evidence.push({ file: file, pattern: 'TKN-003', severity: 'high', context: `Full content passing detected: ${matches[0]}` }); } } // 4. Detect unbounded arrays (TKN-004) const unboundedPattern = /\.(push|concat)\([^)]+\)(?!.*\.slice)/g; for (const file of mdFiles) { const content = Read(file); const matches = content.match(unboundedPattern); if (matches) { evidence.push({ file: file, pattern: 'TKN-004', severity: 'high', context: `Unbounded array growth: ${matches[0]}` }); } } // 5. Detect write-then-read patterns (TKN-005) const writeReadPattern = /Write\([^)]+\)[\s\S]{0,100}Read\([^)]+\)/g; for (const file of mdFiles) { const content = Read(file); const matches = content.match(writeReadPattern); if (matches) { evidence.push({ file: file, pattern: 'TKN-005', severity: 'medium', context: `Write-then-read pattern detected` }); } } // Calculate severity const highCount = evidence.filter(e => e.severity === 'high').length; const mediumCount = evidence.filter(e => e.severity === 'medium').length; let severity = 'none'; if (highCount > 0) severity = 'high'; else if (mediumCount > 2) severity = 'medium'; else if (mediumCount > 0) severity = 'low'; return { status: 'completed', issues_found: evidence.length, severity: severity, execution_time_ms: Date.now() - startTime, details: { patterns_checked: ['TKN-001', 'TKN-002', 'TKN-003', 'TKN-004', 'TKN-005'], patterns_matched: [...new Set(evidence.map(e => e.pattern))], evidence: evidence, recommendations: generateRecommendations(evidence) } }; } function generateRecommendations(evidence) { const recs = []; const patterns = [...new Set(evidence.map(e => e.pattern))]; if (patterns.includes('TKN-001')) { recs.push('Apply prompt_compression: Extract static instructions to templates, use placeholders'); } if (patterns.includes('TKN-002')) { recs.push('Apply state_field_reduction: Remove debug/cache fields, consolidate related fields'); } if (patterns.includes('TKN-003')) { recs.push('Apply lazy_loading: Pass file paths instead of content, let agents read if needed'); } if (patterns.includes('TKN-004')) { recs.push('Apply sliding_window: Add .slice(-N) to array operations to bound growth'); } if (patterns.includes('TKN-005')) { recs.push('Apply output_minimization: Use in-memory data passing, eliminate temporary files'); } return recs; } ``` ## Output Write diagnosis result to `${workDir}/diagnosis/token-consumption-diagnosis.json`: ```json { "status": "completed", "issues_found": 3, "severity": "medium", "execution_time_ms": 1500, "details": { "patterns_checked": ["TKN-001", "TKN-002", "TKN-003", "TKN-004", "TKN-005"], "patterns_matched": ["TKN-001", "TKN-003"], "evidence": [ { "file": "phases/orchestrator.md", "pattern": "TKN-001", "severity": "medium", "context": "File size: 5200 chars (threshold: 4000)" } ], "recommendations": [ "Apply prompt_compression: Extract static instructions to templates" ] } } ``` ## State Update ```javascript updateState({ diagnosis: { ...state.diagnosis, token_consumption: diagnosisResult } }); ``` ## Fix Strategies Mapping | Pattern | Strategy | Implementation | |---------|----------|----------------| | TKN-001 | prompt_compression | Extract static text to variables, use template inheritance | | TKN-002 | state_field_reduction | Audit and consolidate fields, remove non-essential data | | TKN-003 | lazy_loading | Pass paths instead of content, agents load when needed | | TKN-004 | sliding_window | Add `.slice(-N)` after push/concat operations | | TKN-005 | output_minimization | Use return values instead of file relay |