Skip to content

Commit 152a086

Browse files
author
evolver-publish
committed
Release v1.34.1
1 parent 6b51b18 commit 152a086

4 files changed

Lines changed: 154 additions & 154 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.34.0",
3+
"version": "1.34.1",
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: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -44,35 +44,35 @@ const { expandSignals } = require('./gep/learningSignals');
4444

4545
const REPO_ROOT = getRepoRoot();
4646

47-
// Verbose logging helper. Checks EVOLVER_VERBOSE env var (set by --verbose flag in index.js).
47+
// Verbose logging helper. Checks EVOLVER_VERBOSE env const (set by --verbose flag in index.js).
4848
function verbose() {
4949
if (String(process.env.EVOLVER_VERBOSE || '').toLowerCase() !== 'true') return;
50-
var args = Array.prototype.slice.call(arguments);
50+
const args = Array.prototype.slice.call(arguments);
5151
args.unshift('[Verbose]');
5252
console.log.apply(console, args);
5353
}
5454

5555
// Idle-cycle gating: track last Hub fetch to avoid redundant API calls during saturation.
5656
// When evolver is saturated (no actionable signals), Hub calls are throttled to at most
5757
// once per EVOLVER_IDLE_FETCH_INTERVAL_MS (default 30 min) instead of every cycle.
58-
var _lastHubFetchMs = 0;
58+
let _lastHubFetchMs = 0;
5959

