@evomap/evolver 1.89.3 → 1.89.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.
- package/.cursor/BUGBOT.md +182 -0
- package/.env.example +68 -0
- package/.git-commit-guard-token +1 -0
- package/.github/CODEOWNERS +63 -0
- package/.github/ISSUE_TEMPLATE/good_first_issue.md +23 -0
- package/.github/pull_request_template.md +45 -0
- package/.github/workflows/test.yml +75 -0
- package/CHANGELOG.md +1237 -0
- package/README.md +86 -528
- package/README.public.md +569 -0
- package/SECURITY.md +108 -0
- package/assets/gep/events.jsonl +3 -0
- package/examples/atp-consumer-quickstart.md +100 -0
- package/examples/hello-world.md +38 -0
- package/index.js +30 -1
- package/package.json +6 -17
- package/proxy-package.json +39 -0
- package/public.manifest.json +143 -0
- package/src/config.js +23 -0
- package/src/evolve/guards.js +721 -1
- package/src/evolve/pipeline/collect.js +1283 -1
- package/src/evolve/pipeline/dispatch.js +421 -1
- package/src/evolve/pipeline/enrich.js +440 -1
- package/src/evolve/pipeline/hub.js +319 -1
- package/src/evolve/pipeline/select.js +274 -1
- package/src/evolve/pipeline/signals.js +206 -1
- package/src/evolve/utils.js +264 -1
- package/src/evolve.js +350 -1
- package/src/experiment/agentRunner.js +229 -0
- package/src/experiment/cli.js +159 -0
- package/src/experiment/comparison.js +233 -0
- package/src/experiment/metrics.js +75 -0
- package/src/forceUpdate.js +147 -59
- package/src/gep/a2aProtocol.js +4455 -1
- package/src/gep/antiAbuseTelemetry.js +233 -0
- package/src/gep/autoDistillConv.js +205 -1
- package/src/gep/autoDistillLlm.js +315 -1
- package/src/gep/candidateEval.js +92 -1
- package/src/gep/candidates.js +198 -1
- package/src/gep/contentHash.js +30 -1
- package/src/gep/conversationSniffer.js +266 -1
- package/src/gep/crypto.js +89 -1
- package/src/gep/curriculum.js +163 -1
- package/src/gep/deviceId.js +218 -1
- package/src/gep/envFingerprint.js +118 -1
- package/src/gep/epigenetics.js +31 -1
- package/src/gep/execBridge.js +711 -1
- package/src/gep/explore.js +289 -1
- package/src/gep/hash.js +15 -1
- package/src/gep/hubFetch.js +359 -1
- package/src/gep/hubReview.js +207 -1
- package/src/gep/hubSearch.js +526 -1
- package/src/gep/hubVerify.js +306 -1
- package/src/gep/learningSignals.js +89 -1
- package/src/gep/memoryGraph.js +1374 -1
- package/src/gep/memoryGraphAdapter.js +203 -1
- package/src/gep/mutation.js +203 -1
- package/src/gep/narrativeMemory.js +108 -1
- package/src/gep/openPRRegistry.js +205 -1
- package/src/gep/personality.js +423 -1
- package/src/gep/policyCheck.js +599 -1
- package/src/gep/prompt.js +836 -1
- package/src/gep/recallInject.js +409 -1
- package/src/gep/recallVerifier.js +318 -1
- package/src/gep/reflection.js +177 -1
- package/src/gep/sanitize.js +9 -0
- package/src/gep/selector.js +602 -1
- package/src/gep/skillDistiller.js +1294 -1
- package/src/gep/solidify.js +1699 -1
- package/src/gep/strategy.js +136 -1
- package/src/gep/tokenSavings.js +88 -1
- package/src/gep/validator/sandboxExecutor.js +29 -1
- package/src/gep/workspaceKeychain.js +174 -1
- package/src/proxy/extensions/traceControl.js +99 -1
- package/src/proxy/index.js +10 -1
- package/src/proxy/inject.js +52 -1
- package/src/proxy/lifecycle/manager.js +19 -0
- package/src/proxy/mailbox/store.js +2 -1
- package/src/proxy/router/messages_route.js +5 -2
- package/src/proxy/trace/extractor.js +646 -1
- package/src/proxy/trace/usage.js +105 -1
- package/CONTRIBUTING.md +0 -19
- package/assets/cover.png +0 -0
- package/scripts/a2a_export.js +0 -63
- package/scripts/a2a_ingest.js +0 -79
- package/scripts/a2a_promote.js +0 -118
- package/scripts/analyze_by_skill.js +0 -121
- package/scripts/build_binaries.js +0 -479
- package/scripts/check-changelog.js +0 -166
- package/scripts/extract_log.js +0 -85
- package/scripts/generate_history.js +0 -75
- package/scripts/gep_append_event.js +0 -96
- package/scripts/gep_personality_report.js +0 -234
- package/scripts/human_report.js +0 -147
- package/scripts/recall-verify-report.js +0 -234
- package/scripts/recover_loop.js +0 -61
- package/scripts/refresh_stars_badge.js +0 -168
- package/scripts/seed-merchants.js +0 -91
- package/scripts/suggest_version.js +0 -89
- package/scripts/validate-modules.js +0 -38
- package/scripts/validate-suite.js +0 -78
- package/skills/index.json +0 -14
- /package/assets/gep/{genes.seed.json → genes.json} +0 -0
- /package/{skills → bundled-skills}/_meta/SKILL.md +0 -0
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
// recall-verify-report — aggregate kind=recall_verify events from the
|
|
5
|
-
// memory graph jsonl into a Markdown table. Exit 0 = ship gate green
|
|
6
|
-
// (every asset_type has success_rate >= 0.95 and 0 mismatches), exit 2
|
|
7
|
-
// otherwise. Designed to be scripted into deploy.sh as a pre-publish gate.
|
|
8
|
-
//
|
|
9
|
-
// Usage:
|
|
10
|
-
// node scripts/recall-verify-report.js # all events
|
|
11
|
-
// node scripts/recall-verify-report.js --since 1h # last hour
|
|
12
|
-
// node scripts/recall-verify-report.js --since 30m
|
|
13
|
-
// node scripts/recall-verify-report.js --since 2026-05-16T10:00:00Z
|
|
14
|
-
// node scripts/recall-verify-report.js --json # raw JSON for piping
|
|
15
|
-
|
|
16
|
-
const { tryReadMemoryGraphEvents } = require('../src/gep/memoryGraph');
|
|
17
|
-
|
|
18
|
-
const SUCCESS_THRESHOLD = 0.95;
|
|
19
|
-
|
|
20
|
-
function parseSince(value) {
|
|
21
|
-
if (!value) return null;
|
|
22
|
-
// Try relative duration first (1h / 30m / 2d / 45s) — unambiguous.
|
|
23
|
-
const m = String(value).match(/^(\d+)\s*(s|m|h|d)$/i);
|
|
24
|
-
if (m) {
|
|
25
|
-
const n = Number(m[1]);
|
|
26
|
-
const unit = m[2].toLowerCase();
|
|
27
|
-
const factor = unit === 's' ? 1000 : unit === 'm' ? 60000 : unit === 'h' ? 3600000 : 86400000;
|
|
28
|
-
return Date.now() - (n * factor);
|
|
29
|
-
}
|
|
30
|
-
// Then ISO-8601. Require '-' or 'T' so we don't accept loose numeric
|
|
31
|
-
// strings like "5" → year 2001.
|
|
32
|
-
if (/[-T]/.test(String(value))) {
|
|
33
|
-
const iso = Date.parse(value);
|
|
34
|
-
if (!Number.isNaN(iso)) return iso;
|
|
35
|
-
}
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function parseArgs(argv) {
|
|
40
|
-
const args = { since: null, json: false };
|
|
41
|
-
for (let i = 2; i < argv.length; i++) {
|
|
42
|
-
const a = argv[i];
|
|
43
|
-
if (a === '--json') args.json = true;
|
|
44
|
-
else if (a === '--since') {
|
|
45
|
-
args.since = argv[++i];
|
|
46
|
-
} else if (a.startsWith('--since=')) {
|
|
47
|
-
args.since = a.slice('--since='.length);
|
|
48
|
-
} else if (a === '--help' || a === '-h') {
|
|
49
|
-
args.help = true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return args;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function percentile(sorted, p) {
|
|
56
|
-
if (!sorted.length) return 0;
|
|
57
|
-
const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * p));
|
|
58
|
-
return sorted[idx];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function aggregate(events) {
|
|
62
|
-
const byType = new Map();
|
|
63
|
-
for (const ev of events) {
|
|
64
|
-
if (!ev || ev.kind !== 'recall_verify') continue;
|
|
65
|
-
const type = (ev.asset && ev.asset.type) || 'Unknown';
|
|
66
|
-
if (!byType.has(type)) {
|
|
67
|
-
byType.set(type, {
|
|
68
|
-
type,
|
|
69
|
-
total: 0,
|
|
70
|
-
ok: 0,
|
|
71
|
-
missing: 0,
|
|
72
|
-
mismatch: 0,
|
|
73
|
-
skipped: 0,
|
|
74
|
-
latencies: [],
|
|
75
|
-
ages: [],
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
const bucket = byType.get(type);
|
|
79
|
-
bucket.total += 1;
|
|
80
|
-
const v = ev.verification || {};
|
|
81
|
-
if (v.outcome === 'roundtrip_ok') bucket.ok += 1;
|
|
82
|
-
else if (v.outcome === 'roundtrip_missing') bucket.missing += 1;
|
|
83
|
-
else if (v.outcome === 'roundtrip_mismatch') bucket.mismatch += 1;
|
|
84
|
-
else bucket.skipped += 1;
|
|
85
|
-
if (Number.isFinite(v.latency_ms)) bucket.latencies.push(v.latency_ms);
|
|
86
|
-
if (Number.isFinite(v.age_at_verify_ms)) bucket.ages.push(v.age_at_verify_ms);
|
|
87
|
-
}
|
|
88
|
-
const rows = [];
|
|
89
|
-
for (const bucket of byType.values()) {
|
|
90
|
-
const denom = bucket.ok + bucket.missing + bucket.mismatch;
|
|
91
|
-
bucket.success_rate = denom > 0 ? bucket.ok / denom : 0;
|
|
92
|
-
bucket.latencies.sort(function (a, b) { return a - b; });
|
|
93
|
-
bucket.ages.sort(function (a, b) { return a - b; });
|
|
94
|
-
bucket.p50_latency_ms = percentile(bucket.latencies, 0.5);
|
|
95
|
-
bucket.p95_latency_ms = percentile(bucket.latencies, 0.95);
|
|
96
|
-
bucket.p99_latency_ms = percentile(bucket.latencies, 0.99);
|
|
97
|
-
bucket.p50_age_ms = percentile(bucket.ages, 0.5);
|
|
98
|
-
bucket.p95_age_ms = percentile(bucket.ages, 0.95);
|
|
99
|
-
bucket.p99_age_ms = percentile(bucket.ages, 0.99);
|
|
100
|
-
delete bucket.latencies;
|
|
101
|
-
delete bucket.ages;
|
|
102
|
-
rows.push(bucket);
|
|
103
|
-
}
|
|
104
|
-
rows.sort(function (a, b) { return a.type.localeCompare(b.type); });
|
|
105
|
-
|
|
106
|
-
const totals = { type: 'TOTAL', total: 0, ok: 0, missing: 0, mismatch: 0, skipped: 0 };
|
|
107
|
-
for (const r of rows) {
|
|
108
|
-
totals.total += r.total;
|
|
109
|
-
totals.ok += r.ok;
|
|
110
|
-
totals.missing += r.missing;
|
|
111
|
-
totals.mismatch += r.mismatch;
|
|
112
|
-
totals.skipped += r.skipped;
|
|
113
|
-
}
|
|
114
|
-
const totalsDenom = totals.ok + totals.missing + totals.mismatch;
|
|
115
|
-
totals.success_rate = totalsDenom > 0 ? totals.ok / totalsDenom : 0;
|
|
116
|
-
|
|
117
|
-
// Gate severity is monotonic: once a row triggers a worse state, later
|
|
118
|
-
// rows cannot downgrade it. Without this, AntiPattern@0% (RED) followed
|
|
119
|
-
// by Capsule@90% (YELLOW) would report YELLOW — misleading dashboards
|
|
120
|
-
// even though the exit code still reflects RED. (Bugbot review on PR #53.)
|
|
121
|
-
// RANK is the comparison ordinal: GREEN(0) < YELLOW(1) < RED(2).
|
|
122
|
-
const RANK = { GREEN: 0, YELLOW: 1, RED: 2 };
|
|
123
|
-
function escalate(current, candidate) {
|
|
124
|
-
return RANK[candidate] > RANK[current] ? candidate : current;
|
|
125
|
-
}
|
|
126
|
-
let gate = 'GREEN';
|
|
127
|
-
if (rows.length === 0) gate = 'RED';
|
|
128
|
-
else {
|
|
129
|
-
for (const r of rows) {
|
|
130
|
-
if (r.mismatch > 0) { gate = 'RED'; break; }
|
|
131
|
-
if (r.success_rate < SUCCESS_THRESHOLD) {
|
|
132
|
-
gate = escalate(gate, r.success_rate >= 0.85 ? 'YELLOW' : 'RED');
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return { rows, totals, gate };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function fmtPct(rate) {
|
|
140
|
-
return (rate * 100).toFixed(1) + '%';
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function fmtMs(n) {
|
|
144
|
-
if (!Number.isFinite(n) || n === 0) return '—';
|
|
145
|
-
if (n < 1000) return Math.round(n) + 'ms';
|
|
146
|
-
return (n / 1000).toFixed(1) + 's';
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function printMarkdown(result, since) {
|
|
150
|
-
const sinceStr = since ? new Date(since).toISOString() : 'all time';
|
|
151
|
-
console.log('# RecallVerify Report (since ' + sinceStr + ')');
|
|
152
|
-
console.log('');
|
|
153
|
-
if (result.rows.length === 0) {
|
|
154
|
-
console.log('_No `recall_verify` events found in memory graph._');
|
|
155
|
-
console.log('');
|
|
156
|
-
console.log('Ship gate: **RED** (no data — feature may be disabled or daemon has not run a publish cycle yet)');
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
console.log('| asset_type | total | ok | missing | mismatch | skipped | success_rate | p50_latency | p99_latency | p50_age | p99_age |');
|
|
160
|
-
console.log('|--------------|------:|----:|--------:|---------:|--------:|-------------:|------------:|------------:|--------:|--------:|');
|
|
161
|
-
for (const r of result.rows) {
|
|
162
|
-
console.log('| ' + r.type.padEnd(12) +
|
|
163
|
-
' | ' + String(r.total).padStart(5) +
|
|
164
|
-
' | ' + String(r.ok).padStart(3) +
|
|
165
|
-
' | ' + String(r.missing).padStart(7) +
|
|
166
|
-
' | ' + String(r.mismatch).padStart(8) +
|
|
167
|
-
' | ' + String(r.skipped).padStart(7) +
|
|
168
|
-
' | ' + fmtPct(r.success_rate).padStart(12) +
|
|
169
|
-
' | ' + fmtMs(r.p50_latency_ms).padStart(11) +
|
|
170
|
-
' | ' + fmtMs(r.p99_latency_ms).padStart(11) +
|
|
171
|
-
' | ' + fmtMs(r.p50_age_ms).padStart(7) +
|
|
172
|
-
' | ' + fmtMs(r.p99_age_ms).padStart(7) +
|
|
173
|
-
' |');
|
|
174
|
-
}
|
|
175
|
-
const t = result.totals;
|
|
176
|
-
console.log('| ' + 'TOTAL'.padEnd(12) +
|
|
177
|
-
' | ' + String(t.total).padStart(5) +
|
|
178
|
-
' | ' + String(t.ok).padStart(3) +
|
|
179
|
-
' | ' + String(t.missing).padStart(7) +
|
|
180
|
-
' | ' + String(t.mismatch).padStart(8) +
|
|
181
|
-
' | ' + String(t.skipped).padStart(7) +
|
|
182
|
-
' | ' + fmtPct(t.success_rate).padStart(12) +
|
|
183
|
-
' | ' + '—'.padStart(11) +
|
|
184
|
-
' | ' + '—'.padStart(11) +
|
|
185
|
-
' | ' + '—'.padStart(7) +
|
|
186
|
-
' | ' + '—'.padStart(7) +
|
|
187
|
-
' |');
|
|
188
|
-
console.log('');
|
|
189
|
-
console.log('Ship gate: **' + result.gate + '**' + (result.gate === 'GREEN' ? ' (exit 0)' : ' (exit 2)'));
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function main() {
|
|
193
|
-
const args = parseArgs(process.argv);
|
|
194
|
-
if (args.help) {
|
|
195
|
-
console.log('Usage: node scripts/recall-verify-report.js [--since <Nh|Nm|Nd|ISO>] [--json]');
|
|
196
|
-
process.exit(0);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
let sinceMs = null;
|
|
200
|
-
if (args.since) {
|
|
201
|
-
const parsed = parseSince(args.since);
|
|
202
|
-
if (parsed === undefined) {
|
|
203
|
-
console.error('Error: --since must be ISO-8601 or a duration like 1h / 30m / 2d (got: ' + args.since + ')');
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
sinceMs = parsed;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const allEvents = tryReadMemoryGraphEvents(20000);
|
|
210
|
-
const filtered = allEvents.filter(function (ev) {
|
|
211
|
-
if (!ev || ev.kind !== 'recall_verify') return false;
|
|
212
|
-
if (sinceMs != null && Number.isFinite(ev.ts) && ev.ts < sinceMs) return false;
|
|
213
|
-
return true;
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
const result = aggregate(filtered);
|
|
217
|
-
|
|
218
|
-
if (args.json) {
|
|
219
|
-
console.log(JSON.stringify({
|
|
220
|
-
since: sinceMs ? new Date(sinceMs).toISOString() : null,
|
|
221
|
-
...result,
|
|
222
|
-
}, null, 2));
|
|
223
|
-
} else {
|
|
224
|
-
printMarkdown(result, sinceMs);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
process.exit(result.gate === 'GREEN' ? 0 : 2);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (require.main === module) {
|
|
231
|
-
main();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
module.exports = { aggregate, parseSince, parseArgs };
|
package/scripts/recover_loop.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { spawnSync } = require('child_process');
|
|
6
|
-
|
|
7
|
-
function exists(p) {
|
|
8
|
-
try {
|
|
9
|
-
return fs.existsSync(p);
|
|
10
|
-
} catch (e) {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function sleepMs(ms) {
|
|
16
|
-
const n = Number(ms);
|
|
17
|
-
const t = Number.isFinite(n) ? Math.max(0, n) : 0;
|
|
18
|
-
if (t <= 0) return;
|
|
19
|
-
spawnSync('sleep', [String(Math.ceil(t / 1000))], { stdio: 'ignore' });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function resolveWorkspaceRoot() {
|
|
23
|
-
// In OpenClaw exec, cwd is usually the workspace root.
|
|
24
|
-
// Keep it simple: do not try to walk up arbitrarily.
|
|
25
|
-
return process.cwd();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function resolveEvolverEntry(workspaceRoot) {
|
|
29
|
-
const candidates = [
|
|
30
|
-
path.join(workspaceRoot, 'skills', 'evolver', 'index.js'),
|
|
31
|
-
path.join(workspaceRoot, 'skills', 'capability-evolver', 'index.js'),
|
|
32
|
-
];
|
|
33
|
-
for (const p of candidates) {
|
|
34
|
-
if (exists(p)) return p;
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function main() {
|
|
40
|
-
const waitMs = parseInt(String(process.env.EVOLVER_RECOVER_WAIT_MS || '10000'), 10);
|
|
41
|
-
const wait = Number.isFinite(waitMs) ? Math.max(0, waitMs) : 10000;
|
|
42
|
-
|
|
43
|
-
console.log(`[RECOVERY] Waiting ${wait}ms before restart...`);
|
|
44
|
-
sleepMs(wait);
|
|
45
|
-
|
|
46
|
-
const workspaceRoot = resolveWorkspaceRoot();
|
|
47
|
-
const entry = resolveEvolverEntry(workspaceRoot);
|
|
48
|
-
if (!entry) {
|
|
49
|
-
console.error('[RECOVERY] Failed: cannot locate evolver entry under skills/.');
|
|
50
|
-
process.exit(2);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
console.log(`[RECOVERY] Restarting loop via ${path.relative(workspaceRoot, entry)} ...`);
|
|
54
|
-
const r = spawnSync(process.execPath, [entry, '--loop'], { stdio: 'inherit' });
|
|
55
|
-
process.exit(typeof r.status === 'number' ? r.status : 1);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (require.main === module) {
|
|
59
|
-
main();
|
|
60
|
-
}
|
|
61
|
-
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
// refresh_stars_badge.js -- Refresh the static "Stars" badge count in the
|
|
2
|
-
// public README sources to the live GitHub star count.
|
|
3
|
-
//
|
|
4
|
-
// Why this exists:
|
|
5
|
-
// The README stars badge is intentionally STATIC (a plain shields `badge/`
|
|
6
|
-
// URL, not a dynamic `github/stars` one) so it never renders shields.io's
|
|
7
|
-
// "Unable to select next GitHub token from pool" error when their shared
|
|
8
|
-
// GitHub token pool is rate-limited. The trade-off is that the number goes
|
|
9
|
-
// stale. This script re-stamps it at release time so the badge stays current
|
|
10
|
-
// without ever depending on the GitHub API to *render*.
|
|
11
|
-
//
|
|
12
|
-
// Usage:
|
|
13
|
-
// node scripts/refresh_stars_badge.js # update in place
|
|
14
|
-
// node scripts/refresh_stars_badge.js --dry-run # print, write nothing
|
|
15
|
-
// node scripts/refresh_stars_badge.js --repo=O/N # override repo
|
|
16
|
-
// node scripts/refresh_stars_badge.js --count=12345 # skip fetch (testing)
|
|
17
|
-
//
|
|
18
|
-
// Design notes:
|
|
19
|
-
// - Counts come from the PUBLIC repo (default EvoMap/evolver), not this
|
|
20
|
-
// private dev repo.
|
|
21
|
-
// - Fetch uses the already-authenticated `gh` CLI first (deploy.sh preflight
|
|
22
|
-
// guarantees gh auth), falling back to the unauthenticated GitHub REST API.
|
|
23
|
-
// - A fetch failure is NON-FATAL: we warn and exit 0, leaving the badge as
|
|
24
|
-
// is. A flaky GitHub API must never break a release -- avoiding exactly
|
|
25
|
-
// that fragility is the whole reason the badge is static.
|
|
26
|
-
// - It rewrites every README*.md in the repo root that contains the badge,
|
|
27
|
-
// so new translations are picked up automatically.
|
|
28
|
-
|
|
29
|
-
const fs = require('fs');
|
|
30
|
-
const path = require('path');
|
|
31
|
-
const https = require('https');
|
|
32
|
-
const { execSync } = require('child_process');
|
|
33
|
-
|
|
34
|
-
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
35
|
-
const DEFAULT_REPO = 'EvoMap/evolver';
|
|
36
|
-
|
|
37
|
-
// Matches the value segment of `.../badge/Stars-<value>-<color>...` in a
|
|
38
|
-
// shields static badge URL. The value never contains `-` or `/`. Returns a
|
|
39
|
-
// fresh regex each call so callers never share `lastIndex` state.
|
|
40
|
-
const starsBadgeRe = () => /(img\.shields\.io\/badge\/Stars-)([^-/)]+)(-)/g;
|
|
41
|
-
|
|
42
|
-
// Replace the Stars badge value in `content` with `value`. Pure; returns the
|
|
43
|
-
// rewritten string (unchanged if there is no badge or it already matches).
|
|
44
|
-
function rewriteStarsValue(content, value) {
|
|
45
|
-
return content.replace(starsBadgeRe(), (_m, pre, _old, post) => `${pre}${value}${post}`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function parseArgs(argv) {
|
|
49
|
-
const opts = { dryRun: false, repo: DEFAULT_REPO, count: null };
|
|
50
|
-
for (const arg of argv) {
|
|
51
|
-
if (arg === '--dry-run' || arg === '-n') opts.dryRun = true;
|
|
52
|
-
else if (arg.startsWith('--repo=')) opts.repo = arg.slice('--repo='.length);
|
|
53
|
-
else if (arg.startsWith('--count=')) opts.count = Number(arg.slice('--count='.length));
|
|
54
|
-
}
|
|
55
|
-
return opts;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Format an integer the way shields.io's `metric` text formatter does, so the
|
|
59
|
-
// static badge is visually indistinguishable from a dynamic one:
|
|
60
|
-
// 8336 -> "8.3k", 12345 -> "12k", 1100 -> "1.1k", 999 -> "999".
|
|
61
|
-
function metric(n) {
|
|
62
|
-
n = Number(n);
|
|
63
|
-
if (!Number.isFinite(n) || n < 0) return String(n);
|
|
64
|
-
for (const [suffix, size] of [['G', 1e9], ['M', 1e6], ['k', 1e3]]) {
|
|
65
|
-
if (n >= size) {
|
|
66
|
-
const value = n / size;
|
|
67
|
-
const text = value < 10
|
|
68
|
-
? value.toFixed(1).replace(/\.0$/, '')
|
|
69
|
-
: String(Math.round(value));
|
|
70
|
-
return text + suffix;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return String(Math.round(n));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function fetchStarsViaGh(repo) {
|
|
77
|
-
try {
|
|
78
|
-
const out = execSync(`gh api repos/${repo} --jq .stargazers_count`, {
|
|
79
|
-
encoding: 'utf8',
|
|
80
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
81
|
-
}).trim();
|
|
82
|
-
const n = Number(out);
|
|
83
|
-
return Number.isFinite(n) && n > 0 ? n : null;
|
|
84
|
-
} catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function fetchStarsViaApi(repo) {
|
|
90
|
-
return new Promise((resolve) => {
|
|
91
|
-
const req = https.get(
|
|
92
|
-
`https://api.github.com/repos/${repo}`,
|
|
93
|
-
{ headers: { 'User-Agent': 'evolver-refresh-stars-badge', Accept: 'application/vnd.github+json' } },
|
|
94
|
-
(res) => {
|
|
95
|
-
if (res.statusCode !== 200) { res.resume(); return resolve(null); }
|
|
96
|
-
let body = '';
|
|
97
|
-
res.on('data', (c) => (body += c));
|
|
98
|
-
res.on('end', () => {
|
|
99
|
-
try {
|
|
100
|
-
const n = Number(JSON.parse(body).stargazers_count);
|
|
101
|
-
resolve(Number.isFinite(n) && n > 0 ? n : null);
|
|
102
|
-
} catch { resolve(null); }
|
|
103
|
-
});
|
|
104
|
-
},
|
|
105
|
-
);
|
|
106
|
-
req.on('error', () => resolve(null));
|
|
107
|
-
req.setTimeout(10000, () => { req.destroy(); resolve(null); });
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function resolveStarCount(opts) {
|
|
112
|
-
if (Number.isFinite(opts.count) && opts.count > 0) return opts.count;
|
|
113
|
-
return fetchStarsViaGh(opts.repo) || (await fetchStarsViaApi(opts.repo));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function readmeFilesWithBadge() {
|
|
117
|
-
return fs
|
|
118
|
-
.readdirSync(REPO_ROOT)
|
|
119
|
-
.filter((f) => /^README.*\.md$/.test(f))
|
|
120
|
-
.map((f) => path.join(REPO_ROOT, f))
|
|
121
|
-
.filter((p) => starsBadgeRe().test(fs.readFileSync(p, 'utf8')));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async function main() {
|
|
125
|
-
const opts = parseArgs(process.argv.slice(2));
|
|
126
|
-
|
|
127
|
-
const count = await resolveStarCount(opts);
|
|
128
|
-
if (count == null) {
|
|
129
|
-
console.warn('[refresh-stars-badge] could not resolve star count (gh + API both failed); leaving badge unchanged');
|
|
130
|
-
return; // non-fatal
|
|
131
|
-
}
|
|
132
|
-
const value = metric(count);
|
|
133
|
-
console.log(`[refresh-stars-badge] ${opts.repo} = ${count} stars -> "${value}"`);
|
|
134
|
-
|
|
135
|
-
const files = readmeFilesWithBadge();
|
|
136
|
-
if (files.length === 0) {
|
|
137
|
-
console.warn('[refresh-stars-badge] no README*.md with a Stars badge found; nothing to do');
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
let changed = 0;
|
|
142
|
-
for (const file of files) {
|
|
143
|
-
const before = fs.readFileSync(file, 'utf8');
|
|
144
|
-
const after = rewriteStarsValue(before, value);
|
|
145
|
-
const rel = path.relative(REPO_ROOT, file);
|
|
146
|
-
if (after === before) {
|
|
147
|
-
console.log(` ${rel}: already "${value}"`);
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (opts.dryRun) {
|
|
151
|
-
console.log(` [dry-run] ${rel}: would set Stars -> "${value}"`);
|
|
152
|
-
} else {
|
|
153
|
-
fs.writeFileSync(file, after);
|
|
154
|
-
console.log(` ${rel}: Stars -> "${value}"`);
|
|
155
|
-
}
|
|
156
|
-
changed++;
|
|
157
|
-
}
|
|
158
|
-
console.log(`[refresh-stars-badge] ${changed} file(s) ${opts.dryRun ? 'would change' : 'updated'}`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (require.main === module) {
|
|
162
|
-
main().catch((e) => {
|
|
163
|
-
// Never fail the release over a badge refresh.
|
|
164
|
-
console.warn(`[refresh-stars-badge] unexpected error (ignored): ${e && e.message}`);
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
module.exports = { metric, rewriteStarsValue };
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Seed Merchants -- registers 3 merchant services on the ATP network.
|
|
3
|
-
// Run once to bootstrap the network with available service listings.
|
|
4
|
-
//
|
|
5
|
-
// Usage:
|
|
6
|
-
// A2A_HUB_URL=https://evomap.ai node scripts/seed-merchants.js
|
|
7
|
-
|
|
8
|
-
const { merchantAgent } = require('../src/atp');
|
|
9
|
-
|
|
10
|
-
const SEED_SERVICES = [
|
|
11
|
-
{
|
|
12
|
-
title: 'Code Review Agent',
|
|
13
|
-
description: 'Automated code review for JavaScript, Python, and TypeScript projects. Identifies bugs, style issues, and performance opportunities.',
|
|
14
|
-
capabilities: ['code_review', 'javascript', 'python', 'typescript', 'bug_detection'],
|
|
15
|
-
useCases: ['Pull request review', 'Code quality audit', 'Security scan'],
|
|
16
|
-
pricePerTask: 5,
|
|
17
|
-
maxConcurrent: 5,
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
title: 'Translation Agent',
|
|
21
|
-
description: 'Translates text between English, Chinese (Simplified/Traditional), and Japanese with context-aware accuracy.',
|
|
22
|
-
capabilities: ['translation', 'english', 'chinese', 'japanese', 'localization'],
|
|
23
|
-
useCases: ['Document translation', 'UI localization', 'README translation'],
|
|
24
|
-
pricePerTask: 3,
|
|
25
|
-
maxConcurrent: 10,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
title: 'Text Summarization Agent',
|
|
29
|
-
description: 'Generates concise summaries from long documents, reports, and codebases. Supports structured and freeform output.',
|
|
30
|
-
capabilities: ['summarization', 'text_analysis', 'report', 'digest'],
|
|
31
|
-
useCases: ['Meeting notes summary', 'Codebase overview', 'Research digest'],
|
|
32
|
-
pricePerTask: 2,
|
|
33
|
-
maxConcurrent: 10,
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
function handleOrder(order) {
|
|
38
|
-
const title = (order.title || '').toLowerCase();
|
|
39
|
-
const signals = (order.signals || '').toLowerCase();
|
|
40
|
-
|
|
41
|
-
let result;
|
|
42
|
-
if (title.includes('review') || signals.includes('code_review')) {
|
|
43
|
-
result = 'Code review completed. No critical issues found. 2 suggestions for improvement.';
|
|
44
|
-
} else if (title.includes('translat') || signals.includes('translation')) {
|
|
45
|
-
result = 'Translation completed. Source and target text verified for accuracy.';
|
|
46
|
-
} else {
|
|
47
|
-
result = 'Analysis completed. Summary generated from provided content.';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
result,
|
|
52
|
-
output: result,
|
|
53
|
-
pass_rate: 1.0,
|
|
54
|
-
processed_at: new Date().toISOString(),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function main() {
|
|
59
|
-
const hubUrl = process.env.A2A_HUB_URL || process.env.EVOMAP_HUB_URL;
|
|
60
|
-
if (!hubUrl) {
|
|
61
|
-
console.error('[Seed] A2A_HUB_URL or EVOMAP_HUB_URL is required.');
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
console.log('[Seed] Hub:', hubUrl);
|
|
66
|
-
console.log('[Seed] Starting merchant with', SEED_SERVICES.length, 'services...');
|
|
67
|
-
|
|
68
|
-
await merchantAgent.start({
|
|
69
|
-
services: SEED_SERVICES,
|
|
70
|
-
onOrder: handleOrder,
|
|
71
|
-
pollMs: 30000,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
console.log('[Seed] Merchant started. Polling for orders. Press Ctrl+C to stop.');
|
|
75
|
-
|
|
76
|
-
process.on('SIGINT', () => {
|
|
77
|
-
console.log('\n[Seed] Shutting down...');
|
|
78
|
-
merchantAgent.stop();
|
|
79
|
-
process.exit(0);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
process.on('SIGTERM', () => {
|
|
83
|
-
merchantAgent.stop();
|
|
84
|
-
process.exit(0);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
main().catch((err) => {
|
|
89
|
-
console.error('[Seed] Fatal:', err.message || err);
|
|
90
|
-
process.exit(1);
|
|
91
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { execSync } = require('child_process');
|
|
4
|
-
|
|
5
|
-
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
6
|
-
|
|
7
|
-
function ensureDir(dir) {
|
|
8
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function parseSemver(v) {
|
|
12
|
-
const m = String(v || '').trim().match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
13
|
-
if (!m) return null;
|
|
14
|
-
return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function bumpSemver(base, bump) {
|
|
18
|
-
const v = parseSemver(base);
|
|
19
|
-
if (!v) return null;
|
|
20
|
-
if (bump === 'major') return `${v.major + 1}.0.0`;
|
|
21
|
-
if (bump === 'minor') return `${v.major}.${v.minor + 1}.0`;
|
|
22
|
-
if (bump === 'patch') return `${v.major}.${v.minor}.${v.patch + 1}`;
|
|
23
|
-
return `${v.major}.${v.minor}.${v.patch}`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function git(cmd) {
|
|
27
|
-
return execSync(cmd, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getBaseReleaseCommit() {
|
|
31
|
-
try {
|
|
32
|
-
const hash = git('git log -n 1 --pretty=%H --grep="chore(release): prepare v"');
|
|
33
|
-
return hash || null;
|
|
34
|
-
} catch (e) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getCommitSubjectsSince(baseCommit) {
|
|
40
|
-
try {
|
|
41
|
-
if (!baseCommit) {
|
|
42
|
-
const out = git('git log -n 30 --pretty=%s');
|
|
43
|
-
return out ? out.split('\n').filter(Boolean) : [];
|
|
44
|
-
}
|
|
45
|
-
const out = git(`git log ${baseCommit}..HEAD --pretty=%s`);
|
|
46
|
-
return out ? out.split('\n').filter(Boolean) : [];
|
|
47
|
-
} catch (e) {
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function inferBumpFromSubjects(subjects) {
|
|
53
|
-
const subs = (subjects || []).map(s => String(s));
|
|
54
|
-
const hasBreaking = subs.some(s => /\bBREAKING CHANGE\b/i.test(s) || /^[a-z]+(\(.+\))?!:/.test(s));
|
|
55
|
-
if (hasBreaking) return { bump: 'major', reason: 'breaking change marker in commit subject' };
|
|
56
|
-
|
|
57
|
-
const hasFeat = subs.some(s => /^feat(\(.+\))?:/i.test(s));
|
|
58
|
-
if (hasFeat) return { bump: 'minor', reason: 'feature commit detected (feat:)' };
|
|
59
|
-
|
|
60
|
-
const hasFix = subs.some(s => /^(fix|perf)(\(.+\))?:/i.test(s));
|
|
61
|
-
if (hasFix) return { bump: 'patch', reason: 'fix/perf commit detected' };
|
|
62
|
-
|
|
63
|
-
if (subs.length === 0) return { bump: 'none', reason: 'no commits since base release commit' };
|
|
64
|
-
return { bump: 'patch', reason: 'default to patch for non-breaking changes' };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function main() {
|
|
68
|
-
const pkgPath = path.join(REPO_ROOT, 'package.json');
|
|
69
|
-
const baseVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;
|
|
70
|
-
|
|
71
|
-
const baseCommit = getBaseReleaseCommit();
|
|
72
|
-
const subjects = getCommitSubjectsSince(baseCommit);
|
|
73
|
-
const decision = inferBumpFromSubjects(subjects);
|
|
74
|
-
const suggestedVersion = decision.bump === 'none' ? baseVersion : bumpSemver(baseVersion, decision.bump);
|
|
75
|
-
|
|
76
|
-
const out = { baseVersion, baseCommit, subjects, decision, suggestedVersion };
|
|
77
|
-
const memDir = path.join(REPO_ROOT, 'memory');
|
|
78
|
-
ensureDir(memDir);
|
|
79
|
-
fs.writeFileSync(path.join(memDir, 'semver_suggestion.json'), JSON.stringify(out, null, 2) + '\n', 'utf8');
|
|
80
|
-
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
main();
|
|
85
|
-
} catch (e) {
|
|
86
|
-
process.stderr.write(`${e.message}\n`);
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// Usage: node scripts/validate-modules.js ./src/evolve ./src/gep/solidify
|
|
2
|
-
// Validates that each module (1) loads without errors, (2) exports something
|
|
3
|
-
// meaningful, and (3) exported functions are callable (typeof check).
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const modules = process.argv.slice(2);
|
|
6
|
-
if (!modules.length) { console.error('No modules specified'); process.exit(1); }
|
|
7
|
-
|
|
8
|
-
let checked = 0;
|
|
9
|
-
for (const m of modules) {
|
|
10
|
-
const resolved = path.resolve(m);
|
|
11
|
-
const exported = require(resolved);
|
|
12
|
-
|
|
13
|
-
if (exported === undefined || exported === null) {
|
|
14
|
-
console.error('FAIL: ' + m + ' exports null/undefined');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const t = typeof exported;
|
|
19
|
-
if (t === 'object' && Object.keys(exported).length === 0) {
|
|
20
|
-
console.error('FAIL: ' + m + ' exports an empty object (no public API)');
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (t === 'object') {
|
|
25
|
-
const keys = Object.keys(exported);
|
|
26
|
-
for (const k of keys) {
|
|
27
|
-
if (typeof exported[k] === 'function') {
|
|
28
|
-
if (typeof exported[k] !== 'function') {
|
|
29
|
-
console.error('FAIL: ' + m + '.' + k + ' is declared but not a callable function');
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
checked++;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
console.log('ok: ' + checked + ' module(s) validated');
|