Spaces:
Paused
Paused
| // PatternEvolutionEngine – Phase 2 Week 7-8 | |
| // Creative strategy evolution with mutation and A/B testing | |
| import { projectMemory } from '../../services/project/ProjectMemory.js'; | |
| import { getDatabase } from '../../database/index.js'; | |
| interface Strategy { | |
| id: string; | |
| name: string; | |
| approach: string; | |
| timeout: number; | |
| retryCount: number; | |
| fitnessScore: number; | |
| createdAt: Date; | |
| adoptedAt?: Date; | |
| } | |
| interface MutationConfig { | |
| mutationRate: number; | |
| creativityFactor: number; | |
| } | |
| interface TestResult { | |
| strategy: Strategy; | |
| fitnessScore: number; | |
| testDuration: number; | |
| metrics: { | |
| successRate: number; | |
| avgLatency: number; | |
| userSatisfaction: number; | |
| }; | |
| } | |
| export class PatternEvolutionEngine { | |
| private strategies: Map<string, Strategy> = new Map(); | |
| private currentBestStrategy: Strategy | null = null; | |
| constructor() { | |
| this.loadStrategies(); | |
| } | |
| /** | |
| * Main evolution loop | |
| */ | |
| public async evolveStrategies(): Promise<void> { | |
| console.log('🧬 [Evolution] Starting strategy evolution...'); | |
| // 1. Get current best strategy | |
| const currentStrategy = await this.getBestStrategy(); | |
| if (!currentStrategy) { | |
| // Initialize with default strategy | |
| const defaultStrategy = this.createDefaultStrategy(); | |
| await this.saveStrategy(defaultStrategy); | |
| this.currentBestStrategy = defaultStrategy; | |
| console.log('✅ [Evolution] Initialized with default strategy'); | |
| return; | |
| } | |
| // 2. Generate mutations | |
| const mutations = this.generateMutations(currentStrategy, { | |
| mutationRate: 0.15, | |
| creativityFactor: 0.4 | |
| }); | |
| console.log(`🧬 [Evolution] Generated ${mutations.length} mutations`); | |
| // 3. A/B test mutations | |
| const testResults = await this.abTest(mutations); | |
| // 4. Select winners (must be >10% improvement) | |
| const winners = testResults.filter(r => | |
| r.fitnessScore > currentStrategy.fitnessScore * 1.1 | |
| ); | |
| // 5. Adopt best winner if improvement found | |
| if (winners.length > 0) { | |
| const best = winners.sort((a, b) => b.fitnessScore - a.fitnessScore)[0]; | |
| await this.adoptStrategy(best.strategy); | |
| // Log to ProjectMemory | |
| await this.logEvolution({ | |
| oldStrategy: currentStrategy, | |
| newStrategy: best.strategy, | |
| improvement: best.fitnessScore / currentStrategy.fitnessScore, | |
| testResults: testResults.length | |
| }); | |
| console.log(`✅ [Evolution] Adopted new strategy: ${best.strategy.name} (${((best.fitnessScore / currentStrategy.fitnessScore - 1) * 100).toFixed(1)}% improvement)`); | |
| } else { | |
| console.log('ℹ️ [Evolution] No improvement found, keeping current strategy'); | |
| } | |
| } | |
| /** | |
| * Get current best strategy | |
| */ | |
| private async getBestStrategy(): Promise<Strategy | null> { | |
| if (this.currentBestStrategy) { | |
| return this.currentBestStrategy; | |
| } | |
| // Load from database or memory | |
| const strategies = Array.from(this.strategies.values()); | |
| if (strategies.length === 0) { | |
| return null; | |
| } | |
| const best = strategies.sort((a, b) => b.fitnessScore - a.fitnessScore)[0]; | |
| this.currentBestStrategy = best; | |
| return best; | |
| } | |
| /** | |
| * Generate strategy mutations | |
| */ | |
| private generateMutations(strategy: Strategy, config: MutationConfig): Strategy[] { | |
| const mutations: Strategy[] = []; | |
| for (let i = 0; i < 10; i++) { | |
| const mutated: Strategy = { | |
| ...strategy, | |
| id: `${strategy.id}-mut-${i}-${Date.now()}`, | |
| name: `${strategy.name} Mutation ${i + 1}`, | |
| fitnessScore: strategy.fitnessScore, // Will be updated after testing | |
| createdAt: new Date() | |
| }; | |
| // Mutate timeout | |
| if (Math.random() < config.mutationRate) { | |
| mutated.timeout = Math.max(100, strategy.timeout * (1 + (Math.random() - 0.5) * 0.3)); | |
| } | |
| // Mutate retry count | |
| if (Math.random() < config.mutationRate) { | |
| mutated.retryCount = Math.max(0, strategy.retryCount + Math.floor((Math.random() - 0.5) * 2)); | |
| } | |
| // Creative mutations (approach changes) | |
| if (Math.random() < config.creativityFactor) { | |
| mutated.approach = this.generateCreativeApproach(strategy.approach); | |
| } | |
| mutations.push(mutated); | |
| } | |
| return mutations; | |
| } | |
| /** | |
| * Generate creative approach variations | |
| */ | |
| private generateCreativeApproach(currentApproach: string): string { | |
| const variations = [ | |
| 'aggressive', 'conservative', 'balanced', 'adaptive', 'predictive' | |
| ]; | |
| const randomVariation = variations[Math.floor(Math.random() * variations.length)]; | |
| return `${randomVariation}_${currentApproach}`; | |
| } | |
| /** | |
| * A/B test mutations | |
| */ | |
| private async abTest(mutations: Strategy[]): Promise<TestResult[]> { | |
| const results: TestResult[] = []; | |
| for (const mutation of mutations) { | |
| // Simulate testing (in real implementation, this would run actual tests) | |
| const testResult = await this.simulateTest(mutation); | |
| results.push(testResult); | |
| } | |
| return results; | |
| } | |
| /** | |
| * Simulate strategy test (placeholder - should run actual tests) | |
| */ | |
| private async simulateTest(strategy: Strategy): Promise<TestResult> { | |
| // Simulate fitness calculation based on strategy parameters | |
| const baseFitness = 0.5; | |
| // Timeout optimization: shorter is better (up to a point) | |
| const timeoutScore = Math.max(0, 1 - (strategy.timeout / 5000)); | |
| // Retry optimization: balanced retries are better | |
| const retryScore = strategy.retryCount <= 3 ? 1.0 : Math.max(0, 1 - (strategy.retryCount - 3) * 0.2); | |
| // Approach bonus (creative approaches get slight bonus) | |
| const approachBonus = strategy.approach.includes('adaptive') || strategy.approach.includes('predictive') ? 0.1 : 0; | |
| const fitnessScore = baseFitness + timeoutScore * 0.3 + retryScore * 0.2 + approachBonus; | |
| return { | |
| strategy, | |
| fitnessScore: Math.min(1.0, fitnessScore), | |
| testDuration: 1000 + Math.random() * 2000, | |
| metrics: { | |
| successRate: 0.7 + Math.random() * 0.25, | |
| avgLatency: strategy.timeout * (0.8 + Math.random() * 0.4), | |
| userSatisfaction: fitnessScore | |
| } | |
| }; | |
| } | |
| /** | |
| * Adopt new strategy | |
| */ | |
| private async adoptStrategy(strategy: Strategy): Promise<void> { | |
| strategy.adoptedAt = new Date(); | |
| await this.saveStrategy(strategy); | |
| this.currentBestStrategy = strategy; | |
| this.strategies.set(strategy.id, strategy); | |
| } | |
| /** | |
| * Create default strategy | |
| */ | |
| private createDefaultStrategy(): Strategy { | |
| return { | |
| id: 'default-strategy', | |
| name: 'Default Strategy', | |
| approach: 'balanced', | |
| timeout: 3000, | |
| retryCount: 2, | |
| fitnessScore: 0.5, | |
| createdAt: new Date() | |
| }; | |
| } | |
| /** | |
| * Save strategy (placeholder - should persist to database) | |
| */ | |
| private async saveStrategy(strategy: Strategy): Promise<void> { | |
| this.strategies.set(strategy.id, strategy); | |
| // TODO: Persist to database | |
| } | |
| /** | |
| * Load strategies (placeholder) | |
| */ | |
| private loadStrategies(): void { | |
| // TODO: Load from database | |
| } | |
| /** | |
| * Log evolution to ProjectMemory | |
| */ | |
| private async logEvolution(evolution: { | |
| oldStrategy: Strategy; | |
| newStrategy: Strategy; | |
| improvement: number; | |
| testResults: number; | |
| }): Promise<void> { | |
| projectMemory.logLifecycleEvent({ | |
| eventType: 'feature', | |
| status: 'success', | |
| details: { | |
| component: 'PatternEvolutionEngine', | |
| action: 'strategy_evolution', | |
| oldStrategy: evolution.oldStrategy.name, | |
| newStrategy: evolution.newStrategy.name, | |
| improvement: `${((evolution.improvement - 1) * 100).toFixed(1)}%`, | |
| testResults: evolution.testResults, | |
| timestamp: new Date().toISOString() | |
| } | |
| }); | |
| } | |
| /** | |
| * Get current strategy | |
| */ | |
| public getCurrentStrategy(): Strategy | null { | |
| return this.currentBestStrategy; | |
| } | |
| /** | |
| * Get evolution history | |
| */ | |
| public getEvolutionHistory(): Strategy[] { | |
| return Array.from(this.strategies.values()) | |
| .filter(s => s.adoptedAt) | |
| .sort((a, b) => (b.adoptedAt?.getTime() || 0) - (a.adoptedAt?.getTime() || 0)); | |
| } | |
| } | |
| export const patternEvolutionEngine = new PatternEvolutionEngine(); | |