@evomap/evolver 1.89.0 → 1.89.2
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/CONTRIBUTING.md +19 -0
- package/README.ja-JP.md +9 -32
- package/README.ko-KR.md +9 -32
- package/README.md +530 -86
- package/README.zh-CN.md +4 -31
- package/SKILL.md +1 -1
- package/assets/cover.png +0 -0
- package/index.js +14 -1
- package/package.json +17 -6
- package/scripts/a2a_export.js +63 -0
- package/scripts/a2a_ingest.js +79 -0
- package/scripts/a2a_promote.js +118 -0
- package/scripts/analyze_by_skill.js +121 -0
- package/scripts/build_binaries.js +479 -0
- package/scripts/check-changelog.js +166 -0
- package/scripts/extract_log.js +85 -0
- package/scripts/generate_history.js +75 -0
- package/scripts/gep_append_event.js +96 -0
- package/scripts/gep_personality_report.js +234 -0
- package/scripts/human_report.js +147 -0
- package/scripts/recall-verify-report.js +234 -0
- package/scripts/recover_loop.js +61 -0
- package/scripts/seed-merchants.js +91 -0
- package/scripts/suggest_version.js +89 -0
- package/scripts/validate-modules.js +38 -0
- package/scripts/validate-suite.js +78 -0
- package/skills/index.json +14 -0
- package/src/evolve/guards.js +1 -721
- package/src/evolve/pipeline/collect.js +1 -1283
- package/src/evolve/pipeline/dispatch.js +1 -421
- package/src/evolve/pipeline/enrich.js +1 -434
- package/src/evolve/pipeline/hub.js +1 -319
- package/src/evolve/pipeline/select.js +1 -274
- package/src/evolve/pipeline/signals.js +1 -206
- package/src/evolve/utils.js +1 -264
- package/src/evolve.js +1 -350
- package/src/forceUpdate.js +105 -20
- package/src/gep/a2aProtocol.js +1 -4395
- package/src/gep/autoDistillConv.js +1 -205
- package/src/gep/autoDistillLlm.js +1 -315
- package/src/gep/candidateEval.js +1 -92
- package/src/gep/candidates.js +1 -198
- package/src/gep/contentHash.js +1 -30
- package/src/gep/conversationSniffer.js +1 -266
- package/src/gep/crypto.js +1 -89
- package/src/gep/curriculum.js +1 -163
- package/src/gep/deviceId.js +1 -218
- package/src/gep/envFingerprint.js +1 -118
- package/src/gep/epigenetics.js +1 -31
- package/src/gep/execBridge.js +1 -711
- package/src/gep/explore.js +1 -289
- package/src/gep/hash.js +1 -15
- package/src/gep/hubFetch.js +1 -359
- package/src/gep/hubReview.js +1 -207
- package/src/gep/hubSearch.js +1 -526
- package/src/gep/hubVerify.js +1 -306
- package/src/gep/learningSignals.js +1 -89
- package/src/gep/memoryGraph.js +1 -1374
- package/src/gep/memoryGraphAdapter.js +1 -203
- package/src/gep/mutation.js +1 -203
- package/src/gep/narrativeMemory.js +1 -108
- package/src/gep/oauthLogin.js +34 -0
- package/src/gep/openPRRegistry.js +1 -205
- package/src/gep/personality.js +1 -423
- package/src/gep/policyCheck.js +1 -599
- package/src/gep/prompt.js +1 -836
- package/src/gep/recallInject.js +1 -409
- package/src/gep/recallVerifier.js +1 -318
- package/src/gep/reflection.js +1 -177
- package/src/gep/selector.js +1 -602
- package/src/gep/skillDistiller.js +1 -1294
- package/src/gep/skillPublisher.js +1 -1
- package/src/gep/solidify.js +1 -1699
- package/src/gep/strategy.js +1 -136
- package/src/gep/tokenSavings.js +1 -88
- package/src/gep/workspaceKeychain.js +1 -174
- package/src/proxy/extensions/traceControl.js +1 -99
- package/src/proxy/inject.js +1 -52
- package/src/proxy/lifecycle/manager.js +2 -0
- package/src/proxy/trace/extractor.js +1 -534
- package/src/proxy/trace/usage.js +1 -105
- package/.cursor/BUGBOT.md +0 -182
- package/.env.example +0 -68
- package/.git-commit-guard-token +0 -1
- package/.github/CODEOWNERS +0 -63
- package/.github/ISSUE_TEMPLATE/good_first_issue.md +0 -23
- package/.github/pull_request_template.md +0 -45
- package/.github/workflows/test.yml +0 -75
- package/CHANGELOG.md +0 -1123
- package/README.public.md +0 -594
- package/SECURITY.md +0 -108
- package/assets/gep/events.jsonl +0 -3
- package/examples/atp-consumer-quickstart.md +0 -100
- package/examples/hello-world.md +0 -38
- package/proxy-package.json +0 -39
- package/public.manifest.json +0 -141
- /package/assets/gep/{genes.json → genes.seed.json} +0 -0
- /package/{bundled-skills → skills}/_meta/SKILL.md +0 -0
package/README.zh-CN.md
CHANGED
|
@@ -178,7 +178,7 @@ evolver --loop
|
|
|
178
178
|
| 循环模式 (`evolver --loop`) | 在守护进程循环中重复上述流程,带自适应休眠 |
|
|
179
179
|
| 在 OpenClaw 中 | 宿主运行时解释 stdout 中的指令(如 `sessions_spawn(...)`) |
|
|
180
180
|
|
|
181
|
-
> **`--loop` 不是"实时辅助正在干活的 agent"的模式。** 循环模式用于后台自维护任务(validator 验证、worker 任务、ATP 商家自动交付、solidify),它的 stdout 是被 evolver 自己消费的,**不会**传给正在运行的 OpenClaw / Cursor / Claude Code agent——即使这些宿主已经安装,`sessions_spawn(...)` 指令在循环模式下也不会被它们接收。如果你想让 evolver 观察并辅助一次具体的 agent 会话,请在那个 agent 会话内部调用 `evolver
|
|
181
|
+
> **`--loop` 不是"实时辅助正在干活的 agent"的模式。** 循环模式用于后台自维护任务(validator 验证、worker 任务、ATP 商家自动交付、solidify),它的 stdout 是被 evolver 自己消费的,**不会**传给正在运行的 OpenClaw / Cursor / Claude Code agent——即使这些宿主已经安装,`sessions_spawn(...)` 指令在循环模式下也不会被它们接收。如果你想让 evolver 观察并辅助一次具体的 agent 会话,请在那个 agent 会话内部调用 `evolver`(一次一轮),OpenClaw 会在这次运行中接管 stdout 指令。对 OpenClaw 用户还要特别注意:`AGENT_NAME`(或 `AGENT_SESSIONS_DIR`)必须指向真正在产生 session 的那个 agent 目录(`~/.openclaw/agents/<名字>/sessions/`),否则 evolver 会回退到读自己的日志,看上去就像在"空转"。
|
|
182
182
|
|
|
183
183
|
## 适用 / 不适用场景
|
|
184
184
|
|
|
@@ -416,7 +416,7 @@ EVOLVE_REPORT_TOOL=feishu-card
|
|
|
416
416
|
永久关闭:
|
|
417
417
|
|
|
418
418
|
```bash
|
|
419
|
-
EVOLVER_VALIDATOR_ENABLED=0 evolver
|
|
419
|
+
EVOLVER_VALIDATOR_ENABLED=0 evolver --loop
|
|
420
420
|
```
|
|
421
421
|
|
|
422
422
|
### 自动 GitHub Issue 上报
|
|
@@ -426,7 +426,7 @@ EVOLVER_VALIDATOR_ENABLED=0 evolver run --loop
|
|
|
426
426
|
| 变量 | 默认值 | 说明 |
|
|
427
427
|
|------|--------|------|
|
|
428
428
|
| `EVOLVER_AUTO_ISSUE` | `true` | 是否启用自动 issue 上报 |
|
|
429
|
-
| `EVOLVER_ISSUE_REPO` | `
|
|
429
|
+
| `EVOLVER_ISSUE_REPO` | `EvoMap/evolver` | 目标 GitHub 仓库(owner/repo) |
|
|
430
430
|
| `EVOLVER_ISSUE_COOLDOWN_MS` | `86400000`(24 小时) | 同类错误签名的冷却期 |
|
|
431
431
|
| `EVOLVER_ISSUE_MIN_STREAK` | `5` | 触发上报所需的最低连续失败次数 |
|
|
432
432
|
|
|
@@ -474,33 +474,6 @@ EVOLVER_VALIDATOR_ENABLED=0 evolver run --loop
|
|
|
474
474
|
2. **稳定性优先**:如果近期错误率较高,强制进入修复模式,暂停创新功能。
|
|
475
475
|
3. **环境检测**:外部集成(如 Git 同步)仅在检测到相应插件存在时才会启用。
|
|
476
476
|
|
|
477
|
-
## Public 发布
|
|
478
|
-
|
|
479
|
-
本仓库为公开发行版本。
|
|
480
|
-
|
|
481
|
-
- 构建公开产物:`npm run build`
|
|
482
|
-
- 发布公开产物:`npm run publish:public`
|
|
483
|
-
- 演练:`DRY_RUN=true npm run publish:public`
|
|
484
|
-
|
|
485
|
-
必填环境变量:
|
|
486
|
-
|
|
487
|
-
- `PUBLIC_REMOTE`(默认:`public`)
|
|
488
|
-
- `PUBLIC_REPO`(例如 `EvoMap/evolver`)
|
|
489
|
-
- `PUBLIC_OUT_DIR`(默认:`dist-public`)
|
|
490
|
-
- `PUBLIC_USE_BUILD_OUTPUT`(默认:`true`)
|
|
491
|
-
|
|
492
|
-
可选环境变量:
|
|
493
|
-
|
|
494
|
-
- `SOURCE_BRANCH`(默认:`main`)
|
|
495
|
-
- `PUBLIC_BRANCH`(默认:`main`)
|
|
496
|
-
- `RELEASE_TAG`(例如 `v1.0.41`)
|
|
497
|
-
- `RELEASE_TITLE`(例如 `v1.0.41 - GEP protocol`)
|
|
498
|
-
- `RELEASE_NOTES` 或 `RELEASE_NOTES_FILE`
|
|
499
|
-
- `GITHUB_TOKEN`(或 `GH_TOKEN` / `GITHUB_PAT`,用于创建 GitHub Release)
|
|
500
|
-
- `RELEASE_SKIP`(`true` 则跳过创建 GitHub Release;默认会创建)
|
|
501
|
-
- `RELEASE_USE_GH`(`true` 则使用 `gh` CLI,否则默认走 GitHub API)
|
|
502
|
-
- `PUBLIC_RELEASE_ONLY`(`true` 则仅为已存在的 tag 创建 Release;不发布代码)
|
|
503
|
-
|
|
504
477
|
## 版本号规则(SemVer)
|
|
505
478
|
|
|
506
479
|
MAJOR.MINOR.PATCH
|
|
@@ -557,4 +530,4 @@ MAJOR.MINOR.PATCH
|
|
|
557
530
|
|
|
558
531
|
## 许可证
|
|
559
532
|
|
|
560
|
-
[
|
|
533
|
+
[GPL-3.0-or-later](https://opensource.org/licenses/GPL-3.0)
|
package/SKILL.md
CHANGED
package/assets/cover.png
ADDED
|
Binary file
|
package/index.js
CHANGED
|
@@ -1232,6 +1232,19 @@ async function main() {
|
|
|
1232
1232
|
console.warn('[ValidatorDaemon] failed to start: ' + (vdErr && vdErr.message || vdErr));
|
|
1233
1233
|
}
|
|
1234
1234
|
|
|
1235
|
+
// OAuth token auto-refresh: if a device-flow OAuth token is present,
|
|
1236
|
+
// keep it fresh in the background so long-running `evolver run` loops
|
|
1237
|
+
// never hit an expired a2a token mid-request. No-op for node_secret nodes.
|
|
1238
|
+
try {
|
|
1239
|
+
const { loadOAuthToken, startTokenAutoRefresh } = require('./src/gep/oauthLogin');
|
|
1240
|
+
if (loadOAuthToken()) {
|
|
1241
|
+
startTokenAutoRefresh();
|
|
1242
|
+
console.log('[OAuth] token auto-refresh scheduled.');
|
|
1243
|
+
}
|
|
1244
|
+
} catch (oauthRefreshErr) {
|
|
1245
|
+
console.warn('[OAuth] auto-refresh setup failed: ' + (oauthRefreshErr && oauthRefreshErr.message || oauthRefreshErr));
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1235
1248
|
// ATP: auto-start merchant agent if enabled
|
|
1236
1249
|
try {
|
|
1237
1250
|
const { defaultHandler, merchantAgent } = require('./src/atp');
|
|
@@ -2046,7 +2059,7 @@ async function main() {
|
|
|
2046
2059
|
} else if (resp.status >= 500) {
|
|
2047
2060
|
console.error(' Server error. The Hub may be temporarily unavailable.');
|
|
2048
2061
|
console.error(' Try again in a few minutes. If the issue persists, report at:');
|
|
2049
|
-
console.error(' https://github.com/
|
|
2062
|
+
console.error(' https://github.com/EvoMap/evolver/issues');
|
|
2050
2063
|
}
|
|
2051
2064
|
if (isVerbose) {
|
|
2052
2065
|
console.error('[Verbose] Endpoint: ' + endpoint);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver",
|
|
3
|
-
"version": "1.89.
|
|
3
|
+
"version": "1.89.2",
|
|
4
4
|
"description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,12 +28,10 @@
|
|
|
28
28
|
"run": "node index.js run",
|
|
29
29
|
"solidify": "node index.js solidify",
|
|
30
30
|
"review": "node index.js review",
|
|
31
|
-
"distill": "node index.js distill",
|
|
32
|
-
"webui": "node index.js webui",
|
|
33
|
-
"test": "node -e \"const fs=require('fs'),cp=require('child_process');const all=fs.readdirSync('test').filter(f=>f.endsWith('.test.js'));const iso=new Set(['solidifyIntegration.test.js']);const others=all.filter(f=>!iso.has(f)).map(f=>'test/'+f);const isoFiles=all.filter(f=>iso.has(f)).map(f=>'test/'+f);if(others.length)cp.execSync('node --test '+others.join(' '),{stdio:'inherit'});if(isoFiles.length)cp.execSync('node --test '+isoFiles.join(' '),{stdio:'inherit'})\"",
|
|
34
31
|
"a2a:export": "node scripts/a2a_export.js",
|
|
35
32
|
"a2a:ingest": "node scripts/a2a_ingest.js",
|
|
36
|
-
"a2a:promote": "node scripts/a2a_promote.js"
|
|
33
|
+
"a2a:promote": "node scripts/a2a_promote.js",
|
|
34
|
+
"test": "node -e \"const fs=require('fs'),cp=require('child_process');const all=fs.readdirSync('test').filter(f=>f.endsWith('.test.js'));const iso=new Set(['solidifyIntegration.test.js']);const others=all.filter(f=>!iso.has(f)).map(f=>'test/'+f);const isoFiles=all.filter(f=>iso.has(f)).map(f=>'test/'+f);if(others.length)cp.execSync('node --test '+others.join(' '),{stdio:'inherit'});if(isoFiles.length)cp.execSync('node --test '+isoFiles.join(' '),{stdio:'inherit'})\""
|
|
37
35
|
},
|
|
38
36
|
"engines": {
|
|
39
37
|
"node": ">=22.12"
|
|
@@ -50,5 +48,18 @@
|
|
|
50
48
|
},
|
|
51
49
|
"optionalDependencies": {
|
|
52
50
|
"@napi-rs/keyring": "^1.1.6"
|
|
53
|
-
}
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"assets/",
|
|
54
|
+
"index.js",
|
|
55
|
+
"src/",
|
|
56
|
+
"scripts/",
|
|
57
|
+
"skills/",
|
|
58
|
+
"README.md",
|
|
59
|
+
"README.zh-CN.md",
|
|
60
|
+
"README.ja-JP.md",
|
|
61
|
+
"SKILL.md",
|
|
62
|
+
"CONTRIBUTING.md",
|
|
63
|
+
"LICENSE"
|
|
64
|
+
]
|
|
54
65
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const { loadGenes, loadCapsules, readAllEvents } = require('../src/gep/assetStore');
|
|
2
|
+
const { exportEligibleCapsules, exportEligibleGenes, isAllowedA2AAsset } = require('../src/gep/a2a');
|
|
3
|
+
const { buildPublish, buildHello, getTransport } = require('../src/gep/a2aProtocol');
|
|
4
|
+
const { computeAssetId, SCHEMA_VERSION } = require('../src/gep/contentHash');
|
|
5
|
+
|
|
6
|
+
function main() {
|
|
7
|
+
var args = process.argv.slice(2);
|
|
8
|
+
var asJson = args.includes('--json');
|
|
9
|
+
var asProtocol = args.includes('--protocol');
|
|
10
|
+
var withHello = args.includes('--hello');
|
|
11
|
+
var persist = args.includes('--persist');
|
|
12
|
+
var includeEvents = args.includes('--include-events');
|
|
13
|
+
|
|
14
|
+
var capsules = loadCapsules();
|
|
15
|
+
var genes = loadGenes();
|
|
16
|
+
var events = readAllEvents();
|
|
17
|
+
|
|
18
|
+
// Build eligible list: Capsules (filtered) + Genes (filtered) + Events (opt-in)
|
|
19
|
+
var eligibleCapsules = exportEligibleCapsules({ capsules: capsules, events: events });
|
|
20
|
+
var eligibleGenes = exportEligibleGenes({ genes: genes });
|
|
21
|
+
var eligible = eligibleCapsules.concat(eligibleGenes);
|
|
22
|
+
|
|
23
|
+
if (includeEvents) {
|
|
24
|
+
var eligibleEvents = (Array.isArray(events) ? events : []).filter(function (e) {
|
|
25
|
+
return isAllowedA2AAsset(e) && e.type === 'EvolutionEvent';
|
|
26
|
+
});
|
|
27
|
+
for (var ei = 0; ei < eligibleEvents.length; ei++) {
|
|
28
|
+
var ev = eligibleEvents[ei];
|
|
29
|
+
if (!ev.schema_version) ev.schema_version = SCHEMA_VERSION;
|
|
30
|
+
if (!ev.asset_id) { try { ev.asset_id = computeAssetId(ev); } catch (e) {} }
|
|
31
|
+
}
|
|
32
|
+
eligible = eligible.concat(eligibleEvents);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (withHello || asProtocol) {
|
|
36
|
+
var hello = buildHello({ geneCount: genes.length, capsuleCount: capsules.length });
|
|
37
|
+
process.stdout.write(JSON.stringify(hello) + '\n');
|
|
38
|
+
if (persist) { try { getTransport().send(hello); } catch (e) {} }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (asProtocol) {
|
|
42
|
+
for (var i = 0; i < eligible.length; i++) {
|
|
43
|
+
var msg = buildPublish({ asset: eligible[i] });
|
|
44
|
+
process.stdout.write(JSON.stringify(msg) + '\n');
|
|
45
|
+
if (persist) { try { getTransport().send(msg); } catch (e) {} }
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (asJson) {
|
|
51
|
+
process.stdout.write(JSON.stringify(eligible, null, 2) + '\n');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (var j = 0; j < eligible.length; j++) {
|
|
56
|
+
process.stdout.write(JSON.stringify(eligible[j]) + '\n');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try { main(); } catch (e) {
|
|
61
|
+
process.stderr.write((e && e.message ? e.message : String(e)) + '\n');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var assetStore = require('../src/gep/assetStore');
|
|
3
|
+
var a2a = require('../src/gep/a2a');
|
|
4
|
+
var memGraph = require('../src/gep/memoryGraphAdapter');
|
|
5
|
+
var contentHash = require('../src/gep/contentHash');
|
|
6
|
+
var a2aProto = require('../src/gep/a2aProtocol');
|
|
7
|
+
|
|
8
|
+
function readStdin() {
|
|
9
|
+
try { return fs.readFileSync(0, 'utf8'); } catch (e) { return ''; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function parseSignalsFromEnv() {
|
|
13
|
+
var raw = process.env.A2A_SIGNALS || '';
|
|
14
|
+
if (!raw) return [];
|
|
15
|
+
try {
|
|
16
|
+
var maybe = JSON.parse(raw);
|
|
17
|
+
if (Array.isArray(maybe)) return maybe.map(String).filter(Boolean);
|
|
18
|
+
} catch (e) {}
|
|
19
|
+
return String(raw).split(',').map(function (s) { return s.trim(); }).filter(Boolean);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function main() {
|
|
23
|
+
var args = process.argv.slice(2);
|
|
24
|
+
var inputPath = '';
|
|
25
|
+
for (var i = 0; i < args.length; i++) {
|
|
26
|
+
if (args[i] && !args[i].startsWith('--')) { inputPath = args[i]; break; }
|
|
27
|
+
}
|
|
28
|
+
var source = process.env.A2A_SOURCE || 'external';
|
|
29
|
+
var factor = Number.isFinite(Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR))
|
|
30
|
+
? Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR) : 0.6;
|
|
31
|
+
|
|
32
|
+
var text = inputPath ? a2a.readTextIfExists(inputPath) : readStdin();
|
|
33
|
+
var parsed = a2a.parseA2AInput(text);
|
|
34
|
+
var signals = parseSignalsFromEnv();
|
|
35
|
+
|
|
36
|
+
var accepted = 0;
|
|
37
|
+
var rejected = 0;
|
|
38
|
+
var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';
|
|
39
|
+
|
|
40
|
+
for (var j = 0; j < parsed.length; j++) {
|
|
41
|
+
var obj = parsed[j];
|
|
42
|
+
if (!a2a.isAllowedA2AAsset(obj)) continue;
|
|
43
|
+
|
|
44
|
+
if (obj.asset_id && typeof obj.asset_id === 'string') {
|
|
45
|
+
if (!contentHash.verifyAssetId(obj)) {
|
|
46
|
+
rejected += 1;
|
|
47
|
+
if (emitDecisions) {
|
|
48
|
+
try {
|
|
49
|
+
var dm = a2aProto.buildDecision({ assetId: obj.asset_id, localId: obj.id, decision: 'reject', reason: 'asset_id integrity check failed' });
|
|
50
|
+
a2aProto.getTransport().send(dm);
|
|
51
|
+
} catch (e) {}
|
|
52
|
+
}
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var staged = a2a.lowerConfidence(obj, { source: source, factor: factor });
|
|
58
|
+
if (!staged) continue;
|
|
59
|
+
|
|
60
|
+
assetStore.appendExternalCandidateJsonl(staged);
|
|
61
|
+
try { memGraph.recordExternalCandidate({ asset: staged, source: source, signals: signals }); } catch (e) {}
|
|
62
|
+
|
|
63
|
+
if (emitDecisions) {
|
|
64
|
+
try {
|
|
65
|
+
var dm2 = a2aProto.buildDecision({ assetId: staged.asset_id, localId: staged.id, decision: 'quarantine', reason: 'staged as external candidate' });
|
|
66
|
+
a2aProto.getTransport().send(dm2);
|
|
67
|
+
} catch (e) {}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
accepted += 1;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
process.stdout.write('accepted=' + accepted + ' rejected=' + rejected + '\n');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try { main(); } catch (e) {
|
|
77
|
+
process.stderr.write((e && e.message ? e.message : String(e)) + '\n');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
var assetStore = require('../src/gep/assetStore');
|
|
2
|
+
var solidifyMod = require('../src/gep/solidify');
|
|
3
|
+
var contentHash = require('../src/gep/contentHash');
|
|
4
|
+
var a2aProto = require('../src/gep/a2aProtocol');
|
|
5
|
+
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
var out = { flags: new Set(), kv: new Map(), positionals: [] };
|
|
8
|
+
for (var i = 0; i < argv.length; i++) {
|
|
9
|
+
var a = argv[i];
|
|
10
|
+
if (!a) continue;
|
|
11
|
+
if (a.startsWith('--')) {
|
|
12
|
+
var eq = a.indexOf('=');
|
|
13
|
+
if (eq > -1) { out.kv.set(a.slice(2, eq), a.slice(eq + 1)); }
|
|
14
|
+
else {
|
|
15
|
+
var key = a.slice(2);
|
|
16
|
+
var next = argv[i + 1];
|
|
17
|
+
if (next && !String(next).startsWith('--')) { out.kv.set(key, next); i++; }
|
|
18
|
+
else { out.flags.add(key); }
|
|
19
|
+
}
|
|
20
|
+
} else { out.positionals.push(a); }
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function main() {
|
|
26
|
+
var args = parseArgs(process.argv.slice(2));
|
|
27
|
+
var id = String(args.kv.get('id') || '').trim();
|
|
28
|
+
var typeRaw = String(args.kv.get('type') || '').trim().toLowerCase();
|
|
29
|
+
var validated = args.flags.has('validated') || String(args.kv.get('validated') || '') === 'true';
|
|
30
|
+
var limit = Number.isFinite(Number(args.kv.get('limit'))) ? Number(args.kv.get('limit')) : 500;
|
|
31
|
+
|
|
32
|
+
if (!id || !typeRaw) throw new Error('Usage: node scripts/a2a_promote.js --type capsule|gene|event --id <id> --validated');
|
|
33
|
+
if (!validated) throw new Error('Refusing to promote without --validated (local verification must be done first).');
|
|
34
|
+
|
|
35
|
+
var type = typeRaw === 'capsule' ? 'Capsule' : typeRaw === 'gene' ? 'Gene' : typeRaw === 'event' ? 'EvolutionEvent' : '';
|
|
36
|
+
if (!type) throw new Error('Invalid --type. Use capsule, gene, or event.');
|
|
37
|
+
|
|
38
|
+
var external = assetStore.readRecentExternalCandidates(limit);
|
|
39
|
+
var candidate = null;
|
|
40
|
+
for (var i = 0; i < external.length; i++) {
|
|
41
|
+
if (external[i] && external[i].type === type && String(external[i].id) === id) { candidate = external[i]; break; }
|
|
42
|
+
}
|
|
43
|
+
if (!candidate) throw new Error('Candidate not found in external zone: type=' + type + ' id=' + id);
|
|
44
|
+
|
|
45
|
+
if (type === 'Gene') {
|
|
46
|
+
var validation = Array.isArray(candidate.validation) ? candidate.validation : [];
|
|
47
|
+
for (var j = 0; j < validation.length; j++) {
|
|
48
|
+
var c = String(validation[j] || '').trim();
|
|
49
|
+
if (!c) continue;
|
|
50
|
+
if (!solidifyMod.isValidationCommandAllowed(c)) {
|
|
51
|
+
throw new Error('Refusing to promote Gene ' + id + ': validation command rejected by safety check: "' + c + '". Only node/npm/npx commands without shell operators are allowed.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var promoted = JSON.parse(JSON.stringify(candidate));
|
|
57
|
+
if (!promoted.a2a || typeof promoted.a2a !== 'object') promoted.a2a = {};
|
|
58
|
+
promoted.a2a.status = 'promoted';
|
|
59
|
+
promoted.a2a.promoted_at = new Date().toISOString();
|
|
60
|
+
if (!promoted.schema_version) promoted.schema_version = contentHash.SCHEMA_VERSION;
|
|
61
|
+
promoted.asset_id = contentHash.computeAssetId(promoted);
|
|
62
|
+
|
|
63
|
+
var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';
|
|
64
|
+
|
|
65
|
+
if (type === 'EvolutionEvent') {
|
|
66
|
+
assetStore.appendEventJsonl(promoted);
|
|
67
|
+
if (emitDecisions) {
|
|
68
|
+
try {
|
|
69
|
+
var dmEv = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'event promoted for provenance tracking' });
|
|
70
|
+
a2aProto.getTransport().send(dmEv);
|
|
71
|
+
} catch (e) {}
|
|
72
|
+
}
|
|
73
|
+
process.stdout.write('promoted_event=' + id + '\n');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (type === 'Capsule') {
|
|
78
|
+
assetStore.appendCapsule(promoted);
|
|
79
|
+
if (emitDecisions) {
|
|
80
|
+
try {
|
|
81
|
+
var dm = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'capsule promoted after validation' });
|
|
82
|
+
a2aProto.getTransport().send(dm);
|
|
83
|
+
} catch (e) {}
|
|
84
|
+
}
|
|
85
|
+
process.stdout.write('promoted_capsule=' + id + '\n');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var localGenes = assetStore.loadGenes();
|
|
90
|
+
var exists = false;
|
|
91
|
+
for (var k = 0; k < localGenes.length; k++) {
|
|
92
|
+
if (localGenes[k] && localGenes[k].type === 'Gene' && String(localGenes[k].id) === id) { exists = true; break; }
|
|
93
|
+
}
|
|
94
|
+
if (exists) {
|
|
95
|
+
if (emitDecisions) {
|
|
96
|
+
try {
|
|
97
|
+
var dm2 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'reject', reason: 'local gene with same ID already exists' });
|
|
98
|
+
a2aProto.getTransport().send(dm2);
|
|
99
|
+
} catch (e) {}
|
|
100
|
+
}
|
|
101
|
+
process.stdout.write('conflict_keep_local_gene=' + id + '\n');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
assetStore.upsertGene(promoted);
|
|
106
|
+
if (emitDecisions) {
|
|
107
|
+
try {
|
|
108
|
+
var dm3 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'gene promoted after safety audit' });
|
|
109
|
+
a2aProto.getTransport().send(dm3);
|
|
110
|
+
} catch (e) {}
|
|
111
|
+
}
|
|
112
|
+
process.stdout.write('promoted_gene=' + id + '\n');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try { main(); } catch (e) {
|
|
116
|
+
process.stderr.write((e && e.message ? e.message : String(e)) + '\n');
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
5
|
+
const LOG_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');
|
|
6
|
+
const OUT_FILE = path.join(REPO_ROOT, 'evolution_detailed_report.md');
|
|
7
|
+
|
|
8
|
+
function analyzeEvolution() {
|
|
9
|
+
if (!fs.existsSync(LOG_FILE)) {
|
|
10
|
+
console.error("Source file missing.");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const content = fs.readFileSync(LOG_FILE, 'utf8');
|
|
15
|
+
// Split by divider
|
|
16
|
+
const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);
|
|
17
|
+
|
|
18
|
+
const skillUpdates = {}; // Map<SkillName, Array<Changes>>
|
|
19
|
+
const generalUpdates = []; // Array<Changes>
|
|
20
|
+
|
|
21
|
+
// Regex to detect skills/paths
|
|
22
|
+
// e.g. `skills/feishu-card/send.js` or **Target**: `skills/git-sync`
|
|
23
|
+
const skillRegex = /skills\/([a-zA-Z0-9\-_]+)/;
|
|
24
|
+
const actionRegex = /Action:\s*([\s\S]*?)(?=\n\n|\n[A-Z]|$)/i; // Capture Action text
|
|
25
|
+
const statusRegex = /Status:\s*\[?([A-Z\s_]+)\]?/i;
|
|
26
|
+
|
|
27
|
+
entries.forEach(entry => {
|
|
28
|
+
// Extract basic info
|
|
29
|
+
const statusMatch = entry.match(statusRegex);
|
|
30
|
+
const status = statusMatch ? statusMatch[1].trim().toUpperCase() : 'UNKNOWN';
|
|
31
|
+
|
|
32
|
+
// Skip routine checks if we want a *detailed evolution* report (focus on changes)
|
|
33
|
+
// But user asked for "what happened", so routine scans might be boring unless they found something.
|
|
34
|
+
// Let's filter out "STABILITY" or "RUNNING" unless there is a clear "Mutated" or "Fixed" keyword.
|
|
35
|
+
const isInteresting =
|
|
36
|
+
entry.includes('Fixed') ||
|
|
37
|
+
entry.includes('Hardened') ||
|
|
38
|
+
entry.includes('Optimized') ||
|
|
39
|
+
entry.includes('Patched') ||
|
|
40
|
+
entry.includes('Created') ||
|
|
41
|
+
entry.includes('Added') ||
|
|
42
|
+
status === 'SUCCESS' ||
|
|
43
|
+
status === 'COMPLETED';
|
|
44
|
+
|
|
45
|
+
if (!isInteresting) return;
|
|
46
|
+
|
|
47
|
+
// Find associated skill
|
|
48
|
+
const skillMatch = entry.match(skillRegex);
|
|
49
|
+
let skillName = 'General / System';
|
|
50
|
+
if (skillMatch) {
|
|
51
|
+
skillName = skillMatch[1];
|
|
52
|
+
} else {
|
|
53
|
+
// Try heuristics
|
|
54
|
+
if (entry.toLowerCase().includes('feishu card')) skillName = 'feishu-card';
|
|
55
|
+
else if (entry.toLowerCase().includes('git sync')) skillName = 'git-sync';
|
|
56
|
+
else if (entry.toLowerCase().includes('logger')) skillName = 'interaction-logger';
|
|
57
|
+
else if (entry.toLowerCase().includes('evolve')) skillName = 'capability-evolver';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Extract description
|
|
61
|
+
let description = "";
|
|
62
|
+
const actionMatch = entry.match(actionRegex);
|
|
63
|
+
if (actionMatch) {
|
|
64
|
+
description = actionMatch[1].trim();
|
|
65
|
+
} else {
|
|
66
|
+
// Fallback: take lines that look like bullet points or text after header
|
|
67
|
+
const lines = entry.split('\n');
|
|
68
|
+
description = lines.filter(l => l.match(/^[•\-\*]|\w/)).slice(1).join('\n').trim();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Clean up description (remove duplicate "Action:" prefix if captured)
|
|
72
|
+
description = description.replace(/^Action:\s*/i, '');
|
|
73
|
+
|
|
74
|
+
if (!skillUpdates[skillName]) skillUpdates[skillName] = [];
|
|
75
|
+
|
|
76
|
+
// Dedup descriptions slightly (simple check)
|
|
77
|
+
const isDuplicate = skillUpdates[skillName].some(u => u.desc.includes(description.substring(0, 20)));
|
|
78
|
+
if (!isDuplicate) {
|
|
79
|
+
// Extract Date if possible
|
|
80
|
+
const dateMatch = entry.match(/\((\d{4}\/\d{1,2}\/\d{1,2}.*?)\)/);
|
|
81
|
+
const date = dateMatch ? dateMatch[1] : 'Unknown';
|
|
82
|
+
|
|
83
|
+
skillUpdates[skillName].push({
|
|
84
|
+
date,
|
|
85
|
+
status,
|
|
86
|
+
desc: description
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Generate Markdown
|
|
92
|
+
let md = "# Detailed Evolution Report (By Skill)\n\n> Comprehensive breakdown of system changes.\n\n";
|
|
93
|
+
|
|
94
|
+
// Sort skills alphabetically
|
|
95
|
+
const sortedSkills = Object.keys(skillUpdates).sort();
|
|
96
|
+
|
|
97
|
+
sortedSkills.forEach(skill => {
|
|
98
|
+
md += `## ${skill}\n`;
|
|
99
|
+
const updates = skillUpdates[skill];
|
|
100
|
+
|
|
101
|
+
updates.forEach(u => {
|
|
102
|
+
// Icon based on content
|
|
103
|
+
let icon = '*';
|
|
104
|
+
const lowerDesc = u.desc.toLowerCase();
|
|
105
|
+
if (lowerDesc.includes('optimiz')) icon = '[optimize]';
|
|
106
|
+
if (lowerDesc.includes('secur') || lowerDesc.includes('harden') || lowerDesc.includes('permission')) icon = '[security]';
|
|
107
|
+
if (lowerDesc.includes('fix') || lowerDesc.includes('patch')) icon = '[repair]';
|
|
108
|
+
if (lowerDesc.includes('creat') || lowerDesc.includes('add')) icon = '[add]';
|
|
109
|
+
|
|
110
|
+
md += `### ${icon} ${u.date}\n`;
|
|
111
|
+
md += `${u.desc}\n\n`;
|
|
112
|
+
});
|
|
113
|
+
md += `---\n`;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
fs.writeFileSync(OUT_FILE, md);
|
|
117
|
+
console.log(`Generated report for ${sortedSkills.length} skills.`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
analyzeEvolution();
|
|
121
|
+
|