Skip to content

Commit c29c2f3

Browse files
author
evolver-publish
committed
Release v1.32.4
1 parent 6c23b52 commit c29c2f3

8 files changed

Lines changed: 83 additions & 76 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evomap/evolver",
3-
"version": "1.32.2",
3+
"version": "1.32.4",
44
"description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
55
"main": "index.js",
66
"bin": {

src/evolve.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,14 +610,18 @@ function getNextCycleId() {
610610
if (fs.existsSync(STATE_FILE)) {
611611
state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
612612
}
613-
} catch (e) {}
613+
} catch (e) {
614+
console.warn('[Evolve] Failed to read state file:', e && e.message || e);
615+
}
614616

615617
state.cycleCount = (state.cycleCount || 0) + 1;
616618
state.lastRun = Date.now();
617619

618620
try {
619621
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
620-
} catch (e) {}
622+
} catch (e) {
623+
console.warn('[Evolve] Failed to write state file:', e && e.message || e);
624+
}
621625

622626
return String(state.cycleCount).padStart(4, '0');
623627
}

src/gep/assetStore.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,16 @@ function upsertCapsule(capsuleObj) {
283283
writeJsonAtomic(capsulesPath(), { version: current.version || 1, capsules });
284284
}
285285

286-
var FAILED_CAPSULES_MAX = 200;
287-
var FAILED_CAPSULES_TRIM_TO = 100;
286+
const FAILED_CAPSULES_MAX = 200;
287+
const FAILED_CAPSULES_TRIM_TO = 100;
288288

289289
function getDefaultFailedCapsules() { return { version: 1, failed_capsules: [] }; }
290290

