// Copyright 2025 Chris Bunting
// Brief: Intelligent prioritization engine for MCP Code Analysis & Quality Server
// Scope: AI-powered system to prioritize analysis results based on impact and context
import { EventEmitter } from 'events';
import {
UnifiedAnalysisResult,
UnifiedIssue,
PriorityLevel,
SeverityLevel,
RiskLevel,
AnalysisContext,
ImpactAssessment,
CorrelationData,
SuggestionData,
UserPreferences,
HistoricalData,
PatternData,
QualityTrend,
PerformanceData,
IssueCategory,
CrossReferenceType,
ProjectType,
DevelopmentStage,
ExperienceLevel,
TrendDirection,
PatternType
} from '@mcp-code-analysis/shared-types';
import { CacheInterface } from '@mcp-code-analysis/shared-types';
export interface PrioritizationConfig {
weights: {
severity: number;
impact: number;
frequency: number;
context: number;
trends: number;
patterns: number;
};
thresholds: {
critical: number;
high: number;
medium: number;
low: number;
};
learning: {
enabled: boolean;
adaptationRate: number;
feedbackWeight: number;
};
rules: PrioritizationRule[];
}
export interface PrioritizationRule {
id: string;
name: string;
description: string;
condition: (issue: UnifiedIssue, context: AnalysisContext) => boolean;
priority: PriorityLevel;
weight: number;
enabled: boolean;
tags: string[];
}
export interface PriorityScore {
score: number;
confidence: number;
factors: PriorityFactor[];
reasoning: string[];
priority: PriorityLevel;
estimatedEffort: number;
businessValue: number;
technicalDebt: number;
}
export interface PriorityFactor {
name: string;
value: number;
weight: number;
contribution: number;
description: string;
}
export interface LearningData {
userActions: UserActionData[];
patterns: PatternData[];
effectiveness: EffectivenessData[];
adaptations: AdaptationData[];
}
export interface UserActionData {
userId: string;
action: 'accepted' | 'rejected' | 'modified';
issueId: string;
timestamp: Date;
context: AnalysisContext;
reasoning: string;
}
export interface EffectivenessData {
ruleId: string;
effectiveness: number;
sampleSize: number;
timestamp: Date;
context: string;
}
export interface AdaptationData {
parameter: string;
oldValue: number;
newValue: number;
reason: string;
timestamp: Date;
effectiveness: number;
}
export class IntelligentPrioritizationEngine extends EventEmitter {
private config: PrioritizationConfig;
private cache: CacheInterface;
private learningData: LearningData;
private customRules: Map<string, PrioritizationRule> = new Map();
private logger: any; // Will be properly typed with LoggerInterface
constructor(config: PrioritizationConfig, cache: CacheInterface, logger: any) {
super();
this.config = config;
this.cache = cache;
this.logger = logger;
this.learningData = {
userActions: [],
patterns: [],
effectiveness: [],
adaptations: []
};
this.setupEventHandlers();
}
private setupEventHandlers(): void {
this.on('prioritized', this.handlePrioritized.bind(this));
this.on('user-feedback', this.handleUserFeedback.bind(this));
this.on('pattern-detected', this.handlePatternDetected.bind(this));
}
async initialize(): Promise<void> {
this.logger.info('Initializing Intelligent Prioritization Engine');
// Load learning data from cache
await this.loadLearningData();
// Initialize default rules
this.initializeDefaultRules();
// Start learning process if enabled
if (this.config.learning.enabled) {
this.startLearningProcess();
}
this.logger.info('Intelligent Prioritization Engine initialized successfully');
}
async prioritizeResults(
results: UnifiedAnalysisResult[],
context: AnalysisContext
): Promise<UnifiedAnalysisResult[]> {
try {
this.logger.info(`Prioritizing ${results.length} analysis results`);
// Process each result
const prioritizedResults = await Promise.all(
results.map(result => this.prioritizeSingleResult(result, context))
);
// Sort by priority score
prioritizedResults.sort((a, b) => {
const scoreA = this.calculateOverallPriorityScore(a);
const scoreB = this.calculateOverallPriorityScore(b);
return scoreB - scoreA;
});
// Emit prioritization event
this.emit('prioritized', {
results: prioritizedResults,
context,
timestamp: new Date()
});
this.logger.info('Results prioritized successfully');
return prioritizedResults;
} catch (error) {
this.logger.error('Failed to prioritize results:', error);
throw error;
}
}
private async prioritizeSingleResult(
result: UnifiedAnalysisResult,
context: AnalysisContext
): Promise<UnifiedAnalysisResult> {
// Prioritize issues within the result
const prioritizedIssues = await Promise.all(
result.issues.map(issue => this.prioritizeIssue(issue, context))
);
// Sort issues by priority
prioritizedIssues.sort((a, b) => {
const scoreA = this.calculateIssuePriorityScore(a);
const scoreB = this.calculateIssuePriorityScore(b);
return scoreB - scoreA;
});
// Update correlations and suggestions based on prioritization
const enhancedCorrelations = await this.enhanceCorrelations(
result.correlations,
prioritizedIssues,
context
);
const enhancedSuggestions = await this.enhanceSuggestions(
result.suggestions,
prioritizedIssues,
context
);
return {
...result,
issues: prioritizedIssues,
correlations: enhancedCorrelations,
suggestions: enhancedSuggestions,
priority: this.calculateResultPriority(prioritizedIssues)
};
}
private async prioritizeIssue(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<UnifiedIssue> {
// Calculate priority score
const priorityScore = await this.calculatePriorityScore(issue, context);
// Apply custom rules
const ruleAdjustments = await this.applyCustomRules(issue, context);
// Apply learning-based adjustments
const learningAdjustments = this.config.learning.enabled
? await this.applyLearningAdjustments(issue, context)
: 0;
// Calculate final priority
const finalScore = priorityScore.score + ruleAdjustments + learningAdjustments;
const finalPriority = this.scoreToPriority(finalScore);
// Enhance cross-references based on priority
const enhancedCrossReferences = await this.enhanceCrossReferences(
(issue.crossReferences || []).map(ref => ref.type),
issue,
context
);
return {
...issue,
priority: finalPriority,
crossReferences: enhancedCrossReferences as any,
impact: this.enhanceImpactAssessment(issue.impact, finalScore, context)
};
}
private async calculatePriorityScore(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<PriorityScore> {
const factors: PriorityFactor[] = [];
// Severity factor
const severityScore = this.calculateSeverityScore(issue.severity);
factors.push({
name: 'severity',
value: severityScore,
weight: this.config.weights.severity,
contribution: severityScore * this.config.weights.severity,
description: `Severity level: ${issue.severity}`
});
// Impact factor
const impactScore = this.calculateImpactScore(issue.impact);
factors.push({
name: 'impact',
value: impactScore,
weight: this.config.weights.impact,
contribution: impactScore * this.config.weights.impact,
description: `Business and technical impact assessment`
});
// Context factor
const contextScore = await this.calculateContextScore(issue, context);
factors.push({
name: 'context',
value: contextScore,
weight: this.config.weights.context,
contribution: contextScore * this.config.weights.context,
description: `Project and team context relevance`
});
// Frequency factor
const frequencyScore = await this.calculateFrequencyScore(issue, context);
factors.push({
name: 'frequency',
value: frequencyScore,
weight: this.config.weights.frequency,
contribution: frequencyScore * this.config.weights.frequency,
description: `Historical frequency and recurrence patterns`
});
// Trends factor
const trendsScore = await this.calculateTrendsScore(issue, context);
factors.push({
name: 'trends',
value: trendsScore,
weight: this.config.weights.trends,
contribution: trendsScore * this.config.weights.trends,
description: `Quality and performance trends`
});
// Patterns factor
const patternsScore = await this.calculatePatternsScore(issue, context);
factors.push({
name: 'patterns',
value: patternsScore,
weight: this.config.weights.patterns,
contribution: patternsScore * this.config.weights.patterns,
description: `Pattern recognition and anti-patterns`
});
// Calculate total score
const totalScore = factors.reduce((sum, factor) => sum + factor.contribution, 0);
// Calculate confidence
const confidence = this.calculateConfidence(factors);
// Generate reasoning
const reasoning = this.generateReasoning(factors, issue, context);
return {
score: totalScore,
confidence,
factors,
reasoning,
priority: this.scoreToPriority(totalScore),
estimatedEffort: this.estimateEffort(issue, context),
businessValue: this.calculateBusinessValue(issue, context),
technicalDebt: this.calculateTechnicalDebt(issue, context)
};
}
private calculateSeverityScore(severity: SeverityLevel): number {
const severityMap = {
[SeverityLevel.ERROR]: 1.0,
[SeverityLevel.WARNING]: 0.7,
[SeverityLevel.INFO]: 0.4,
[SeverityLevel.HINT]: 0.1
};
return severityMap[severity] || 0.5;
}
private calculateImpactScore(impact: ImpactAssessment): number {
const weights = {
business: 0.4,
technical: 0.3,
user: 0.2,
risk: 0.1
};
const normalizedImpact = {
business: impact.businessImpact / 10,
technical: impact.technicalImpact / 10,
user: impact.userImpact / 10,
risk: this.riskLevelToScore(impact.riskLevel)
};
return (
normalizedImpact.business * weights.business +
normalizedImpact.technical * weights.technical +
normalizedImpact.user * weights.user +
normalizedImpact.risk * weights.risk
);
}
private async calculateContextScore(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<number> {
let score = 0.5; // Base score
// Project type relevance
const projectTypeScore = this.getProjectTypeRelevance(issue, context.projectType);
score += projectTypeScore * 0.3;
// Development stage relevance
const stageScore = this.getDevelopmentStageRelevance(issue, context.developmentStage);
score += stageScore * 0.2;
// Team experience relevance
const experienceScore = this.getExperienceRelevance(issue, context.teamContext.experienceLevel);
score += experienceScore * 0.2;
// User preferences relevance
const preferenceScore = this.getPreferenceRelevance(issue, context.userPreferences);
score += preferenceScore * 0.3;
return Math.min(Math.max(score, 0), 1);
}
private async calculateFrequencyScore(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<number> {
const cacheKey = `frequency:${issue.ruleId}:${context.technologyStack.join('-')}`;
const cached = await this.cache.get<number>(cacheKey);
if (cached !== undefined) {
return cached;
}
// Calculate frequency based on historical data
const frequency = this.calculateIssueFrequency(issue, context.historicalData);
const normalizedFrequency = Math.min(frequency / 10, 1); // Normalize to 0-1
// Cache the result
await this.cache.set(cacheKey, normalizedFrequency, 300000); // 5 minutes
return normalizedFrequency;
}
private async calculateTrendsScore(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<number> {
const qualityTrends = context.historicalData.qualityTrends;
const performanceHistory = context.historicalData.performanceHistory;
let trendScore = 0.5; // Base score
// Analyze quality trends
const qualityTrendScore = this.analyzeQualityTrends(issue, qualityTrends);
trendScore += qualityTrendScore * 0.6;
// Analyze performance trends
const performanceTrendScore = this.analyzePerformanceTrends(issue, performanceHistory);
trendScore += performanceTrendScore * 0.4;
return Math.min(Math.max(trendScore, 0), 1);
}
private async calculatePatternsScore(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<number> {
const patterns = context.historicalData.recurringPatterns;
let patternScore = 0.5; // Base score
// Check for matching patterns
const matchingPatterns = patterns.filter(pattern =>
this.isPatternMatch(issue, pattern)
);
if (matchingPatterns.length > 0) {
// Higher score for more frequent and severe patterns
const avgFrequency = matchingPatterns.reduce((sum, p) => sum + p.frequency, 0) / matchingPatterns.length;
const avgSeverity = matchingPatterns.reduce((sum, p) => sum + this.severityToScore(p.severity), 0) / matchingPatterns.length;
patternScore += (avgFrequency / 10) * 0.5 + avgSeverity * 0.5;
}
return Math.min(Math.max(patternScore, 0), 1);
}
private async applyCustomRules(
issue: UnifiedIssue,
context: AnalysisContext
): Promise<number> {
let adjustment = 0;
for (const rule of this.config.rules) {
if (rule.enabled && rule.condition(issue, context)) {
const ruleScore = this.priorityToScore(rule.priority);
adjustment += ruleScore * rule.weight;
}
}
// Apply custom rules
for (const customRule of this.customRules.values()) {
if (customRule.enabled && customRule.condition(issue, context)) {
const ruleScore = this.priorityToScore(customRule.priority);
adjustment += ruleScore * customRule.weight;
}
}
return adjustment;
}
private applyLearningAdjustments(
issue: UnifiedIssue,
context: AnalysisContext
): number {
if (!this.config.learning.enabled) {
return 0;
}
let adjustment = 0;
// Analyze user action patterns
const userActionScore = this.analyzeUserActions(issue, context);
adjustment += userActionScore * this.config.learning.feedbackWeight;
// Analyze rule effectiveness
const effectivenessScore = this.analyzeRuleEffectiveness(issue);
adjustment += effectivenessScore * this.config.learning.adaptationRate;
return adjustment;
}
private calculateConfidence(factors: PriorityFactor[]): number {
if (factors.length === 0) {
return 0;
}
// Calculate confidence based on factor variance and completeness
const values = factors.map(f => f.value);
const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
// Higher variance means lower confidence
const variancePenalty = Math.min(variance * 0.5, 0.3);
// Base confidence on number of factors
const factorBonus = Math.min(factors.length * 0.1, 0.3);
return Math.max(0, Math.min(1, 1 - variancePenalty + factorBonus));
}
private generateReasoning(
factors: PriorityFactor[],
issue: UnifiedIssue,
context: AnalysisContext
): string[] {
const reasoning: string[] = [];
// Add top contributing factors
const topFactors = factors
.sort((a, b) => b.contribution - a.contribution)
.slice(0, 3);
topFactors.forEach(factor => {
reasoning.push(`${factor.name}: ${factor.description} (score: ${factor.value.toFixed(2)}, weight: ${factor.weight})`);
});
// Add context-specific reasoning
if (context.projectType === ProjectType.WEB_APP && issue.category === IssueCategory.SECURITY) {
reasoning.push('Security issues are critical for web applications');
}
if (context.developmentStage === DevelopmentStage.PRODUCTION && issue.severity === SeverityLevel.ERROR) {
reasoning.push('Errors in production require immediate attention');
}
return reasoning;
}
private scoreToPriority(score: number): PriorityLevel {
if (score >= this.config.thresholds.critical) {
return PriorityLevel.CRITICAL;
} else if (score >= this.config.thresholds.high) {
return PriorityLevel.HIGH;
} else if (score >= this.config.thresholds.medium) {
return PriorityLevel.MEDIUM;
} else {
return PriorityLevel.LOW;
}
}
private priorityToScore(priority: PriorityLevel): number {
const priorityMap = {
[PriorityLevel.CRITICAL]: 1.0,
[PriorityLevel.HIGH]: 0.8,
[PriorityLevel.MEDIUM]: 0.6,
[PriorityLevel.LOW]: 0.4,
[PriorityLevel.INFO]: 0.2
};
return priorityMap[priority] || 0.5;
}
private riskLevelToScore(riskLevel: RiskLevel): number {
const riskMap = {
[RiskLevel.CRITICAL]: 1.0,
[RiskLevel.HIGH]: 0.8,
[RiskLevel.MEDIUM]: 0.6,
[RiskLevel.LOW]: 0.4
};
return riskMap[riskLevel] || 0.5;
}
private severityToScore(severity: SeverityLevel): number {
return this.calculateSeverityScore(severity);
}
private initializeDefaultRules(): void {
const defaultRules: PrioritizationRule[] = [
{
id: 'security-critical',
name: 'Security Critical Issues',
description: 'Elevate priority for security-related issues',
condition: (issue, _context) =>
issue.category === IssueCategory.SECURITY &&
issue.severity === SeverityLevel.ERROR,
priority: PriorityLevel.CRITICAL,
weight: 0.9,
enabled: true,
tags: ['security', 'critical']
},
{
id: 'production-blocking',
name: 'Production Blocking Issues',
description: 'Elevate priority for issues blocking production',
condition: (issue, context) =>
context.developmentStage === DevelopmentStage.PRODUCTION &&
issue.severity === SeverityLevel.ERROR,
priority: PriorityLevel.CRITICAL,
weight: 0.8,
enabled: true,
tags: ['production', 'blocking']
},
{
id: 'performance-critical',
name: 'Performance Critical Issues',
description: 'Elevate priority for performance bottlenecks',
condition: (issue, _context) =>
issue.category === IssueCategory.PERFORMANCE &&
issue.impact.businessImpact > 7,
priority: PriorityLevel.HIGH,
weight: 0.7,
enabled: true,
tags: ['performance', 'critical']
}
];
defaultRules.forEach(rule => {
this.customRules.set(rule.id, rule);
});
}
private async loadLearningData(): Promise<void> {
try {
const cached = await this.cache.get<LearningData>('learning-data');
if (cached) {
this.learningData = cached;
this.logger.info('Learning data loaded from cache');
}
} catch (error) {
this.logger.warn('Failed to load learning data:', error);
}
}
private async saveLearningData(): Promise<void> {
try {
await this.cache.set('learning-data', this.learningData, 3600000); // 1 hour
} catch (error) {
this.logger.warn('Failed to save learning data:', error);
}
}
private startLearningProcess(): void {
// Start periodic learning updates
setInterval(() => {
this.updateLearningModels();
}, 300000); // Every 5 minutes
this.logger.info('Learning process started');
}
private async updateLearningModels(): Promise<void> {
try {
// Analyze user actions
await this.analyzeUserActionPatterns();
// Update rule effectiveness
await this.updateRuleEffectiveness();
// Adapt parameters based on learning
await this.adaptParameters();
// Save updated learning data
await this.saveLearningData();
this.logger.debug('Learning models updated');
} catch (error) {
this.logger.error('Failed to update learning models:', error);
}
}
private handlePrioritized(_data: any): void {
this.logger.debug('Results prioritized event handled');
}
private handleUserFeedback(data: any): void {
// Process user feedback for learning
const { action, issueId, context } = data;
this.learningData.userActions.push({
userId: context.userPreferences?.toString() || 'anonymous',
action: action.outcome,
issueId,
timestamp: new Date(),
context: context.projectContext,
reasoning: action.reasoning || ''
});
}
private handlePatternDetected(data: any): void {
// Process detected patterns
this.learningData.patterns.push(data.pattern);
}
// Helper methods for score calculations
private getProjectTypeRelevance(issue: UnifiedIssue, projectType: ProjectType): number {
const relevanceMap: Record<ProjectType, Record<IssueCategory, number>> = {
[ProjectType.WEB_APP]: {
[IssueCategory.SECURITY]: 0.9,
[IssueCategory.PERFORMANCE]: 0.8,
[IssueCategory.ACCESSIBILITY]: 0.7,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.MAINTAINABILITY]: 0.5,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4,
[IssueCategory.DOCUMENTATION]: 0.6
},
[ProjectType.API]: {
[IssueCategory.SECURITY]: 0.9,
[IssueCategory.PERFORMANCE]: 0.8,
[IssueCategory.MAINTAINABILITY]: 0.7,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.ACCESSIBILITY]: 0.2,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4,
[IssueCategory.DOCUMENTATION]: 0.8
},
[ProjectType.LIBRARY]: {
[IssueCategory.MAINTAINABILITY]: 0.9,
[IssueCategory.PERFORMANCE]: 0.8,
[IssueCategory.DOCUMENTATION]: 0.7,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.SECURITY]: 0.4,
[IssueCategory.ACCESSIBILITY]: 0.2,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4
},
[ProjectType.MICROSERVICE]: {
[IssueCategory.SECURITY]: 0.8,
[IssueCategory.PERFORMANCE]: 0.9,
[IssueCategory.MAINTAINABILITY]: 0.6,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.ACCESSIBILITY]: 0.2,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4,
[IssueCategory.DOCUMENTATION]: 0.7
},
[ProjectType.MOBILE_APP]: {
[IssueCategory.SECURITY]: 0.8,
[IssueCategory.PERFORMANCE]: 0.9,
[IssueCategory.ACCESSIBILITY]: 0.8,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.MAINTAINABILITY]: 0.5,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4,
[IssueCategory.DOCUMENTATION]: 0.5
},
[ProjectType.DESKTOP_APP]: {
[IssueCategory.SECURITY]: 0.7,
[IssueCategory.PERFORMANCE]: 0.8,
[IssueCategory.ACCESSIBILITY]: 0.6,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.MAINTAINABILITY]: 0.5,
[IssueCategory.TECHNICAL_DEBT]: 0.4,
[IssueCategory.COMPLEXITY]: 0.4,
[IssueCategory.DOCUMENTATION]: 0.4
},
[ProjectType.MONOLITH]: {
[IssueCategory.SECURITY]: 0.7,
[IssueCategory.PERFORMANCE]: 0.7,
[IssueCategory.MAINTAINABILITY]: 0.8,
[IssueCategory.SYNTAX]: 0.3,
[IssueCategory.STYLE]: 0.3,
[IssueCategory.ACCESSIBILITY]: 0.2,
[IssueCategory.TECHNICAL_DEBT]: 0.5,
[IssueCategory.COMPLEXITY]: 0.5,
[IssueCategory.DOCUMENTATION]: 0.6
}
};
return relevanceMap[projectType]?.[issue.category] || 0.5;
}
private getDevelopmentStageRelevance(issue: UnifiedIssue, stage: DevelopmentStage): number {
const stageMap: Record<DevelopmentStage, Record<SeverityLevel, number>> = {
[DevelopmentStage.PLANNING]: {
[SeverityLevel.ERROR]: 0.6,
[SeverityLevel.WARNING]: 0.7,
[SeverityLevel.INFO]: 0.8,
[SeverityLevel.HINT]: 0.5
},
[DevelopmentStage.DEVELOPMENT]: {
[SeverityLevel.ERROR]: 0.8,
[SeverityLevel.WARNING]: 0.7,
[SeverityLevel.INFO]: 0.6,
[SeverityLevel.HINT]: 0.4
},
[DevelopmentStage.TESTING]: {
[SeverityLevel.ERROR]: 0.9,
[SeverityLevel.WARNING]: 0.8,
[SeverityLevel.INFO]: 0.6,
[SeverityLevel.HINT]: 0.4
},
[DevelopmentStage.PRODUCTION]: {
[SeverityLevel.ERROR]: 1.0,
[SeverityLevel.WARNING]: 0.9,
[SeverityLevel.INFO]: 0.6,
[SeverityLevel.HINT]: 0.3
},
[DevelopmentStage.MAINTENANCE]: {
[SeverityLevel.ERROR]: 0.9,
[SeverityLevel.WARNING]: 0.8,
[SeverityLevel.INFO]: 0.7,
[SeverityLevel.HINT]: 0.5
},
[DevelopmentStage.DEPLOYMENT]: {
[SeverityLevel.ERROR]: 0.95,
[SeverityLevel.WARNING]: 0.85,
[SeverityLevel.INFO]: 0.6,
[SeverityLevel.HINT]: 0.4
}
};
return stageMap[stage]?.[issue.severity] || 0.5;
}
private getExperienceRelevance(_issue: UnifiedIssue, experienceLevel: ExperienceLevel): number {
const experienceMap: Record<ExperienceLevel, number> = {
[ExperienceLevel.JUNIOR]: 0.8,
[ExperienceLevel.MID]: 0.6,
[ExperienceLevel.SENIOR]: 0.4,
[ExperienceLevel.EXPERT]: 0.3
};
return experienceMap[experienceLevel] || 0.5;
}
private getPreferenceRelevance(issue: UnifiedIssue, preferences: UserPreferences): number {
let score = 0.5;
// Check if issue category is preferred
if (preferences.preferredCategories.includes(issue.category)) {
score += 0.3;
}
// Check severity threshold
if (this.severityToScore(issue.severity) >= this.severityToScore(preferences.severityThreshold)) {
score += 0.2;
}
return Math.min(score, 1.0);
}
private calculateIssueFrequency(issue: UnifiedIssue, historicalData: HistoricalData): number {
// Count occurrences of similar issues in historical data
const similarIssues = historicalData.previousIssues.filter(prevId =>
prevId.includes(issue.ruleId) || prevId.includes(issue.category)
);
return similarIssues.length;
}
private analyzeQualityTrends(_issue: UnifiedIssue, trends: QualityTrend[]): number {
const relevantTrends = trends.filter(trend =>
trend.metric.includes('quality') || trend.metric.includes('defects')
);
if (relevantTrends.length === 0) {
return 0.5;
}
// Calculate trend direction and magnitude
const avgTrend = relevantTrends.reduce((sum, trend) => {
const trendValue = trend.trend === TrendDirection.IMPROVING ? -1 :
trend.trend === TrendDirection.DECLINING ? 1 : 0;
return sum + trendValue;
}, 0) / relevantTrends.length;
// Higher score for declining trends
return 0.5 + (avgTrend * 0.5);
}
private analyzePerformanceTrends(issue: UnifiedIssue, history: PerformanceData[]): number {
if (issue.category !== IssueCategory.PERFORMANCE) {
return 0.5;
}
const relevantHistory = history.filter(h =>
h.metric.includes('performance') || h.metric.includes('response')
);
if (relevantHistory.length === 0) {
return 0.5;
}
// Calculate performance degradation
const avgDeviation = relevantHistory.reduce((sum, h) => sum + h.deviation, 0) / relevantHistory.length;
// Higher score for higher deviations
return Math.min(0.5 + (avgDeviation * 0.5), 1.0);
}
private isPatternMatch(issue: UnifiedIssue, pattern: PatternData): boolean {
return pattern.type === PatternType.ANTI_PATTERN &&
pattern.locations.some(loc =>
loc.filePath === issue.location.filePath ||
pattern.description.toLowerCase().includes(issue.ruleId.toLowerCase())
);
}
private analyzeUserActions(issue: UnifiedIssue, context: AnalysisContext): number {
const relevantActions = this.learningData.userActions.filter(action =>
action.issueId === issue.id ||
action.context.technologyStack.join('-') === context.technologyStack.join('-')
);
if (relevantActions.length === 0) {
return 0;
}
// Calculate acceptance rate
const acceptanceRate = relevantActions.filter(action =>
action.action === 'accepted'
).length / relevantActions.length;
return (acceptanceRate - 0.5) * 2; // Convert to -1 to 1 range
}
private analyzeRuleEffectiveness(issue: UnifiedIssue): number {
const ruleEffectiveness = this.learningData.effectiveness.filter(eff =>
eff.ruleId === issue.ruleId
);
if (ruleEffectiveness.length === 0) {
return 0;
}
const avgEffectiveness = ruleEffectiveness.reduce((sum, eff) =>
sum + eff.effectiveness, 0
) / ruleEffectiveness.length;
return (avgEffectiveness - 0.5) * 2; // Convert to -1 to 1 range
}
private estimateEffort(issue: UnifiedIssue, context: AnalysisContext): number {
// Base effort estimation
let effort = 1;
// Adjust by severity
effort *= this.severityToScore(issue.severity) * 2;
// Adjust by impact
effort *= (issue.impact.effortEstimate / 5);
// Adjust by team experience
const experienceMultiplier = {
[ExperienceLevel.JUNIOR]: 1.5,
[ExperienceLevel.MID]: 1.2,
[ExperienceLevel.SENIOR]: 1.0,
[ExperienceLevel.EXPERT]: 0.8
};
effort *= experienceMultiplier[context.teamContext.experienceLevel];
return Math.round(effort);
}
private calculateBusinessValue(issue: UnifiedIssue, context: AnalysisContext): number {
let value = issue.impact.businessImpact;
// Adjust by project type
const projectTypeMultiplier: Record<ProjectType, number> = {
[ProjectType.WEB_APP]: 1.2,
[ProjectType.API]: 1.1,
[ProjectType.LIBRARY]: 0.9,
[ProjectType.MICROSERVICE]: 1.0,
[ProjectType.MOBILE_APP]: 1.1,
[ProjectType.DESKTOP_APP]: 1.0,
[ProjectType.MONOLITH]: 0.9
};
value *= projectTypeMultiplier[context.projectType] || 1.0;
// Adjust by development stage
const stageMultiplier: Record<DevelopmentStage, number> = {
[DevelopmentStage.PLANNING]: 0.8,
[DevelopmentStage.DEVELOPMENT]: 1.0,
[DevelopmentStage.TESTING]: 1.1,
[DevelopmentStage.PRODUCTION]: 1.3,
[DevelopmentStage.MAINTENANCE]: 1.2,
[DevelopmentStage.DEPLOYMENT]: 1.25
};
value *= stageMultiplier[context.developmentStage] || 1.0;
return Math.min(Math.round(value), 10);
}
private calculateTechnicalDebt(issue: UnifiedIssue, _context: AnalysisContext): number {
let debt = 5; // Base technical debt
// Adjust by complexity
debt *= (1 + issue.impact.technicalImpact / 10);
// Adjust by category - use only existing categories
const categoryMultiplier: Record<IssueCategory, number> = {
[IssueCategory.SECURITY]: 1.4,
[IssueCategory.PERFORMANCE]: 1.3,
[IssueCategory.ACCESSIBILITY]: 1.1,
[IssueCategory.SYNTAX]: 0.8,
[IssueCategory.STYLE]: 0.6,
[IssueCategory.MAINTAINABILITY]: 1.5,
[IssueCategory.TECHNICAL_DEBT]: 1.6,
[IssueCategory.COMPLEXITY]: 1.2,
[IssueCategory.DOCUMENTATION]: 0.9
};
debt *= categoryMultiplier[issue.category] || 1.0;
return Math.min(Math.round(debt), 10);
}
private calculateOverallPriorityScore(result: UnifiedAnalysisResult): number {
if (result.issues.length === 0) {
return 0;
}
const issueScores = result.issues.map(issue => this.calculateIssuePriorityScore(issue));
return issueScores.reduce((sum, score) => sum + score, 0) / issueScores.length;
}
private calculateIssuePriorityScore(issue: UnifiedIssue): number {
return this.priorityToScore(issue.priority || PriorityLevel.LOW);
}
private calculateResultPriority(issues: UnifiedIssue[]): PriorityLevel {
if (issues.length === 0) {
return PriorityLevel.INFO;
}
const scores = issues.map(issue => this.calculateIssuePriorityScore(issue));
const avgScore = scores.reduce((sum, score) => sum + score, 0) / scores.length;
return this.scoreToPriority(avgScore);
}
private async enhanceCorrelations(
correlations: CorrelationData[],
issues: UnifiedIssue[],
_context: AnalysisContext
): Promise<CorrelationData[]> {
// Enhance correlations based on prioritized issues
return correlations.map(correlation => ({
...correlation,
confidence: Math.min(correlation.confidence * 1.1, 1.0), // Slight confidence boost
relatedIssues: correlation.relatedIssues.filter(issueId =>
issues.some(issue => issue.id === issueId)
)
}));
}
private async enhanceSuggestions(
suggestions: SuggestionData[],
issues: UnifiedIssue[],
context: AnalysisContext
): Promise<SuggestionData[]> {
// Enhance suggestions based on prioritized issues
return suggestions.map(suggestion => ({
...suggestion,
priority: this.enhanceSuggestionPriority(suggestion, issues),
impact: this.enhanceSuggestionImpact(suggestion, issues, context)
}));
}
private enhanceSuggestionPriority(suggestion: SuggestionData, issues: UnifiedIssue[]): PriorityLevel {
const relatedIssues = issues.filter(issue =>
suggestion.id.includes(issue.id) ||
suggestion.description.toLowerCase().includes(issue.ruleId.toLowerCase())
);
if (relatedIssues.length === 0) {
return suggestion.priority;
}
const maxIssuePriority = relatedIssues.reduce((max, issue) => {
const issueScore = this.calculateIssuePriorityScore(issue);
const maxScore = this.priorityToScore(max);
return issueScore > maxScore ? issue.priority : max;
}, PriorityLevel.LOW);
return maxIssuePriority;
}
private enhanceSuggestionImpact(
suggestion: SuggestionData,
issues: UnifiedIssue[],
_context: AnalysisContext
): ImpactAssessment {
const relatedIssues = issues.filter(issue =>
suggestion.id.includes(issue.id) ||
suggestion.description.toLowerCase().includes(issue.ruleId.toLowerCase())
);
if (relatedIssues.length === 0) {
return suggestion.impact;
}
// Aggregate impact from related issues
const businessImpact = Math.max(...relatedIssues.map(issue => issue.impact.businessImpact));
const technicalImpact = Math.max(...relatedIssues.map(issue => issue.impact.technicalImpact));
const userImpact = Math.max(...relatedIssues.map(issue => issue.impact.userImpact));
const effortEstimate = Math.min(...relatedIssues.map(issue => issue.impact.effortEstimate));
const riskLevelScores = relatedIssues.map(issue => this.riskLevelToScore(issue.impact.riskLevel));
const maxRiskScore = Math.max(...riskLevelScores);
const riskLevel = this.scoreToRiskLevel(maxRiskScore);
return {
businessImpact,
technicalImpact,
userImpact,
priorityScore: (businessImpact + technicalImpact + userImpact) / 3,
effortEstimate,
riskLevel
};
}
private scoreToRiskLevel(score: number): RiskLevel {
if (score >= 0.8) return RiskLevel.CRITICAL;
if (score >= 0.6) return RiskLevel.HIGH;
if (score >= 0.4) return RiskLevel.MEDIUM;
return RiskLevel.LOW;
}
private async enhanceCrossReferences(
crossReferences: CrossReferenceType[],
_issue: UnifiedIssue,
_context: AnalysisContext
): Promise<CrossReferenceType[]> {
// Enhance cross-references based on priority
return crossReferences.map(ref => ref); // No enhancement needed for enum type
}
private enhanceImpactAssessment(
impact: ImpactAssessment,
score: number,
_context: AnalysisContext
): ImpactAssessment {
// Enhance impact assessment based on priority score
const multiplier = 1 + (score - 0.5) * 0.2; // Adjust by ±10%
return {
...impact,
businessImpact: Math.min(impact.businessImpact * multiplier, 10),
technicalImpact: Math.min(impact.technicalImpact * multiplier, 10),
userImpact: Math.min(impact.userImpact * multiplier, 10),
priorityScore: Math.min(impact.priorityScore * multiplier, 10)
};
}
private async analyzeUserActionPatterns(): Promise<void> {
// Analyze patterns in user actions for learning
// Implementation would include pattern recognition algorithms
}
private async updateRuleEffectiveness(): Promise<void> {
// Update rule effectiveness based on user feedback
// Implementation would include statistical analysis
}
private async adaptParameters(): Promise<void> {
// Adapt configuration parameters based on learning
// Implementation would include optimization algorithms
}
// Public API methods
async addCustomRule(rule: PrioritizationRule): Promise<void> {
this.customRules.set(rule.id, rule);
this.logger.info(`Custom rule added: ${rule.name}`);
}
async removeCustomRule(ruleId: string): Promise<void> {
this.customRules.delete(ruleId);
this.logger.info(`Custom rule removed: ${ruleId}`);
}
async updateConfig(config: Partial<PrioritizationConfig>): Promise<void> {
this.config = { ...this.config, ...config };
this.logger.info('Prioritization configuration updated');
}
async getLearningStats(): Promise<any> {
return {
totalUserActions: this.learningData.userActions.length,
totalPatterns: this.learningData.patterns.length,
totalEffectiveness: this.learningData.effectiveness.length,
totalAdaptations: this.learningData.adaptations.length,
learningEnabled: this.config.learning.enabled
};
}
async shutdown(): Promise<void> {
this.logger.info('Shutting down Intelligent Prioritization Engine');
// Save learning data
await this.saveLearningData();
// Clear event listeners
this.removeAllListeners();
this.logger.info('Intelligent Prioritization Engine shutdown complete');
}
}