@evomap/evolver 1.89.19 → 1.90.0

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.
Files changed (68) hide show
  1. package/index.js +85 -1
  2. package/package.json +1 -1
  3. package/scripts/skill2recipes.js +118 -0
  4. package/src/adapters/claudeCode.js +3 -3
  5. package/src/adapters/codex.js +2 -2
  6. package/src/adapters/kiro.js +2 -2
  7. package/src/adapters/opencode.js +2 -2
  8. package/src/evolve/guards.js +1 -1
  9. package/src/evolve/pipeline/collect.js +1 -1
  10. package/src/evolve/pipeline/dispatch.js +1 -1
  11. package/src/evolve/pipeline/enrich.js +1 -1
  12. package/src/evolve/pipeline/hub.js +1 -1
  13. package/src/evolve/pipeline/select.js +1 -1
  14. package/src/evolve/pipeline/signals.js +1 -1
  15. package/src/evolve/utils.js +1 -1
  16. package/src/evolve.js +1 -1
  17. package/src/gep/a2aProtocol.js +1 -1
  18. package/src/gep/antiAbuseTelemetry.js +1 -1
  19. package/src/gep/autoDistillConv.js +1 -1
  20. package/src/gep/autoDistillLlm.js +1 -1
  21. package/src/gep/candidateEval.js +1 -1
  22. package/src/gep/candidates.js +1 -1
  23. package/src/gep/contentHash.js +1 -1
  24. package/src/gep/conversationDistiller.js +1 -1
  25. package/src/gep/conversationSniffer.js +1 -1
  26. package/src/gep/crypto.js +1 -1
  27. package/src/gep/curriculum.js +1 -1
  28. package/src/gep/deviceId.js +1 -1
  29. package/src/gep/envFingerprint.js +1 -1
  30. package/src/gep/epigenetics.js +1 -1
  31. package/src/gep/execBridge.js +1 -1
  32. package/src/gep/explore.js +1 -1
  33. package/src/gep/hash.js +1 -1
  34. package/src/gep/hubFetch.js +1 -1
  35. package/src/gep/hubReview.js +1 -1
  36. package/src/gep/hubSearch.js +1 -1
  37. package/src/gep/hubVerify.js +1 -1
  38. package/src/gep/learningSignals.js +1 -1
  39. package/src/gep/memoryGraph.js +1 -1
  40. package/src/gep/memoryGraphAdapter.js +1 -1
  41. package/src/gep/mutation.js +1 -1
  42. package/src/gep/narrativeMemory.js +1 -1
  43. package/src/gep/openPRRegistry.js +1 -1
  44. package/src/gep/personality.js +1 -1
  45. package/src/gep/policyCheck.js +1 -1
  46. package/src/gep/prompt.js +1 -1
  47. package/src/gep/recallInject.js +1 -1
  48. package/src/gep/recallVerifier.js +1 -1
  49. package/src/gep/reflection.js +1 -1
  50. package/src/gep/savingsCore.js +1 -1
  51. package/src/gep/selector.js +1 -1
  52. package/src/gep/skill2recipes.js +511 -0
  53. package/src/gep/skillDistiller.js +1 -1
  54. package/src/gep/solidify.js +1 -1
  55. package/src/gep/strategy.js +1 -1
  56. package/src/gep/tokenSavings.js +1 -1
  57. package/src/gep/trajectoryExport.js +1 -1
  58. package/src/gep/workspaceKeychain.js +1 -1
  59. package/src/proxy/extensions/traceControl.js +1 -1
  60. package/src/proxy/inject.js +1 -1
  61. package/src/proxy/mailbox/store.js +14 -2
  62. package/src/proxy/sync/outbound.js +44 -3
  63. package/src/proxy/trace/extractor.js +1 -1
  64. package/src/proxy/trace/usage.js +1 -1
  65. package/src/solo/breaker.js +25 -0
  66. package/src/solo/gitGuard.js +65 -0
  67. package/skills/_meta/SKILL.md +0 -41
  68. package/skills/index.json +0 -14