291291
function appendFailedCapsule(capsuleObj) {
292292
if (!capsuleObj || typeof capsuleObj !== 'object') return;
293293
ensureSchemaFields(capsuleObj);
294-
var current = readJsonIfExists(failedCapsulesPath(), getDefaultFailedCapsules());
295-
var list = Array.isArray(current.failed_capsules) ? current.failed_capsules : [];
294+
const current = readJsonIfExists(failedCapsulesPath(), getDefaultFailedCapsules());
295+
let list = Array.isArray(current.failed_capsules) ? current.failed_capsules : [];
296296
list.push(capsuleObj);
297297
if (list.length > FAILED_CAPSULES_MAX) {
298298
list = list.slice(list.length - FAILED_CAPSULES_TRIM_TO);
@@ -301,10 +301,10 @@ function appendFailedCapsule(capsuleObj) {
301301
}
302302

303303
function readRecentFailedCapsules(limit) {
304-
var n = Number.isFinite(Number(limit)) && Number(limit) > 0 ? Number(limit) : 50;
304+
const n = Number.isFinite(Number(limit)) && Number(limit) > 0 ? Number(limit) : 50;
305305
try {
306-
var current = readJsonIfExists(failedCapsulesPath(), getDefaultFailedCapsules());
307-
var list = Array.isArray(current.failed_capsules) ? current.failed_capsules : [];
306+
const current = readJsonIfExists(failedCapsulesPath(), getDefaultFailedCapsules());
307+
const list = Array.isArray(current.failed_capsules) ? current.failed_capsules : [];
308308
return list.slice(Math.max(0, list.length - n));
309309
} catch (e) {
310310
console.warn('[AssetStore] Failed to read failed_capsules.json:', e && e.message || e);

src/gep/envFingerprint.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ function captureEnvFingerprint() {
5252
region: region,
5353
cwd: crypto.createHash('sha256').update(process.cwd()).digest('hex').slice(0, 12),
5454
container: isContainer(),
55+
captured_at: new Date().toISOString(),
5556
};
5657
}
5758

src/gep/issueReporter.js

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const MAX_LOG_CHARS = 2000;
1818
const MAX_EVENTS = 5;
1919

2020
function getConfig() {
21-
var enabled = String(process.env.EVOLVER_AUTO_ISSUE || 'true').toLowerCase();
21+
const enabled = String(process.env.EVOLVER_AUTO_ISSUE || 'true').toLowerCase();
2222
if (enabled === 'false' || enabled === '0') return null;
2323
return {
2424
repo: process.env.EVOLVER_ISSUE_REPO || DEFAULT_REPO,
@@ -37,7 +37,7 @@ function getStatePath() {
3737

3838
function readState() {
3939
try {
40-
var p = getStatePath();
40+
const p = getStatePath();
4141
if (fs.existsSync(p)) {
4242
return JSON.parse(fs.readFileSync(p, 'utf8'));
4343
}
@@ -47,7 +47,7 @@ function readState() {
4747

4848
function writeState(state) {
4949
try {
50-
var dir = getEvolutionDir();
50+
const dir = getEvolutionDir();
5151
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
5252
fs.writeFileSync(getStatePath(), JSON.stringify(state, null, 2) + '\n');
5353
} catch (_) {}
@@ -60,7 +60,7 @@ function truncateNodeId(nodeId) {
6060
}
6161

6262
function computeErrorKey(signals) {
63-
var relevant = signals
63+
const relevant = signals
6464
.filter(function (s) {
6565
return s.startsWith('recurring_errsig') ||
6666
s.startsWith('ban_gene:') ||
@@ -74,19 +74,19 @@ function computeErrorKey(signals) {
7474
}
7575

7676
function extractErrorSignature(signals) {
77-
var errSig = signals.find(function (s) { return s.startsWith('recurring_errsig'); });
77+
const errSig = signals.find(function (s) { return s.startsWith('recurring_errsig'); });
7878
if (errSig) {
7979
return errSig.replace(/^recurring_errsig\(\d+x\):/, '').trim().slice(0, 200);
8080
}
81-
var banned = signals.find(function (s) { return s.startsWith('ban_gene:'); });
81+
const banned = signals.find(function (s) { return s.startsWith('ban_gene:'); });
8282
if (banned) return 'Repeated failures with gene: ' + banned.replace('ban_gene:', '');
8383
return 'Persistent evolution failure';
8484
}
8585

8686
function extractStreakCount(signals) {
87-
for (var i = 0; i < signals.length; i++) {
87+
for (let i = 0; i < signals.length; i++) {
8888
if (signals[i].startsWith('consecutive_failure_streak_')) {
89-
var n = parseInt(signals[i].replace('consecutive_failure_streak_', ''), 10);
89+
const n = parseInt(signals[i].replace('consecutive_failure_streak_', ''), 10);
9090
if (Number.isFinite(n)) return n;
9191
}
9292
}
@@ -95,12 +95,12 @@ function extractStreakCount(signals) {
9595

9696
function formatRecentEvents(events) {
9797
if (!Array.isArray(events) || events.length === 0) return '_No recent events available._';
98-
var failed = events.filter(function (e) { return e && e.outcome && e.outcome.status === 'failed'; });
99-
var rows = failed.slice(-MAX_EVENTS).map(function (e, idx) {
100-
var intent = e.intent || '-';
101-
var gene = (Array.isArray(e.genes_used) && e.genes_used[0]) || '-';
102-
var outcome = (e.outcome && e.outcome.status) || '-';
103-
var reason = (e.outcome && e.outcome.reason) || '';
98+
const failed = events.filter(function (e) { return e && e.outcome && e.outcome.status === 'failed'; });
99+
const rows = failed.slice(-MAX_EVENTS).map(function (e, idx) {
100+
const intent = e.intent || '-';
101+
const gene = (Array.isArray(e.genes_used) && e.genes_used[0]) || '-';
102+
const outcome = (e.outcome && e.outcome.status) || '-';
103+
let reason = (e.outcome && e.outcome.reason) || '';
104104
if (reason.length > 80) reason = reason.slice(0, 80) + '...';
105105
reason = redactString(reason);
106106
return '| ' + (idx + 1) + ' | ' + intent + ' | ' + gene + ' | ' + outcome + ' | ' + reason + ' |';
@@ -110,15 +110,15 @@ function formatRecentEvents(events) {
110110
}
111111

112112
function buildIssueBody(opts) {
113-
var fp = opts.envFingerprint || captureEnvFingerprint();
114-
var signals = opts.signals || [];
115-
var recentEvents = opts.recentEvents || [];
116-
var sessionLog = opts.sessionLog || '';
117-
var streakCount = extractStreakCount(signals);
118-
var errorSig = extractErrorSignature(signals);
119-
var nodeId = truncateNodeId(getNodeId());
120-
121-
var failureSignals = signals.filter(function (s) {
113+
const fp = opts.envFingerprint || captureEnvFingerprint();
114+
const signals = opts.signals || [];
115+
const recentEvents = opts.recentEvents || [];
116+
const sessionLog = opts.sessionLog || '';
117+
const streakCount = extractStreakCount(signals);
118+
const errorSig = extractErrorSignature(signals);
119+
const nodeId = truncateNodeId(getNodeId());
120+
121+
const failureSignals = signals.filter(function (s) {
122122
return s.startsWith('recurring_') ||
123123
s.startsWith('consecutive_failure') ||
124124
s.startsWith('failure_loop') ||
@@ -127,17 +127,17 @@ function buildIssueBody(opts) {
127127
s === 'force_innovation_after_repair_loop';
128128
}).join(', ');
129129

130-
var sanitizedLog = redactString(
130+
const sanitizedLog = redactString(
131131
typeof sessionLog === 'string' ? sessionLog.slice(-MAX_LOG_CHARS) : ''
132132
);
133133

134-
var eventsTable = formatRecentEvents(recentEvents);
134+
const eventsTable = formatRecentEvents(recentEvents);
135135

136-
var reportId = crypto.createHash('sha256')
136+
const reportId = crypto.createHash('sha256')
137137
.update(nodeId + '|' + Date.now() + '|' + errorSig)
138138
.digest('hex').slice(0, 12);
139139

140-
var body = [
140+
const body = [
141141
'## Environment',
142142
'- **Evolver Version:** ' + (fp.evolver_version || 'unknown'),
143143
'- **Node.js:** ' + (fp.node_version || process.version),
@@ -172,21 +172,21 @@ function buildIssueBody(opts) {
172172
function shouldReport(signals, config) {
173173
if (!config) return false;
174174

175-
var hasFailureLoop = signals.includes('failure_loop_detected');
176-
var hasRecurringAndHigh = signals.includes('recurring_error') && signals.includes('high_failure_ratio');
175+
const hasFailureLoop = signals.includes('failure_loop_detected');
176+
const hasRecurringAndHigh = signals.includes('recurring_error') && signals.includes('high_failure_ratio');
177177

178178
if (!hasFailureLoop && !hasRecurringAndHigh) return false;
179179

180-
var streakCount = extractStreakCount(signals);
180+
const streakCount = extractStreakCount(signals);
181181
if (streakCount > 0 && streakCount < config.minStreak) return false;
182182

183-
var state = readState();
184-
var errorKey = computeErrorKey(signals);
183+
const state = readState();
184+
const errorKey = computeErrorKey(signals);
185185

186186
if (state.lastReportedAt) {
187-
var elapsed = Date.now() - new Date(state.lastReportedAt).getTime();
187+
const elapsed = Date.now() - new Date(state.lastReportedAt).getTime();
188188
if (elapsed < config.cooldownMs) {
189-
var recentKeys = Array.isArray(state.recentIssueKeys) ? state.recentIssueKeys : [];
189+
const recentKeys = Array.isArray(state.recentIssueKeys) ? state.recentIssueKeys : [];
190190
if (recentKeys.includes(errorKey)) {
191191
return false;
192192
}
@@ -197,8 +197,8 @@ function shouldReport(signals, config) {
197197
}
198198

199199
async function createGithubIssue(repo, title, body, token) {
200-
var url = 'https://api.github.com/repos/' + repo + '/issues';
201-
var response = await fetch(url, {
200+
const url = 'https://api.github.com/repos/' + repo + '/issues';
201+
const response = await fetch(url, {
202202
method: 'POST',
203203
headers: {
204204
'Authorization': 'Bearer ' + token,
@@ -211,41 +211,41 @@ async function createGithubIssue(repo, title, body, token) {
211211
});
212212

213213
if (!response.ok) {
214-
var errText = '';
214+
let errText = '';
215215
try { errText = await response.text(); } catch (_) {}
216216
throw new Error('GitHub API ' + response.status + ': ' + errText.slice(0, 200));
217217
}
218218

219-
var data = await response.json();
219+
const data = await response.json();
220220
return { number: data.number, url: data.html_url };
221221
}
222222

223223
async function maybeReportIssue(opts) {
224-
var config = getConfig();
224+
const config = getConfig();
225225
if (!config) return;
226226

227-
var signals = opts.signals || [];
227+
const signals = opts.signals || [];
228228

229229
if (!shouldReport(signals, config)) return;
230230

231-
var token = getGithubToken();
231+
const token = getGithubToken();
232232
if (!token) {
233233
console.log('[IssueReporter] No GitHub token available. Skipping auto-report.');
234234
return;
235235
}
236236

237-
var errorSig = extractErrorSignature(signals);
238-
var titleSig = errorSig.slice(0, 80);
239-
var title = '[Auto] Recurring failure: ' + titleSig;
240-
var body = buildIssueBody(opts);
237+
const errorSig = extractErrorSignature(signals);
238+
const titleSig = errorSig.slice(0, 80);
239+
const title = '[Auto] Recurring failure: ' + titleSig;
240+
const body = buildIssueBody(opts);
241241

242242
try {
243-
var result = await createGithubIssue(config.repo, title, body, token);
243+
const result = await createGithubIssue(config.repo, title, body, token);
244244
console.log('[IssueReporter] Created GitHub issue #' + result.number + ': ' + result.url);
245245

246-
var state = readState();
247-
var errorKey = computeErrorKey(signals);
248-
var recentKeys = Array.isArray(state.recentIssueKeys) ? state.recentIssueKeys : [];
246+
const state = readState();
247+
const errorKey = computeErrorKey(signals);
248+
let recentKeys = Array.isArray(state.recentIssueKeys) ? state.recentIssueKeys : [];
249249
recentKeys.push(errorKey);
250250
if (recentKeys.length > 20) recentKeys = recentKeys.slice(-20);
251251
writeState({

src/gep/learningSignals.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ function add(tags, value) {
1111
}
1212

1313
function expandSignals(signals, extraText) {
14-
var raw = Array.isArray(signals) ? signals.map(function (s) { return String(s); }) : [];
15-
var tags = [];
14+
const raw = Array.isArray(signals) ? signals.map(function (s) { return String(s); }) : [];
15+
const tags = [];
1616

17-
for (var i = 0; i < raw.length; i++) {
18-
var signal = raw[i];
17+
for (let i = 0; i < raw.length; i++) {
18+
const signal = raw[i];
1919
add(tags, signal);
20-
var base = signal.split(':')[0];
20+
const base = signal.split(':')[0];
2121
if (base && base !== signal) add(tags, base);
2222
}
2323

24-
var text = (raw.join(' ') + ' ' + String(extraText || '')).toLowerCase();
24+
const text = (raw.join(' ') + ' ' + String(extraText || '')).toLowerCase();
2525

2626
if (/(error|exception|failed|unstable|log_error|runtime|429)/.test(text)) {
2727
add(tags, 'problem:reliability');
@@ -62,7 +62,7 @@ function expandSignals(signals, extraText) {
6262

6363
function geneTags(gene) {
6464
if (!gene || typeof gene !== 'object') return [];
65-
var inputs = [];
65+
let inputs = [];
6666
if (gene.category) inputs.push('action:' + String(gene.category).toLowerCase());
6767
if (Array.isArray(gene.signals_match)) inputs = inputs.concat(gene.signals_match);
6868
if (typeof gene.id === 'string') inputs.push(gene.id);
@@ -71,12 +71,12 @@ function geneTags(gene) {
7171
}
7272

7373
function scoreTagOverlap(gene, signals) {
74-
var signalTags = expandSignals(signals, '');
75-
var geneTagList = geneTags(gene);
74+
const signalTags = expandSignals(signals, '');
75+
const geneTagList = geneTags(gene);
7676
if (signalTags.length === 0 || geneTagList.length === 0) return 0;
77-
var signalSet = new Set(signalTags);
78-
var hits = 0;
79-
for (var i = 0; i < geneTagList.length; i++) {
77+
const signalSet = new Set(signalTags);
78+
let hits = 0;
79+
for (let i = 0; i < geneTagList.length; i++) {
8080
if (signalSet.has(geneTagList[i])) hits++;
8181
}
8282
return hits;

src/gep/signals.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ function extractSignals({ recentSessionTranscript, todayLog, memorySnippet, user
237237
/|||\s*|\s*|||||||/.test(corpus) ||
238238
/||||||||/.test(corpus) ||
239239
/|||||||/.test(corpus)) {
240-
signals.push('user_feature_request:' + (featureRequestSnippet || ''));
240+
signals.push('user_feature_request');
241+
if (featureRequestSnippet) signals.push('user_feature_request:' + featureRequestSnippet);
241242
}
242243

243244
// user_improvement_suggestion: 4 languages + snippet
@@ -263,7 +264,8 @@ function extractSignals({ recentSessionTranscript, todayLog, memorySnippet, user
263264
/|||||/.test(corpus) ||
264265
/|||||/.test(corpus);
265266
if (hasImprovement) {
266-
signals.push('user_improvement_suggestion:' + (improvementSnippet || ''));
267+
signals.push('user_improvement_suggestion');
268+
if (improvementSnippet) signals.push('user_improvement_suggestion:' + improvementSnippet);
267269
}
268270
}
269271

test/skillDistiller.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ describe('validateSynthesizedGene', () => {
143143
it('accepts a valid gene', () => {
144144
var gene = {
145145
type: 'Gene', id: 'gene_distilled_test', category: 'repair',
146-
signals_match: ['error'], strategy: ['fix the bug'],
146+
signals_match: ['error'], strategy: ['identify the root cause', 'apply the fix', 'verify the solution'],
147147
constraints: { max_files: 8, forbidden_paths: ['.git', 'node_modules'] },
148148
};
149149
var result = validateSynthesizedGene(gene, []);
@@ -307,7 +307,7 @@ describe('buildDistillationPrompt', () => {
307307
var genes = [{ id: 'gene_a', signals_match: ['err'] }];
308308
var caps = [makeCapsule('c1', 'gene_a', 'success', 0.9)];
309309
var prompt = buildDistillationPrompt(analysis, genes, caps);
310-
assert.ok(prompt.includes('actionable operations'));
310+
assert.ok(prompt.includes('actionable'));
311311
assert.ok(prompt.includes('gene_distilled_'));
312312
assert.ok(prompt.includes('Gene synthesis engine'));
313313
assert.ok(prompt.includes('forbidden_paths'));
@@ -416,7 +416,7 @@ describe('prepareDistillation', () => {
416416

417417
var llmResponse = JSON.stringify({
418418
type: 'Gene', id: 'gene_distilled_idem', category: 'repair',
419-
signals_match: ['error'], strategy: ['fix it'],
419+
signals_match: ['error'], strategy: ['identify root cause', 'apply targeted fix', 'verify correction'],
420420
constraints: { max_files: 5, forbidden_paths: ['.git', 'node_modules'] },
421421
});
422422
var complete = completeDistillation(llmResponse);

0 commit comments

Comments
 (0)