closed-loop-cli 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of closed-loop-cli might be problematic. Click here for more details.

@@ -1,973 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.AutogenesisEngine = void 0;
40
- const fs = __importStar(require("fs"));
41
- const path = __importStar(require("path"));
42
- const child_process_1 = require("child_process");
43
- const shell_tools_1 = require("../tools/shell-tools");
44
- const meta_agent_1 = require("./meta-agent");
45
- const tui_tools_1 = require("../tools/tui-tools");
46
- const repo_map_1 = require("../tools/repo-map");
47
- const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
48
- const dotenv = __importStar(require("dotenv"));
49
- const task_agent_1 = require("./task-agent");
50
- const state_manager_1 = require("./state-manager");
51
- const research_manager_1 = require("./research-manager");
52
- const dgm_archive_1 = require("./dgm-archive");
53
- const fitness_evaluator_1 = require("./fitness-evaluator");
54
- const mutation_strategies_1 = require("./mutation-strategies");
55
- dotenv.config();
56
- const apiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN || '';
57
- const baseURL = process.env.ANTHROPIC_BASE_URL || undefined;
58
- const defaultModel = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]';
59
- // SEPL (Self-Evolution Protocol Layer) Engine
60
- class AutogenesisEngine {
61
- substrate;
62
- effort = 'standard';
63
- codeactMode = false;
64
- constructor() {
65
- this.substrate = {
66
- prompts: new Map(),
67
- tools: new Map(),
68
- agents: new Map(),
69
- workspaceVersion: '1.0.0'
70
- };
71
- const envEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL || 'standard';
72
- this.effort = (envEffort === 'max' || envEffort === 'ultracode') ? 'ultracode' : 'standard';
73
- this.initializeSubstrates();
74
- }
75
- setEffort(effort) {
76
- this.effort = effort;
77
- console.log(`\x1b[36m[AutogenesisEngine]\x1b[0m Effort level set to: \x1b[32m${this.effort.toUpperCase()}\x1b[0m`);
78
- }
79
- initializeSubstrates() {
80
- // Register baseline substrates
81
- this.substrate.prompts.set('system', {
82
- id: 'system',
83
- template: 'Standard coding agent prompt...',
84
- version: '1.0.0'
85
- });
86
- this.substrate.tools.set('readFile', { name: 'readFile', description: 'Reads files', version: '1.0.0' });
87
- this.substrate.tools.set('writeFile', { name: 'writeFile', description: 'Writes files', version: '1.0.0' });
88
- this.substrate.tools.set('editFile', { name: 'editFile', description: 'Edits files', version: '1.0.0' });
89
- this.substrate.tools.set('runCommand', { name: 'runCommand', description: 'Runs terminal commands', version: '1.0.0' });
90
- }
91
- /**
92
- * SEPL Phase 1: Reflect (R)
93
- * Analyzes current workspace compile status and tests logs to identify improvement areas.
94
- */
95
- async reflect() {
96
- const spinner = new tui_tools_1.Spinner('AGP - Reflect: Checking codebase compile & test status...');
97
- spinner.start();
98
- // Check if git is initialized and clean
99
- const status = await (0, shell_tools_1.runCommand)('git status --porcelain');
100
- // Run tests as a diagnostic baseline
101
- const testResult = await (0, shell_tools_1.runCommand)('npm test');
102
- if (testResult.exitCode !== 0) {
103
- spinner.stop(false, 'AGP - Reflect: Diagnostic checks failed. Core compilation or tests are currently FAILING.');
104
- return `Reflect Analysis: Core compilation or test suite is currently FAILING.\nLogs:\n${testResult.stderr || testResult.stdout}`;
105
- }
106
- spinner.stop(true, 'AGP - Reflect: Codebase compiles and tests pass. Workspace is stable.');
107
- return 'Reflect Analysis: Core compilation and test suite are passing. Workspace is stable.';
108
- }
109
- /**
110
- * SEPL Phase 2: Select (S)
111
- * Formulates a proposal of what should be optimized (prompts, tools, or code).
112
- */
113
- select(analysis, targetTask) {
114
- console.log('\x1b[32m✔\x1b[0m AGP - Select: Evolutionary path formulated.');
115
- return `Proposal: Mutate the codebase to implement the target task: "${targetTask}". Analysis confirms workspace status: ${analysis.substring(0, 100)}...`;
116
- }
117
- /**
118
- * SEPL Phase 3: Improve (I)
119
- * Executes the modification proposal by running the Meta-Agent.
120
- */
121
- async improve(proposal, targetTask) {
122
- console.log('\x1b[36m[AGP - Improve]\x1b[0m Triggering Self-Modification Loop...');
123
- // Delegate actual code mutation to the Meta-Agent
124
- return await (0, meta_agent_1.runSelfImprovingTask)(targetTask, this.effort, this.codeactMode);
125
- }
126
- /**
127
- * SEPL Phase 4: Evaluate (E)
128
- * Evaluates the mutated candidate codebase against compilation, tests, and SAHOO.
129
- * Note: The Meta-Agent's internally integrated SAHOO Gateway handles file-specific checks,
130
- * while AGP evaluates overall workspace stability here.
131
- */
132
- async evaluate() {
133
- const result = await this.verifyBuildAndTest();
134
- return {
135
- success: result.success,
136
- message: result.success
137
- ? 'Evaluate Passed: Codebase compiles and passes all unit tests.'
138
- : `Evaluate Failed: ${result.message}`
139
- };
140
- }
141
- /**
142
- * SEPL Phase 5: Commit (C)
143
- * Commits the mutation to Git or executes rollback if evaluation fails.
144
- */
145
- async commit(evaluationSuccess, rollbackMessage, targetTask) {
146
- if (evaluationSuccess) {
147
- const spinner = new tui_tools_1.Spinner('AGP - Commit: Evolution successful. Committing snapshot...');
148
- spinner.start();
149
- // Extract and save reusable skill playbook
150
- if (targetTask) {
151
- try {
152
- const diffRes = await this.gitGetDiff();
153
- if (diffRes.exitCode === 0 && diffRes.stdout.trim()) {
154
- spinner.stop(true, 'AGP - Commit: Code healthy. Extracting reusable skill from changes...');
155
- const { extractAndSaveSkill } = require('../tools/skills');
156
- await extractAndSaveSkill(targetTask, diffRes.stdout);
157
- }
158
- }
159
- catch (e) {
160
- console.error('[Skill Registry] Failed to register skill:', e);
161
- }
162
- }
163
- spinner.stop(true);
164
- const commitRes = await this.commitAll();
165
- if (commitRes.exitCode === 0 && targetTask) {
166
- const revRes = await (0, shell_tools_1.runCommand)('git rev-parse HEAD');
167
- if (revRes.exitCode === 0) {
168
- const hash = revRes.stdout.trim();
169
- const currentRefactorResult = (0, state_manager_1.getEvolutionState)().lastRefactorResult;
170
- const { appendArchive } = require('./state-manager');
171
- appendArchive({
172
- commitHash: hash,
173
- task: targetTask,
174
- cycle: (0, state_manager_1.getEvolutionState)().currentCycle,
175
- metrics: currentRefactorResult?.metrics
176
- });
177
- }
178
- }
179
- }
180
- else {
181
- const spinner = new tui_tools_1.Spinner('AGP - Rollback: Verification failed. Reverting mutations...');
182
- spinner.start();
183
- await this.gitResetClean();
184
- spinner.stop(false, `AGP - Rollback: Codebase reverted to prior HEAD checkpoint.`);
185
- console.log(`\x1b[33mFailure Reason: ${rollbackMessage}\x1b[0m`);
186
- }
187
- }
188
- /**
189
- * Helper to calculate prompt utility score: higher is better.
190
- */
191
- calculatePromptScore(timeSeconds, totalTokens) {
192
- const timeWeight = 0.4;
193
- const tokenWeight = 0.6;
194
- if (totalTokens === 0 || timeSeconds === 0)
195
- return 0;
196
- return 100000 / (timeSeconds * timeWeight + totalTokens * tokenWeight);
197
- }
198
- /**
199
- * Atomic workspace rollback. Resets HEAD and cleans untracked files.
200
- */
201
- async gitResetClean() {
202
- await (0, shell_tools_1.runCommand)('git reset --hard HEAD');
203
- await (0, shell_tools_1.runCommand)('git clean -fd');
204
- }
205
- /**
206
- * Runs npm run build and npm test with a managed spinner.
207
- * Returns success status and a descriptive message.
208
- */
209
- async verifyBuildAndTest() {
210
- const spinner = new tui_tools_1.Spinner('Verifying: Running build & test suites...');
211
- spinner.start();
212
- const compile = await (0, shell_tools_1.runCommand)('npm run build');
213
- if (compile.exitCode !== 0) {
214
- spinner.stop(false, 'Verification failed (Compilation error).');
215
- return { success: false, message: `Compilation error:\n${compile.stdout}\n${compile.stderr}` };
216
- }
217
- const test = await (0, shell_tools_1.runCommand)('npm test');
218
- if (test.exitCode !== 0) {
219
- spinner.stop(false, 'Verification failed (Tests failed).');
220
- return { success: false, message: `Test suite failed:\n${test.stdout}\n${test.stderr}` };
221
- }
222
- spinner.stop(true, 'Verification passed: Build & tests succeeded.');
223
- return { success: true, message: 'Build & tests succeeded.' };
224
- }
225
- /**
226
- * Stages all changes and commits with the standard auto-evolution message.
227
- */
228
- async commitAll() {
229
- const spinner = new tui_tools_1.Spinner('Committing: Staging all changes and committing...');
230
- spinner.start();
231
- const addRes = await (0, shell_tools_1.runCommand)('git add -A');
232
- if (addRes.exitCode !== 0) {
233
- spinner.stop(false, 'Commit failed: git add -A failed.');
234
- return addRes;
235
- }
236
- const commitRes = await (0, shell_tools_1.runCommand)('git commit -m "Auto-evolution step: code modification successfully passed SAHOO & AGP gates."');
237
- if (commitRes.exitCode !== 0) {
238
- spinner.stop(false, 'Commit failed: git commit failed.');
239
- }
240
- else {
241
- spinner.stop(true, 'Evolution transaction committed successfully.');
242
- }
243
- return commitRes;
244
- }
245
- /**
246
- * Thin wrapper around git diff for readability.
247
- */
248
- async gitGetDiff() {
249
- return await (0, shell_tools_1.runCommand)('git diff');
250
- }
251
- /**
252
- * Thin wrapper for targeted git add <path>.
253
- */
254
- async gitAdd(target) {
255
- return await (0, shell_tools_1.runCommand)(`git add ${target}`);
256
- }
257
- /**
258
- * Thin wrapper for git commit with a custom message.
259
- */
260
- async gitCommit(message) {
261
- return await (0, shell_tools_1.runCommand)(`git commit -m "${message}"`);
262
- }
263
- /**
264
- * Benchmarks a system prompt on a standard task.
265
- * Returns token usage, execution time, and compilation success.
266
- */
267
- async benchmarkPrompt(systemPrompt) {
268
- const benchmarkTask = "Create a typescript helper file src/tools/math-helper.ts that exports a sum(a: number, b: number) function. Ensure it compiles. Do not change any other files.";
269
- // Clear any previous math-helper.ts file
270
- const helperPath = path.join(process.cwd(), 'src/tools/math-helper.ts');
271
- if (fs.existsSync(helperPath)) {
272
- fs.unlinkSync(helperPath);
273
- }
274
- // Reset workspace to clean baseline
275
- await this.gitResetClean();
276
- const startTime = Date.now();
277
- let success = false;
278
- let inputTokens = 0;
279
- let outputTokens = 0;
280
- let timeSeconds = 0;
281
- try {
282
- // Delegate to Task Agent directly with the specified system prompt override
283
- const report = await (0, task_agent_1.runTaskAgent)(benchmarkTask, { systemPrompt });
284
- timeSeconds = report.timeSeconds;
285
- inputTokens = report.inputTokens;
286
- outputTokens = report.outputTokens;
287
- // Verify compile
288
- const verification = await this.verifyBuildAndTest();
289
- if (verification.success) {
290
- success = true;
291
- }
292
- }
293
- catch (err) {
294
- // Failed to execute task or compile
295
- }
296
- finally {
297
- // Clean up changes
298
- if (fs.existsSync(helperPath)) {
299
- fs.unlinkSync(helperPath);
300
- }
301
- await this.gitResetClean();
302
- }
303
- if (!timeSeconds) {
304
- timeSeconds = (Date.now() - startTime) / 1000;
305
- }
306
- const totalTokens = inputTokens + outputTokens;
307
- const score = success ? this.calculatePromptScore(timeSeconds, totalTokens) : 0;
308
- return { success, time: timeSeconds, tokens: totalTokens, score };
309
- }
310
- /**
311
- * Runs the prompt optimization and benchmarking pipeline.
312
- */
313
- async runPromptOptimization() {
314
- const workspaceRoot = process.cwd();
315
- const promptPath = path.join(workspaceRoot, 'src/orchestrator/system-prompt.txt');
316
- let baselinePrompt = '';
317
- if (fs.existsSync(promptPath)) {
318
- baselinePrompt = fs.readFileSync(promptPath, 'utf-8');
319
- }
320
- else {
321
- baselinePrompt = `You are an elite coding agent designed to operate inside a codebase workspace.
322
- Your primary objective is to fulfill the user's coding tasks accurately and cleanly.
323
-
324
- You have access to a set of local tools to read, write, edit files and execute terminal commands.
325
- Always prefer editing precise parts of files using editFile instead of overwriting the whole file with writeFile unless it is a new file.
326
- When running commands, verify compilation and test outcomes. If a test fails, you must attempt to fix the issues (Self-Healing).
327
-
328
- Be concise and professional. Formulate plans before making changes.`;
329
- }
330
- console.log(`\n\x1b[35m=== STEP 1: BENCHMARKING BASELINE SYSTEM PROMPT ===\x1b[0m`);
331
- const baselineReport = await this.benchmarkPrompt(baselinePrompt);
332
- console.log(`Baseline Prompt Benchmark Result:`);
333
- console.log(`- Success: ${baselineReport.success ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m'}`);
334
- console.log(`- Time: ${baselineReport.time.toFixed(1)}s`);
335
- console.log(`- Tokens: ${baselineReport.tokens}`);
336
- console.log(`- Score: ${baselineReport.score.toFixed(2)}`);
337
- console.log(`\n\x1b[35m=== STEP 2: GENERATING OPTIMIZED CANDIDATE SYSTEM PROMPT ===\x1b[0m`);
338
- const optimizerSpinner = new tui_tools_1.Spinner('AGP - Optimizer: Refinement model generating optimized system prompt...');
339
- optimizerSpinner.start();
340
- const anthropic = new sdk_1.default({
341
- apiKey: apiKey,
342
- baseURL: baseURL,
343
- });
344
- const optimizerPrompt = `You are an expert system prompt engineer. Your goal is to optimize the following system prompt for an autonomous coding agent.
345
- You need to make the prompt more concise, remove redundancy, and explicitly instruct the agent to reduce token waste and thinking overhead, while ensuring it retains all functionality (using file-tools, rulez, self-healing, compiling, running tests).
346
-
347
- Here is the Current System Prompt:
348
- """
349
- ${baselinePrompt}
350
- """
351
-
352
- Provide your output strictly as the new optimized system prompt. Do not write any markdown wrappers (like \`\`\` or \`\`\`txt), explanations, greetings, or conversational headers/footers. Output ONLY the raw optimized system prompt text.`;
353
- let candidatePrompt = '';
354
- try {
355
- const response = await anthropic.messages.create({
356
- model: defaultModel,
357
- max_tokens: 1500,
358
- messages: [{ role: 'user', content: optimizerPrompt }]
359
- });
360
- const block = response.content.find(b => b.type === 'text');
361
- if (!block || !block.text) {
362
- throw new Error('Failed to retrieve system prompt candidate from LLM.');
363
- }
364
- candidatePrompt = block.text.trim();
365
- optimizerSpinner.stop(true, 'AGP - Optimizer: Prompt candidate generated.');
366
- }
367
- catch (err) {
368
- optimizerSpinner.stop(false, 'AGP - Optimizer: Prompt candidate generation failed.');
369
- throw new Error(`Prompt Optimization Failed: ${err.message}`);
370
- }
371
- console.log('\n\x1b[33m┌── Candidate System Prompt ──────────────────────────────────────────────────────┐\x1b[0m');
372
- candidatePrompt.split('\n').forEach(line => console.log(`\x1b[33m│\x1b[0m ${line}`));
373
- console.log('\x1b[33m└─────────────────────────────────────────────────────────────────────────────────┘\x1b[0m\n');
374
- console.log(`\x1b[35m=== STEP 3: BENCHMARKING CANDIDATE SYSTEM PROMPT ===\x1b[0m`);
375
- const candidateReport = await this.benchmarkPrompt(candidatePrompt);
376
- console.log(`Candidate Prompt Benchmark Result:`);
377
- console.log(`- Success: ${candidateReport.success ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m'}`);
378
- console.log(`- Time: ${candidateReport.time.toFixed(1)}s`);
379
- console.log(`- Tokens: ${candidateReport.tokens}`);
380
- console.log(`- Score: ${candidateReport.score.toFixed(2)}`);
381
- console.log(`\n\x1b[35m=== STEP 4: COMPARING PERFORMANCE METRICS ===\x1b[0m`);
382
- console.log(`Baseline Score: \x1b[1m${baselineReport.score.toFixed(2)}\x1b[0m`);
383
- console.log(`Candidate Score: \x1b[1m${candidateReport.score.toFixed(2)}\x1b[0m`);
384
- if (candidateReport.success && candidateReport.score > baselineReport.score) {
385
- console.log(`\n\x1b[32;1m[Optimization Approved] Candidate prompt is more efficient. Overwriting system-prompt.txt...\x1b[0m`);
386
- fs.writeFileSync(promptPath, candidatePrompt, 'utf-8');
387
- // Commit the changes to Git
388
- await this.gitAdd('src/orchestrator/system-prompt.txt');
389
- await this.gitCommit('chore: optimize Task Agent system prompt via automated benchmarking loop');
390
- console.log(`\x1b[32m[Git Status] System prompt snapshot committed to repository HEAD.\x1b[0m`);
391
- }
392
- else {
393
- console.log(`\n\x1b[31;1m[Optimization Rejected] Candidate prompt did not improve performance. Retaining baseline.\x1b[0m`);
394
- }
395
- (0, state_manager_1.updateEvolutionState)({
396
- lastPromptOptimization: {
397
- success: candidateReport.success,
398
- baselineScore: baselineReport.score,
399
- candidateScore: candidateReport.score,
400
- approved: candidateReport.success && candidateReport.score > baselineReport.score,
401
- time: new Date().toISOString()
402
- }
403
- });
404
- (0, state_manager_1.appendHistory)({
405
- cycle: (0, state_manager_1.getEvolutionState)().currentCycle,
406
- type: 'prompt_opt',
407
- description: `Optimized system prompt. Baseline: ${baselineReport.score.toFixed(2)}, Candidate: ${candidateReport.score.toFixed(2)}`,
408
- success: candidateReport.success && candidateReport.score > baselineReport.score
409
- });
410
- }
411
- /**
412
- * Generates a refactoring proposal by scanning the codebase repository map.
413
- */
414
- async getAutonomousRefactorProposal() {
415
- const workspaceRoot = process.cwd();
416
- const repoMap = (0, repo_map_1.generateRepoMap)(workspaceRoot);
417
- const scanSpinner = new tui_tools_1.Spinner('AGP - Scan: Auditing codebase structure for optimizations...');
418
- scanSpinner.start();
419
- // 1. Context Gathering: logs & learnings
420
- let evolutionLog = '';
421
- const logPath = path.join(workspaceRoot, 'evolution.log');
422
- if (fs.existsSync(logPath)) {
423
- try {
424
- const fullLog = fs.readFileSync(logPath, 'utf-8');
425
- const lines = fullLog.split('\n');
426
- evolutionLog = lines.slice(-40).join('\n'); // Ingest last 40 lines of log
427
- }
428
- catch (e) { }
429
- }
430
- let learningsMd = '';
431
- const learningsPath = path.join(workspaceRoot, 'Learnings.md');
432
- if (fs.existsSync(learningsPath)) {
433
- try {
434
- learningsMd = fs.readFileSync(learningsPath, 'utf-8');
435
- }
436
- catch (e) { }
437
- }
438
- const anthropic = new sdk_1.default({
439
- apiKey: apiKey,
440
- baseURL: baseURL,
441
- });
442
- try {
443
- // Step 1: Select 2 target candidate files based on Repo Map, Logs, and Learnings
444
- const candidatePrompt = `You are an expert software architect. Your goal is to select the top 2 files in this codebase that would benefit most from refactoring (improving type-safety, code duplication, helper functions cleanup, or performance).
445
- Review the codebase map, past evolution logs, and lessons learned.
446
-
447
- Codebase Repository Map:
448
- ${repoMap}
449
-
450
- Last 40 lines of evolution logs (shows recent runs/warnings/failures):
451
- ${evolutionLog || 'No log history available.'}
452
-
453
- Learnings Registry (shows past insights):
454
- ${learningsMd || 'No past learnings recorded.'}
455
-
456
- Output your response strictly as a JSON object containing a list of 2 candidate target files (relative paths). Do not include any other text, markdown blocks, or formatting, just the raw JSON.
457
-
458
- Format:
459
- {
460
- "candidates": [
461
- { "targetFile": "relative/path/to/file1.ts" },
462
- { "targetFile": "relative/path/to/file2.ts" }
463
- ]
464
- }`;
465
- const candidateResponse = await anthropic.messages.create({
466
- model: defaultModel,
467
- max_tokens: 4000,
468
- messages: [{ role: 'user', content: candidatePrompt }]
469
- });
470
- const candBlock = candidateResponse.content.find(b => b.type === 'text');
471
- if (!candBlock || !candBlock.text) {
472
- console.error('DEBUG - candidateResponse content:', JSON.stringify(candidateResponse.content));
473
- throw new Error('Failed to retrieve candidates from LLM.');
474
- }
475
- const candText = candBlock.text.trim().replace(/^```json/, '').replace(/```$/, '').trim();
476
- const candJson = JSON.parse(candText);
477
- const candidates = candJson.candidates || [];
478
- if (candidates.length === 0) {
479
- throw new Error('No candidates identified by the LLM.');
480
- }
481
- // Step 2: Read candidate file contents
482
- let fileContext = '';
483
- for (const cand of candidates) {
484
- const fullPath = path.join(workspaceRoot, cand.targetFile);
485
- if (fs.existsSync(fullPath)) {
486
- try {
487
- const fileContent = fs.readFileSync(fullPath, 'utf-8');
488
- fileContext += `\n--- FILE: ${cand.targetFile} ---\n${fileContent}\n`;
489
- }
490
- catch (e) {
491
- fileContext += `\n--- FILE: ${cand.targetFile} (Could not read file contents) ---\n`;
492
- }
493
- }
494
- else {
495
- fileContext += `\n--- FILE: ${cand.targetFile} (File not found on disk) ---\n`;
496
- }
497
- }
498
- // Step 3: Evaluate and Select Winner based on actual code inspection
499
- const evaluationPrompt = `You are an expert software architect. Analyze the actual code content of the candidate files below and select the single best refactoring proposal.
500
- Evaluate each file and design a specific refactor goal.
501
- Score each proposal out of 10 based on:
502
- 1. Impact (readability, duplication reduction, safety, performance).
503
- 2. Feasibility (compilation safety, low risk of breaking tests).
504
-
505
- Candidate File Contents:
506
- ${fileContext}
507
-
508
- Output your response strictly as a JSON object containing the winning proposal's target file and the specific refactoring goal. Do not include any other text, markdown blocks, or formatting, just the raw JSON.
509
-
510
- Format:
511
- {
512
- "winningProposal": {
513
- "targetFile": "relative/path/to/file.ts",
514
- "refactorGoal": "A concise, specific description of the refactoring goal (e.g., 'Refactor search-tools to use strong interfaces instead of any[]')",
515
- "impactScore": 8.5,
516
- "feasibilityScore": 9.0
517
- }
518
- }`;
519
- const evaluationResponse = await anthropic.messages.create({
520
- model: defaultModel,
521
- max_tokens: 4000,
522
- messages: [{ role: 'user', content: evaluationPrompt }]
523
- });
524
- const evalBlock = evaluationResponse.content.find(b => b.type === 'text');
525
- if (!evalBlock || !evalBlock.text) {
526
- throw new Error('Failed to retrieve evaluation from LLM.');
527
- }
528
- const evalText = evalBlock.text.trim().replace(/^```json/, '').replace(/```$/, '').trim();
529
- const evalJson = JSON.parse(evalText);
530
- const winningProposal = evalJson.winningProposal;
531
- if (!winningProposal || !winningProposal.targetFile || !winningProposal.refactorGoal) {
532
- throw new Error('Invalid JSON structure returned for winning proposal.');
533
- }
534
- console.log(`\n\x1b[32m✔\x1b[0m AGP - Scan: Selected best proposal: ${winningProposal.targetFile} (Impact: ${winningProposal.impactScore || 'N/A'}, Feasibility: ${winningProposal.feasibilityScore || 'N/A'})`);
535
- scanSpinner.stop(true, 'AGP - Scan: Codebase audit complete.');
536
- return {
537
- targetFile: winningProposal.targetFile,
538
- refactorGoal: winningProposal.refactorGoal
539
- };
540
- }
541
- catch (err) {
542
- scanSpinner.stop(false, 'AGP - Scan: Codebase audit failed.');
543
- throw new Error(`Refactoring Analysis Failed: ${err.message}`);
544
- }
545
- }
546
- /**
547
- * Scans codebase for refactoring opportunities and triggers an autonomous evolution run.
548
- */
549
- async runAutonomousRefactor() {
550
- const proposal = await this.getAutonomousRefactorProposal();
551
- console.log('\n\x1b[35m┌── Autonomous Refactoring Proposal ──────────────────────────────────────────────┐\x1b[0m');
552
- console.log(`\x1b[35m│\x1b[0m Target File: \x1b[1m\x1b[32m${proposal.targetFile}\x1b[0m`);
553
- console.log(`\x1b[35m│\x1b[0m Refactor Goal: \x1b[33m${proposal.refactorGoal}\x1b[0m`);
554
- console.log('\x1b[35m└─────────────────────────────────────────────────────────────────────────────────┘\x1b[0m\n');
555
- (0, state_manager_1.updateEvolutionState)({
556
- lastRefactorProposal: {
557
- targetFile: proposal.targetFile,
558
- refactorGoal: proposal.refactorGoal,
559
- time: new Date().toISOString()
560
- }
561
- });
562
- const taskText = `Refactor the file "${proposal.targetFile}" to achieve the following goal: ${proposal.refactorGoal}. Do not modify any other file unless required for compilation. Compile and verify tests pass.`;
563
- // Delegate to evolution loop
564
- await this.runEvolutionStep(taskText);
565
- }
566
- /**
567
- * High-Level Autogenesis Evolution Run
568
- */
569
- async runEvolutionStep(targetTask) {
570
- console.log('\x1b[35m=== STARTING AUTOGENESIS PROTOCOL EVOLUTION STEP ===\x1b[0m');
571
- // Start active research session
572
- research_manager_1.ResearchManager.startSession(targetTask, this.effort);
573
- (0, state_manager_1.updateEvolutionState)({
574
- status: 'reflecting',
575
- currentTask: `Executing task: "${targetTask}"`
576
- });
577
- // 1. Reflect
578
- const analysis = await this.reflect();
579
- (0, state_manager_1.updateEvolutionState)({
580
- status: 'scanning',
581
- currentTask: 'Selecting mutation plan'
582
- });
583
- // 2. Select
584
- const proposal = this.select(analysis, targetTask);
585
- (0, state_manager_1.updateEvolutionState)({
586
- status: 'refactoring',
587
- currentTask: `Mutating codebase for task: "${targetTask}"`
588
- });
589
- // 3. Improve & 4. Evaluate (The Meta-Agent execution is self-safeguarded by SAHOO)
590
- let executionSuccess = false;
591
- let failReason = '';
592
- try {
593
- await this.improve(proposal, targetTask);
594
- (0, state_manager_1.updateEvolutionState)({
595
- status: 'evaluating',
596
- currentTask: 'Running verification test suite'
597
- });
598
- // Double check overall workspace via AGP evaluate
599
- const evalResult = await this.evaluate();
600
- if (evalResult.success) {
601
- executionSuccess = true;
602
- }
603
- else {
604
- failReason = evalResult.message;
605
- }
606
- }
607
- catch (err) {
608
- failReason = err.message;
609
- }
610
- // 5. Commit or Rollback
611
- (0, state_manager_1.updateEvolutionState)({
612
- status: executionSuccess ? 'committing' : 'rolling_back',
613
- currentTask: executionSuccess ? 'Committing changes to Git' : 'Rolling back workspace modifications'
614
- });
615
- await this.commit(executionSuccess, failReason, targetTask);
616
- // End active research session
617
- research_manager_1.ResearchManager.endSession(executionSuccess ? 'success' : 'failed');
618
- const targetFile = targetTask.includes('Refactor the file "')
619
- ? targetTask.split('"')[1]
620
- : (targetTask.includes('file "') ? targetTask.split('"')[1] : 'Workspace');
621
- const currentRefactorResult = (0, state_manager_1.getEvolutionState)().lastRefactorResult;
622
- (0, state_manager_1.updateEvolutionState)({
623
- status: 'idle',
624
- currentTask: null,
625
- lastRefactorResult: {
626
- success: executionSuccess,
627
- targetFile: targetFile,
628
- message: executionSuccess ? 'Evolution succeeded.' : `Evolution failed: ${failReason}`,
629
- time: new Date().toISOString(),
630
- reason: executionSuccess ? undefined : failReason,
631
- metrics: currentRefactorResult?.metrics
632
- }
633
- });
634
- (0, state_manager_1.appendHistory)({
635
- cycle: (0, state_manager_1.getEvolutionState)().currentCycle,
636
- type: 'refactor',
637
- description: targetTask.length > 80 ? targetTask.substring(0, 80) + '...' : targetTask,
638
- success: executionSuccess,
639
- details: executionSuccess ? undefined : failReason
640
- });
641
- console.log('\x1b[35m=== AUTOGENESIS STEP COMPLETED ===\x1b[0m\n');
642
- }
643
- runChildProcess(args) {
644
- return new Promise((resolve) => {
645
- const child = (0, child_process_1.spawn)('node', args, {
646
- stdio: 'inherit',
647
- env: { ...process.env, CLAUDE_CODE_EFFORT_LEVEL: this.effort }
648
- });
649
- child.on('close', (code) => {
650
- resolve(code ?? 1);
651
- });
652
- child.on('error', () => {
653
- resolve(1);
654
- });
655
- });
656
- }
657
- /**
658
- * Continuous Self-Evolution Daemon Loop
659
- */
660
- async runContinuousEvolution(maxCycles, tokenBudget) {
661
- const historyPath = path.join(process.cwd(), 'evolution-history.json');
662
- const tokenPath = path.join(process.cwd(), 'session-tokens.json');
663
- // Clear previous token file on start
664
- if (fs.existsSync(tokenPath)) {
665
- try {
666
- fs.unlinkSync(tokenPath);
667
- }
668
- catch (e) { }
669
- }
670
- (0, state_manager_1.updateEvolutionState)({
671
- status: 'idle',
672
- currentCycle: 0,
673
- maxCycles,
674
- tokenBudget,
675
- tokensUsed: { input: 0, output: 0, total: 0 }
676
- });
677
- let cycle = 0;
678
- let consecutiveFailures = 0;
679
- while (true) {
680
- cycle++;
681
- if (maxCycles > 0 && cycle > maxCycles) {
682
- console.log(`\n\x1b[32m[Continuous Evolution] Completed maximum cycles (${maxCycles}). Stopping.\x1b[0m`);
683
- (0, state_manager_1.updateEvolutionState)({ status: 'idle', currentTask: null });
684
- break;
685
- }
686
- console.log(`\n\x1b[35m==================================================\x1b[0m`);
687
- console.log(`\x1b[35m STARTING CONTINUOUS EVOLUTION CYCLE ${cycle} \x1b[0m`);
688
- console.log(`\x1b[35m==================================================\x1b[0m\n`);
689
- (0, state_manager_1.updateEvolutionState)({
690
- status: 'reflecting',
691
- currentCycle: cycle,
692
- currentTask: 'Checking workspace baseline status'
693
- });
694
- // 1. Check token budget
695
- let totalInput = 0;
696
- let totalOutput = 0;
697
- if (fs.existsSync(tokenPath)) {
698
- try {
699
- const data = JSON.parse(fs.readFileSync(tokenPath, 'utf-8'));
700
- totalInput = data.inputTokens || 0;
701
- totalOutput = data.outputTokens || 0;
702
- }
703
- catch (e) { }
704
- }
705
- const totalTokens = totalInput + totalOutput;
706
- console.log(`Current Session Cumulative Token Usage: ${totalTokens} / ${tokenBudget}`);
707
- (0, state_manager_1.updateEvolutionState)({
708
- tokensUsed: {
709
- input: totalInput,
710
- output: totalOutput,
711
- total: totalTokens
712
- }
713
- });
714
- if (totalTokens > tokenBudget) {
715
- console.log(`\n\x1b[31;1m[Budget Exceeded] Token usage (${totalTokens}) has exceeded the budget cap (${tokenBudget}). Halting daemon.\x1b[0m`);
716
- (0, state_manager_1.updateEvolutionState)({ status: 'idle', currentTask: 'Token budget exceeded' });
717
- break;
718
- }
719
- (0, state_manager_1.updateEvolutionState)({
720
- status: 'scanning',
721
- currentTask: 'Generating next mutation proposal'
722
- });
723
- // 2. Fetch Refactor Proposal and check history to avoid ping-pong loops
724
- let proposal;
725
- try {
726
- proposal = await this.getAutonomousRefactorProposal();
727
- let historyList = [];
728
- if (fs.existsSync(historyPath)) {
729
- try {
730
- historyList = JSON.parse(fs.readFileSync(historyPath, 'utf-8')) || [];
731
- }
732
- catch (e) { }
733
- }
734
- const proposalKey = `${proposal.targetFile}::${proposal.refactorGoal}`;
735
- if (historyList.includes(proposalKey)) {
736
- console.log(`\n\x1b[33m[Divergence Prevention] Proposal "${proposalKey}" has been successfully executed recently. Skipping to prevent cycles.\x1b[0m`);
737
- // Try a second time to get a different proposal
738
- proposal = await this.getAutonomousRefactorProposal();
739
- }
740
- }
741
- catch (err) {
742
- console.error(`\n\x1b[31m[Proposal Error] Failed to scan proposal: ${err.message}\x1b[0m`);
743
- }
744
- if (proposal) {
745
- const proposalKey = `${proposal.targetFile}::${proposal.refactorGoal}`;
746
- console.log(`\n\x1b[36m[Daemon Worker] Spawning refactor child worker for target: ${proposal.targetFile}...\x1b[0m`);
747
- (0, state_manager_1.updateEvolutionState)({
748
- status: 'refactoring',
749
- currentTask: `Refactoring: ${proposal.refactorGoal}`,
750
- lastRefactorProposal: {
751
- targetFile: proposal.targetFile,
752
- refactorGoal: proposal.refactorGoal,
753
- time: new Date().toISOString()
754
- }
755
- });
756
- // Spawn --refactor worker
757
- const refactorExit = await this.runChildProcess(['dist/index.js', '--refactor']);
758
- if (refactorExit === 0) {
759
- console.log(`\n\x1b[32m✔ [Daemon Worker] Refactor cycle completed successfully.\x1b[0m`);
760
- consecutiveFailures = 0; // Reset failures on success
761
- // Append to history cache
762
- let historyList = [];
763
- if (fs.existsSync(historyPath)) {
764
- try {
765
- historyList = JSON.parse(fs.readFileSync(historyPath, 'utf-8')) || [];
766
- }
767
- catch (e) { }
768
- }
769
- historyList.push(proposalKey);
770
- if (historyList.length > 20) {
771
- historyList.shift();
772
- }
773
- fs.writeFileSync(historyPath, JSON.stringify(historyList, null, 2), 'utf-8');
774
- }
775
- else {
776
- console.log(`\n\x1b[31m❌ [Daemon Worker] Refactor cycle failed or was rolled back. (Exit Code: ${refactorExit})\x1b[0m`);
777
- consecutiveFailures++;
778
- // Ensure git rollback just in case the child process crashed mid-way or didn't roll back
779
- await this.gitResetClean();
780
- // DGM-inspired Evolutionary Backtracking
781
- if (consecutiveFailures >= 2) {
782
- const state = (0, state_manager_1.getEvolutionState)();
783
- const archive = state.archive || [];
784
- if (archive.length > 0) {
785
- const parentNode = archive[archive.length - 1];
786
- console.log(`\n\x1b[31m[DGM Backtracking]\x1b[0m Consecutive failures (${consecutiveFailures}) exceeded limit. Backtracking to parent node cycle ${parentNode.cycle} (commit: ${parentNode.commitHash.substring(0, 7)})...`);
787
- const spinner = new tui_tools_1.Spinner('DGM - Backtracking: Resetting workspace to stable parent node...');
788
- spinner.start();
789
- await (0, shell_tools_1.runCommand)(`git reset --hard ${parentNode.commitHash}`);
790
- await (0, shell_tools_1.runCommand)('git clean -fd');
791
- spinner.stop(true, 'DGM - Backtracking: Workspace successfully restored to stable parent node.');
792
- consecutiveFailures = 0; // Reset consecutive failures after backtracking
793
- }
794
- }
795
- }
796
- }
797
- // 3. Spawns Prompt Optimizer
798
- console.log(`\n\x1b[36m[Daemon Worker] Spawning prompt optimization child worker...\x1b[0m`);
799
- (0, state_manager_1.updateEvolutionState)({
800
- status: 'optimizing_prompt',
801
- currentTask: 'Optimizing System Prompt Benchmarks'
802
- });
803
- const optimizeExit = await this.runChildProcess(['dist/index.js', '--optimize-prompt']);
804
- if (optimizeExit === 0) {
805
- console.log(`\n\x1b[32m✔ [Daemon Worker] Prompt optimization benchmark completed.\x1b[0m`);
806
- }
807
- else {
808
- console.log(`\n\x1b[31m❌ [Daemon Worker] Prompt optimization benchmark failed. (Exit Code: ${optimizeExit})\x1b[0m`);
809
- await this.gitResetClean();
810
- }
811
- console.log(`\n\x1b[33m[Daemon Cooldown] Sleeping for 60 seconds before next cycle...\x1b[0m`);
812
- (0, state_manager_1.updateEvolutionState)({
813
- status: 'cooldown',
814
- currentTask: 'Cooldown period (60s)'
815
- });
816
- await new Promise(resolve => setTimeout(resolve, 60000));
817
- }
818
- }
819
- /**
820
- * DGM Evolution Loop
821
- * Implements Darwin Gödel Machine open-ended evolution:
822
- * 1. Measure baseline fitness
823
- * 2. Select parent from archive (fitness-weighted)
824
- * 3. Select mutation strategy (adaptive)
825
- * 4. Apply mutation via Meta-Agent
826
- * 5. Evaluate candidate fitness empirically
827
- * 6. Add to archive if fitness improved or maintained
828
- * 7. Commit if better; rollback if worse
829
- */
830
- async runDGMEvolution(task, maxGenerations = 5) {
831
- console.log('\x1b[35m=== STARTING DGM (Darwin Gödel Machine) EVOLUTION ===\x1b[0m');
832
- console.log(`Task: "${task}"`);
833
- console.log(`Max Generations: ${maxGenerations}\n`);
834
- const archive = new dgm_archive_1.DGMArchive(process.cwd());
835
- research_manager_1.ResearchManager.startSession(`DGM Evolution: ${task}`, this.effort);
836
- // Step 1: Measure baseline fitness
837
- (0, state_manager_1.updateEvolutionState)({ status: 'reflecting', currentTask: 'DGM: Measuring baseline fitness' });
838
- console.log('\x1b[34m[DGM]\x1b[0m Measuring baseline fitness...');
839
- const baselineFitness = await (0, fitness_evaluator_1.evaluateFitness)();
840
- console.log(`\x1b[32m[DGM]\x1b[0m Baseline: ${baselineFitness.summary}`);
841
- // Register initial baseline into archive if empty
842
- const archiveStats = archive.getStats();
843
- let baselineEntry = archiveStats.bestEntryId ? archive.findById(archiveStats.bestEntryId) : null;
844
- if (!baselineEntry) {
845
- const gitHeadRes = await (0, shell_tools_1.runCommand)('git rev-parse HEAD');
846
- const commitHash = gitHeadRes.exitCode === 0 ? gitHeadRes.stdout.trim() : 'unknown';
847
- baselineEntry = archive.addEntry({
848
- commitHash,
849
- parentId: null,
850
- fitness: baselineFitness.score,
851
- mutationStrategy: 'baseline',
852
- task: 'Initial baseline snapshot',
853
- metadata: {
854
- passCount: baselineFitness.passCount,
855
- failCount: baselineFitness.failCount,
856
- totalTests: baselineFitness.totalTests,
857
- passRate: baselineFitness.passRate
858
- }
859
- });
860
- console.log(`\x1b[34m[DGM]\x1b[0m Registered baseline snapshot: ${baselineEntry.id} (fitness: ${(baselineFitness.score * 100).toFixed(1)}%)`);
861
- }
862
- (0, state_manager_1.updateEvolutionState)({
863
- currentFitness: baselineFitness.score,
864
- bestFitness: Math.max((0, state_manager_1.getEvolutionState)().bestFitness, baselineFitness.score),
865
- dgmPopulationSize: archive.getStats().totalEntries,
866
- dgmBestEntryId: archive.getStats().bestEntryId
867
- });
868
- let currentBestFitness = baselineFitness.score;
869
- // Step 2-7: Evolution loop
870
- for (let gen = 1; gen <= maxGenerations; gen++) {
871
- console.log(`\n\x1b[35m─── DGM Generation ${gen}/${maxGenerations} ───\x1b[0m`);
872
- // 2a. Select parent from archive (fitness-weighted)
873
- const parent = archive.getBestParent('fitness_weighted');
874
- if (parent) {
875
- console.log(`\x1b[34m[DGM]\x1b[0m Selected parent: ${parent.id} (fitness: ${(parent.fitness * 100).toFixed(1)}%, strategy: ${parent.mutationStrategy})`);
876
- }
877
- // 2b. Select mutation strategy (adaptive)
878
- (0, state_manager_1.updateEvolutionState)({ status: 'scanning', currentTask: `DGM Gen ${gen}: Selecting mutation strategy` });
879
- const mutationSel = (0, mutation_strategies_1.selectMutationStrategy)(archive, task, currentBestFitness);
880
- console.log(`\x1b[34m[DGM]\x1b[0m Mutation: \x1b[33m${mutationSel.strategy}\x1b[0m — ${mutationSel.rationale}`);
881
- // 2c. Generate mutation prompt
882
- const mutationTask = (0, mutation_strategies_1.generateMutationPrompt)(mutationSel.strategy, task, {
883
- parentEntry: parent,
884
- currentFitness: currentBestFitness
885
- });
886
- // 3. Apply mutation via Meta-Agent
887
- (0, state_manager_1.updateEvolutionState)({ status: 'refactoring', currentTask: `DGM Gen ${gen}: Applying ${mutationSel.strategy} mutation` });
888
- research_manager_1.ResearchManager.logDecision('DGM Mutation', `Gen ${gen}: Applying strategy ${mutationSel.strategy}`, 'info');
889
- let mutationSucceeded = false;
890
- try {
891
- await (0, meta_agent_1.runSelfImprovingTask)(mutationTask, this.effort);
892
- mutationSucceeded = true;
893
- }
894
- catch (err) {
895
- console.error(`\x1b[31m[DGM Gen ${gen}]\x1b[0m Mutation failed: ${err.message}`);
896
- research_manager_1.ResearchManager.logDecision('DGM Mutation', `Gen ${gen}: Mutation error — ${err.message}`, 'failure');
897
- }
898
- if (!mutationSucceeded) {
899
- console.log(`\x1b[33m[DGM Gen ${gen}]\x1b[0m Skipping fitness evaluation due to mutation failure.`);
900
- continue;
901
- }
902
- // 4. Evaluate candidate fitness empirically
903
- (0, state_manager_1.updateEvolutionState)({ status: 'evaluating', currentTask: `DGM Gen ${gen}: Evaluating candidate fitness` });
904
- console.log(`\x1b[34m[DGM Gen ${gen}]\x1b[0m Evaluating candidate fitness...`);
905
- const candidateFitness = await (0, fitness_evaluator_1.evaluateFitness)();
906
- const comparison = (0, fitness_evaluator_1.compareToBaseline)(candidateFitness, { ...baselineFitness });
907
- console.log(`\x1b[${comparison.improved ? '32' : '33'}m[DGM Gen ${gen}]\x1b[0m ${comparison.message}`);
908
- research_manager_1.ResearchManager.logDecision('DGM Fitness', `Gen ${gen}: ${comparison.message}`, comparison.improved ? 'success' : 'info');
909
- // 5. Add to archive + commit/rollback decision
910
- (0, state_manager_1.updateEvolutionState)({ status: comparison.improved ? 'committing' : 'rolling_back', currentTask: `DGM Gen ${gen}: ${comparison.improved ? 'Committing' : 'Rolling back'}` });
911
- if (candidateFitness.compileSuccess && candidateFitness.score >= currentBestFitness) {
912
- // Commit the mutation
913
- const commitRes = await this.commitAll();
914
- let newCommitHash = 'unknown';
915
- if (commitRes.exitCode === 0) {
916
- const revRes = await (0, shell_tools_1.runCommand)('git rev-parse HEAD');
917
- newCommitHash = revRes.exitCode === 0 ? revRes.stdout.trim() : 'unknown';
918
- }
919
- // Add to DGM archive
920
- const newEntry = archive.addEntry({
921
- commitHash: newCommitHash,
922
- parentId: parent?.id ?? baselineEntry.id,
923
- fitness: candidateFitness.score,
924
- mutationStrategy: mutationSel.strategy,
925
- task,
926
- metadata: {
927
- passCount: candidateFitness.passCount,
928
- failCount: candidateFitness.failCount,
929
- totalTests: candidateFitness.totalTests,
930
- passRate: candidateFitness.passRate
931
- }
932
- });
933
- archive.pruneOldEntries();
934
- currentBestFitness = Math.max(currentBestFitness, candidateFitness.score);
935
- console.log(`\x1b[32m[DGM Gen ${gen}]\x1b[0m Committed & archived: ${newEntry.id} (fitness: ${(candidateFitness.score * 100).toFixed(1)}%)`);
936
- (0, state_manager_1.appendHistory)({
937
- cycle: gen,
938
- type: 'dgm_evolution',
939
- description: `DGM Gen ${gen}: ${mutationSel.strategy} → fitness ${(candidateFitness.score * 100).toFixed(1)}%`,
940
- success: true
941
- });
942
- }
943
- else {
944
- // Rollback — candidate did not improve fitness
945
- console.log(`\x1b[31m[DGM Gen ${gen}]\x1b[0m Rolling back — candidate did not improve fitness.`);
946
- await this.gitResetClean();
947
- research_manager_1.ResearchManager.logDecision('DGM Rollback', `Gen ${gen}: Reverted — fitness did not improve`, 'info');
948
- (0, state_manager_1.appendHistory)({
949
- cycle: gen,
950
- type: 'dgm_evolution',
951
- description: `DGM Gen ${gen}: ${mutationSel.strategy} → rolled back (fitness unchanged or regressed)`,
952
- success: false
953
- });
954
- }
955
- // Update state
956
- const updatedStats = archive.getStats();
957
- (0, state_manager_1.updateEvolutionState)({
958
- currentFitness: candidateFitness.score,
959
- bestFitness: currentBestFitness,
960
- dgmPopulationSize: updatedStats.totalEntries,
961
- dgmBestEntryId: updatedStats.bestEntryId
962
- });
963
- }
964
- research_manager_1.ResearchManager.endSession(currentBestFitness > baselineFitness.score ? 'success' : 'failed');
965
- const finalStats = archive.getStats();
966
- console.log(`\n\x1b[35m=== DGM EVOLUTION COMPLETE ===\x1b[0m`);
967
- console.log(`Final best fitness: ${(currentBestFitness * 100).toFixed(1)}% (started: ${(baselineFitness.score * 100).toFixed(1)}%)`);
968
- console.log(`Archive size: ${finalStats.totalEntries} snapshots`);
969
- console.log(`Generation depth: ${finalStats.generationDepth}`);
970
- (0, state_manager_1.updateEvolutionState)({ status: 'idle', currentTask: null });
971
- }
972
- }
973
- exports.AutogenesisEngine = AutogenesisEngine;