import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; import { WorkflowEngine, WorkflowState, WorkflowPhase } from '../core/workflow-engine'; export class WorkflowCommands { private workflowEngine: WorkflowEngine; constructor() { this.workflowEngine = new WorkflowEngine(); } registerCommands(program: Command): void { const workflowCommand = program .command('workflow') .description('Workflow management commands'); workflowCommand .command('list') .description('List available workflows') .action(async () => { try { const workflows = await this.workflowEngine.listWorkflows(); if (workflows.length === 0) { console.log(chalk.yellow('No workflows found in .vcsys/workflows/')); return; } console.log(chalk.blue('📋 Available Workflows:')); console.log(''); workflows.forEach((workflow, index) => { console.log(chalk.bold(`${index + 1}. ${workflow.name}`)); console.log(chalk.gray(` ID: ${workflow.id}`)); console.log(chalk.gray(` ${workflow.description}`)); console.log(''); }); } catch (error) { console.error(chalk.red('❌ Failed to list workflows:'), error); } }); workflowCommand .command('start ') .description('Start a workflow') .action(async (workflowId: string) => { const spinner = ora('Starting workflow...').start(); try { const workflow = await this.workflowEngine.loadWorkflow(workflowId); const state = await this.workflowEngine.startWorkflow(workflowId); spinner.succeed(chalk.green('✅ Workflow started successfully!')); console.log(chalk.blue(`🚀 Started: ${workflow.workflow.name}`)); console.log(chalk.gray(`Version: ${workflow.workflow.version}`)); console.log(chalk.gray(`Description: ${workflow.workflow.description}`)); console.log(''); // Show first phase const firstPhase = workflow.phases[0]; console.log(chalk.yellow('📍 Current Phase:')); console.log(chalk.bold(`${firstPhase.name}`)); console.log(chalk.gray(`${firstPhase.description}`)); console.log(chalk.gray(`Agents: ${firstPhase.agents.join(', ')}`)); console.log(''); console.log(chalk.blue('💡 Next steps:')); console.log(chalk.gray(' - Run: vcsys workflow status')); console.log(chalk.gray(' - Run: vcsys workflow next')); } catch (error) { spinner.fail(chalk.red('❌ Failed to start workflow')); console.error(error); } }); workflowCommand .command('status') .description('Show current workflow status') .action(async () => { try { const state = await this.workflowEngine.getWorkflowStatus(); if (!state) { console.log(chalk.yellow('No active workflow found')); console.log(chalk.gray('💡 Start a workflow with: vcsys workflow start ')); return; } const currentPhaseInfo = await this.workflowEngine.getCurrentPhase(); const isComplete = await this.workflowEngine.isWorkflowComplete(); console.log(chalk.blue('📊 Workflow Status:')); console.log(''); console.log(chalk.bold(`Workflow: ${state.workflowId}`)); console.log(chalk.gray(`Started: ${state.startedAt.toLocaleString()}`)); console.log(chalk.gray(`Last Updated: ${state.lastUpdated.toLocaleString()}`)); console.log(''); if (isComplete) { console.log(chalk.green('✅ Workflow Complete!')); console.log(chalk.gray(`Completed phases: ${state.completedPhases.length}`)); } else if (currentPhaseInfo) { console.log(chalk.yellow('📍 Current Phase:')); console.log(chalk.bold(`${currentPhaseInfo.phase.name}`)); console.log(chalk.gray(`Status: ${this.getStatusEmoji(state.phaseStatus)} ${state.phaseStatus}`)); console.log(chalk.gray(`Description: ${currentPhaseInfo.phase.description}`)); console.log(chalk.gray(`Agents: ${currentPhaseInfo.phase.agents.join(', ')}`)); } console.log(''); console.log(chalk.blue('📈 Progress:')); console.log(chalk.gray(`Completed phases: ${state.completedPhases.length}`)); if (state.completedPhases.length > 0) { console.log(chalk.green('✅ Completed:')); state.completedPhases.forEach(phase => { console.log(chalk.green(` - ${phase}`)); }); } // Show artifacts if any const totalArtifacts = Object.values(state.artifacts).flat().length; if (totalArtifacts > 0) { console.log(''); console.log(chalk.blue(`📄 Artifacts: ${totalArtifacts} created`)); } } catch (error) { console.error(chalk.red('❌ Failed to get workflow status:'), error); } }); workflowCommand .command('next') .description('Get next workflow step') .action(async () => { try { const state = await this.workflowEngine.getWorkflowStatus(); if (!state) { console.log(chalk.yellow('No active workflow found')); return; } const isComplete = await this.workflowEngine.isWorkflowComplete(); if (isComplete) { console.log(chalk.green('🎉 Workflow is complete!')); return; } const currentPhaseInfo = await this.workflowEngine.getCurrentPhase(); const nextPhaseInfo = await this.workflowEngine.getNextPhase(); if (currentPhaseInfo && state.phaseStatus !== 'completed') { console.log(chalk.yellow('📍 Current Phase (In Progress):')); this.displayPhaseInfo(currentPhaseInfo.phase); console.log(chalk.blue('🎯 Required Actions:')); console.log(chalk.gray('1. Complete current phase deliverables')); console.log(chalk.gray('2. Validate quality gates')); console.log(chalk.gray('3. Run: vcsys workflow advance')); } if (nextPhaseInfo) { console.log(''); console.log(chalk.blue('⏭️ Next Phase:')); this.displayPhaseInfo(nextPhaseInfo.phase); // Check dependencies const canProceed = await this.workflowEngine.validateDependencies(nextPhaseInfo.phase); if (!canProceed) { console.log(chalk.red('⚠️ Cannot proceed: Dependencies not met')); } } else { console.log(''); console.log(chalk.green('🏁 No more phases - workflow near completion')); } } catch (error) { console.error(chalk.red('❌ Failed to get next step:'), error); } }); workflowCommand .command('advance') .description('Advance to next workflow phase') .action(async () => { const spinner = ora('Advancing workflow...').start(); try { const state = await this.workflowEngine.getWorkflowStatus(); if (!state) { spinner.fail(chalk.red('No active workflow found')); return; } const currentPhaseInfo = await this.workflowEngine.getCurrentPhase(); if (currentPhaseInfo) { // Validate dependencies for current phase completion const canAdvance = await this.workflowEngine.validateDependencies(currentPhaseInfo.phase); if (!canAdvance) { spinner.fail(chalk.red('Cannot advance: Phase dependencies not met')); return; } } const newState = await this.workflowEngine.advancePhase(); const isComplete = await this.workflowEngine.isWorkflowComplete(); if (isComplete) { spinner.succeed(chalk.green('🎉 Workflow completed successfully!')); console.log(chalk.green('All phases have been completed.')); } else { spinner.succeed(chalk.green('✅ Advanced to next phase')); const nextPhaseInfo = await this.workflowEngine.getCurrentPhase(); if (nextPhaseInfo) { console.log(''); console.log(chalk.yellow('📍 New Current Phase:')); this.displayPhaseInfo(nextPhaseInfo.phase); } } } catch (error) { spinner.fail(chalk.red('❌ Failed to advance workflow')); console.error(error); } }); workflowCommand .command('reset') .description('Reset current workflow state') .action(async () => { const spinner = ora('Resetting workflow...').start(); try { await this.workflowEngine.resetWorkflow(); spinner.succeed(chalk.green('✅ Workflow state reset')); console.log(chalk.gray('You can start a new workflow with: vcsys workflow start ')); } catch (error) { spinner.fail(chalk.red('❌ Failed to reset workflow')); console.error(error); } }); workflowCommand .command('update-status ') .description('Update current phase status (pending|in_progress|completed|blocked)') .action(async (status: string) => { try { const validStatuses = ['pending', 'in_progress', 'completed', 'blocked']; if (!validStatuses.includes(status)) { console.error(chalk.red(`Invalid status. Must be one of: ${validStatuses.join(', ')}`)); return; } const newState = await this.workflowEngine.updatePhaseStatus(status as any); console.log(chalk.green(`✅ Phase status updated to: ${status}`)); } catch (error) { console.error(chalk.red('❌ Failed to update status:'), error); } }); workflowCommand .command('add-artifact ') .description('Add artifact to workflow phase') .action(async (phaseName: string, artifact: string) => { try { await this.workflowEngine.addArtifact(phaseName, artifact); console.log(chalk.green(`✅ Artifact added to ${phaseName}: ${artifact}`)); } catch (error) { console.error(chalk.red('❌ Failed to add artifact:'), error); } }); } private displayPhaseInfo(phase: WorkflowPhase): void { console.log(chalk.bold(`${phase.name}`)); console.log(chalk.gray(`Description: ${phase.description}`)); console.log(chalk.gray(`Agents: ${phase.agents.join(', ')}`)); if (phase.deliverables.length > 0) { console.log(chalk.blue('📄 Deliverables:')); phase.deliverables.forEach(deliverable => { console.log(chalk.gray(` - ${deliverable}`)); }); } if (phase.quality_gates.length > 0) { console.log(chalk.yellow('🎯 Quality Gates:')); phase.quality_gates.forEach(gate => { console.log(chalk.gray(` - ${gate}`)); }); } if (phase.dependencies && phase.dependencies.length > 0) { console.log(chalk.red('⚠️ Dependencies:')); phase.dependencies.forEach(dep => { console.log(chalk.gray(` - ${dep}`)); }); } } private getStatusEmoji(status: string): string { switch (status) { case 'pending': return '⏳'; case 'in_progress': return '🔄'; case 'completed': return '✅'; case 'blocked': return '🚧'; default: return '❓'; } } }