claude-flow-tbowman01
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
472 lines (458 loc) • 19.1 kB
JavaScript
import { success, error, warning, info } from '../cli-core.js';
import chalk from 'chalk';
const { blue, yellow, green, magenta, cyan } = chalk;
let sparcConfig = null;
async function loadSparcConfig() {
if (sparcConfig) {
return sparcConfig;
}
try {
const configPath = '.roomodes';
const { readFile } = await import('fs/promises');
const content = await readFile(configPath, 'utf-8');
sparcConfig = JSON.parse(content);
return sparcConfig;
}
catch (error) {
throw new Error(`Failed to load SPARC configuration: ${error instanceof Error ? error.message : String(error)}`);
}
}
export async function sparcAction(ctx) {
const subcommand = ctx.args[0];
switch (subcommand) {
case 'modes':
await listSparcModes(ctx);
break;
case 'info':
await showModeInfo(ctx);
break;
case 'run':
await runSparcMode(ctx);
break;
case 'tdd':
await runTddFlow(ctx);
break;
case 'workflow':
await runSparcWorkflow(ctx);
break;
default:
await showSparcHelp();
break;
}
}
async function listSparcModes(ctx) {
try {
const config = await loadSparcConfig();
const verbose = ctx.flags.verbose;
success('Available SPARC Modes:');
console.log();
for (const mode of config.customModes) {
console.log(`${cyan('•')} ${green(mode.name)} ${blue(`(${mode.slug})`)}`);
if (verbose) {
console.log(` ${mode.roleDefinition}`);
console.log(` Tools: ${mode.groups.join(', ')}`);
console.log();
}
}
if (!verbose) {
console.log();
info('Use --verbose for detailed descriptions');
}
}
catch (err) {
error(`Failed to list SPARC modes: ${err.message}`);
}
}
async function showModeInfo(ctx) {
const modeSlug = ctx.args[1];
if (!modeSlug) {
error('Usage: sparc info <mode-slug>');
return;
}
try {
const config = await loadSparcConfig();
const mode = config.customModes.find((m) => m.slug === modeSlug);
if (!mode) {
error(`Mode not found: ${modeSlug}`);
console.log('Available modes:');
for (const m of config.customModes) {
console.log(` ${m.slug} - ${m.name}`);
}
return;
}
success(`SPARC Mode: ${mode.name}`);
console.log();
console.log(blue('Role Definition:'));
console.log(mode.roleDefinition);
console.log();
console.log(blue('Custom Instructions:'));
console.log(mode.customInstructions);
console.log();
console.log(blue('Tool Groups:'));
console.log(mode.groups.join(', '));
console.log();
console.log(blue('Source:'));
console.log(mode.source);
}
catch (err) {
error(`Failed to show mode info: ${err.message}`);
}
}
async function runSparcMode(ctx) {
const modeSlug = ctx.args[1];
const taskDescription = ctx.args.slice(2).join(' ');
if (!modeSlug || !taskDescription) {
error('Usage: sparc run <mode-slug> <task-description>');
return;
}
try {
const config = await loadSparcConfig();
const mode = config.customModes.find((m) => m.slug === modeSlug);
if (!mode) {
error(`Mode not found: ${modeSlug}`);
return;
}
// Build the enhanced task prompt using SPARC methodology
const enhancedTask = buildSparcPrompt(mode, taskDescription, ctx.flags);
const instanceId = `sparc-${modeSlug}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
// Build tools based on mode groups
const tools = buildToolsFromGroups(mode.groups);
if (ctx.flags.dryRun || ctx.flags['dry-run']) {
warning('DRY RUN - SPARC Mode Configuration:');
console.log(`Mode: ${mode.name} (${mode.slug})`);
console.log(`Instance ID: ${instanceId}`);
console.log(`Tools: ${tools}`);
console.log(`Task: ${taskDescription}`);
console.log();
console.log('Enhanced prompt preview:');
console.log(enhancedTask.substring(0, 300) + '...');
return;
}
success(`Starting SPARC mode: ${mode.name}`);
console.log(`📝 Instance ID: ${instanceId}`);
console.log(`🎯 Mode: ${mode.slug}`);
console.log(`🔧 Tools: ${tools}`);
console.log(`📋 Task: ${taskDescription}`);
console.log();
// Execute Claude with SPARC configuration
await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);
}
catch (err) {
error(`Failed to run SPARC mode: ${err.message}`);
}
}
async function runTddFlow(ctx) {
const taskDescription = ctx.args.slice(1).join(' ');
if (!taskDescription) {
error('Usage: sparc tdd <task-description>');
return;
}
try {
const config = await loadSparcConfig();
// Build TDD workflow using SPARC methodology
const workflow = [
{
mode: 'spec-pseudocode',
phase: 'Specification',
description: `Create detailed spec and pseudocode for: ${taskDescription}`,
},
{ mode: 'tdd', phase: 'Red', description: `Write failing tests for: ${taskDescription}` },
{
mode: 'code',
phase: 'Green',
description: `Implement minimal code to pass tests for: ${taskDescription}`,
},
{
mode: 'refinement-optimization-mode',
phase: 'Refactor',
description: `Refactor and optimize implementation for: ${taskDescription}`,
},
{
mode: 'integration',
phase: 'Integration',
description: `Integrate and verify complete solution for: ${taskDescription}`,
},
];
if (ctx.flags.dryRun || ctx.flags['dry-run']) {
warning('DRY RUN - TDD Workflow:');
for (const step of workflow) {
console.log(`${cyan(step.phase)}: ${step.mode} - ${step.description}`);
}
return;
}
success('Starting SPARC TDD Workflow');
console.log('Following Test-Driven Development with SPARC methodology');
console.log();
for (let i = 0; i < workflow.length; i++) {
const step = workflow[i];
const mode = config.customModes.find((m) => m.slug === step.mode);
if (!mode) {
warning(`Mode not found: ${step.mode}, skipping step`);
continue;
}
info(`Phase ${i + 1}/5: ${step.phase} (${mode.name})`);
console.log(`📋 ${step.description}`);
console.log();
const enhancedTask = buildSparcPrompt(mode, step.description, {
...ctx.flags,
tddPhase: step.phase,
workflowStep: i + 1,
totalSteps: workflow.length,
});
const tools = buildToolsFromGroups(mode.groups);
const instanceId = `sparc-tdd-${step.phase.toLowerCase()}-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);
// Store phase completion in memory for next step
if (ctx.flags.sequential !== false) {
console.log('Phase completed. Press Enter to continue to next phase, or Ctrl+C to stop...');
await new Promise(async (resolve) => {
const readline = await import('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('', () => {
rl.close();
resolve();
});
});
}
}
success('SPARC TDD Workflow completed!');
}
catch (err) {
error(`Failed to run TDD flow: ${err.message}`);
}
}
async function runSparcWorkflow(ctx) {
const workflowFile = ctx.args[1];
if (!workflowFile) {
error('Usage: sparc workflow <workflow-file.json>');
return;
}
try {
const { readFile } = await import('fs/promises');
const workflowContent = await readFile(workflowFile, 'utf-8');
const workflow = JSON.parse(workflowContent);
if (!workflow.steps || !Array.isArray(workflow.steps)) {
error("Invalid workflow file: missing 'steps' array");
return;
}
const config = await loadSparcConfig();
success(`Loading SPARC workflow: ${workflow.name || 'Unnamed'}`);
console.log(`📋 Steps: ${workflow.steps.length}`);
console.log(`📝 Description: ${workflow.description || 'No description'}`);
console.log();
if (ctx.flags.dryRun || ctx.flags['dry-run']) {
warning('DRY RUN - Workflow Steps:');
for (let i = 0; i < workflow.steps.length; i++) {
const step = workflow.steps[i];
console.log(`${i + 1}. ${cyan(step.mode)} - ${step.description || step.task}`);
}
return;
}
for (let i = 0; i < workflow.steps.length; i++) {
const step = workflow.steps[i];
const mode = config.customModes.find((m) => m.slug === step.mode);
if (!mode) {
warning(`Mode not found: ${step.mode}, skipping step ${i + 1}`);
continue;
}
info(`Step ${i + 1}/${workflow.steps.length}: ${mode.name}`);
console.log(`📋 ${step.description || step.task}`);
console.log();
const enhancedTask = buildSparcPrompt(mode, step.description || step.task, {
...ctx.flags,
workflowStep: i + 1,
totalSteps: workflow.steps.length,
workflowName: workflow.name,
});
const tools = buildToolsFromGroups(mode.groups);
const instanceId = `sparc-workflow-${i + 1}-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);
if (workflow.sequential !== false && i < workflow.steps.length - 1) {
console.log('Step completed. Press Enter to continue, or Ctrl+C to stop...');
await new Promise((resolve) => {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('', () => {
rl.close();
resolve();
});
});
}
}
success('SPARC workflow completed!');
}
catch (err) {
error(`Failed to run workflow: ${err.message}`);
}
}
function buildSparcPrompt(mode, taskDescription, flags) {
const memoryNamespace = flags.namespace || mode.slug || 'default';
return `# SPARC Development Mode: ${mode.name}
## Your Role
${mode.roleDefinition}
## Your Task
${taskDescription}
## Mode-Specific Instructions
${mode.customInstructions}
## SPARC Development Environment
You are working within the SPARC (Specification, Pseudocode, Architecture, Refinement, Completion) methodology using claude-flow orchestration features.
### Available Development Tools
- **Memory Persistence**: Use \`npx claude-flow memory store <key> "<value>"\` to save progress and findings
- **Memory Retrieval**: Use \`npx claude-flow memory query <search>\` to access previous work
- **Namespace**: Your work is stored in the "${memoryNamespace}" namespace
### SPARC Methodology Integration
${flags.tddPhase
? `
**Current TDD Phase**: ${flags.tddPhase}
- Follow the Red-Green-Refactor cycle
- Store test results and refactoring notes in memory
`
: ''}
${flags.workflowStep
? `
**Workflow Progress**: Step ${flags.workflowStep} of ${flags.totalSteps}
- Review previous steps: \`npx claude-flow memory query previous_steps\`
- Store this step's output: \`npx claude-flow memory store step_${flags.workflowStep}_output "<results>"\`
`
: ''}
### Best Practices
1. **Modular Development**: Keep all files under 500 lines
2. **Environment Safety**: Never hardcode secrets or environment values
3. **Memory Usage**: Store key findings and decisions in memory for future reference
4. **Tool Integration**: Use \`new_task\` for subtasks and \`attempt_completion\` when finished
### Memory Commands Examples
\`\`\`bash
# Store your progress
npx claude-flow memory store ${memoryNamespace}_progress "Current status and findings"
# Check for previous work
npx claude-flow memory query ${memoryNamespace}
# Store phase-specific results
npx claude-flow memory store ${memoryNamespace}_${flags.tddPhase || 'results'} "Phase output and decisions"
\`\`\`
### Integration with Other SPARC Modes
When working with other SPARC modes, use memory to:
- Share findings with spec-pseudocode mode
- Pass requirements to architect mode
- Coordinate with code and tdd modes
- Communicate results to integration mode
Now proceed with your task following the SPARC methodology and your specific role instructions.`;
}
function buildToolsFromGroups(groups) {
const toolMappings = {
read: ['View', 'LS', 'GlobTool', 'GrepTool'],
edit: ['Edit', 'Replace', 'MultiEdit', 'Write'],
browser: ['WebFetch'],
mcp: ['mcp_tools'],
command: ['Bash', 'Terminal'],
};
const tools = new Set();
// Always include basic tools
tools.add('View');
tools.add('Edit');
tools.add('Bash');
for (const group of groups) {
if (Array.isArray(group)) {
// Handle nested group definitions
const groupName = group[0];
if (toolMappings[groupName]) {
toolMappings[groupName].forEach((tool) => tools.add(tool));
}
}
else if (toolMappings[group]) {
toolMappings[group].forEach((tool) => tools.add(tool));
}
}
return Array.from(tools).join(',');
}
async function executeClaudeWithSparc(enhancedTask, tools, instanceId, flags) {
const claudeArgs = [enhancedTask];
claudeArgs.push('--allowedTools', tools);
if (flags.noPermissions || flags['no-permissions']) {
claudeArgs.push('--dangerously-skip-permissions');
}
if (flags.config) {
claudeArgs.push('--mcp-config', flags.config);
}
if (flags.verbose) {
claudeArgs.push('--verbose');
}
try {
const { spawn } = await import('child_process');
const child = spawn('claude', claudeArgs, {
env: {
...process.env,
CLAUDE_INSTANCE_ID: instanceId,
CLAUDE_SPARC_MODE: 'true',
CLAUDE_FLOW_MEMORY_ENABLED: 'true',
CLAUDE_FLOW_MEMORY_NAMESPACE: flags.namespace || 'sparc',
},
stdio: 'inherit',
});
const status = await new Promise((resolve) => {
child.on('close', (code) => {
resolve({ success: code === 0, code });
});
});
if (status.success) {
success(`SPARC instance ${instanceId} completed successfully`);
}
else {
error(`SPARC instance ${instanceId} exited with code ${status.code}`);
}
}
catch (err) {
error(`Failed to execute Claude: ${err.message}`);
}
}
async function showSparcHelp() {
console.log(`${cyan('SPARC')} - ${green('Specification, Pseudocode, Architecture, Refinement, Completion')}`);
console.log();
console.log('SPARC development methodology with TDD and multi-agent coordination.');
console.log();
console.log(blue('Commands:'));
console.log(' modes List all available SPARC modes');
console.log(' info <mode> Show detailed information about a mode');
console.log(' run <mode> <task> Execute a task using a specific SPARC mode');
console.log(' tdd <task> Run full TDD workflow using SPARC methodology');
console.log(' workflow <file> Execute a custom SPARC workflow from JSON file');
console.log();
console.log(blue('Common Modes:'));
console.log(' spec-pseudocode Create specifications and pseudocode');
console.log(' architect Design system architecture');
console.log(' code Implement code solutions');
console.log(' tdd Test-driven development');
console.log(' debug Debug and troubleshoot issues');
console.log(' security-review Security analysis and review');
console.log(' docs-writer Documentation creation');
console.log(' integration System integration and testing');
console.log();
console.log(blue('Options:'));
console.log(' --namespace <ns> Memory namespace for this session');
console.log(' --no-permissions Skip permission prompts');
console.log(' --config <file> MCP configuration file');
console.log(' --verbose Enable verbose output');
console.log(' --dry-run Preview what would be executed');
console.log(' --sequential Wait between workflow steps (default: true)');
console.log();
console.log(blue('Examples:'));
console.log(` ${yellow('claude-flow sparc modes')} # List all modes`);
console.log(` ${yellow('claude-flow sparc run code')} "implement user auth" # Run specific mode`);
console.log(` ${yellow('claude-flow sparc tdd')} "payment processing system" # Full TDD workflow`);
console.log(` ${yellow('claude-flow sparc workflow')} project-workflow.json # Custom workflow`);
console.log();
console.log(blue('TDD Workflow:'));
console.log(' 1. Specification - Define requirements and create pseudocode');
console.log(' 2. Red Phase - Write failing tests');
console.log(' 3. Green Phase - Implement minimal code to pass tests');
console.log(' 4. Refactor Phase - Optimize and clean up code');
console.log(' 5. Integration - Verify complete solution');
console.log();
console.log('For more information: https://github.com/ruvnet/claude-code-flow/docs/sparc.md');
}
//# sourceMappingURL=sparc.js.map