package/index.js CHANGED
@@ -833,7 +833,32 @@ function refuseHelloIfDaemonRunning(toolLabel) {
833
833
  async function main() {
834
834
  const args = process.argv.slice(2);
835
835
  const command = args[0];
836
- const isLoop = args.includes('--loop') || args.includes('--mad-dog');
836
+ // Solo mode (--solo): the "constrained wild" profile. Implies loop (a solo
837
+ // run IS a Mad Dog loop) but hard-cuts the network + ATP, snapshots the
838
+ // target repo each cycle and rolls back on failure, and circuit-breaks on
839
+ // repeated failures instead of blind-respawning. It is a NEW side path — the
840
+ // wild --mad-dog / controlled-daemon behavior below is untouched when isSolo
841
+ // is false.
842
+ const isSolo = args.includes('--solo');
843
+ const isLoop = args.includes('--loop') || args.includes('--mad-dog') || isSolo;
844
+ // Solo lockdown: hard-cut network + autonomous spend at the SOURCE, in-process,
845
+ // before any module reads these envs. The block-level `if (!isSolo)` gates
846
+ // below are belt-and-suspenders for the startup path; THIS is what also closes
847
+ // the in-cycle paths (src/evolve/guards.js starts autoBuyer/autoDeliver from
848
+ // inside evolve.run()) and the validator daemon (network + staked credits).
849
+ // These are overwrites, not defaults — a user cannot re-enable ATP/hub/validator
850
+ // under --solo by setting the env themselves. That is the "no escape valve" the
851
+ // boss pinned. Numeric knobs (e.g. EVOLVER_SOLO_MAX_FAILS) stay tunable; the
852
+ // four safety cuts do not.
853
+ if (isSolo) {
854
+ process.env.A2A_HUB_URL = '';
855
+ process.env.EVOMAP_HUB_URL = '';
856
+ process.env.EVOLVER_ATP = 'off'; // getAtpMode() → 'off'
857
+ process.env.EVOLVER_ATP_AUTOBUY = 'off'; // getConsent() → disabled (env wins over ack)
858
+ process.env.EVOLVER_ATP_AUTODELIVER = 'off';
859
+ process.env.EVOLVER_VALIDATOR_ENABLED = 'false';
860
+ process.env.EVOMAP_PROXY = '0';
861
+ }
837
862
  const isVerbose = args.includes('--verbose') || args.includes('-v') ||
838
863
  String(process.env.EVOLVER_VERBOSE || '').toLowerCase() === 'true';
839
864
  if (isVerbose) process.env.EVOLVER_VERBOSE = 'true';
@@ -1414,6 +1439,9 @@ async function main() {
1414
1439
  const progressUpdateMs = parseMs(process.env.EVOLVER_PROGRESS_UPDATE_MS, 60000); // 1 min default
1415
1440
 
1416
1441
  // Start hub heartbeat (keeps node alive independently of evolution cycles)
1442
+ if (isSolo) {
1443
+ console.log('[Solo] 断网模式:不连 hub,不启心跳/SSE/proxy/validator,仅本地自进化。');
1444
+ } else {
1417
1445
  try {
1418
1446
  if (process.env.EVOMAP_PROXY === '1' || process.env.A2A_TRANSPORT === 'mailbox') {
1419
1447
  const { startProxy } = require('./src/proxy');
@@ -1464,6 +1492,7 @@ async function main() {
1464
1492
  } catch (e) {
1465
1493
  console.warn('[Heartbeat] Failed to start: ' + (e.message || e));
1466
1494
  }
1495
+ }
1467
1496
 
1468
1497
  // RecallVerify worker: starts once per process; drains the publish-
1469
1498
  // verification queue with backoff. unref'd so it never blocks exit.
@@ -1478,6 +1507,9 @@ async function main() {
1478
1507
  // Validator daemon: independent timer that fetches and executes
1479
1508
  // validation tasks regardless of the main evolve loop's idle gating.
1480
1509
  // Honors EVOLVER_VALIDATOR_ENABLED and the persisted feature flag.
1510
+ // Solo: skip entirely — the validator uses network + staked credits, and
1511
+ // its daemon timer arms even when disabled, so don't even construct it.
1512
+ if (!isSolo) {
1481
1513
  try {
1482
1514
  const { startValidatorDaemon } = require('./src/gep/validator');
1483
1515
  if (startValidatorDaemon()) {
@@ -1486,6 +1518,7 @@ async function main() {
1486
1518
  } catch (vdErr) {
1487
1519
  console.warn('[ValidatorDaemon] failed to start: ' + (vdErr && vdErr.message || vdErr));
1488
1520
  }
1521
+ }
1489
1522
 
1490
1523
  // OAuth token auto-refresh: if a device-flow OAuth token is present,
1491
1524
  // keep it fresh in the background so long-running `evolver run` loops
@@ -1501,6 +1534,9 @@ async function main() {
1501
1534
  }
1502
1535
 
1503
1536
  // ATP: auto-start merchant agent if enabled
1537
+ if (isSolo) {
1538
+ console.log('[Solo] 禁 ATP:不加载自治交易模块,不碰花钱通道。');
1539
+ } else {
1504
1540
  try {
1505
1541
  const { defaultHandler, merchantAgent } = require('./src/atp');
1506
1542
  const atpMode = defaultHandler.getAtpMode();
@@ -1607,6 +1643,7 @@ async function main() {
1607
1643
  } catch (autoBuyInitErr) {
1608
1644
  console.warn('[ATP-AutoBuyer] Init failed: ' + (autoBuyInitErr && autoBuyInitErr.message || autoBuyInitErr));
1609
1645
  }
1646
+ }
1610
1647
 
1611
1648
  // Hoist module refs used inside the loop to avoid repeated module lookups per cycle
1612
1649
  const idleScheduler = require('./src/gep/idleScheduler');
@@ -1614,6 +1651,22 @@ async function main() {
1614
1651
  const { autoDistillLlm } = require('./src/gep/autoDistillLlm'); // P3: autonomous LLM distillation (shadow-first, off by default)
1615
1652
  const { tryExplore } = require('./src/gep/explore');
1616
1653
 
1654
+ // Solo-mode setup (--solo): git safety net + circuit breaker. repoRoot is
1655
+ // the TARGET project being evolved (getRepoRoot), NOT evolver's own source.
1656
+ const gitGuard = isSolo ? require('./src/solo/gitGuard') : null;
1657
+ const soloBreaker = isSolo ? require('./src/solo/breaker') : null;
1658
+ const soloRepoRoot = isSolo ? require('./src/gep/paths').getRepoRoot() : null;
1659
+ const soloMaxConsecutiveFailures = Math.max(1, parseMs(process.env.EVOLVER_SOLO_MAX_FAILS, 5) || 5);
1660
+ let soloBreakerState = { consecutiveFailures: 0 };
1661
+ if (isSolo) {
1662
+ console.log('════════════════════════════════════════════════════════');
1663
+ console.log('[Solo] Mad Dog · 受约束的野性模式已启动');
1664
+ console.log('[Solo] 兜底四道:断网 · 禁ATP · 每 cycle git 快照/失败回滚 · 连续失败熔断');
1665
+ console.log('[Solo] 默认免人审。目标仓:' + soloRepoRoot);
1666
+ console.log('[Solo] 无 hub 审计,仅本地 git 可追溯。');
1667
+ console.log('════════════════════════════════════════════════════════');
1668
+ }
1669
+
1617
1670
  let currentSleepMs = minSleepMs;
1618
1671
  let cycleCount = 0;
1619
1672
 
@@ -1630,6 +1683,9 @@ async function main() {
1630
1683
 
1631
1684
  const t0 = Date.now();
1632
1685
  let ok = false;
1686
+ // Solo: snapshot the target repo before the cycle self-modifies it, so
1687
+ // a failed cycle can be rolled back to this exact point.
1688
+ const soloSnap = isSolo ? gitGuard.snapshot(soloRepoRoot) : null;
1633
1689
  // Issue #19: write progress at cycle start, refresh it every
1634
1690
  // progressUpdateMs (default 60s) while evolve.run() is active, and
1635
1691
  // wrap evolve.run() with Promise.race(timeout) so a hung internal
@@ -1715,6 +1771,23 @@ async function main() {
1715
1771
  }
1716
1772
  const dt = Date.now() - t0;
1717
1773
 
1774
+ // Solo: on a failed cycle, roll the target repo back to the pre-cycle
1775
+ // snapshot (undo the broken self-edit) and advance the circuit breaker;
1776
+ // a good cycle resets it. The breaker trip (exit) is enforced just
1777
+ // before the suicide block below.
1778
+ if (isSolo) {
1779
+ const b = soloBreaker.step(soloBreakerState, ok, soloMaxConsecutiveFailures);
1780
+ soloBreakerState = b.state;
1781
+ if (!ok) {
1782
+ const rolledBack = gitGuard.rollbackTo(soloRepoRoot, soloSnap);
1783
+ if (rolledBack) {
1784
+ console.warn('[Solo] cycle 失败,已 git 回滚目标仓到 ' + String(soloSnap).slice(0, 12) + ' (连续失败 ' + soloBreakerState.consecutiveFailures + '/' + soloMaxConsecutiveFailures + ')');
1785
+ } else {
1786
+ console.error('[Solo] cycle 失败且回滚未成功(无快照或 git 出错)。连续失败 ' + soloBreakerState.consecutiveFailures + '/' + soloMaxConsecutiveFailures);
1787
+ }
1788
+ }
1789
+ }
1790
+
1718
1791
  // Adaptive sleep: treat very fast cycles as "idle", backoff; otherwise reset to min.
1719
1792
  if (!ok || dt < idleThresholdMs) {
1720
1793
  currentSleepMs = Math.min(maxSleepMs, Math.max(minSleepMs, currentSleepMs * 2));
@@ -1790,6 +1863,17 @@ async function main() {
1790
1863
  if (isVerbose) console.warn('[OMLS] Scheduler error: ' + (e.message || e));
1791
1864
  }
1792
1865
 
1866
+ // Solo circuit breaker: replace the wild loop's blind sleep-and-retry
1867
+ // with a hard stop after N consecutive failures. Stopping (exit 1) —
1868
+ // rather than respawning — is the point: a solo run that keeps failing
1869
+ // must not thrash forever. An external supervisor may restart it, but
1870
+ // the process itself refuses to blind-loop.
1871
+ if (isSolo && soloBreakerState.consecutiveFailures >= soloMaxConsecutiveFailures) {
1872
+ console.error('[Solo] 连续失败 ' + soloBreakerState.consecutiveFailures + ' 次达阈值,熔断停机(非盲重生)。');
1873
+ releaseLock();
1874
+ process.exit(1);
1875
+ }
1876
+
1793
1877
  // Suicide check (memory leak protection). On Windows the
1794
1878
  // in-process respawn opens a cmd popup (Issue #528), so by default
1795
1879
  // we delegate to an external supervisor by exiting with a non-zero
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evomap/evolver",
3
- "version": "1.89.19",
3
+ "version": "1.90.0",
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": {
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // skill2recipes -- CLI: hydrolyze + verify a set of Skills into GEP assets,
5
+ // then compose and publish them as a Recipe to the EvoMap market
6
+ // (https://evomap.ai/market?tab=recipes).
7
+ //
8
+ // Usage:
9
+ // # From a manifest (recommended -- supports optional/condition per step):
10
+ // node scripts/skill2recipes.js --manifest ./examples/recipe.manifest.json
11
+ //
12
+ // # Inline, ordered by argument position:
13
+ // node scripts/skill2recipes.js --title "Bug Fix Pipeline" \
14
+ // ./skills/triage ./skills/patch ./skills/verify
15
+ //
16
+ // Options:
17
+ // --manifest <path> JSON manifest { title, description, steps:[...] }
18
+ // --title <str> Recipe title (>=3 chars; overrides manifest)
19
+ // --description <str> Recipe description
20
+ // --price <n> price_per_execution (Credits, min 1)
21
+ // --repo-root <path> Where validation commands run (default: cwd)
22
+ // --no-publish Hydrolyze + verify + build asset_ids locally, but do
23
+ // not POST anything to the Hub (dry run).
24
+ // --no-strict Allow steps whose validation falls back to node --version.
25
+ //
26
+ // Env:
27
+ // A2A_NODE_ID (required) registered EvoMap node id -> recipe owner
28
+ // A2A_HUB_URL (default https://evomap.ai)
29
+
30
+ const fs = require('fs');
31
+ const path = require('path');
32
+
33
+ process.env.A2A_TRANSPORT = 'http';
34
+ if (!process.env.A2A_HUB_URL) process.env.A2A_HUB_URL = 'https://evomap.ai';
35
+ // Keep stdout pure JSON: silence the "[evolver] Using host git repository"
36
+ // banner that paths.js prints on first require. Human-readable status lines go
37
+ // to stderr (console.error) so `... | jq` on stdout always works.
38
+ if (!process.env.EVOLVER_QUIET_PARENT_GIT) process.env.EVOLVER_QUIET_PARENT_GIT = '1';
39
+
40
+ const skill2recipes = require('../src/gep/skill2recipes');
41
+
42
+ function parseArgs(argv) {
43
+ const out = { _: [], publish: true, strict: true };
44
+ for (let i = 0; i < argv.length; i++) {
45
+ const a = argv[i];
46
+ if (a === '--manifest') out.manifest = argv[++i];
47
+ else if (a === '--title') out.title = argv[++i];
48
+ else if (a === '--description') out.description = argv[++i];
49
+ else if (a === '--price') out.pricePerExecution = Number(argv[++i]);
50
+ else if (a === '--repo-root') out.repoRoot = argv[++i];
51
+ else if (a === '--no-publish') out.publish = false;
52
+ else if (a === '--no-strict') out.strict = false;
53
+ else if (a === '-h' || a === '--help') out.help = true;
54
+ else if (a.startsWith('--')) { console.error('unknown flag: ' + a); process.exit(2); }
55
+ else out._.push(a);
56
+ }
57
+ return out;
58
+ }
59
+
60
+ function usage() {
61
+ console.log([
62
+ 'skill2recipes -- compose published Skills into a GEP Recipe',
63
+ '',
64
+ 'From a manifest:',
65
+ ' node scripts/skill2recipes.js --manifest ./examples/recipe.manifest.json',
66
+ '',
67
+ 'Inline (ordered by position):',
68
+ ' node scripts/skill2recipes.js --title "Bug Fix Pipeline" ./skills/a ./skills/b',
69
+ '',
70
+ 'Flags: --title --description --price --repo-root --no-publish --no-strict',
71
+ ].join('\n'));
72
+ }
73
+
74
+ async function main() {
75
+ const args = parseArgs(process.argv.slice(2));
76
+ if (args.help) { usage(); return; }
77
+
78
+ if (!process.env.A2A_NODE_ID && args.publish) {
79
+ console.error('WARN: A2A_NODE_ID not set -- recipe owner will be derived from a device fingerprint and the Hub may reject it. Register at https://evomap.ai and export A2A_NODE_ID.');
80
+ }
81
+
82
+ let manifest;
83
+ if (args.manifest) {
84
+ const p = path.resolve(args.manifest);
85
+ if (!fs.existsSync(p)) { console.error('manifest not found: ' + p); process.exit(1); }
86
+ try { manifest = JSON.parse(fs.readFileSync(p, 'utf8')); }
87
+ catch (e) { console.error('manifest is not valid JSON: ' + e.message); process.exit(1); }
88
+ } else if (args._.length) {
89
+ manifest = { steps: args._ };
90
+ } else {
91
+ usage();
92
+ console.error('\nERROR: provide --manifest <path> or one or more skill paths.');
93
+ process.exit(2);
94
+ }
95
+
96
+ const res = await skill2recipes.composeRecipeFromSkills(manifest, {
97
+ title: args.title,
98
+ description: args.description,
99
+ pricePerExecution: args.pricePerExecution,
100
+ repoRoot: args.repoRoot,
101
+ publish: args.publish,
102
+ strict: args.strict,
103
+ });
104
+
105
+ console.log(JSON.stringify(res, null, 2));
106
+
107
+ if (!res.ok) {
108
+ console.error('\nFAILED: ' + (res.reason || 'unknown') + (res.skill_path ? ' at ' + res.skill_path : ''));
109
+ process.exit(1);
110
+ }
111
+ if (res.recipe_id) {
112
+ console.error('\nOK recipe ' + res.recipe_id + (args.publish ? ' published -> ' + res.market_url : ' built (dry run, not published)'));
113
+ } else if (!args.publish) {
114
+ console.error('\nOK dry run complete (no network calls; ' + (res.steps ? res.steps.length : 0) + ' step(s) built, not published)');
115
+ }
116
+ }
117
+
118
+ main().catch((e) => { console.error('ERROR:', e && e.message ? e.message : e); console.error(e); process.exit(1); });
@@ -78,13 +78,13 @@ function buildClaudeMdSection() {
78
78
  ## Evolution Memory (Evolver)
79
79
 
80
80
  This project uses evolver for self-evolution. Hooks automatically:
81
- 1. Inject recent evolution memory at session start
81
+ 1. Run quietly at session start and load recent evolution memory when useful
82
82
  2. Detect evolution signals during file edits
83
83
  3. Record outcomes at session end
84
- 4. (Opt-in) Surface matching distilled capabilities for each prompt set
84
+ 4. (Opt-in) Surface matching distilled capabilities for each prompt - set
85
85
  \`EVOLVER_RECALL_MODE=shadow\` to preview, \`enforce\` to inject (default off).
86
86
 
87
- For substantive tasks, call \`gep_recall\` before work and \`gep_record_outcome\` after.
87
+ Use Evolver context only when it is directly relevant. Do not narrate routine Evolver checks, hook status, or empty recall/search results to the user.
88
88
  Signals: log_error, perf_bottleneck, user_feature_request, capability_gap, deployment_issue, test_failure.`;
89
89
  }
90
90
 
@@ -90,11 +90,11 @@ function buildAgentsMdSection() {
90
90
  ## Evolution Memory (Evolver)
91
91
 
92
92
  This project uses evolver for self-evolution. Hooks automatically:
93
- 1. Inject recent evolution memory at session start
93
+ 1. Run quietly at session start and load recent evolution memory when useful
94
94
  2. Detect evolution signals during file edits
95
95
  3. Record outcomes at session end
96
96
 
97
- For substantive tasks, call \`gep_recall\` before work and \`gep_record_outcome\` after.
97
+ Use Evolver context only when it is directly relevant. Do not narrate routine Evolver checks, hook status, or empty recall/search results to the user.
98
98
  Signals: log_error, perf_bottleneck, user_feature_request, capability_gap, deployment_issue, test_failure.`;
99
99
  }
100
100
 
@@ -67,11 +67,11 @@ function buildAgentsMdSection() {
67
67
  ## Evolution Memory (Evolver)
68
68
 
69
69
  This project uses evolver for self-evolution. Hooks automatically:
70
- 1. Inject recent evolution memory on prompt submit
70
+ 1. Run quietly on prompt submit and load recent evolution memory when useful
71
71
  2. Detect evolution signals during file edits
72
72
  3. Record outcomes at session end
73
73
 
74
- For substantive tasks, call \`gep_recall\` before work and \`gep_record_outcome\` after.
74
+ Use Evolver context only when it is directly relevant. Do not narrate routine Evolver checks, hook status, or empty recall/search results to the user.
75
75
  Signals: log_error, perf_bottleneck, user_feature_request, capability_gap, deployment_issue, test_failure.`;
76
76
  }
77
77
 
@@ -82,11 +82,11 @@ function buildAgentsMdSection() {
82
82
  ## Evolution Memory (Evolver)
83
83
 
84
84
  This project uses evolver for self-evolution. Hooks automatically:
85
- 1. Inject recent evolution memory at session start
85
+ 1. Run quietly at session start and load recent evolution memory when useful
86
86
  2. Detect evolution signals during file edits
87
87
  3. Record outcomes at session end
88
88
 
89
- For substantive tasks, call \`gep_recall\` before work and \`gep_record_outcome\` after.
89
+ Use Evolver context only when it is directly relevant. Do not narrate routine Evolver checks, hook status, or empty recall/search results to the user.
90
90
  Signals: log_error, perf_bottleneck, user_feature_request, capability_gap, deployment_issue, test_failure.`;
91
91
  }
92
92