widgetdc-cortex / apps /backend /src /mcp /cognitive /PatternEvolutionEngine.ts
Kraft102's picture
Initial deployment - WidgeTDC Cortex Backend v2.1.0
529090e
// 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();