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

340 lines 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FeatureAnalyzer = void 0; const glob_1 = require("glob"); class FeatureAnalyzer { constructor(projectPath) { this.projectPath = projectPath; } async analyzeFeasibility(features, basicAnalysis) { const results = []; for (const feature of features) { const feasibility = await this.analyzeFeatureFeasibility(feature, basicAnalysis); results.push(feasibility); } return results; } async analyzeFeatureFeasibility(feature, basicAnalysis) { let score = 100; // Start with perfect score const concerns = []; const opportunities = []; // Analyze complexity impact const complexityPenalty = this.calculateComplexityPenalty(feature); score -= complexityPenalty; if (complexityPenalty > 20) { concerns.push(`High complexity (${feature.complexity}) may extend timeline`); } // Analyze integration requirements const integrationAnalysis = await this.analyzeIntegrationRequirements(feature, basicAnalysis); score -= integrationAnalysis.penalty; concerns.push(...integrationAnalysis.concerns); opportunities.push(...integrationAnalysis.opportunities); // Analyze dependencies if (feature.dependencies.length > 0) { score -= feature.dependencies.length * 5; concerns.push(`Depends on ${feature.dependencies.length} other features`); } // Analyze risks const riskPenalty = this.calculateRiskPenalty(feature); score -= riskPenalty; if (riskPenalty > 15) { concerns.push('Multiple high-impact risks identified'); } // Category-specific analysis const categoryAnalysis = await this.analyzeCategorySpecific(feature, basicAnalysis); score -= categoryAnalysis.penalty; concerns.push(...categoryAnalysis.concerns); opportunities.push(...categoryAnalysis.opportunities); // Estimate impact const impact = await this.estimateImpact(feature, basicAnalysis); // Determine feasibility level let feasibility; if (score >= 70) feasibility = 'high'; else if (score >= 40) feasibility = 'medium'; else feasibility = 'low'; // Suggest approach based on analysis const suggestedApproach = this.suggestImplementationApproach(feature, feasibility); return { featureId: feature.id, featureName: feature.name, feasibility, score: Math.max(0, Math.min(100, score)), concerns, opportunities, estimatedImpact: impact, suggestedApproach, }; } calculateComplexityPenalty(feature) { const penalties = { simple: 0, medium: 10, complex: 25, 'very-complex': 40, }; return penalties[feature.complexity]; } async analyzeIntegrationRequirements(feature, basicAnalysis) { let penalty = 0; const concerns = []; const opportunities = []; for (const integration of feature.integrationPoints) { // Check if integration point exists const exists = await this.checkIntegrationPointExists(integration, basicAnalysis); if (!exists) { penalty += 10; concerns.push(`Integration point "${integration.component}" may not exist`); } else { opportunities.push(`Can leverage existing ${integration.type} infrastructure`); } // Check change complexity if (integration.requiredChanges.length > 3) { penalty += 5; concerns.push(`Complex changes required for ${integration.component}`); } } return { penalty, concerns, opportunities }; } async checkIntegrationPointExists(integration, basicAnalysis) { switch (integration.type) { case 'api': return basicAnalysis.fileStats.routes > 0; case 'database': return basicAnalysis.techStack.some((tech) => tech.toLowerCase().includes('database') || tech.toLowerCase().includes('mongo') || tech.toLowerCase().includes('postgres') || tech.toLowerCase().includes('mysql')); case 'ui': return basicAnalysis.fileStats.components > 0; case 'service': // Check for service pattern files const serviceFiles = await (0, glob_1.glob)('**/services/**/*.{js,ts}', { cwd: this.projectPath, ignore: ['node_modules/**'], }); return serviceFiles.length > 0; case 'config': return basicAnalysis.fileStats.config > 0; default: return true; } } calculateRiskPenalty(feature) { let penalty = 0; for (const risk of feature.risks) { // Impact scoring const impactScore = { low: 1, medium: 3, high: 5, critical: 10, }[risk.impact]; // Probability scoring const probabilityScore = { unlikely: 0.25, possible: 0.5, likely: 0.75, certain: 1, }[risk.probability]; penalty += impactScore * probabilityScore * 3; } return Math.round(penalty); } async analyzeCategorySpecific(feature, basicAnalysis) { let penalty = 0; const concerns = []; const opportunities = []; switch (feature.category) { case 'api': if (basicAnalysis.fileStats.routes === 0) { penalty += 15; concerns.push('No existing API structure detected'); } else { opportunities.push('Existing API patterns can be followed'); } break; case 'ui': if (basicAnalysis.fileStats.components === 0) { penalty += 15; concerns.push('No existing UI components detected'); } else { opportunities.push('Can reuse existing component patterns'); } break; case 'database': const hasDb = basicAnalysis.techStack.some((tech) => tech.toLowerCase().includes('database') || tech.toLowerCase().includes('db')); if (!hasDb) { penalty += 20; concerns.push('No database infrastructure detected'); } break; case 'security': if (!basicAnalysis.techStack.some((tech) => tech.toLowerCase().includes('auth'))) { concerns.push('No existing authentication system detected'); penalty += 10; } break; case 'analytics': // Check for existing analytics const analyticsFiles = await (0, glob_1.glob)('**/analytics/**/*.{js,ts}', { cwd: this.projectPath, ignore: ['node_modules/**'], }); if (analyticsFiles.length === 0) { concerns.push('No existing analytics infrastructure'); penalty += 5; } break; } return { penalty, concerns, opportunities }; } async estimateImpact(feature, _basicAnalysis) { // Base estimates let files = 0; let components = 0; let tests = 0; // Complexity multipliers const complexityMultiplier = { simple: 1, medium: 2.5, complex: 5, 'very-complex': 10, }[feature.complexity]; // Category-based estimates switch (feature.category) { case 'api': files = Math.ceil(3 * complexityMultiplier); // Routes, controllers, middleware tests = Math.ceil(2 * complexityMultiplier); // Unit and integration tests break; case 'ui': components = Math.ceil(2 * complexityMultiplier); // Components and containers files = Math.ceil(4 * complexityMultiplier); // Components, styles, utils, types tests = Math.ceil(2 * complexityMultiplier); // Component and integration tests break; case 'database': files = Math.ceil(2 * complexityMultiplier); // Models and migrations tests = Math.ceil(1.5 * complexityMultiplier); // Model tests break; case 'integration': files = Math.ceil(2.5 * complexityMultiplier); // Service files and configs tests = Math.ceil(2 * complexityMultiplier); // Integration tests break; default: files = Math.ceil(2 * complexityMultiplier); tests = Math.ceil(1.5 * complexityMultiplier); } // Add integration impact files += feature.integrationPoints.length * 2; tests += feature.integrationPoints.length; return { files, components, tests }; } suggestImplementationApproach(feature, feasibility) { const approaches = { high: { api: 'Follow existing API patterns. Create new routes in the established structure.', ui: 'Extend existing component library. Maintain current styling patterns.', database: 'Use existing ORM/database patterns. Follow current schema conventions.', integration: 'Leverage existing service architecture. Use established integration patterns.', infrastructure: 'Build on current DevOps setup. Extend existing CI/CD pipelines.', analytics: 'Integrate with current monitoring. Extend existing metrics collection.', security: 'Enhance current auth system. Follow established security patterns.', }, medium: { api: 'Consider creating a separate API module. Plan for gradual integration.', ui: 'Create new component namespace. Plan progressive enhancement.', database: 'Design migration strategy. Consider compatibility layer.', integration: 'Implement adapter pattern. Create abstraction layer.', infrastructure: 'Phase implementation. Start with development environment.', analytics: 'Start with basic metrics. Plan incremental enhancement.', security: 'Implement in phases. Start with basic authentication.', }, low: { api: 'Consider microservice approach. Plan extensive testing.', ui: 'Prototype separately first. Plan careful integration.', database: 'Evaluate database choice. Consider data migration carefully.', integration: 'Research alternatives. Consider third-party solutions.', infrastructure: 'Seek expert consultation. Consider managed services.', analytics: 'Start with third-party service. Plan custom implementation later.', security: 'Use proven libraries. Consider security audit.', }, }; return (approaches[feasibility][feature.category] || 'Conduct detailed technical spike before implementation.'); } async detectPotentialConflicts(features) { const conflicts = []; for (const feature of features) { const featureConflicts = await this.analyzeFeatureConflicts(feature, features); if (featureConflicts.conflicts.length > 0) { conflicts.push(featureConflicts); } } return conflicts; } async analyzeFeatureConflicts(feature, allFeatures) { const conflicts = []; // Check for overlapping integration points for (const otherFeature of allFeatures) { if (otherFeature.id === feature.id) continue; // Check integration conflicts const overlappingIntegrations = feature.integrationPoints.filter((ip) => otherFeature.integrationPoints.some((oip) => oip.component === ip.component && oip.type === ip.type)); if (overlappingIntegrations.length > 0) { conflicts.push({ type: 'file', description: `Both "${feature.name}" and "${otherFeature.name}" modify same components`, severity: 'medium', resolution: 'Coordinate changes or implement in sequence', }); } // Check for circular dependencies if (feature.dependencies.includes(otherFeature.id) && otherFeature.dependencies.includes(feature.id)) { conflicts.push({ type: 'dependency', description: `Circular dependency between "${feature.name}" and "${otherFeature.name}"`, severity: 'high', resolution: 'Refactor to remove circular dependency', }); } } // Check for API conflicts if (feature.category === 'api') { const apiFeatures = allFeatures.filter((f) => f.id !== feature.id && f.category === 'api'); if (apiFeatures.length > 0) { // Simple check for potential route conflicts conflicts.push({ type: 'api', description: 'Multiple API features may have route conflicts', severity: 'low', resolution: 'Ensure unique route paths and proper namespacing', }); } } return { featureId: feature.id, conflicts, }; } async generateIntegrationMap(features) { const integrationMap = new Map(); for (const feature of features) { for (const integration of feature.integrationPoints) { const key = `${integration.type}:${integration.component}`; if (!integrationMap.has(key)) { integrationMap.set(key, new Set()); } integrationMap.get(key).add(feature.id); } } return integrationMap; } } exports.FeatureAnalyzer = FeatureAnalyzer; //# sourceMappingURL=featureAnalyzer.js.map