@evomap/evolver 1.67.4 → 1.67.6
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.
- package/README.ja-JP.md +55 -2
- package/README.md +55 -2
- package/README.zh-CN.md +55 -2
- package/SECURITY.md +66 -0
- package/assets/gep/candidates.jsonl +6 -2
- package/index.js +41 -25
- package/package.json +1 -1
- package/src/adapters/scripts/evolver-session-end.js +194 -0
- package/src/adapters/scripts/evolver-session-start.js +93 -0
- package/src/adapters/scripts/evolver-signal-detect.js +69 -0
- package/src/evolve.js +1 -1
- package/src/gep/.integrity +0 -0
- package/src/gep/a2aProtocol.js +1 -1
- package/src/gep/candidateEval.js +1 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/contentHash.js +1 -1
- package/src/gep/crypto.js +1 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +1 -1
- package/src/gep/envFingerprint.js +1 -1
- package/src/gep/explore.js +1 -1
- package/src/gep/hubReview.js +1 -1
- package/src/gep/hubSearch.js +1 -1
- package/src/gep/hubVerify.js +1 -1
- package/src/gep/integrityCheck.js +1 -1
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1 -1
- package/src/gep/memoryGraphAdapter.js +1 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/prompt.js +1 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/shield.js +1 -1
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// evolver-session-end.js
|
|
3
|
+
// Records evolution outcome at session end.
|
|
4
|
+
// Collects git diff stats, extracts signals, records via Hub API or local memory.
|
|
5
|
+
// Input: stdin JSON. Output: stdout JSON with followup_message.
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
|
|
11
|
+
function findEvolverRoot() {
|
|
12
|
+
const candidates = [
|
|
13
|
+
process.env.EVOLVER_ROOT,
|
|
14
|
+
path.resolve(__dirname, '..', '..', '..'),
|
|
15
|
+
];
|
|
16
|
+
for (const c of candidates) {
|
|
17
|
+
if (c && fs.existsSync(path.join(c, 'package.json'))) {
|
|
18
|
+
try {
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(c, 'package.json'), 'utf8'));
|
|
20
|
+
if (pkg.name === '@evomap/evolver' || pkg.name === 'evolver') return c;
|
|
21
|
+
} catch { /* skip */ }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const homeSkills = path.join(require('os').homedir(), 'skills', 'evolver');
|
|
25
|
+
if (fs.existsSync(path.join(homeSkills, 'package.json'))) return homeSkills;
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function findMemoryGraph(evolverRoot) {
|
|
30
|
+
if (process.env.MEMORY_GRAPH_PATH && fs.existsSync(process.env.MEMORY_GRAPH_PATH)) {
|
|
31
|
+
return process.env.MEMORY_GRAPH_PATH;
|
|
32
|
+
}
|
|
33
|
+
const candidates = [
|
|
34
|
+
evolverRoot && path.join(evolverRoot, 'memory', 'evolution', 'memory_graph.jsonl'),
|
|
35
|
+
evolverRoot && path.join(evolverRoot, 'MEMORY', 'evolution', 'memory_graph.jsonl'),
|
|
36
|
+
];
|
|
37
|
+
for (const c of candidates) {
|
|
38
|
+
if (c && fs.existsSync(c)) return c;
|
|
39
|
+
}
|
|
40
|
+
if (evolverRoot) {
|
|
41
|
+
const defaultPath = path.join(evolverRoot, 'memory', 'evolution', 'memory_graph.jsonl');
|
|
42
|
+
fs.mkdirSync(path.dirname(defaultPath), { recursive: true });
|
|
43
|
+
return defaultPath;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getGitDiffStats() {
|
|
49
|
+
try {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const stat = execSync('git diff --stat HEAD~1 2>/dev/null || git diff --stat 2>/dev/null || echo ""', {
|
|
52
|
+
cwd,
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
timeout: 5000,
|
|
55
|
+
}).trim();
|
|
56
|
+
const diffContent = execSync('git diff HEAD~1 --no-color 2>/dev/null || git diff --no-color 2>/dev/null || echo ""', {
|
|
57
|
+
cwd,
|
|
58
|
+
encoding: 'utf8',
|
|
59
|
+
timeout: 5000,
|
|
60
|
+
}).trim();
|
|
61
|
+
const filesChanged = (stat.match(/\d+ files? changed/) || ['0'])[0];
|
|
62
|
+
const insertions = (stat.match(/(\d+) insertions?/) || [null, '0'])[1];
|
|
63
|
+
const deletions = (stat.match(/(\d+) deletions?/) || [null, '0'])[1];
|
|
64
|
+
return {
|
|
65
|
+
stat,
|
|
66
|
+
summary: `${filesChanged}, +${insertions}/-${deletions}`,
|
|
67
|
+
diffSnippet: diffContent.slice(0, 2000),
|
|
68
|
+
hasChanges: stat.length > 0,
|
|
69
|
+
};
|
|
70
|
+
} catch {
|
|
71
|
+
return { stat: '', summary: 'unknown', diffSnippet: '', hasChanges: false };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function detectSignals(text) {
|
|
76
|
+
if (!text) return [];
|
|
77
|
+
const lower = text.toLowerCase();
|
|
78
|
+
const signals = [];
|
|
79
|
+
if (/error:|exception:|failed/i.test(lower)) signals.push('log_error');
|
|
80
|
+
if (/timeout|slow|latency|bottleneck/i.test(lower)) signals.push('perf_bottleneck');
|
|
81
|
+
if (/add|implement|feature|new function|new module/i.test(lower)) signals.push('user_feature_request');
|
|
82
|
+
if (/improve|enhance|refactor|optimize/i.test(lower)) signals.push('user_improvement_suggestion');
|
|
83
|
+
if (/not supported|unsupported|not implemented/i.test(lower)) signals.push('capability_gap');
|
|
84
|
+
if (/deploy|ci|pipeline|build failed/i.test(lower)) signals.push('deployment_issue');
|
|
85
|
+
if (/test fail|assertion|expect\(/i.test(lower)) signals.push('test_failure');
|
|
86
|
+
return [...new Set(signals)];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function recordToHub(outcome) {
|
|
90
|
+
const hubUrl = process.env.EVOMAP_HUB_URL || process.env.A2A_HUB_URL;
|
|
91
|
+
const apiKey = process.env.EVOMAP_API_KEY || process.env.A2A_NODE_SECRET;
|
|
92
|
+
const nodeId = process.env.EVOMAP_NODE_ID || process.env.A2A_NODE_ID;
|
|
93
|
+
if (!hubUrl || !apiKey) return false;
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const payload = JSON.stringify({
|
|
97
|
+
gene_id: outcome.geneId || 'ad_hoc',
|
|
98
|
+
signals: outcome.signals,
|
|
99
|
+
status: outcome.status,
|
|
100
|
+
score: outcome.score,
|
|
101
|
+
summary: outcome.summary,
|
|
102
|
+
sender_id: nodeId || undefined,
|
|
103
|
+
});
|
|
104
|
+
const curlCmd = `curl -s -m 8 -X POST`
|
|
105
|
+
+ ` -H "Content-Type: application/json"`
|
|
106
|
+
+ ` -H "Authorization: Bearer ${apiKey}"`
|
|
107
|
+
+ ` -d '${payload.replace(/'/g, "'\\''")}'`
|
|
108
|
+
+ ` "${hubUrl.replace(/\/+$/, '')}/a2a/evolution/record"`;
|
|
109
|
+
execSync(curlCmd, { timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function recordToLocal(graphPath, outcome) {
|
|
117
|
+
try {
|
|
118
|
+
const entry = {
|
|
119
|
+
timestamp: new Date().toISOString(),
|
|
120
|
+
gene_id: outcome.geneId || 'ad_hoc',
|
|
121
|
+
signals: outcome.signals,
|
|
122
|
+
outcome: {
|
|
123
|
+
status: outcome.status,
|
|
124
|
+
score: outcome.score,
|
|
125
|
+
note: outcome.summary,
|
|
126
|
+
},
|
|
127
|
+
source: 'hook:session-end',
|
|
128
|
+
};
|
|
129
|
+
fs.appendFileSync(graphPath, JSON.stringify(entry) + '\n', 'utf8');
|
|
130
|
+
return true;
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function main() {
|
|
137
|
+
let inputData = '';
|
|
138
|
+
let handled = false;
|
|
139
|
+
process.stdin.setEncoding('utf8');
|
|
140
|
+
process.stdin.on('data', chunk => { inputData += chunk; });
|
|
141
|
+
process.stdin.on('end', () => {
|
|
142
|
+
if (handled) return;
|
|
143
|
+
handled = true;
|
|
144
|
+
try {
|
|
145
|
+
const diffInfo = getGitDiffStats();
|
|
146
|
+
|
|
147
|
+
if (!diffInfo.hasChanges) {
|
|
148
|
+
process.stdout.write(JSON.stringify({}));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const signals = detectSignals(diffInfo.diffSnippet);
|
|
153
|
+
if (signals.length === 0) signals.push('stable_success_plateau');
|
|
154
|
+
|
|
155
|
+
const hasErrors = signals.includes('log_error') || signals.includes('test_failure');
|
|
156
|
+
const status = hasErrors ? 'failed' : 'success';
|
|
157
|
+
const score = hasErrors ? 0.3 : 0.8;
|
|
158
|
+
|
|
159
|
+
const outcome = {
|
|
160
|
+
geneId: 'ad_hoc',
|
|
161
|
+
signals,
|
|
162
|
+
status,
|
|
163
|
+
score,
|
|
164
|
+
summary: `Session end: ${diffInfo.summary}. Signals: [${signals.join(', ')}]`,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const evolverRoot = findEvolverRoot();
|
|
168
|
+
const graphPath = findMemoryGraph(evolverRoot);
|
|
169
|
+
|
|
170
|
+
const hubOk = recordToHub(outcome);
|
|
171
|
+
const localOk = graphPath ? recordToLocal(graphPath, outcome) : false;
|
|
172
|
+
|
|
173
|
+
const target = hubOk ? 'Hub' : localOk ? 'local memory' : 'nowhere (no Hub or local path)';
|
|
174
|
+
const msg = `[Evolution] Session outcome recorded to ${target}: ${outcome.summary}`;
|
|
175
|
+
|
|
176
|
+
process.stdout.write(JSON.stringify({
|
|
177
|
+
followup_message: msg,
|
|
178
|
+
stopMessage: msg,
|
|
179
|
+
additionalContext: msg,
|
|
180
|
+
}));
|
|
181
|
+
} catch (e) {
|
|
182
|
+
process.stdout.write(JSON.stringify({}));
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
if (handled) return;
|
|
188
|
+
handled = true;
|
|
189
|
+
process.stdout.write(JSON.stringify({}));
|
|
190
|
+
process.exit(0);
|
|
191
|
+
}, 7000);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
main();
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// evolver-session-start.js
|
|
3
|
+
// Reads recent evolution memory and injects it as context for the agent session.
|
|
4
|
+
// Input: stdin JSON (session context). Output: stdout JSON with agent_message.
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
function findEvolverRoot() {
|
|
10
|
+
const candidates = [
|
|
11
|
+
process.env.EVOLVER_ROOT,
|
|
12
|
+
path.resolve(__dirname, '..', '..', '..'),
|
|
13
|
+
];
|
|
14
|
+
for (const c of candidates) {
|
|
15
|
+
if (c && fs.existsSync(path.join(c, 'package.json'))) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(c, 'package.json'), 'utf8'));
|
|
18
|
+
if (pkg.name === '@evomap/evolver' || pkg.name === 'evolver') return c;
|
|
19
|
+
} catch { /* skip */ }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const homeSkills = path.join(require('os').homedir(), 'skills', 'evolver');
|
|
23
|
+
if (fs.existsSync(path.join(homeSkills, 'package.json'))) return homeSkills;
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function findMemoryGraph(evolverRoot) {
|
|
28
|
+
if (process.env.MEMORY_GRAPH_PATH && fs.existsSync(process.env.MEMORY_GRAPH_PATH)) {
|
|
29
|
+
return process.env.MEMORY_GRAPH_PATH;
|
|
30
|
+
}
|
|
31
|
+
const candidates = [
|
|
32
|
+
evolverRoot && path.join(evolverRoot, 'memory', 'evolution', 'memory_graph.jsonl'),
|
|
33
|
+
evolverRoot && path.join(evolverRoot, 'MEMORY', 'evolution', 'memory_graph.jsonl'),
|
|
34
|
+
];
|
|
35
|
+
for (const c of candidates) {
|
|
36
|
+
if (c && fs.existsSync(c)) return c;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readLastN(filePath, n) {
|
|
42
|
+
try {
|
|
43
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
44
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
45
|
+
return lines.slice(-n).map(line => {
|
|
46
|
+
try { return JSON.parse(line); } catch { return null; }
|
|
47
|
+
}).filter(Boolean);
|
|
48
|
+
} catch { return []; }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatOutcome(entry) {
|
|
52
|
+
const status = entry.outcome ? entry.outcome.status : 'unknown';
|
|
53
|
+
const score = entry.outcome && entry.outcome.score != null ? entry.outcome.score : '?';
|
|
54
|
+
const note = entry.outcome && entry.outcome.note ? entry.outcome.note : '';
|
|
55
|
+
const signals = Array.isArray(entry.signals) ? entry.signals.slice(0, 3).join(', ') : '';
|
|
56
|
+
const ts = entry.timestamp ? entry.timestamp.slice(0, 10) : '';
|
|
57
|
+
const icon = status === 'success' ? '+' : status === 'failed' ? '-' : '?';
|
|
58
|
+
return `[${icon}] ${ts} score=${score} signals=[${signals}] ${note}`.slice(0, 200);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function main() {
|
|
62
|
+
const evolverRoot = findEvolverRoot();
|
|
63
|
+
const graphPath = findMemoryGraph(evolverRoot);
|
|
64
|
+
|
|
65
|
+
if (!graphPath) {
|
|
66
|
+
process.stdout.write(JSON.stringify({}));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const entries = readLastN(graphPath, 5);
|
|
71
|
+
if (entries.length === 0) {
|
|
72
|
+
process.stdout.write(JSON.stringify({}));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const successCount = entries.filter(e => e.outcome && e.outcome.status === 'success').length;
|
|
77
|
+
const failCount = entries.filter(e => e.outcome && e.outcome.status === 'failed').length;
|
|
78
|
+
|
|
79
|
+
const lines = entries.map(formatOutcome);
|
|
80
|
+
const summary = [
|
|
81
|
+
`[Evolution Memory] Recent ${entries.length} outcomes (${successCount} success, ${failCount} failed):`,
|
|
82
|
+
...lines,
|
|
83
|
+
'',
|
|
84
|
+
'Use successful approaches. Avoid repeating failed patterns.',
|
|
85
|
+
].join('\n');
|
|
86
|
+
|
|
87
|
+
process.stdout.write(JSON.stringify({
|
|
88
|
+
agent_message: summary,
|
|
89
|
+
additionalContext: summary,
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
main();
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// evolver-signal-detect.js
|
|
3
|
+
// Lightweight signal detection on file edit events.
|
|
4
|
+
// Input: stdin JSON (edit event). Output: stdout JSON with additional_context.
|
|
5
|
+
|
|
6
|
+
const SIGNAL_KEYWORDS = {
|
|
7
|
+
perf_bottleneck: ['timeout', 'slow', 'latency', 'bottleneck', 'oom', 'out of memory', 'performance'],
|
|
8
|
+
capability_gap: ['not supported', 'unsupported', 'not implemented', 'missing feature', 'not available'],
|
|
9
|
+
log_error: ['error:', 'exception:', 'typeerror', 'referenceerror', 'syntaxerror', 'failed'],
|
|
10
|
+
user_feature_request: ['add feature', 'implement', 'new function', 'new module', 'please add'],
|
|
11
|
+
recurring_error: ['same error', 'still failing', 'not fixed', 'keeps failing', 'repeatedly'],
|
|
12
|
+
deployment_issue: ['deploy failed', 'build failed', 'ci failed', 'pipeline', 'rollback'],
|
|
13
|
+
test_failure: ['test failed', 'test failure', 'assertion', 'expect(', 'assert.'],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function detectSignals(text) {
|
|
17
|
+
if (!text || typeof text !== 'string') return [];
|
|
18
|
+
const lower = text.toLowerCase();
|
|
19
|
+
const found = [];
|
|
20
|
+
for (const [signal, keywords] of Object.entries(SIGNAL_KEYWORDS)) {
|
|
21
|
+
for (const kw of keywords) {
|
|
22
|
+
if (lower.includes(kw)) {
|
|
23
|
+
found.push(signal);
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [...new Set(found)];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main() {
|
|
32
|
+
let inputData = '';
|
|
33
|
+
let handled = false;
|
|
34
|
+
process.stdin.setEncoding('utf8');
|
|
35
|
+
process.stdin.on('data', chunk => { inputData += chunk; });
|
|
36
|
+
process.stdin.on('end', () => {
|
|
37
|
+
if (handled) return;
|
|
38
|
+
handled = true;
|
|
39
|
+
try {
|
|
40
|
+
const input = inputData.trim() ? JSON.parse(inputData) : {};
|
|
41
|
+
const content = input.content || input.file_content || input.diff || '';
|
|
42
|
+
const filePath = input.path || input.file_path || '';
|
|
43
|
+
|
|
44
|
+
const signals = detectSignals(content);
|
|
45
|
+
|
|
46
|
+
if (signals.length === 0) {
|
|
47
|
+
process.stdout.write(JSON.stringify({}));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const ctx = `[Evolution Signal] Detected: [${signals.join(', ')}] in ${filePath || 'edited file'}. Consider recording this outcome.`;
|
|
52
|
+
process.stdout.write(JSON.stringify({
|
|
53
|
+
additional_context: ctx,
|
|
54
|
+
additionalContext: ctx,
|
|
55
|
+
}));
|
|
56
|
+
} catch {
|
|
57
|
+
process.stdout.write(JSON.stringify({}));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
if (handled) return;
|
|
63
|
+
handled = true;
|
|
64
|
+
process.stdout.write(JSON.stringify({}));
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}, 1500);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main();
|