// Evolution Strategy Presets (v1.1) // Controls the balance between repair, optimize, and innovate intents. // // Usage: set EVOLVE_STRATEGY env var to one of: balanced, innovate, harden, repair-only, // early-stabilize, steady-state, or "auto" for adaptive selection. // Default: balanced (or auto-detected based on cycle count / saturation signals) // // Each strategy defines: // repair/optimize/innovate - target allocation ratios (inform the LLM prompt) // repairLoopThreshold - repair ratio in last 8 cycles that triggers forced innovation // label - human-readable name injected into the GEP prompt var fs = require('fs'); var path = require('path'); var STRATEGIES = { 'balanced': { repair: 0.20, optimize: 0.30, innovate: 0.50, repairLoopThreshold: 0.50, label: 'Balanced', description: 'Normal operation. Steady growth with stability.', }, 'innovate': { repair: 0.05, optimize: 0.15, innovate: 0.80, repairLoopThreshold: 0.30, label: 'Innovation Focus', description: 'System is stable. Maximize new features and capabilities.', }, 'harden': { repair: 0.40, optimize: 0.40, innovate: 0.20, repairLoopThreshold: 0.70, label: 'Hardening', description: 'After a big change. Focus on stability and robustness.', }, 'repair-only': { repair: 0.80, optimize: 0.20, innovate: 0.00, repairLoopThreshold: 1.00, label: 'Repair Only', description: 'Emergency. Fix everything before doing anything else.', }, 'early-stabilize': { repair: 0.60, optimize: 0.25, innovate: 0.15, repairLoopThreshold: 0.80, label: 'Early Stabilization', description: 'First cycles. Prioritize fixing existing issues before innovating.', }, 'steady-state': { repair: 0.60, optimize: 0.30, innovate: 0.10, repairLoopThreshold: 0.90, label: 'Steady State', description: 'Evolution saturated. Maintain existing capabilities. Minimal innovation.', }, }; // Read evolution_state.json to get the current cycle count for auto-detection. function _readCycleCount() { try { // evolver/memory/evolution_state.json (local to the skill) var localPath = path.resolve(__dirname, '..', '..', 'memory', 'evolution_state.json'); // workspace/memory/evolution/evolution_state.json (canonical path used by evolve.js) var workspacePath = path.resolve(__dirname, '..', '..', '..', '..', 'memory', 'evolution', 'evolution_state.json'); var candidates = [localPath, workspacePath]; for (var i = 0; i < candidates.length; i++) { if (fs.existsSync(candidates[i])) { var data = JSON.parse(fs.readFileSync(candidates[i], 'utf8')); return data && Number.isFinite(data.cycleCount) ? data.cycleCount : 0; } } } catch (e) {} return 0; } function resolveStrategy(opts) { var signals = (opts && Array.isArray(opts.signals)) ? opts.signals : []; var name = String(process.env.EVOLVE_STRATEGY || 'balanced').toLowerCase().trim(); // Backward compatibility: FORCE_INNOVATION=true maps to 'innovate' if (!process.env.EVOLVE_STRATEGY) { var fi = String(process.env.FORCE_INNOVATION || process.env.EVOLVE_FORCE_INNOVATION || '').toLowerCase(); if (fi === 'true') name = 'innovate'; } // Auto-detection: when no explicit strategy is set (defaults to 'balanced'), // apply heuristics inspired by Echo-MingXuan's "fix first, innovate later" pattern. var isDefault = !process.env.EVOLVE_STRATEGY || name === 'balanced' || name === 'auto'; if (isDefault) { // Early-stabilize: first 5 cycles should focus on fixing existing issues. var cycleCount = _readCycleCount(); if (cycleCount > 0 && cycleCount <= 5) { name = 'early-stabilize'; } // Saturation detection: if saturation signals are present, switch to steady-state. if (signals.indexOf('force_steady_state') !== -1) { name = 'steady-state'; } else if (signals.indexOf('evolution_saturation') !== -1) { name = 'steady-state'; } } // Explicit "auto" maps to whatever was auto-detected above (or balanced if no heuristic fired). if (name === 'auto') name = 'balanced'; var strategy = STRATEGIES[name] || STRATEGIES['balanced']; strategy.name = name; return strategy; } function getStrategyNames() { return Object.keys(STRATEGIES); } module.exports = { resolveStrategy, getStrategyNames, STRATEGIES };