UNPKG

sf-agent-framework

Version:

AI Agent Orchestration Framework for Salesforce Development - Two-phase architecture with 70% context reduction

540 lines (484 loc) โ€ข 17.2 kB
/** * Workflow Initializer * * Purpose: Intelligent workflow selection based on project complexity analysis * Implements scale-adaptive logic to recommend appropriate workflow tracks * * @module WorkflowInitializer * @version 1.0.0 * @date 2025-11-25 */ const inquirer = require('inquirer'); const chalk = require('chalk'); const ora = require('ora'); const fs = require('fs-extra'); const path = require('path'); class WorkflowInitializer { constructor(rootDir = process.cwd()) { this.rootDir = rootDir; this.configPath = path.join(rootDir, 'sf-core', 'config', 'workflow-tracks.yaml'); } /** * Initialize workflow with intelligent selection */ async initialize() { console.log(chalk.cyan.bold('\n๐Ÿš€ SF-Agent Workflow Initialization\n')); console.log(chalk.gray("Let's analyze your project to recommend the best workflow...\n")); try { // Step 1: Gather project information const projectInfo = await this.gatherProjectInfo(); // Step 2: Analyze complexity const complexity = await this.analyzeComplexity(projectInfo); // Step 3: Recommend workflow track const recommendation = this.recommendTrack(complexity); // Step 4: Present recommendation and get confirmation const selectedTrack = await this.presentRecommendation(recommendation, complexity); // Step 5: Initialize selected workflow const initialized = await this.initializeWorkflow(selectedTrack, projectInfo); if (initialized) { this.displaySuccessMessage(selectedTrack); } return initialized; } catch (error) { console.error(chalk.red('\nโœ— Workflow initialization failed:'), error.message); return false; } } /** * Gather project information from user */ async gatherProjectInfo() { console.log(chalk.yellow('๐Ÿ“‹ Step 1: Project Information\n')); const answers = await inquirer.prompt([ { type: 'list', name: 'projectType', message: 'What type of project are you working on?', choices: [ { name: '๐Ÿ› Bug fix / Hot fix', value: 'bug-fix' }, { name: 'โœจ Small enhancement', value: 'small-enhancement' }, { name: '๐ŸŽฏ New feature', value: 'new-feature' }, { name: '๐Ÿ—๏ธ New application/component', value: 'new-application' }, { name: '๐Ÿ”„ Org migration/upgrade', value: 'org-migration' }, { name: '๐Ÿ”— Integration project', value: 'integration' }, { name: '๐Ÿข Enterprise-wide initiative', value: 'enterprise-initiative' }, ], }, { type: 'list', name: 'orgComplexity', message: 'How would you describe your Salesforce org complexity?', choices: [ { name: '๐ŸŸข Simple (< 50 custom objects)', value: 'simple' }, { name: '๐ŸŸก Medium (50-200 custom objects)', value: 'medium' }, { name: '๐ŸŸ  Complex (200-500 custom objects)', value: 'complex' }, { name: '๐Ÿ”ด Enterprise (500+ custom objects)', value: 'enterprise' }, ], }, { type: 'list', name: 'teamSize', message: 'What is your team size?', choices: [ { name: '๐Ÿ‘ค Solo (just me)', value: 'solo' }, { name: '๐Ÿ‘ฅ Small (2-5 people)', value: 'small' }, { name: '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Medium (6-15 people)', value: 'medium' }, { name: '๐Ÿข Large (15+ people)', value: 'large' }, ], }, { type: 'checkbox', name: 'requirements', message: 'Select any special requirements (space to select, enter to continue):', choices: [ { name: '๐Ÿ”’ Compliance (HIPAA, GDPR, SOX, etc.)', value: 'compliance' }, { name: '๐Ÿ›ก๏ธ High security requirements', value: 'security' }, { name: '๐Ÿ”— Complex integrations (3+ systems)', value: 'complex-integrations' }, { name: '๐Ÿ“Š Data migration', value: 'data-migration' }, { name: 'โšก Performance critical', value: 'performance' }, { name: '๐ŸŒ Multi-org deployment', value: 'multi-org' }, { name: '๐Ÿ“ฆ Package development', value: 'package-dev' }, ], }, { type: 'list', name: 'timeline', message: 'What is your timeline?', choices: [ { name: 'โฑ๏ธ Urgent (< 1 day)', value: 'urgent' }, { name: '๐Ÿ“… Standard (1-7 days)', value: 'standard' }, { name: '๐Ÿ“† Extended (1-4 weeks)', value: 'extended' }, { name: '๐Ÿ—“๏ธ Long-term (1+ months)', value: 'long-term' }, ], }, { type: 'confirm', name: 'hasExistingDocs', message: 'Do you have existing documentation or requirements?', default: false, }, ]); return answers; } /** * Analyze project complexity and assign score */ async analyzeComplexity(projectInfo) { const spinner = ora('Analyzing project complexity...').start(); // Simulate analysis delay await new Promise((resolve) => setTimeout(resolve, 1000)); let score = 0; const factors = []; // Project type scoring (0-40 points) const typeScores = { 'bug-fix': 10, 'small-enhancement': 20, 'new-feature': 40, 'new-application': 60, 'org-migration': 80, integration: 70, 'enterprise-initiative': 90, }; const typeScore = typeScores[projectInfo.projectType] || 40; score += typeScore; factors.push({ category: 'Project Type', value: projectInfo.projectType, score: typeScore, weight: 'High', }); // Org complexity scoring (0-25 points) const orgScores = { simple: 0, medium: 10, complex: 20, enterprise: 25, }; const orgScore = orgScores[projectInfo.orgComplexity] || 10; score += orgScore; factors.push({ category: 'Org Complexity', value: projectInfo.orgComplexity, score: orgScore, weight: 'Medium', }); // Team size scoring (0-15 points) const teamScores = { solo: 0, small: 5, medium: 10, large: 15, }; const teamScore = teamScores[projectInfo.teamSize] || 5; score += teamScore; factors.push({ category: 'Team Size', value: projectInfo.teamSize, score: teamScore, weight: 'Low', }); // Special requirements scoring (0-20 points) const reqScore = Math.min(projectInfo.requirements.length * 4, 20); score += reqScore; if (projectInfo.requirements.length > 0) { factors.push({ category: 'Special Requirements', value: projectInfo.requirements.join(', '), score: reqScore, weight: 'Medium', }); } // Timeline scoring (0-10 points) const timelineScores = { urgent: 0, // Need quick workflow standard: 3, extended: 6, 'long-term': 10, }; const timelineScore = timelineScores[projectInfo.timeline] || 3; score += timelineScore; factors.push({ category: 'Timeline', value: projectInfo.timeline, score: timelineScore, weight: 'Low', }); // Normalize score to 0-100 const normalizedScore = Math.min(score, 100); spinner.succeed(chalk.green('Complexity analysis complete')); return { score: normalizedScore, category: this.getComplexityCategory(normalizedScore), factors: factors, projectInfo: projectInfo, }; } /** * Get complexity category based on score */ getComplexityCategory(score) { if (score < 30) return 'Low'; if (score < 60) return 'Medium'; if (score < 80) return 'High'; return 'Very High'; } /** * Recommend workflow track based on complexity */ recommendTrack(complexity) { const score = complexity.score; const projectInfo = complexity.projectInfo; // Quick track: Score < 30 if (score < 30) { return { track: 'quick', name: 'โšก Quick Flow', reason: 'Low complexity - optimized for speed', estimatedTime: '5-10 minutes', phases: ['implementation'], agents: ['sf-developer-lean', 'sf-qa-lean'], description: 'Streamlined workflow for bug fixes and small changes', benefits: ['Minimal overhead', 'Fast execution', 'Focus on implementation'], bestFor: ['Bug fixes', 'Small enhancements', 'Quick configuration changes'], }; } // Balanced track: Score 30-70 if (score < 70) { return { track: 'balanced', name: '๐Ÿ“‹ Balanced Flow', reason: 'Medium complexity - comprehensive yet efficient', estimatedTime: '15-30 minutes', phases: ['planning', 'implementation', 'validation'], agents: [ 'sf-business-analyst', 'sf-architect', 'sf-developer-lean', 'sf-qa-lean', 'sf-devops-lead-lean', ], description: 'Full-featured workflow with architecture and planning', benefits: [ 'Comprehensive planning', 'Architecture design', 'Quality validation', 'Deployment ready', ], bestFor: ['New features', 'Standard projects', 'Most common scenarios'], }; } // Enterprise track: Score >= 70 return { track: 'enterprise', name: '๐Ÿข Enterprise Flow', reason: 'High complexity - full governance and compliance', estimatedTime: '30-60 minutes', phases: ['analysis', 'planning', 'solutioning', 'implementation', 'deployment'], agents: [ 'sf-product-manager', 'sf-business-analyst', 'sf-architect', 'sf-technical-architect', 'sf-data-architect', 'sf-security-architect', 'sf-developer-lean', 'sf-qa-lean', 'sf-devops-lead-lean', 'sf-release-manager', ], description: 'Comprehensive workflow with full analysis and governance', benefits: [ 'Complete analysis phase', 'Full architecture review', 'Security and compliance', 'Data architecture', 'Comprehensive testing', 'Release management', ], bestFor: [ 'Enterprise initiatives', 'Complex integrations', 'Compliance-driven projects', 'Multi-org deployments', 'Mission-critical systems', ], }; } /** * Present recommendation and get user confirmation */ async presentRecommendation(recommendation, complexity) { console.log(chalk.yellow('\n\n๐Ÿ“Š Step 2: Complexity Analysis Results\n')); // Display complexity score console.log(chalk.white(` Complexity Score: ${chalk.bold(complexity.score)}/100`)); console.log(chalk.white(` Category: ${chalk.bold(complexity.category)}\n`)); // Display contributing factors console.log(chalk.gray(' Contributing factors:')); complexity.factors.forEach((factor) => { const scoreColor = factor.score > 15 ? 'red' : factor.score > 8 ? 'yellow' : 'green'; console.log( chalk.gray(` โ€ข ${factor.category}: `) + chalk[scoreColor](`${factor.score} points `) + chalk.gray(`(${factor.weight} weight)`) ); }); // Display recommendation console.log(chalk.cyan.bold('\n\n๐ŸŽฏ Step 3: Recommended Workflow\n')); console.log(chalk.white.bold(` ${recommendation.name}`)); console.log(chalk.gray(` ${recommendation.description}\n`)); console.log( chalk.white(' Estimated Time: ') + chalk.yellow.bold(recommendation.estimatedTime) ); console.log(chalk.white(' Phases: ') + chalk.cyan(recommendation.phases.join(' โ†’ '))); console.log(chalk.white(' Agents Involved: ') + chalk.gray(recommendation.agents.length)); console.log(chalk.white('\n โœจ Benefits:')); recommendation.benefits.forEach((benefit) => { console.log(chalk.gray(` โ€ข ${benefit}`)); }); console.log(chalk.white('\n ๐ŸŽฏ Best For:')); recommendation.bestFor.forEach((use) => { console.log(chalk.gray(` โ€ข ${use}`)); }); // Get user confirmation or allow override const { confirmed, selectedTrack } = await inquirer.prompt([ { type: 'confirm', name: 'confirmed', message: '\nUse recommended workflow?', default: true, }, { type: 'list', name: 'selectedTrack', message: 'Select workflow track:', when: (answers) => !answers.confirmed, choices: [ { name: 'โšก Quick Flow (5-10 min)', value: 'quick' }, { name: '๐Ÿ“‹ Balanced Flow (15-30 min)', value: 'balanced' }, { name: '๐Ÿข Enterprise Flow (30-60 min)', value: 'enterprise' }, ], }, ]); if (confirmed) { return recommendation.track; } else { return selectedTrack; } } /** * Initialize the selected workflow */ async initializeWorkflow(track, projectInfo) { const spinner = ora('Initializing workflow...').start(); try { // Create workflow directory structure const workflowDir = path.join(this.rootDir, 'docs', 'workflows', `current-${track}`); await fs.ensureDir(workflowDir); // Create workflow manifest const manifest = { track: track, initialized: new Date().toISOString(), projectInfo: projectInfo, status: 'initialized', currentPhase: null, completedPhases: [], agents: [], artifacts: [], }; await fs.writeJson(path.join(workflowDir, 'workflow-manifest.json'), manifest, { spaces: 2 }); // Create phase directories const trackDefinitions = { quick: ['implementation'], balanced: ['planning', 'implementation', 'validation'], enterprise: ['analysis', 'planning', 'solutioning', 'implementation', 'deployment'], }; const phases = trackDefinitions[track] || ['planning', 'implementation']; for (const phase of phases) { await fs.ensureDir(path.join(workflowDir, phase)); } spinner.succeed(chalk.green('Workflow initialized successfully')); return true; } catch (error) { spinner.fail(chalk.red('Failed to initialize workflow')); console.error(error); return false; } } /** * Display success message with next steps */ displaySuccessMessage(track) { console.log(chalk.green.bold('\n\nโœ… Workflow Initialized Successfully!\n')); const nextSteps = { quick: [ 'Start with /sf-developer-lean to implement your change', 'Run /sf-qa-lean to validate your implementation', 'Use /sf-devops-lead-lean to deploy when ready', ], balanced: [ 'Begin with /sf-business-analyst to document requirements', 'Continue with /sf-architect for solution design', 'Proceed to /sf-developer-lean for implementation', 'Validate with /sf-qa-lean', 'Deploy with /sf-devops-lead-lean', ], enterprise: [ 'Start analysis phase with /sf-product-manager', 'Document requirements with /sf-business-analyst', 'Design architecture with /sf-architect', 'Review security with /sf-security-architect', 'Implement with /sf-developer-lean', 'Complete testing with /sf-qa-lean', 'Manage release with /sf-release-manager', ], }; console.log(chalk.white('๐Ÿ“‹ Next Steps:\n')); const steps = nextSteps[track] || nextSteps.balanced; steps.forEach((step, index) => { console.log(chalk.gray(` ${index + 1}. ${step}`)); }); console.log(chalk.cyan.bold('\n\n๐Ÿ’ก Quick Commands:\n')); console.log(chalk.gray(' sfa workflow:status - Check workflow status')); console.log(chalk.gray(' sfa workflow:next - Get next recommended action')); console.log(chalk.gray(' sfa agents:list - See all available agents')); console.log(chalk.gray(' sfa phase <name> - Switch to different phase\n')); } /** * Get current workflow status */ async getWorkflowStatus() { try { const workflowDirs = await fs.readdir(path.join(this.rootDir, 'docs', 'workflows')); const currentWorkflow = workflowDirs.find((dir) => dir.startsWith('current-')); if (!currentWorkflow) { return { initialized: false, message: 'No active workflow. Run "sfa workflow:init" to get started.', }; } const manifestPath = path.join( this.rootDir, 'docs', 'workflows', currentWorkflow, 'workflow-manifest.json' ); const manifest = await fs.readJson(manifestPath); return { initialized: true, track: manifest.track, status: manifest.status, currentPhase: manifest.currentPhase, completedPhases: manifest.completedPhases, projectInfo: manifest.projectInfo, startedAt: manifest.initialized, }; } catch (error) { return { initialized: false, error: error.message, }; } } } module.exports = WorkflowInitializer;