6060
function shouldSkipHubCalls(signals) {
6161
if (!Array.isArray(signals)) return false;
62-
var saturationIndicators = ['force_steady_state', 'evolution_saturation', 'empty_cycle_loop_detected'];
63-
var hasSaturation = false;
64-
for (var si = 0; si < saturationIndicators.length; si++) {
62+
const saturationIndicators = ['force_steady_state', 'evolution_saturation', 'empty_cycle_loop_detected'];
63+
let hasSaturation = false;
64+
for (let si = 0; si < saturationIndicators.length; si++) {
6565
if (signals.indexOf(saturationIndicators[si]) !== -1) { hasSaturation = true; break; }
6666
}
6767
if (!hasSaturation) return false;
6868

69-
var actionablePatterns = [
69+
const actionablePatterns = [
7070
'log_error', 'recurring_error', 'capability_gap', 'perf_bottleneck',
7171
'external_task', 'bounty_task', 'overdue_task', 'urgent',
7272
'unsupported_input_type',
7373
];
74-
for (var ai = 0; ai < signals.length; ai++) {
75-
var s = signals[ai];
74+
for (let ai = 0; ai < signals.length; ai++) {
75+
const s = signals[ai];
7676
if (actionablePatterns.indexOf(s) !== -1) return false;
7777
if (s.indexOf('errsig:') === 0) return false;
7878
if (s.indexOf('user_feature_request:') === 0 && s.length > 21) return false;
@@ -556,14 +556,14 @@ function getMutationDirective(logContent) {
556556

557557
const STATE_FILE = path.join(getEvolutionDir(), 'evolution_state.json');
558558
const DORMANT_HYPOTHESIS_FILE = path.join(getEvolutionDir(), 'dormant_hypothesis.json');
559-
var DORMANT_TTL_MS = 3600 * 1000;
559+
const DORMANT_TTL_MS = 3600 * 1000;
560560

561561
function writeDormantHypothesis(data) {
562562
try {
563-
var dir = getEvolutionDir();
563+
const dir = getEvolutionDir();
564564
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
565-
var obj = Object.assign({}, data, { created_at: new Date().toISOString(), ttl_ms: DORMANT_TTL_MS });
566-
var tmp = DORMANT_HYPOTHESIS_FILE + '.tmp';
565+
const obj = Object.assign({}, data, { created_at: new Date().toISOString(), ttl_ms: DORMANT_TTL_MS });
566+
const tmp = DORMANT_HYPOTHESIS_FILE + '.tmp';
567567
fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\n', 'utf8');
568568
fs.renameSync(tmp, DORMANT_HYPOTHESIS_FILE);
569569
console.log('[DormantHypothesis] Saved partial state before backoff: ' + (data.backoff_reason || 'unknown'));
@@ -575,11 +575,11 @@ function writeDormantHypothesis(data) {
575575
function readDormantHypothesis() {
576576
try {
577577
if (!fs.existsSync(DORMANT_HYPOTHESIS_FILE)) return null;
578-
var raw = fs.readFileSync(DORMANT_HYPOTHESIS_FILE, 'utf8');
578+
const raw = fs.readFileSync(DORMANT_HYPOTHESIS_FILE, 'utf8');
579579
if (!raw.trim()) return null;
580-
var obj = JSON.parse(raw);
581-
var createdAt = obj.created_at ? new Date(obj.created_at).getTime() : 0;
582-
var ttl = Number.isFinite(Number(obj.ttl_ms)) ? Number(obj.ttl_ms) : DORMANT_TTL_MS;
580+
const obj = JSON.parse(raw);
581+
const createdAt = obj.created_at ? new Date(obj.created_at).getTime() : 0;
582+
const ttl = Number.isFinite(Number(obj.ttl_ms)) ? Number(obj.ttl_ms) : DORMANT_TTL_MS;
583583
if (Date.now() - createdAt > ttl) {
584584
clearDormantHypothesis();
585585
console.log('[DormantHypothesis] Expired (age: ' + Math.round((Date.now() - createdAt) / 1000) + 's). Discarded.');
@@ -974,7 +974,7 @@ async function run() {
974974
return;
975975
}
976976

977-
var dormantHypothesis = readDormantHypothesis();
977+
const dormantHypothesis = readDormantHypothesis();
978978
if (dormantHypothesis) {
979979
console.log('[DormantHypothesis] Recovered partial state from previous backoff: ' + (dormantHypothesis.backoff_reason || 'unknown'));
980980
clearDormantHypothesis();
@@ -1186,9 +1186,9 @@ async function run() {
11861186
verbose('Recent events: ' + recentEvents.length + ', session log size: ' + recentMasterLog.length + ' chars');
11871187

11881188
if (dormantHypothesis && Array.isArray(dormantHypothesis.signals) && dormantHypothesis.signals.length > 0) {
1189-
var dormantSignals = dormantHypothesis.signals;
1190-
var injected = 0;
1191-
for (var dsi = 0; dsi < dormantSignals.length; dsi++) {
1189+
const dormantSignals = dormantHypothesis.signals;
1190+
let injected = 0;
1191+
for (let dsi = 0; dsi < dormantSignals.length; dsi++) {
11921192
if (!signals.includes(dormantSignals[dsi])) {
11931193
signals.push(dormantSignals[dsi]);
11941194
injected++;
@@ -1200,12 +1200,12 @@ async function run() {
12001200
}
12011201

12021202
// --- Idle-cycle gating: skip Hub API calls during saturation to save credits ---
1203-
var _idleFetchInterval = parseInt(String(process.env.EVOLVER_IDLE_FETCH_INTERVAL_MS || ''), 10);
1203+
let _idleFetchInterval = parseInt(String(process.env.EVOLVER_IDLE_FETCH_INTERVAL_MS || ''), 10);
12041204
if (!Number.isFinite(_idleFetchInterval) || _idleFetchInterval <= 0) _idleFetchInterval = 1800000;
1205-
var skipHubCalls = false;
1205+
let skipHubCalls = false;
12061206

12071207
if (shouldSkipHubCalls(signals)) {
1208-
var _elapsed = Date.now() - _lastHubFetchMs;
1208+
const _elapsed = Date.now() - _lastHubFetchMs;
12091209
if (_lastHubFetchMs > 0 && _elapsed < _idleFetchInterval) {
12101210
skipHubCalls = true;
12111211
console.log('[IdleGating] Saturated with no actionable signals. Skipping Hub API calls (last fetch ' + Math.round(_elapsed / 1000) + 's ago, threshold ' + Math.round(_idleFetchInterval / 1000) + 's).');
@@ -1543,18 +1543,18 @@ async function run() {
15431543
console.log('[Reflection] Failed (non-fatal): ' + (e && e.message ? e.message : e));
15441544
}
15451545

1546-
var recentFailedCapsules = [];
1546+
let recentFailedCapsules = [];
15471547
try {
15481548
recentFailedCapsules = readRecentFailedCapsules(50);
15491549
} catch (e) {
15501550
console.log('[FailedCapsules] Read failed (non-fatal): ' + e.message);
15511551
}
15521552

15531553
// Heartbeat hints: novelty score and capability gaps for diversity-directed drift
1554-
var heartbeatNovelty = null;
1555-
var heartbeatCapGaps = [];
1554+
let heartbeatNovelty = null;
1555+
let heartbeatCapGaps = [];
15561556
try {
1557-
var { getNoveltyHint, getCapabilityGaps: getCapGaps } = require('./gep/a2aProtocol');
1557+
const { getNoveltyHint, getCapabilityGaps: getCapGaps } = require('./gep/a2aProtocol');
15581558
heartbeatNovelty = getNoveltyHint();
15591559
heartbeatCapGaps = getCapGaps() || [];
15601560
} catch (e) {}

src/gep/selector.js

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function matchPatternToSignals(pattern, signals) {
3333
function scoreGene(gene, signals) {
3434
if (!gene || gene.type !== 'Gene') return 0;
3535
const patterns = Array.isArray(gene.signals_match) ? gene.signals_match : [];
36-
var tagScore = scoreTagOverlap(gene, signals);
36+
const tagScore = scoreTagOverlap(gene, signals);
3737
if (patterns.length === 0) return tagScore > 0 ? tagScore * 0.6 : 0;
3838
let score = 0;
3939
for (const pat of patterns) {
@@ -54,11 +54,11 @@ function getEpigeneticBoostLocal(gene, envFingerprint) {
5454

5555
function scoreGeneLearning(gene, signals, envFingerprint) {
5656
if (!gene || gene.type !== 'Gene') return 0;
57-
var boost = 0;
57+
let boost = 0;
5858

59-
var history = Array.isArray(gene.learning_history) ? gene.learning_history.slice(-8) : [];
60-
for (var i = 0; i < history.length; i++) {
61-
var entry = history[i];
59+
const history = Array.isArray(gene.learning_history) ? gene.learning_history.slice(-8) : [];
60+
for (let i = 0; i < history.length; i++) {
61+
const entry = history[i];
6262
if (!entry) continue;
6363
if (entry.outcome === 'success') boost += 0.12;
6464
else if (entry.mode === 'hard') boost -= 0.22;
@@ -68,13 +68,13 @@ function scoreGeneLearning(gene, signals, envFingerprint) {
6868
boost += getEpigeneticBoostLocal(gene, envFingerprint);
6969

7070
if (Array.isArray(gene.anti_patterns) && gene.anti_patterns.length > 0) {
71-
var overlapPenalty = 0;
72-
var signalTags = new Set(require('./learningSignals').expandSignals(signals, ''));
73-
var recentAntiPatterns = gene.anti_patterns.slice(-6);
74-
for (var j = 0; j < recentAntiPatterns.length; j++) {
75-
var anti = recentAntiPatterns[j];
71+
let overlapPenalty = 0;
72+
const signalTags = new Set(require('./learningSignals').expandSignals(signals, ''));
73+
const recentAntiPatterns = gene.anti_patterns.slice(-6);
74+
for (let j = 0; j < recentAntiPatterns.length; j++) {
75+
const anti = recentAntiPatterns[j];
7676
if (!anti || !Array.isArray(anti.learning_signals)) continue;
77-
var overlap = anti.learning_signals.some(function (tag) { return signalTags.has(String(tag)); });
77+
const overlap = anti.learning_signals.some(function (tag) { return signalTags.has(String(tag)); });
7878
if (overlap) overlapPenalty += anti.mode === 'hard' ? 0.4 : 0.18;
7979
}
8080
boost -= overlapPenalty;
@@ -90,19 +90,19 @@ function scoreGeneLearning(gene, signals, envFingerprint) {
9090
// This replaces the binary driftEnabled flag with a continuous spectrum.
9191
function computeDriftIntensity(opts) {
9292
// If explicitly enabled/disabled, use that as the baseline
93-
var driftEnabled = !!(opts && opts.driftEnabled);
93+
const driftEnabled = !!(opts && opts.driftEnabled);
9494

9595
// Effective population size: active gene count in the pool
96-
var effectivePopulationSize = opts && Number.isFinite(Number(opts.effectivePopulationSize))
96+
const effectivePopulationSize = opts && Number.isFinite(Number(opts.effectivePopulationSize))
9797
? Number(opts.effectivePopulationSize)
9898
: null;
9999

100100
// If no Ne provided, fall back to gene pool size
101-
var genePoolSize = opts && Number.isFinite(Number(opts.genePoolSize))
101+
const genePoolSize = opts && Number.isFinite(Number(opts.genePoolSize))
102102
? Number(opts.genePoolSize)
103103
: null;
104104

105-
var ne = effectivePopulationSize || genePoolSize || null;
105+
const ne = effectivePopulationSize || genePoolSize || null;
106106

107107
if (driftEnabled) {
108108
// Explicit drift: use moderate-to-high intensity
@@ -125,24 +125,24 @@ function selectGene(genes, signals, opts) {
125125
const preferredGeneId = opts && typeof opts.preferredGeneId === 'string' ? opts.preferredGeneId : null;
126126

127127
// Diversity-directed drift: capability_gaps from Hub heartbeat
128-
var capabilityGaps = opts && Array.isArray(opts.capabilityGaps) ? opts.capabilityGaps : [];
129-
var noveltyScore = opts && Number.isFinite(Number(opts.noveltyScore)) ? Number(opts.noveltyScore) : null;
128+
const capabilityGaps = opts && Array.isArray(opts.capabilityGaps) ? opts.capabilityGaps : [];
129+
const noveltyScore = opts && Number.isFinite(Number(opts.noveltyScore)) ? Number(opts.noveltyScore) : null;
130130

131131
// Compute continuous drift intensity based on effective population size
132-
var driftIntensity = computeDriftIntensity({
132+
const driftIntensity = computeDriftIntensity({
133133
driftEnabled: driftEnabled,
134134
effectivePopulationSize: opts && opts.effectivePopulationSize,
135135
genePoolSize: genesList.length,
136136
});
137-
var useDrift = driftEnabled || driftIntensity > 0.15;
137+
const useDrift = driftEnabled || driftIntensity > 0.15;
138138

139-
var DISTILLED_PREFIX = 'gene_distilled_';
140-
var DISTILLED_SCORE_FACTOR = 0.8;
139+
const DISTILLED_PREFIX = 'gene_distilled_';
140+
const DISTILLED_SCORE_FACTOR = 0.8;
141141

142142
const envFingerprint = captureEnvFingerprint();
143143
const scored = genesList
144144
.map(g => {
145-
var s = scoreGene(g, signals);
145+
let s = scoreGene(g, signals);
146146
s += scoreGeneLearning(g, signals, envFingerprint);
147147
if (s > 0 && g.id && String(g.id).startsWith(DISTILLED_PREFIX)) s *= DISTILLED_SCORE_FACTOR;
148148
return { gene: g, score: s };
@@ -174,26 +174,26 @@ function selectGene(genes, signals, opts) {
174174
// Diversity-directed drift: when capability gaps are available, prefer genes that
175175
// cover gap areas instead of pure random selection. This replaces the blind
176176
// random drift with an informed exploration toward under-covered capabilities.
177-
var selectedIdx = 0;
178-
var driftMode = 'selection';
177+
let selectedIdx = 0;
178+
let driftMode = 'selection';
179179
if (driftIntensity > 0 && filtered.length > 1 && Math.random() < driftIntensity) {
180180
if (capabilityGaps.length > 0) {
181181
// Directed drift: score each candidate by how well its signals_match
182182
// covers the capability gap dimensions
183-
var gapScores = filtered.map(function(entry, idx) {
184-
var g = entry.gene;
185-
var patterns = Array.isArray(g.signals_match) ? g.signals_match : [];
186-
var gapHits = 0;
187-
for (var gi = 0; gi < capabilityGaps.length && gi < 5; gi++) {
188-
var gapSignal = capabilityGaps[gi];
183+
const gapScores = filtered.map(function(entry, idx) {
184+
const g = entry.gene;
185+
const patterns = Array.isArray(g.signals_match) ? g.signals_match : [];
186+
let gapHits = 0;
187+
for (let gi = 0; gi < capabilityGaps.length && gi < 5; gi++) {
188+
const gapSignal = capabilityGaps[gi];
189189
if (typeof gapSignal === 'string' && patterns.some(function(p) { return matchPatternToSignals(p, [gapSignal]); })) {
190190
gapHits++;
191191
}
192192
}
193193
return { idx: idx, gapHits: gapHits, baseScore: entry.score };
194194
});
195195

196-
var hasGapHits = gapScores.some(function(gs) { return gs.gapHits > 0; });
196+
const hasGapHits = gapScores.some(function(gs) { return gs.gapHits > 0; });
197197
if (hasGapHits) {
198198
// Sort by gap coverage first, then by base score
199199
gapScores.sort(function(a, b) {
@@ -203,7 +203,7 @@ function selectGene(genes, signals, opts) {
203203
driftMode = 'diversity_directed';
204204
} else {
205205
// No gap match: fall back to novelty-weighted random selection
206-
var topN = Math.min(filtered.length, Math.max(2, Math.ceil(filtered.length * driftIntensity)));
206+
let topN = Math.min(filtered.length, Math.max(2, Math.ceil(filtered.length * driftIntensity)));
207207
// If novelty score is low (agent is too similar to others), increase exploration range
208208
if (noveltyScore != null && noveltyScore < 0.3 && topN < filtered.length) {
209209
topN = Math.min(filtered.length, topN + 1);
@@ -213,7 +213,7 @@ function selectGene(genes, signals, opts) {
213213
}
214214
} else {
215215
// No capability gap data: original random drift behavior
216-
var topN = Math.min(filtered.length, Math.max(2, Math.ceil(filtered.length * driftIntensity)));
216+
const topN = Math.min(filtered.length, Math.max(2, Math.ceil(filtered.length * driftIntensity)));
217217
selectedIdx = Math.floor(Math.random() * topN);
218218
driftMode = 'random';
219219
}
@@ -242,31 +242,31 @@ function selectCapsule(capsules, signals) {
242242
function computeSignalOverlap(signalsA, signalsB) {
243243
if (!Array.isArray(signalsA) || !Array.isArray(signalsB)) return 0;
244244
if (signalsA.length === 0 || signalsB.length === 0) return 0;
245-
var setB = new Set(signalsB.map(function (s) { return String(s).toLowerCase(); }));
246-
var hits = 0;
247-
for (var i = 0; i < signalsA.length; i++) {
245+
const setB = new Set(signalsB.map(function (s) { return String(s).toLowerCase(); }));
246+
let hits = 0;
247+
for (let i = 0; i < signalsA.length; i++) {
248248
if (setB.has(String(signalsA[i]).toLowerCase())) hits++;
249249
}
250250
return hits / Math.max(signalsA.length, 1);
251251
}
252252

253-
var FAILED_CAPSULE_BAN_THRESHOLD = 2;
254-
var FAILED_CAPSULE_OVERLAP_MIN = 0.6;
253+
const FAILED_CAPSULE_BAN_THRESHOLD = 2;
254+
const FAILED_CAPSULE_OVERLAP_MIN = 0.6;
255255

256256
function banGenesFromFailedCapsules(failedCapsules, signals, existingBans) {
257-
var bans = existingBans instanceof Set ? new Set(existingBans) : new Set();
257+
const bans = existingBans instanceof Set ? new Set(existingBans) : new Set();
258258
if (!Array.isArray(failedCapsules) || failedCapsules.length === 0) return bans;
259-
var geneFailCounts = {};
260-
for (var i = 0; i < failedCapsules.length; i++) {
261-
var fc = failedCapsules[i];
259+
const geneFailCounts = {};
260+
for (let i = 0; i < failedCapsules.length; i++) {
261+
const fc = failedCapsules[i];
262262
if (!fc || !fc.gene) continue;
263-
var overlap = computeSignalOverlap(signals, fc.trigger || []);
263+
const overlap = computeSignalOverlap(signals, fc.trigger || []);
264264
if (overlap < FAILED_CAPSULE_OVERLAP_MIN) continue;
265-
var gid = String(fc.gene);
265+
const gid = String(fc.gene);
266266
geneFailCounts[gid] = (geneFailCounts[gid] || 0) + 1;
267267
}
268-
var keys = Object.keys(geneFailCounts);
269-
for (var j = 0; j < keys.length; j++) {
268+
const keys = Object.keys(geneFailCounts);
269+
for (let j = 0; j < keys.length; j++) {
270270
if (geneFailCounts[keys[j]] >= FAILED_CAPSULE_BAN_THRESHOLD) {
271271
bans.add(keys[j]);
272272
}
@@ -279,7 +279,7 @@ function selectGeneAndCapsule({ genes, capsules, signals, memoryAdvice, driftEna
279279
memoryAdvice && memoryAdvice.bannedGeneIds instanceof Set ? memoryAdvice.bannedGeneIds : new Set();
280280
const preferredGeneId = memoryAdvice && memoryAdvice.preferredGeneId ? memoryAdvice.preferredGeneId : null;
281281

282-
var effectiveBans = banGenesFromFailedCapsules(
282+
const effectiveBans = banGenesFromFailedCapsules(
283283
Array.isArray(failedCapsules) ? failedCapsules : [],
284284
signals,
285285
bannedGeneIds

0 commit comments

Comments
 (0)