with one click
enhance-orchestrator
// Use when coordinating multiple enhancers for /enhance command. Runs analyzers in parallel and produces unified report.
// Use when coordinating multiple enhancers for /enhance command. Runs analyzers in parallel and produces unified report.
Use when improving agent prompts, frontmatter, and tool restrictions.
Use when improving CLAUDE.md or AGENTS.md project memory files.
Use when checking cross-file consistency: tools vs frontmatter, agent references, duplicate rules, contradictions.
Use when improving documentation structure, accuracy, and RAG readiness.
Use when reviewing hooks for safety, timeouts, and correct frontmatter.
Use when analyzing plugin structures, MCP tools, and plugin security patterns.
| name | enhance-orchestrator |
| description | Use when coordinating multiple enhancers for /enhance command. Runs analyzers in parallel and produces unified report. |
| version | 5.1.0 |
| argument-hint | [path] [--apply] [--focus=TYPE] |
Coordinate all enhancement analyzers in parallel and produce a unified report.
const args = '$ARGUMENTS'.split(' ').filter(Boolean);
const targetPath = args.find(a => !a.startsWith('--')) || '.';
const flags = {
apply: args.includes('--apply'),
focus: args.find(a => a.startsWith('--focus='))?.split('=')[1],
verbose: args.includes('--verbose'),
showSuppressed: args.includes('--show-suppressed'),
resetLearned: args.includes('--reset-learned'),
noLearn: args.includes('--no-learn'),
exportLearned: args.includes('--export-learned')
};
// Validate focus type
const VALID_FOCUS = ['plugin', 'agent', 'claudemd', 'claude-memory', 'docs', 'prompt', 'hooks', 'skills', 'cross-file'];
if (flags.focus && !VALID_FOCUS.includes(flags.focus)) {
console.error(`Invalid --focus: "${flags.focus}". Valid: ${VALID_FOCUS.join(', ')}`);
return;
}
Detect what exists in target path:
const discovery = {
plugins: await Glob({ pattern: 'plugins/*/.claude-plugin/plugin.json', path: targetPath }),
agents: await Glob({ pattern: '**/agents/*.md', path: targetPath }),
claudemd: await Glob({ pattern: '**/CLAUDE.md', path: targetPath }) ||
await Glob({ pattern: '**/AGENTS.md', path: targetPath }),
docs: await Glob({ pattern: 'docs/**/*.md', path: targetPath }),
prompts: await Glob({ pattern: '**/prompts/**/*.md', path: targetPath }) ||
await Glob({ pattern: '**/commands/**/*.md', path: targetPath }),
hooks: await Glob({ pattern: '**/hooks/**/*.md', path: targetPath }),
skills: await Glob({ pattern: '**/skills/**/SKILL.md', path: targetPath }),
// Cross-file runs if agents OR skills exist (analyzes relationships)
'cross-file': discovery.agents?.length || discovery.skills?.length ? ['enabled'] : []
};
// Use relative path from skill directory to plugin lib
// Path: skills/enhance-orchestrator/ -> ../../lib/
const { getSuppressionPath } = require('../../lib/cross-platform');
const { loadAutoSuppressions, getProjectId, clearAutoSuppressions } = require('../../lib/enhance/auto-suppression');
const suppressionPath = getSuppressionPath();
const projectId = getProjectId(targetPath);
if (flags.resetLearned) {
clearAutoSuppressions(suppressionPath, projectId);
console.log(`Cleared suppressions for project: ${projectId}`);
}
const autoLearned = loadAutoSuppressions(suppressionPath, projectId);
CRITICAL: MUST spawn these EXACT agents using Task(). Do NOT use Explore or other agents.
| Focus Type | Agent to Spawn | Model | JS Analyzer |
|---|---|---|---|
plugin | enhance:plugin-enhancer | sonnet | lib/enhance/plugin-analyzer.js |
agent | enhance:agent-enhancer | opus | lib/enhance/agent-analyzer.js |
claudemd | enhance:claudemd-enhancer | opus | lib/enhance/projectmemory-analyzer.js |
docs | enhance:docs-enhancer | opus | lib/enhance/docs-analyzer.js |
prompt | enhance:prompt-enhancer | opus | lib/enhance/prompt-analyzer.js |
hooks | enhance:hooks-enhancer | opus | lib/enhance/hook-analyzer.js |
skills | enhance:skills-enhancer | opus | lib/enhance/skill-analyzer.js |
cross-file | enhance:cross-file-enhancer | sonnet | lib/enhance/cross-file-analyzer.js |
Each agent has Bash(node:*) to run its JS analyzer. Do NOT substitute with Explore agents.
// EXACT agent mapping - do not change
const ENHANCER_AGENTS = {
plugin: 'enhance:plugin-enhancer',
agent: 'enhance:agent-enhancer',
claudemd: 'enhance:claudemd-enhancer',
docs: 'enhance:docs-enhancer',
prompt: 'enhance:prompt-enhancer',
hooks: 'enhance:hooks-enhancer',
skills: 'enhance:skills-enhancer',
'cross-file': 'enhance:cross-file-enhancer'
};
const promises = [];
// Pre-fetch repo-intel data for the enhancer agents.
//
// What each query gives the enhancers and how it shapes their suggestions:
//
// doc-drift - doc files with low code coupling. The docs-enhancer
// de-prioritises edits to docs that aren't "alive" (low
// coupling) and prioritises the ones that are - those
// are the ones users actually read against the code.
// stale-docs - symbol-level: the doc references a function/class
// that no longer exists in code. Highest-precision
// drift signal; trumps the heuristic doc-drift score.
// conventions - commit-message style + naming patterns. Passed to
// agent-prompts, skills, and prompts enhancers so
// their generated language matches the project voice
// (e.g. terse vs. verbose, "feat:" vs "Add ", etc.).
let docDriftContext = '';
let conventionsContext = '';
try {
const { binary } = require(`${pluginRoot}/lib/agentsys`).get();
const { libRoot } = require(`${pluginRoot}/lib/agentsys`).get(); const { getStateDirPath } = require(`${libRoot}/platform/state-dir`);
const fs = require('fs');
const cwd = process.cwd();
const mapFile = require('path').join(getStateDirPath(cwd), 'repo-intel.json');
const q = (args) => { try { return JSON.parse(binary.runAnalyzer(args)); } catch { return null; } };
if (fs.existsSync(mapFile)) {
const docDrift = q(['repo-intel', 'query', 'doc-drift', '--top', '20', '--map-file', mapFile, cwd]);
const staleDocs = q(['repo-intel', 'query', 'stale-docs', '--top', '20', '--map-file', mapFile, cwd]);
const conventions = q(['repo-intel', 'query', 'conventions', '--map-file', mapFile, cwd]);
if (docDrift && docDrift.length > 0) {
const stale = docDrift.filter(d => d.codeCoupling === 0).map(d => d.path);
if (stale.length > 0) {
docDriftContext = '\nDoc-drift (docs with zero code coupling, likely stale): ' + stale.join(', ');
}
}
if (staleDocs && staleDocs.length > 0) {
docDriftContext += '\nStale doc refs (symbol-level):\n' +
staleDocs.slice(0, 10).map(s => ` ${s.doc}:${s.line} "${s.reference}" [${s.issue}]`).join('\n');
}
if (conventions) {
conventionsContext = '\nProject conventions: ' + JSON.stringify(conventions);
}
}
} catch (e) {
console.error(`[INFO] repo-intel context skipped: ${e.message}`);
}
for (const [type, agentType] of Object.entries(ENHANCER_AGENTS)) {
if (focus && focus !== type) continue;
if (!discovery[type]?.length) continue;
// Append relevant context per enhancer type
let extraContext = '';
if (type === 'docs') extraContext = docDriftContext;
if (['agent-prompts', 'skills', 'prompts'].includes(type)) extraContext = conventionsContext;
// MUST use exact subagent_type - these agents have Bash(node:*) to run JS analyzers
promises.push(Task({
subagent_type: agentType,
prompt: `Analyze ${type} in ${targetPath}.
MUST use Skill tool to invoke your enhance-* skill.
The skill runs the JavaScript analyzer and returns structured findings.
verbose: ${flags.verbose}${extraContext}
Return JSON: { "enhancerType": "${type}", "findings": [...], "summary": { high, medium, low } }`
}));
}
// MUST use Promise.all for parallel execution
const results = await Promise.all(promises);
function aggregateResults(enhancerResults) {
const findings = [];
const byEnhancer = {};
for (const result of enhancerResults) {
if (!result?.findings) continue;
for (const finding of result.findings) {
findings.push({ ...finding, source: result.enhancerType });
}
byEnhancer[result.enhancerType] = result.summary;
}
return {
findings,
byEnhancer,
totals: {
high: findings.filter(f => f.certainty === 'HIGH').length,
medium: findings.filter(f => f.certainty === 'MEDIUM').length,
low: findings.filter(f => f.certainty === 'LOW').length
}
};
}
Generate report directly from aggregated findings:
const { generateReport } = require('../../lib/enhance/reporter');
const report = generateReport(aggregated, {
verbose: flags.verbose,
showAutoFixable: flags.apply
});
console.log(report);
if (!flags.noLearn) {
const { analyzeForAutoSuppression, saveAutoSuppressions } = require('../../lib/enhance/auto-suppression');
const newSuppressions = analyzeForAutoSuppression(aggregated.findings, fileContents, { projectRoot: targetPath });
if (newSuppressions.length > 0) {
saveAutoSuppressions(suppressionPath, projectId, newSuppressions);
console.log(`\nLearned ${newSuppressions.length} new suppressions.`);
}
}
if (flags.apply) {
const autoFixable = aggregated.findings.filter(f => f.certainty === 'HIGH' && f.autoFixable);
if (autoFixable.length > 0) {
console.log(`\n## Applying ${autoFixable.length} Auto-Fixes\n`);
const byEnhancer = {};
for (const fix of autoFixable) {
const type = fix.source;
if (!byEnhancer[type]) byEnhancer[type] = [];
byEnhancer[type].push(fix);
}
for (const [type, fixes] of Object.entries(byEnhancer)) {
await Task({
subagent_type: enhancerAgents[type],
prompt: `Apply HIGH certainty fixes: ${JSON.stringify(fixes, null, 2)}`
});
}
console.log(`Applied ${autoFixable.length} fixes.`);
}
}
# Enhancement Analysis Report
**Target**: {targetPath}
**Date**: {timestamp}
**Enhancers Run**: {list}
## Executive Summary
| Enhancer | HIGH | MEDIUM | LOW | Auto-Fixable |
|----------|------|--------|-----|--------------|
| plugin | 2 | 3 | 1 | 1 |
| agent | 1 | 2 | 0 | 1 |
| **Total**| **3**| **5** | **1**| **2** |
## HIGH Certainty Issues
[Grouped by enhancer, then file]
## MEDIUM Certainty Issues
[...]
## Auto-Fix Summary
{n} issues can be fixed with `--apply` flag.
Expected: the orchestrator (the command that spawned this agent) has already checked <stateDir>/repo-intel.json and either pre-fetched the data into your context or skipped (user declined to generate). Do not call AskUserQuestion here - subagents cannot interact with the user.
If the pre-fetched data is empty, proceed with the available context. The orchestrator has already made the decision on the user's behalf.
Binary: agent-analyzer auto-downloads to ~/.agent-sh/bin/ from agent-sh/agent-analyzer GitHub releases (~10 MB) on first use. The lib/agentsys resolver locates the agentsys install (CC marketplace clone, npm global, or sibling repo).