UNPKG

strategic-intelligence-mcp

Version:

Strategic Intelligence MCP Server - connecting technical progress to business outcomes with systematic strategic planning

477 lines 22.3 kB
export class GoalProgressAnalytics { assessGoalHealth(goal, relatedMilestones, correlations) { // Assess each dimension of goal health const progressDimension = this.assessProgressDimension(goal, relatedMilestones); const velocityDimension = this.assessVelocityDimension(goal, relatedMilestones); const confidenceDimension = this.assessConfidenceDimension(goal); const dependencyDimension = this.assessDependencyDimension(goal, relatedMilestones); const alignmentDimension = this.assessAlignmentDimension(goal, correlations); // Calculate overall health score const dimensionsArray = [progressDimension, velocityDimension, confidenceDimension, dependencyDimension, alignmentDimension]; const healthScore = dimensionsArray.reduce((sum, dim) => sum + dim.score, 0) / dimensionsArray.length; const overallHealth = this.determineOverallHealth(healthScore); // Identify blockers and accelerators const blockers = this.identifyBlockers(goal, relatedMilestones); const accelerators = this.identifyAccelerators(goal, relatedMilestones); const riskFactors = this.assessRiskFactors(goal, relatedMilestones); const dimensions = { progress: progressDimension, velocity: velocityDimension, confidence: confidenceDimension, dependency: dependencyDimension, alignment: alignmentDimension }; return { goalId: goal.id, goalName: goal.title, overallHealth, healthScore, dimensions, blockers, accelerators, recommendations: this.generateHealthRecommendations(overallHealth, dimensions, blockers), riskFactors, lastAssessment: new Date().toISOString() }; } assessProgressDimension(goal, milestones) { const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); if (linkedMilestones.length === 0) { return { score: 20, status: 'poor', description: 'No technical milestones linked to this goal', trend: 'stable', evidence: ['Goal has no technical implementation plan'] }; } const completedCount = linkedMilestones.filter(m => m.status === 'completed').length; const inProgressCount = linkedMilestones.filter(m => m.status === 'in-progress').length; const progressPercentage = (completedCount / linkedMilestones.length) * 100; let score = progressPercentage; let status = 'fair'; if (progressPercentage >= 80) status = 'excellent'; else if (progressPercentage >= 60) status = 'good'; else if (progressPercentage >= 40) status = 'fair'; else if (progressPercentage >= 20) status = 'poor'; else status = 'critical'; // Boost score if there's active progress if (inProgressCount > 0) { score += 10; } const evidence = [ `${completedCount}/${linkedMilestones.length} milestones completed (${progressPercentage.toFixed(1)}%)`, `${inProgressCount} milestones currently in progress` ]; return { score: Math.min(100, score), status, description: `${progressPercentage.toFixed(1)}% of linked technical milestones completed`, trend: inProgressCount > 0 ? 'improving' : 'stable', evidence }; } assessVelocityDimension(goal, milestones) { const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); const completedMilestones = linkedMilestones.filter(m => m.status === 'completed' && m.completionDate); if (completedMilestones.length < 2) { return { score: 50, status: 'fair', description: 'Insufficient completion history to assess velocity', trend: 'stable', evidence: ['Need at least 2 completed milestones for velocity analysis'] }; } // Calculate completion velocity (milestones per month) const completionDates = completedMilestones.map(m => new Date(m.completionDate).getTime()).sort(); const timeSpan = (completionDates[completionDates.length - 1] - completionDates[0]) / (1000 * 60 * 60 * 24 * 30); // months const velocity = completedMilestones.length / Math.max(timeSpan, 0.5); // milestones per month // Assess if velocity is adequate for remaining work const remainingMilestones = linkedMilestones.length - completedMilestones.length; const estimatedMonthsToComplete = remainingMilestones / velocity; let score = 70; // Base score let status = 'good'; if (estimatedMonthsToComplete <= 2) { score = 90; status = 'excellent'; } else if (estimatedMonthsToComplete <= 4) { score = 75; status = 'good'; } else if (estimatedMonthsToComplete <= 6) { score = 60; status = 'fair'; } else { score = 40; status = 'poor'; } return { score, status, description: `Current velocity: ${velocity.toFixed(1)} milestones/month, ${estimatedMonthsToComplete.toFixed(1)} months to completion`, trend: 'stable', // Would need more data points to determine trend evidence: [ `${completedMilestones.length} milestones completed over ${timeSpan.toFixed(1)} months`, `${remainingMilestones} milestones remaining` ] }; } assessConfidenceDimension(goal) { const confidence = goal.confidence || 50; let status = 'fair'; if (confidence >= 80) status = 'excellent'; else if (confidence >= 65) status = 'good'; else if (confidence >= 45) status = 'fair'; else if (confidence >= 25) status = 'poor'; else status = 'critical'; return { score: confidence, status, description: `Goal confidence level at ${confidence}%`, trend: 'stable', evidence: [`Confidence score: ${confidence}%`] }; } assessDependencyDimension(goal, milestones) { const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); if (linkedMilestones.length === 0) { return { score: 30, status: 'poor', description: 'No technical dependencies mapped', trend: 'stable', evidence: ['Goal lacks technical implementation plan'] }; } // Assess dependency complexity const totalDependencies = linkedMilestones.reduce((sum, m) => sum + m.dependencies.length, 0); const avgDependencies = totalDependencies / linkedMilestones.length; // Check external dependencies from goal definition const externalDeps = (goal.dependencies?.externalFactors || []).length + (goal.dependencies?.businessPrerequisites || []).length; let score = 70; // Base score // Lower score for high dependency complexity if (avgDependencies > 3) score -= 20; else if (avgDependencies > 1.5) score -= 10; if (externalDeps > 3) score -= 15; else if (externalDeps > 1) score -= 5; // Check if dependencies are being managed const blockedMilestones = linkedMilestones.filter(m => m.status === 'delayed').length; if (blockedMilestones > 0) score -= (blockedMilestones * 10); let status = 'good'; if (score >= 80) status = 'excellent'; else if (score >= 60) status = 'good'; else if (score >= 40) status = 'fair'; else if (score >= 20) status = 'poor'; else status = 'critical'; return { score: Math.max(0, score), status, description: `${avgDependencies.toFixed(1)} avg technical dependencies, ${externalDeps} external dependencies`, trend: blockedMilestones > 0 ? 'declining' : 'stable', evidence: [ `${totalDependencies} total technical dependencies across ${linkedMilestones.length} milestones`, `${externalDeps} external business dependencies`, `${blockedMilestones} milestones currently blocked` ] }; } assessAlignmentDimension(goal, correlations) { const goalCorrelations = correlations.filter(c => c.businessGoalId === goal.id); if (goalCorrelations.length === 0) { return { score: 40, status: 'fair', description: 'No technical-business correlations detected', trend: 'stable', evidence: ['Goal needs stronger technical work alignment'] }; } const avgCorrelation = goalCorrelations.reduce((sum, c) => sum + Math.abs(c.correlationStrength), 0) / goalCorrelations.length; const strongCorrelations = goalCorrelations.filter(c => Math.abs(c.correlationStrength) >= 70).length; let score = avgCorrelation; let status = 'fair'; if (avgCorrelation >= 80) status = 'excellent'; else if (avgCorrelation >= 65) status = 'good'; else if (avgCorrelation >= 45) status = 'fair'; else if (avgCorrelation >= 25) status = 'poor'; else status = 'critical'; // Bonus for having multiple strong correlations if (strongCorrelations >= 2) score += 10; return { score: Math.min(100, score), status, description: `${avgCorrelation.toFixed(1)}% average correlation strength with ${goalCorrelations.length} technical milestones`, trend: 'stable', evidence: [ `${goalCorrelations.length} technical correlations detected`, `${strongCorrelations} strong correlations (70%+)`, `Average correlation strength: ${avgCorrelation.toFixed(1)}%` ] }; } determineOverallHealth(healthScore) { if (healthScore >= 80) return 'excellent'; if (healthScore >= 65) return 'good'; if (healthScore >= 45) return 'fair'; if (healthScore >= 25) return 'poor'; return 'critical'; } identifyBlockers(goal, milestones) { const blockers = []; const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); // Technical blockers from delayed milestones const delayedMilestones = linkedMilestones.filter(m => m.status === 'delayed'); delayedMilestones.forEach(milestone => { blockers.push({ id: `technical-delay-${milestone.id}`, type: 'technical', description: `Milestone "${milestone.name}" is delayed`, severity: milestone.businessContext.strategicImportance >= 80 ? 'critical' : milestone.businessContext.strategicImportance >= 60 ? 'high' : 'medium', impact: `Blocks ${milestone.businessContext.revenueImplication.toLocaleString()} in projected revenue`, recommendedAction: 'Assess blockers and reallocate resources to critical path', estimatedResolutionTime: '1-2 weeks' }); }); // Dependency blockers const externalDeps = goal.dependencies?.externalFactors || []; if (externalDeps.length > 0) { blockers.push({ id: `external-deps-${goal.id}`, type: 'external', description: `${externalDeps.length} external dependencies may impact progress`, severity: 'medium', impact: 'May cause delays or require scope adjustments', recommendedAction: 'Develop contingency plans for external dependencies', estimatedResolutionTime: 'ongoing monitoring' }); } return blockers; } identifyAccelerators(goal, milestones) { const accelerators = []; const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); // Technical accelerators from high-performing areas const highImpactCompleted = linkedMilestones.filter(m => m.status === 'completed' && m.businessContext.strategicImportance >= 80); if (highImpactCompleted.length > 0) { accelerators.push({ id: `momentum-${goal.id}`, type: 'technical', description: `Strong execution momentum with ${highImpactCompleted.length} high-impact milestones completed`, potentialImpact: 'Can leverage lessons learned to accelerate remaining work', implementationEffort: 'low', timeToRealization: 'immediate' }); } // Market timing accelerators const earlyMarketMilestones = linkedMilestones.filter(m => m.businessContext.marketTiming === 'early'); if (earlyMarketMilestones.length > 0) { accelerators.push({ id: `market-timing-${goal.id}`, type: 'market', description: 'Early market timing advantage available', potentialImpact: 'First-mover advantage can accelerate goal achievement', implementationEffort: 'medium', timeToRealization: '3-6 months' }); } return accelerators; } assessRiskFactors(goal, milestones) { const risks = []; const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); // Timeline risk const highComplexityCount = linkedMilestones.filter(m => m.complexity === 'critical' || m.complexity === 'high').length; if (highComplexityCount > linkedMilestones.length * 0.5) { risks.push({ id: `timeline-risk-${goal.id}`, type: 'timeline', description: `${highComplexityCount} high/critical complexity milestones may cause delays`, probability: 70, impact: 'high', mitigationStrategy: 'Break down complex milestones, add buffer time, ensure expert resources' }); } // Resource risk const totalEffort = linkedMilestones.reduce((sum, m) => sum + m.effort, 0); if (totalEffort > 1000) { // More than 1000 person-hours risks.push({ id: `resource-risk-${goal.id}`, type: 'resource', description: `High resource requirement (${totalEffort} person-hours)`, probability: 60, impact: 'medium', mitigationStrategy: 'Ensure adequate team capacity, consider prioritization or phasing' }); } return risks; } generateHealthRecommendations(overallHealth, dimensions, blockers) { const recommendations = []; if (overallHealth === 'critical' || overallHealth === 'poor') { recommendations.push('URGENT: This goal requires immediate attention and intervention'); } // Dimension-specific recommendations if (dimensions.progress.score < 50) { recommendations.push('Accelerate technical milestone completion to improve progress'); } if (dimensions.velocity.score < 60) { recommendations.push('Review and optimize development velocity to meet timeline'); } if (dimensions.confidence.score < 50) { recommendations.push('Address uncertainty factors to improve goal confidence'); } if (dimensions.dependency.score < 60) { recommendations.push('Actively manage dependencies to prevent cascade delays'); } if (dimensions.alignment.score < 60) { recommendations.push('Strengthen alignment between technical work and business objectives'); } // Blocker-specific recommendations const criticalBlockers = blockers.filter(b => b.severity === 'critical'); if (criticalBlockers.length > 0) { recommendations.push(`Address ${criticalBlockers.length} critical blocker(s) immediately`); } return recommendations; } calculateVelocityMetrics(goal, milestones) { const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); const completedMilestones = linkedMilestones.filter(m => m.status === 'completed' && m.completionDate); if (completedMilestones.length < 2) { return { goalId: goal.id, currentVelocity: 0, targetVelocity: 0, velocityTrend: 'stalled', efficiency: 0, projectedCompletion: 'insufficient-data', confidenceInterval: { optimistic: 'unknown', realistic: 'unknown', pessimistic: 'unknown' } }; } // Calculate current velocity const completionDates = completedMilestones.map(m => new Date(m.completionDate).getTime()).sort(); const timeSpan = (completionDates[completionDates.length - 1] - completionDates[0]) / (1000 * 60 * 60 * 24 * 30); // months const currentVelocity = completedMilestones.length / Math.max(timeSpan, 0.5); // Calculate target velocity const remainingMilestones = linkedMilestones.length - completedMilestones.length; const monthsToTarget = 6; // Assume 6 month target for simplicity const targetVelocity = remainingMilestones / monthsToTarget; // Determine velocity trend let velocityTrend = 'steady'; if (completedMilestones.length >= 3) { const recentVelocity = 2 / Math.max((completionDates[completionDates.length - 1] - completionDates[completionDates.length - 3]) / (1000 * 60 * 60 * 24 * 30), 0.5); if (recentVelocity > currentVelocity * 1.2) velocityTrend = 'accelerating'; else if (recentVelocity < currentVelocity * 0.8) velocityTrend = 'decelerating'; } // Calculate efficiency const efficiency = Math.min(100, (currentVelocity / Math.max(targetVelocity, 0.1)) * 100); // Project completion const monthsToComplete = remainingMilestones / Math.max(currentVelocity, 0.1); const projectedDate = new Date(); projectedDate.setMonth(projectedDate.getMonth() + monthsToComplete); return { goalId: goal.id, currentVelocity, targetVelocity, velocityTrend, efficiency, projectedCompletion: projectedDate.toISOString(), confidenceInterval: { optimistic: new Date(projectedDate.getTime() - 30 * 24 * 60 * 60 * 1000).toISOString(), realistic: projectedDate.toISOString(), pessimistic: new Date(projectedDate.getTime() + 60 * 24 * 60 * 60 * 1000).toISOString() } }; } generateCompletionForecast(goal, milestones, correlations) { const linkedMilestones = milestones.filter(m => m.linkedGoals.includes(goal.id)); const velocityMetrics = this.calculateVelocityMetrics(goal, milestones); // Use correlation-weighted forecasting as primary method const goalCorrelations = correlations.filter(c => c.businessGoalId === goal.id); const avgCorrelation = goalCorrelations.length > 0 ? goalCorrelations.reduce((sum, c) => sum + Math.abs(c.correlationStrength), 0) / goalCorrelations.length : 50; // Adjust forecast based on correlation strength const correlationMultiplier = avgCorrelation / 100; const adjustedProjection = new Date(velocityMetrics.projectedCompletion); if (correlationMultiplier < 0.5) { // Weak correlations suggest delays adjustedProjection.setMonth(adjustedProjection.getMonth() + 2); } const confidence = Math.min(90, 40 + (avgCorrelation * 0.5) + (velocityMetrics.efficiency * 0.3)); return { goalId: goal.id, forecastMethod: 'correlation-weighted', projectedCompletionDate: adjustedProjection.toISOString(), confidence, scenarioAnalysis: { best: { date: new Date(adjustedProjection.getTime() - 45 * 24 * 60 * 60 * 1000).toISOString(), probability: 20 }, likely: { date: adjustedProjection.toISOString(), probability: 60 }, worst: { date: new Date(adjustedProjection.getTime() + 90 * 24 * 60 * 60 * 1000).toISOString(), probability: 20 } }, criticalPath: linkedMilestones .filter(m => m.businessContext.strategicImportance >= 80) .map(m => m.name), assumptions: [ 'Current development velocity continues', `Correlation strength (${avgCorrelation.toFixed(1)}%) remains stable`, 'No major external blockers emerge' ], riskFactors: [ 'High complexity milestones may take longer than estimated', 'External dependencies could introduce delays', 'Resource allocation changes could impact velocity' ] }; } } //# sourceMappingURL=goalProgressAnalytics.js.map