UNPKG

context-forge

Version:

AI orchestration platform with autonomous teams, enhancement planning, migration tools, 25+ slash commands, checkpoints & hooks. Multi-IDE: Claude, Cursor, Windsurf, Cline, Copilot

761 lines 29.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnhancementPlanner = void 0; class EnhancementPlanner { constructor(projectPath, config) { this.projectPath = projectPath; this.config = config; } async createPlan(basicAnalysis) { // Sort features by dependencies and priority const sortedFeatures = this.topologicalSort(this.config.features); // Create phases based on implementation strategy const phases = await this.createPhases(sortedFeatures, basicAnalysis); // Add checkpoints const checkpoints = this.generateCheckpoints(phases); // Update config with generated plan return { ...this.config, enhancementPhases: phases, checkpoints: checkpoints, // Type conversion needed due to interface mismatch estimatedDuration: this.calculateTotalDuration(phases), }; } topologicalSort(features) { const sorted = []; const visited = new Set(); const visiting = new Set(); const visit = (featureId) => { if (visited.has(featureId)) return; if (visiting.has(featureId)) { throw new Error(`Circular dependency detected involving feature: ${featureId}`); } visiting.add(featureId); const feature = features.find((f) => f.id === featureId); if (!feature) return; // Visit dependencies first for (const depId of feature.dependencies) { visit(depId); } visiting.delete(featureId); visited.add(featureId); sorted.push(feature); }; // Visit all features features.forEach((feature) => visit(feature.id)); return sorted; } async createPhases(sortedFeatures, _basicAnalysis) { const phases = []; switch (this.config.implementationStrategy) { case 'sequential': phases.push(...this.createSequentialPhases(sortedFeatures)); break; case 'parallel': phases.push(...this.createParallelPhases(sortedFeatures)); break; case 'hybrid': phases.push(...this.createHybridPhases(sortedFeatures)); break; } // Add setup phase if needed if (this.needsSetupPhase(sortedFeatures)) { phases.unshift(this.createSetupPhase(sortedFeatures)); } // Add deployment phase phases.push(this.createDeploymentPhase(sortedFeatures)); return phases; } createSequentialPhases(features) { return features.map((feature, index) => { const tasks = this.generateFeatureTasks(feature); return { id: `phase-${index + 1}`, name: `Implement ${feature.name}`, description: `Complete implementation of ${feature.name} feature`, features: [feature.id], tasks, dependencies: index > 0 ? [`phase-${index}`] : [], checkpoints: this.generateFeatureCheckpoints(feature), estimatedDuration: feature.estimatedEffort, validationCriteria: [ ...feature.acceptanceCriteria, 'All tests passing', 'Code review completed', 'Documentation updated', ], rollbackStrategy: this.generateRollbackStrategy(feature), }; }); } createParallelPhases(features) { // Group features that can be done in parallel const groups = []; const assigned = new Set(); features.forEach((feature) => { if (assigned.has(feature.id)) return; // Find features that can be done in parallel with this one const group = [feature]; assigned.add(feature.id); features.forEach((otherFeature) => { if (!assigned.has(otherFeature.id) && !this.haveDependencyConflict(feature, otherFeature, features)) { group.push(otherFeature); assigned.add(otherFeature.id); } }); groups.push(group); }); return groups.map((group, index) => { const tasks = group.flatMap((feature) => this.generateFeatureTasks(feature)); return { id: `phase-${index + 1}`, name: `Parallel Implementation: ${group.map((f) => f.name).join(', ')}`, description: `Implement ${group.length} features in parallel`, features: group.map((f) => f.id), tasks, dependencies: index > 0 ? [`phase-${index}`] : [], checkpoints: group.flatMap((f) => this.generateFeatureCheckpoints(f)), estimatedDuration: this.calculateParallelDuration(group), validationCriteria: group.flatMap((f) => f.acceptanceCriteria), rollbackStrategy: this.generateMultiFeatureRollback(group), }; }); } createHybridPhases(features) { const phases = []; const processed = new Set(); // First, handle critical and high priority features sequentially const criticalFeatures = features.filter((f) => (f.priority === 'critical' || f.priority === 'high') && !processed.has(f.id)); criticalFeatures.forEach((feature) => { phases.push({ id: `phase-${phases.length + 1}`, name: `Critical: ${feature.name}`, description: `Implement critical feature: ${feature.name}`, features: [feature.id], tasks: this.generateFeatureTasks(feature), dependencies: phases.length > 0 ? [`phase-${phases.length}`] : [], checkpoints: this.generateFeatureCheckpoints(feature), estimatedDuration: feature.estimatedEffort, validationCriteria: feature.acceptanceCriteria, rollbackStrategy: this.generateRollbackStrategy(feature), }); processed.add(feature.id); }); // Then, group remaining features for parallel execution const remainingFeatures = features.filter((f) => !processed.has(f.id)); if (remainingFeatures.length > 0) { const parallelPhases = this.createParallelPhases(remainingFeatures); parallelPhases.forEach((phase) => { phase.id = `phase-${phases.length + 1}`; phase.dependencies = phases.length > 0 ? [`phase-${phases.length}`] : []; phases.push(phase); }); } return phases; } needsSetupPhase(features) { // Check if any features require infrastructure setup return features.some((f) => f.category === 'infrastructure' || f.technicalRequirements.some((req) => req.toLowerCase().includes('setup') || req.toLowerCase().includes('install') || req.toLowerCase().includes('configure'))); } createSetupPhase(_features) { const setupTasks = [ { id: 'setup-1', name: 'Environment Setup', description: 'Configure development environment for new features', type: 'create', subtasks: [ 'Install required dependencies', 'Configure environment variables', 'Set up development tools', ], estimatedHours: 2, complexity: 'simple', dependencies: [], validationSteps: ['Dependencies installed', 'Environment configured'], }, { id: 'setup-2', name: 'Project Structure', description: 'Create necessary directories and base files', type: 'create', subtasks: [ 'Create feature directories', 'Set up configuration files', 'Initialize testing structure', ], estimatedHours: 1, complexity: 'trivial', dependencies: ['setup-1'], validationSteps: ['Directory structure created', 'Base files in place'], }, ]; return { id: 'phase-setup', name: 'Environment Setup', description: 'Prepare project for feature implementation', features: [], tasks: setupTasks, dependencies: [], checkpoints: [ { id: 'setup-complete', name: 'Setup Complete', description: 'Verify environment is ready for development', category: 'important', autoTrigger: false, conditions: ['setup', 'complete', 'verified'], }, ], estimatedDuration: '1 day', validationCriteria: [ 'All dependencies installed', 'Development environment functional', 'Testing framework ready', ], }; } createDeploymentPhase(features) { const deploymentTasks = [ { id: 'deploy-1', name: 'Integration Testing', description: 'Run comprehensive integration tests', type: 'test', subtasks: [ 'Run all feature tests', 'Perform integration tests', 'Check performance benchmarks', ], estimatedHours: 4, complexity: 'medium', dependencies: [], validationSteps: ['All tests passing', 'Performance acceptable'], }, { id: 'deploy-2', name: 'Documentation Update', description: 'Update all documentation for new features', type: 'document', subtasks: [ 'Update API documentation', 'Update user guides', 'Update technical documentation', ], estimatedHours: 3, complexity: 'simple', dependencies: ['deploy-1'], validationSteps: ['Documentation complete', 'Examples provided'], }, { id: 'deploy-3', name: 'Deployment', description: 'Deploy features to production', type: 'deploy', subtasks: [ 'Prepare deployment package', 'Deploy to staging', 'Verify staging deployment', 'Deploy to production', ], estimatedHours: 4, complexity: 'medium', dependencies: ['deploy-2'], validationSteps: ['Staging verified', 'Production deployed'], }, ]; return { id: 'phase-deployment', name: 'Testing and Deployment', description: 'Final testing and deployment of all features', features: features.map((f) => f.id), tasks: deploymentTasks, dependencies: [], // Will be set based on previous phases checkpoints: [ { id: 'pre-deployment', name: 'Pre-Deployment Check', description: 'Final verification before deployment', category: 'critical', autoTrigger: false, conditions: ['deployment', 'ready', 'approved'], }, ], estimatedDuration: '2-3 days', validationCriteria: [ 'All features tested', 'Documentation complete', 'Performance verified', 'Security checked', ], }; } generateFeatureTasks(feature) { const tasks = []; // Planning task tasks.push({ id: `${feature.id}-plan`, name: `Plan ${feature.name} Implementation`, description: `Detailed planning and design for ${feature.name}`, type: 'document', subtasks: [ 'Review requirements', 'Design technical approach', 'Identify integration points', 'Plan testing strategy', ], estimatedHours: feature.complexity === 'simple' ? 2 : 4, complexity: 'simple', dependencies: [], validationSteps: ['Design reviewed', 'Approach approved'], aiContext: `Feature: ${feature.name}\nDescription: ${feature.description}\nRequirements: ${feature.technicalRequirements.join(', ')}`, }); // Implementation tasks based on category switch (feature.category) { case 'api': tasks.push(...this.generateApiTasks(feature)); break; case 'ui': tasks.push(...this.generateUiTasks(feature)); break; case 'database': tasks.push(...this.generateDatabaseTasks(feature)); break; case 'integration': tasks.push(...this.generateIntegrationTasks(feature)); break; default: tasks.push(...this.generateGenericTasks(feature)); } // Testing task tasks.push({ id: `${feature.id}-test`, name: `Test ${feature.name}`, description: `Comprehensive testing of ${feature.name}`, type: 'test', subtasks: [ 'Write unit tests', 'Write integration tests', 'Perform manual testing', 'Fix any issues found', ], estimatedHours: this.estimateTestingHours(feature), complexity: feature.complexity === 'simple' ? 'simple' : 'medium', dependencies: tasks.map((t) => t.id), validationSteps: ['All tests passing', 'Coverage adequate'], }); return tasks; } generateApiTasks(feature) { return [ { id: `${feature.id}-api-routes`, name: 'Create API Routes', description: `Implement API endpoints for ${feature.name}`, type: 'create', targetFiles: ['routes/', 'api/'], subtasks: [ 'Define route structure', 'Implement endpoint handlers', 'Add request validation', 'Add error handling', ], estimatedHours: this.estimateApiHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-plan`], validationSteps: ['Routes accessible', 'Validation working'], }, { id: `${feature.id}-api-logic`, name: 'Implement Business Logic', description: `Core logic implementation for ${feature.name}`, type: 'create', targetFiles: ['services/', 'controllers/'], subtasks: [ 'Implement service layer', 'Add data processing', 'Implement business rules', 'Add logging', ], estimatedHours: this.estimateLogicHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-api-routes`], validationSteps: ['Logic implemented', 'Business rules enforced'], }, ]; } generateUiTasks(feature) { return [ { id: `${feature.id}-ui-components`, name: 'Create UI Components', description: `Build UI components for ${feature.name}`, type: 'create', targetFiles: ['components/', 'src/components/'], subtasks: [ 'Create component structure', 'Implement component logic', 'Add styling', 'Handle user interactions', ], estimatedHours: this.estimateUiHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-plan`], validationSteps: ['Components render', 'Interactions work'], }, { id: `${feature.id}-ui-integration`, name: 'Integrate with Application', description: `Integrate ${feature.name} into the application`, type: 'modify', subtasks: [ 'Add routing', 'Connect to state management', 'Integrate with API', 'Update navigation', ], estimatedHours: Math.ceil(this.estimateUiHours(feature) * 0.5), complexity: 'medium', dependencies: [`${feature.id}-ui-components`], validationSteps: ['Integration complete', 'Feature accessible'], }, ]; } generateDatabaseTasks(feature) { return [ { id: `${feature.id}-db-schema`, name: 'Design Database Schema', description: `Create database schema for ${feature.name}`, type: 'create', targetFiles: ['models/', 'migrations/', 'schemas/'], subtasks: [ 'Design data models', 'Create migrations', 'Define relationships', 'Add indexes', ], estimatedHours: this.estimateDatabaseHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-plan`], validationSteps: ['Schema created', 'Migrations run successfully'], }, { id: `${feature.id}-db-access`, name: 'Implement Data Access', description: `Create data access layer for ${feature.name}`, type: 'create', targetFiles: ['repositories/', 'dao/'], subtasks: [ 'Create repository methods', 'Implement queries', 'Add data validation', 'Optimize performance', ], estimatedHours: Math.ceil(this.estimateDatabaseHours(feature) * 0.7), complexity: 'medium', dependencies: [`${feature.id}-db-schema`], validationSteps: ['Data access working', 'Queries optimized'], }, ]; } generateIntegrationTasks(feature) { return [ { id: `${feature.id}-integration-setup`, name: 'Set Up Integration', description: `Configure integration for ${feature.name}`, type: 'create', targetFiles: ['integrations/', 'services/'], subtasks: [ 'Configure credentials', 'Set up connection', 'Create integration client', 'Add error handling', ], estimatedHours: 4, complexity: 'medium', dependencies: [`${feature.id}-plan`], validationSteps: ['Connection established', 'Authentication working'], }, { id: `${feature.id}-integration-impl`, name: 'Implement Integration Logic', description: `Implement integration features for ${feature.name}`, type: 'create', subtasks: [ 'Implement API calls', 'Add data transformation', 'Handle responses', 'Add retry logic', ], estimatedHours: this.estimateIntegrationHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-integration-setup`], validationSteps: ['Integration functional', 'Error handling tested'], }, ]; } generateGenericTasks(feature) { return [ { id: `${feature.id}-implementation`, name: `Implement ${feature.name}`, description: `Core implementation of ${feature.name}`, type: 'create', subtasks: feature.technicalRequirements, estimatedHours: this.estimateGenericHours(feature), complexity: feature.complexity, dependencies: [`${feature.id}-plan`], validationSteps: feature.acceptanceCriteria, }, ]; } generateFeatureCheckpoints(feature) { const checkpoints = []; // Add critical checkpoints for high-risk features if (feature.priority === 'critical' || feature.complexity === 'very-complex') { checkpoints.push({ id: `${feature.id}-review`, name: `${feature.name} Review`, description: `Technical review of ${feature.name} implementation`, category: 'critical', autoTrigger: false, conditions: ['implementation', 'complete', 'review'], }); } // Add validation checkpoint checkpoints.push({ id: `${feature.id}-validation`, name: `${feature.name} Validation`, description: `Validate ${feature.name} meets all requirements`, category: 'important', autoTrigger: true, conditions: ['tests', 'passing', 'criteria', 'met'], }); return checkpoints; } generateRollbackStrategy(feature) { return { automatic: false, triggers: [ { condition: `Critical failure in ${feature.name}`, severity: 'critical', action: 'rollback', }, { condition: 'Tests failing after implementation', severity: 'error', action: 'pause', }, ], procedures: [ { phase: feature.id, steps: [ 'Stop all services', `Revert ${feature.name} changes`, 'Restore previous state', 'Run verification tests', ], verificationPoints: [ 'Previous functionality restored', 'No regression issues', 'System stable', ], estimatedDuration: '30-60 minutes', }, ], dataBackupRequired: feature.category === 'database', estimatedTime: '1 hour', }; } generateMultiFeatureRollback(features) { return { automatic: false, triggers: features.flatMap((f) => [ { condition: `Critical failure in ${f.name}`, severity: 'critical', action: 'rollback', }, ]), procedures: features.map((f) => ({ phase: f.id, steps: ['Stop affected services', `Rollback ${f.name}`, 'Verify rollback'], verificationPoints: ['Feature removed', 'System stable'], estimatedDuration: '30 minutes', })), dataBackupRequired: features.some((f) => f.category === 'database'), estimatedTime: `${features.length} hours`, }; } generateCheckpoints(phases) { return phases.flatMap((phase) => phase.checkpoints.map((checkpoint) => ({ phaseId: phase.id, name: checkpoint.name, description: checkpoint.description, validationSteps: phase.validationCriteria, }))); } haveDependencyConflict(feature1, feature2, allFeatures) { // Check direct dependencies if (feature1.dependencies.includes(feature2.id) || feature2.dependencies.includes(feature1.id)) { return true; } // Check transitive dependencies const getDependencyChain = (featureId) => { const chain = new Set(); const toVisit = [featureId]; while (toVisit.length > 0) { const current = toVisit.pop(); if (chain.has(current)) continue; chain.add(current); const feature = allFeatures.find((f) => f.id === current); if (feature) { toVisit.push(...feature.dependencies); } } return chain; }; const chain1 = getDependencyChain(feature1.id); const chain2 = getDependencyChain(feature2.id); return chain1.has(feature2.id) || chain2.has(feature1.id); } calculateParallelDuration(features) { // Duration is the max of all features const durations = features.map((f) => this.parseDuration(f.estimatedEffort)); const maxDays = Math.max(...durations); if (maxDays < 5) return `${maxDays} days`; if (maxDays < 20) return `${Math.ceil(maxDays / 5)} weeks`; return `${Math.ceil(maxDays / 20)} months`; } calculateTotalDuration(phases) { let totalDays = 0; // For sequential parts, add durations // For parallel parts, take the max phases.forEach((phase) => { const days = this.parseDuration(phase.estimatedDuration); totalDays += days; }); // Add buffer for integration and unexpected issues totalDays *= 1.2; if (totalDays < 5) return `${Math.ceil(totalDays)} days`; if (totalDays < 20) return `${Math.ceil(totalDays / 5)} weeks`; return `${Math.ceil(totalDays / 20)} months`; } parseDuration(duration) { const lower = duration.toLowerCase(); if (lower.includes('hour')) { return 0.5; } else if (lower.includes('day')) { const match = lower.match(/(\d+)(?:-(\d+))?\s*days?/); if (match) { const min = parseInt(match[1]); const max = match[2] ? parseInt(match[2]) : min; return (min + max) / 2; } return 1; } else if (lower.includes('week')) { const match = lower.match(/(\d+)(?:-(\d+))?\s*weeks?/); if (match) { const min = parseInt(match[1]); const max = match[2] ? parseInt(match[2]) : min; return ((min + max) / 2) * 5; } return 5; } else if (lower.includes('month')) { const match = lower.match(/(\d+)(?:-(\d+))?\s*months?/); if (match) { const min = parseInt(match[1]); const max = match[2] ? parseInt(match[2]) : min; return ((min + max) / 2) * 20; } return 20; } return 3; // Default to 3 days } // Estimation methods estimateTestingHours(feature) { const base = { simple: 2, medium: 4, complex: 8, 'very-complex': 16, }[feature.complexity]; return base + feature.integrationPoints.length; } estimateApiHours(feature) { const base = { simple: 4, medium: 8, complex: 16, 'very-complex': 32, }[feature.complexity]; return base; } estimateLogicHours(feature) { const base = { simple: 3, medium: 8, complex: 16, 'very-complex': 24, }[feature.complexity]; return base + feature.technicalRequirements.length * 0.5; } estimateUiHours(feature) { const base = { simple: 4, medium: 12, complex: 24, 'very-complex': 40, }[feature.complexity]; return base; } estimateDatabaseHours(feature) { const base = { simple: 3, medium: 6, complex: 12, 'very-complex': 20, }[feature.complexity]; return base; } estimateIntegrationHours(feature) { const base = { simple: 6, medium: 12, complex: 24, 'very-complex': 40, }[feature.complexity]; return base; } estimateGenericHours(feature) { const base = { simple: 4, medium: 10, complex: 20, 'very-complex': 40, }[feature.complexity]; return base; } } exports.EnhancementPlanner = EnhancementPlanner; //# sourceMappingURL=enhancementPlanner.js.map