@evomap/evolver 1.90.0 → 2.0.0-beta.1

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 (231) hide show
  1. package/README.md +27 -564
  2. package/bin/evolver-llm-proxy.js +3 -0
  3. package/bin/evolver-mcp.js +2 -0
  4. package/bin/evolver-proxy.js +3 -0
  5. package/bin/evolver.js +4 -0
  6. package/index.js +1 -3670
  7. package/package.json +32 -62
  8. package/CONTRIBUTING.md +0 -19
  9. package/LICENSE +0 -641
  10. package/README.ja-JP.md +0 -521
  11. package/README.ko-KR.md +0 -520
  12. package/README.zh-CN.md +0 -531
  13. package/SKILL.md +0 -365
  14. package/assets/cover.png +0 -0
  15. package/assets/gep/genes.seed.json +0 -496
  16. package/conformance/savings-core/constants.json +0 -30
  17. package/conformance/savings-core/golden-vectors.json +0 -333
  18. package/scripts/a2a_export.js +0 -63
  19. package/scripts/a2a_ingest.js +0 -79
  20. package/scripts/a2a_promote.js +0 -118
  21. package/scripts/analyze_by_skill.js +0 -121
  22. package/scripts/build_binaries.js +0 -479
  23. package/scripts/check-changelog.js +0 -166
  24. package/scripts/extract_log.js +0 -85
  25. package/scripts/generate_history.js +0 -75
  26. package/scripts/gep_append_event.js +0 -96
  27. package/scripts/gep_personality_report.js +0 -234
  28. package/scripts/human_report.js +0 -147
  29. package/scripts/recall-verify-report.js +0 -234
  30. package/scripts/recover_loop.js +0 -61
  31. package/scripts/refresh_stars_badge.js +0 -168
  32. package/scripts/seed-merchants.js +0 -91
  33. package/scripts/skill2recipes.js +0 -118
  34. package/scripts/suggest_version.js +0 -89
  35. package/scripts/validate-modules.js +0 -38
  36. package/scripts/validate-suite.js +0 -78
  37. package/src/adapters/claudeCode.js +0 -194
  38. package/src/adapters/codex.js +0 -216
  39. package/src/adapters/cursor.js +0 -91
  40. package/src/adapters/hookAdapter.js +0 -469
  41. package/src/adapters/kiro.js +0 -195
  42. package/src/adapters/opencode.js +0 -326
  43. package/src/adapters/scripts/_lockPaths.js +0 -74
  44. package/src/adapters/scripts/_memoryFiltering.js +0 -35
  45. package/src/adapters/scripts/_runtimePaths.js +0 -440
  46. package/src/adapters/scripts/evolver-session-end.js +0 -321
  47. package/src/adapters/scripts/evolver-session-start.js +0 -587
  48. package/src/adapters/scripts/evolver-signal-detect.js +0 -98
  49. package/src/adapters/scripts/evolver-task-recall.js +0 -173
  50. package/src/atp/atpExecute.js +0 -283
  51. package/src/atp/atpTaskPickup.js +0 -233
  52. package/src/atp/autoBuyer.js +0 -382
  53. package/src/atp/autoDeliver.js +0 -215
  54. package/src/atp/cli.js +0 -354
  55. package/src/atp/cliAutobuyPrompt.js +0 -154
  56. package/src/atp/consumerAgent.js +0 -157
  57. package/src/atp/defaultHandler.js +0 -69
  58. package/src/atp/heartbeatSignalsHandler.js +0 -254
  59. package/src/atp/hubClient.js +0 -317
  60. package/src/atp/index.js +0 -38
  61. package/src/atp/merchantAgent.js +0 -118
  62. package/src/atp/protocol.js +0 -41
  63. package/src/atp/questionComposer.js +0 -133
  64. package/src/atp/serviceHelper.js +0 -92
  65. package/src/canary.js +0 -13
  66. package/src/config.js +0 -351
  67. package/src/evolve/guards.js +0 -1
  68. package/src/evolve/pipeline/collect.js +0 -1
  69. package/src/evolve/pipeline/dispatch.js +0 -1
  70. package/src/evolve/pipeline/enrich.js +0 -1
  71. package/src/evolve/pipeline/hub.js +0 -1
  72. package/src/evolve/pipeline/select.js +0 -1
  73. package/src/evolve/pipeline/signals.js +0 -1
  74. package/src/evolve/utils.js +0 -1
  75. package/src/evolve.js +0 -1
  76. package/src/experiment/agentRunner.js +0 -229
  77. package/src/experiment/cli.js +0 -159
  78. package/src/experiment/comparison.js +0 -233
  79. package/src/experiment/metrics.js +0 -75
  80. package/src/forceUpdate.js +0 -991
  81. package/src/gep/a2a.js +0 -173
  82. package/src/gep/a2aProtocol.js +0 -1
  83. package/src/gep/analyzer.js +0 -35
  84. package/src/gep/antiAbuseTelemetry.js +0 -1
  85. package/src/gep/assetCallLog.js +0 -197
  86. package/src/gep/assetStore.js +0 -723
  87. package/src/gep/assets.js +0 -36
  88. package/src/gep/autoDistillConv.js +0 -1
  89. package/src/gep/autoDistillLlm.js +0 -1
  90. package/src/gep/bridge.js +0 -138
  91. package/src/gep/candidateEval.js +0 -1
  92. package/src/gep/candidates.js +0 -1
  93. package/src/gep/claimNudge.js +0 -121
  94. package/src/gep/cliContracts.js +0 -1190
  95. package/src/gep/contentHash.js +0 -1
  96. package/src/gep/conversationDistiller.js +0 -1
  97. package/src/gep/conversationSniffer.js +0 -1
  98. package/src/gep/crypto.js +0 -1
  99. package/src/gep/curriculum.js +0 -1
  100. package/src/gep/deviceId.js +0 -1
  101. package/src/gep/directoryClient.js +0 -115
  102. package/src/gep/envFingerprint.js +0 -1
  103. package/src/gep/epigenetics.js +0 -1
  104. package/src/gep/execBridge.js +0 -1
  105. package/src/gep/executionTrace.js +0 -291
  106. package/src/gep/explore.js +0 -1
  107. package/src/gep/featureFlags.js +0 -121
  108. package/src/gep/gitOps.js +0 -265
  109. package/src/gep/hash.js +0 -1
  110. package/src/gep/hostErrorClassifier.js +0 -34
  111. package/src/gep/hubFetch.js +0 -1
  112. package/src/gep/hubReview.js +0 -1
  113. package/src/gep/hubSearch.js +0 -1
  114. package/src/gep/hubVerify.js +0 -1
  115. package/src/gep/idleScheduler.js +0 -400
  116. package/src/gep/issueReporter.js +0 -416
  117. package/src/gep/learningSignals.js +0 -1
  118. package/src/gep/llmReview.js +0 -92
  119. package/src/gep/localStateAwareness.js +0 -243
  120. package/src/gep/mailboxTransport.js +0 -119
  121. package/src/gep/memoryGraph.js +0 -1
  122. package/src/gep/memoryGraphAdapter.js +0 -1
  123. package/src/gep/mutation.js +0 -1
  124. package/src/gep/narrativeMemory.js +0 -1
  125. package/src/gep/oauthLogin.js +0 -181
  126. package/src/gep/openPRRegistry.js +0 -1
  127. package/src/gep/paths.js +0 -522
  128. package/src/gep/personality.js +0 -1
  129. package/src/gep/policyCheck.js +0 -1
  130. package/src/gep/portable.js +0 -103
  131. package/src/gep/privacyClient.js +0 -235
  132. package/src/gep/prompt.js +0 -1
  133. package/src/gep/questionGenerator.js +0 -518
  134. package/src/gep/recallInject.js +0 -1
  135. package/src/gep/recallVerifier.js +0 -1
  136. package/src/gep/reflection.js +0 -1
  137. package/src/gep/sanitize.js +0 -264
  138. package/src/gep/savingsCore.js +0 -1
  139. package/src/gep/schemas/capsule.js +0 -170
  140. package/src/gep/schemas/gene.js +0 -154
  141. package/src/gep/schemas/index.js +0 -8
  142. package/src/gep/schemas/protocol.js +0 -51
  143. package/src/gep/schemas/task.js +0 -74
  144. package/src/gep/selector.js +0 -1
  145. package/src/gep/selfPR.js +0 -469
  146. package/src/gep/signals.js +0 -776
  147. package/src/gep/skill2gep.js +0 -1056
  148. package/src/gep/skill2gepAudit.js +0 -303
  149. package/src/gep/skill2recipes.js +0 -511
  150. package/src/gep/skillDistiller.js +0 -1
  151. package/src/gep/skillPublisher.js +0 -358
  152. package/src/gep/solidify.js +0 -1
  153. package/src/gep/strategy.js +0 -1
  154. package/src/gep/taskReceiver.js +0 -575
  155. package/src/gep/tokenSavings.js +0 -1
  156. package/src/gep/trajectoryExport.js +0 -1
  157. package/src/gep/validationReport.js +0 -55
  158. package/src/gep/validator/index.js +0 -411
  159. package/src/gep/validator/reporter.js +0 -210
  160. package/src/gep/validator/sandboxExecutor.js +0 -480
  161. package/src/gep/validator/stakeBootstrap.js +0 -357
  162. package/src/gep/workspaceKeychain.js +0 -1
  163. package/src/ops/cleanup.js +0 -80
  164. package/src/ops/commentary.js +0 -60
  165. package/src/ops/health_check.js +0 -104
  166. package/src/ops/index.js +0 -11
  167. package/src/ops/innovation.js +0 -67
  168. package/src/ops/lifecycle.js +0 -798
  169. package/src/ops/self_repair.js +0 -76
  170. package/src/ops/skills_monitor.js +0 -147
  171. package/src/ops/trigger.js +0 -33
  172. package/src/proxy/clientSettings.js +0 -405
  173. package/src/proxy/envelope.js +0 -59
  174. package/src/proxy/extensions/dmHandler.js +0 -45
  175. package/src/proxy/extensions/sessionHandler.js +0 -141
  176. package/src/proxy/extensions/skillUpdater.js +0 -64
  177. package/src/proxy/extensions/traceControl.js +0 -1
  178. package/src/proxy/index.js +0 -1395
  179. package/src/proxy/inject.js +0 -1
  180. package/src/proxy/lifecycle/manager.js +0 -1568
  181. package/src/proxy/mailbox/state.js +0 -207
  182. package/src/proxy/mailbox/store.js +0 -602
  183. package/src/proxy/router/cache_passthrough.js +0 -26
  184. package/src/proxy/router/features.js +0 -84
  185. package/src/proxy/router/gemini_route.js +0 -154
  186. package/src/proxy/router/messages_route.js +0 -535
  187. package/src/proxy/router/model_router.js +0 -113
  188. package/src/proxy/router/models_route.js +0 -52
  189. package/src/proxy/router/ollama_route.js +0 -103
  190. package/src/proxy/router/responses_route.js +0 -170
  191. package/src/proxy/router/vertex_route.js +0 -110
  192. package/src/proxy/server/http.js +0 -363
  193. package/src/proxy/server/routes.js +0 -558
  194. package/src/proxy/server/settings.js +0 -115
  195. package/src/proxy/sync/engine.js +0 -179
  196. package/src/proxy/sync/inbound.js +0 -211
  197. package/src/proxy/sync/outbound.js +0 -361
  198. package/src/proxy/task/monitor.js +0 -131
  199. package/src/proxy/trace/extractor.js +0 -1
  200. package/src/proxy/trace/usage.js +0 -1
  201. package/src/solo/breaker.js +0 -25
  202. package/src/solo/gitGuard.js +0 -65
  203. package/src/webui/client/clientJs/assets.js +0 -111
  204. package/src/webui/client/clientJs/bootstrap.js +0 -92
  205. package/src/webui/client/clientJs/common.js +0 -77
  206. package/src/webui/client/clientJs/i18n.js +0 -366
  207. package/src/webui/client/clientJs/index.js +0 -35
  208. package/src/webui/client/clientJs/interactions.js +0 -351
  209. package/src/webui/client/clientJs/overview.js +0 -152
  210. package/src/webui/client/clientJs/personality.js +0 -285
  211. package/src/webui/client/clientJs/pipelines.js +0 -330
  212. package/src/webui/client/indexHtml.js +0 -221
  213. package/src/webui/client/static.js +0 -23
  214. package/src/webui/client/stylesCss.js +0 -639
  215. package/src/webui/client/vendor/README.md +0 -15
  216. package/src/webui/client/vendor/echarts.min.js +0 -45
  217. package/src/webui/index.js +0 -14
  218. package/src/webui/observer/assets.js +0 -146
  219. package/src/webui/observer/index.js +0 -37
  220. package/src/webui/observer/interactions.js +0 -127
  221. package/src/webui/observer/jsonl.js +0 -75
  222. package/src/webui/observer/paths.js +0 -46
  223. package/src/webui/observer/personality.js +0 -43
  224. package/src/webui/observer/pipelineEvents.js +0 -58
  225. package/src/webui/observer/redact.js +0 -63
  226. package/src/webui/observer/runs.js +0 -356
  227. package/src/webui/observer/safety.js +0 -57
  228. package/src/webui/observer/skills.js +0 -70
  229. package/src/webui/observer/status.js +0 -71
  230. package/src/webui/server/http.js +0 -138
  231. package/src/webui/server/routes.js +0 -41
@@ -1,518 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // questionGenerator -- analyzes evolution context (signals, session transcripts,
3
- // recent events) and generates proactive questions for the Hub bounty system.
4
- //
5
- // Questions are sent via the A2A fetch payload.questions field. The Hub creates
6
- // bounties from them, enabling multi-agent collaborative problem solving.
7
- //
8
- // Two entry points:
9
- // generateQuestions() -- standard path, runs at cycle start (rate-limited)
10
- // generateUrgentQuestions() -- post-solidify path, bypasses cooldown for
11
- // high-priority situations (failed solidify,
12
- // low confidence, validation failures)
13
- // ---------------------------------------------------------------------------
14
-
15
- const fs = require('fs');
16
- const path = require('path');
17
- const { getEvolutionDir } = require('./paths');
18
-
19
- const QUESTION_STATE_FILE = path.join(getEvolutionDir(), 'question_generator_state.json');
20
- const MIN_INTERVAL_MS = 30 * 60 * 1000; // standard path: at most once per 30 minutes
21
- const URGENT_INTERVAL_MS = 5 * 60 * 1000; // urgent path: at most once per 5 minutes
22
- const EXPLORE_INTERVAL_MS = 6 * 60 * 60 * 1000; // exploration path: at most once per 6 hours
23
- const MAX_QUESTIONS_PER_CYCLE = 3;
24
- const MAX_URGENT_QUESTIONS = 2;
25
-
26
- // Problem-signal triggers used by the standard strategies. Their presence means
27
- // the agent is "stuck"; the exploration (healthy-agent) strategy stays out of
28
- // the way when any of these fire, and is filtered out of a question's topic
29
- // anchor so a curiosity question never reads like a distress signal.
30
- var PROBLEM_SIGNALS = [
31
- 'recurring_error', 'high_failure_ratio', 'capability_gap', 'unsupported_input_type',
32
- 'evolution_saturation', 'force_steady_state', 'consecutive_failure_streak',
33
- 'user_feature_request', 'perf_bottleneck', 'hub_search_miss_with_problem',
34
- 'repair_loop_detected', 'force_innovation_after_repair_loop',
35
- 'plateau_pivot_required', 'plateau_pivot_suggested',
36
- ];
37
-
38
- // Common words stripped before ranking topic keywords for exploration questions.
39
- var EXPLORE_STOPWORDS = new Set([
40
- 'the', 'and', 'for', 'that', 'this', 'with', 'from', 'have', 'what', 'your',
41
- 'agent', 'about', 'into', 'then', 'than', 'they', 'them', 'their', 'there',
42
- 'here', 'will', 'would', 'could', 'should', 'been', 'were', 'using', 'used',
43
- 'cycle', 'evolution', 'error', 'errors', 'failed', 'failure', 'null', 'undefined',
44
- 'true', 'false', 'console', 'return', 'function', 'const', 'value', 'result',
45
- ]);
46
-
47
- // Infrastructure / user-local failures that the ecosystem cannot resolve.
48
- // Keep in sync with the hub-side bounty spam guard so the two gates never
49
- // disagree about what is worth asking the community.
50
- var INFRA_ERROR_RE = /\b(401|403|429|500|502|503|504|529)\b|invalid[\s_-]?api[\s_-]?key|authentication[\s_-]?error|unauthorized|permission[\s_-]?denied|rate[\s_-]?limit|too[\s_-]?many[\s_-]?requests|overloaded[\s_-]?error|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|EPIPE|fetch[\s_-]?failed|network[\s_-]?error|connection[\s_-]?refused|context[\s_-]?length|token[\s_-]?limit|(?:context|input)[\s_-]?window[\s_-]?exceeded|maximum[\s_-]?context[\s_-]?length/i;
51
-
52
- function isInfraError(text) {
53
- if (!text || typeof text !== 'string') return false;
54
- return INFRA_ERROR_RE.test(text);
55
- }
56
-
57
- function readState() {
58
- try {
59
- if (fs.existsSync(QUESTION_STATE_FILE)) {
60
- return JSON.parse(fs.readFileSync(QUESTION_STATE_FILE, 'utf8'));
61
- }
62
- } catch (_) {}
63
- return { lastAskedAt: null, lastUrgentAt: null, recentQuestions: [] };
64
- }
65
-
66
- function writeState(state) {
67
- try {
68
- var dir = path.dirname(QUESTION_STATE_FILE);
69
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
70
- fs.writeFileSync(QUESTION_STATE_FILE, JSON.stringify(state, null, 2) + '\n');
71
- } catch (_) {}
72
- }
73
-
74
- function isDuplicate(question, recentQuestions) {
75
- var qLower = question.toLowerCase();
76
- for (var i = 0; i < recentQuestions.length; i++) {
77
- var prev = String(recentQuestions[i] || '').toLowerCase();
78
- if (prev === qLower) return true;
79
- var qWords = new Set(qLower.split(/\s+/).filter(function(w) { return w.length > 2; }));
80
- var pWords = new Set(prev.split(/\s+/).filter(function(w) { return w.length > 2; }));
81
- if (qWords.size === 0 || pWords.size === 0) continue;
82
- var overlap = 0;
83
- qWords.forEach(function(w) { if (pWords.has(w)) overlap++; });
84
- if (overlap / Math.max(qWords.size, pWords.size) > 0.7) return true;
85
- }
86
- return false;
87
- }
88
-
89
- function extractErrorContext(transcript, maxLen) {
90
- var lines = transcript.split('\n');
91
- for (var i = 0; i < lines.length; i++) {
92
- if (/error|exception|failed|cannot|not supported|unsupported|not implemented/i.test(lines[i])) {
93
- return lines[i].replace(/\s+/g, ' ').trim().slice(0, maxLen || 150);
94
- }
95
- }
96
- return '';
97
- }
98
-
99
- function extractRecentGeneIds(recentEvents, count) {
100
- var ids = [];
101
- var last = recentEvents.slice(-(count || 5));
102
- for (var j = 0; j < last.length; j++) {
103
- var genes = last[j].genes_used;
104
- if (Array.isArray(genes) && genes.length > 0) ids.push(genes[0]);
105
- }
106
- return Array.from(new Set(ids));
107
- }
108
-
109
- // Pull a few salient domain keywords from the agent's recent work (session
110
- // transcript + memory). Deterministic frequency ranking, no NLP dependency.
111
- // Returns up to `max` distinctive lowercase terms, or [] when there is nothing
112
- // substantive -- used to ground exploration questions in the agent's real
113
- // activity so they are specific (and clear the hub relevance gate), not generic.
114
- function extractTopicKeywords(transcript, memory, max) {
115
- var text = (String(transcript || '') + ' ' + String(memory || '')).toLowerCase();
116
- var words = text.match(/[a-z][a-z0-9_-]{4,}/g) || [];
117
- var freq = {};
118
- for (var i = 0; i < words.length; i++) {
119
- var w = words[i];
120
- if (EXPLORE_STOPWORDS.has(w)) continue;
121
- freq[w] = (freq[w] || 0) + 1;
122
- }
123
- var ranked = Object.keys(freq)
124
- .filter(function (w) { return freq[w] >= 2; })
125
- .sort(function (a, b) { return freq[b] - freq[a]; });
126
- return ranked.slice(0, max || 5);
127
- }
128
-
129
- // Exploration strategy: a healthy, productively-running agent proactively asks
130
- // the network how to extend itself -- complementary capabilities, reusable
131
- // patterns, or adjacent high-value problems. This is the path that keeps organic
132
- // bounty demand flowing when no problem signals are firing (problem strategies
133
- // only fire when the agent is stuck). Anchored on the agent's real recent work
134
- // so the question is specific, not noise; returns null when there is no anchor.
135
- function buildExplorationCandidate(signals, recentEvents, transcript, memory) {
136
- var topicSignals = (signals || []).filter(function (s) {
137
- s = String(s || '');
138
- if (!/^[a-z][a-z0-9_]{3,40}$/i.test(s)) return false;
139
- if (s.indexOf('errsig') === 0 || s.indexOf('ban_gene') === 0 || s.indexOf('recurring_') === 0) return false;
140
- return !PROBLEM_SIGNALS.some(function (p) { return s === p || s.indexOf(p) === 0; });
141
- }).slice(0, 4);
142
-
143
- var keywords = extractTopicKeywords(transcript, memory, 5);
144
- var genes = extractRecentGeneIds(recentEvents, 5);
145
-
146
- // Require real work artifacts (domain keywords from the transcript/memory, or
147
- // recent genes) to ground the question. A bare signal name is too thin an
148
- // anchor to make a useful bounty, so topic signals only enrich the tags.
149
- if (keywords.length === 0 && genes.length === 0) return null;
150
-
151
- var focus = keywords.length > 0 ? keywords.slice(0, 5).join(', ') : genes.join(', ');
152
- var question = 'A productively-running agent working on ' + focus
153
- + ' wants to extend its capabilities. What reusable patterns, automation genes, '
154
- + 'or complementary tools in this area would be most valuable to build next, and '
155
- + 'what adjacent high-value problems is the ecosystem not yet solving well here?';
156
-
157
- return {
158
- question: question,
159
- amount: 0,
160
- signals: ['capability_frontier', 'exploration', 'proactive_curiosity']
161
- .concat(keywords.slice(0, 2))
162
- .concat(topicSignals.slice(0, 2)),
163
- priority: 0,
164
- };
165
- }
166
-
167
- // ---------------------------------------------------------------------------
168
- // Standard strategies (cycle-start, rate-limited by MIN_INTERVAL_MS)
169
- // ---------------------------------------------------------------------------
170
-
171
- function buildStandardCandidates(signals, recentEvents, transcript, memory) {
172
- var candidates = [];
173
- var signalSet = new Set(signals);
174
-
175
- // Strategy 1: Recurring errors the agent cannot resolve
176
- if (signalSet.has('recurring_error') || signalSet.has('high_failure_ratio')) {
177
- var errSig = signals.find(function(s) { return s.startsWith('recurring_errsig'); });
178
- if (errSig) {
179
- var errDetail = errSig.replace(/^recurring_errsig\(\d+x\):/, '').trim().slice(0, 120);
180
- // Skip infra/user-local failures (invalid api key, 429, network issues)
181
- // -- the community cannot fix the user's own environment.
182
- if (!isInfraError(errDetail)) {
183
- candidates.push({
184
- question: 'Recurring error in evolution cycle that auto-repair cannot resolve: ' + errDetail + ' -- What approaches or patches have worked for similar issues?',
185
- amount: 0,
186
- signals: ['recurring_error', 'auto_repair_failed'],
187
- priority: 3,
188
- });
189
- }
190
- }
191
- }
192
-
193
- // Strategy 2: Capability gaps detected from user conversations
194
- if (signalSet.has('capability_gap') || signalSet.has('unsupported_input_type')) {
195
- var gapContext = extractErrorContext(transcript, 150);
196
- if (gapContext && !isInfraError(gapContext)) {
197
- candidates.push({
198
- question: 'Capability gap detected in agent environment: ' + gapContext + ' -- How can this be addressed or what alternative approaches exist?',
199
- amount: 0,
200
- signals: ['capability_gap'],
201
- priority: 2,
202
- });
203
- }
204
- }
205
-
206
- // Strategy 3: Stagnation / saturation -- seek new directions
207
- if (signalSet.has('evolution_saturation') || signalSet.has('force_steady_state')) {
208
- var uniqueGenes = extractRecentGeneIds(recentEvents, 5);
209
- candidates.push({
210
- question: 'Agent evolution has reached saturation after exhausting genes: [' + uniqueGenes.join(', ') + ']. What new evolution directions, automation patterns, or capability genes would be most valuable?',
211
- amount: 0,
212
- signals: ['evolution_saturation', 'innovation_needed'],
213
- priority: 1,
214
- });
215
- }
216
-
217
- // Strategy 4: Consecutive failure streak -- seek external help
218
- var failStreak = signals.find(function(s) { return s.startsWith('consecutive_failure_streak_'); });
219
- if (failStreak) {
220
- var streakCount = parseInt(failStreak.replace('consecutive_failure_streak_', ''), 10) || 0;
221
- if (streakCount >= 3) {
222
- var failGene = signals.find(function(s) { return s.startsWith('ban_gene:'); });
223
- var failGeneId = failGene ? failGene.replace('ban_gene:', '') : 'unknown';
224
- candidates.push({
225
- question: 'Agent has failed ' + streakCount + ' consecutive evolution cycles (last gene: ' + failGeneId + '). The current approach is exhausted. What alternative strategies or environmental fixes should be tried?',
226
- amount: 0,
227
- signals: ['failure_streak', 'external_help_needed'],
228
- priority: 3,
229
- });
230
- }
231
- }
232
-
233
- // Strategy 5: User feature requests the agent can amplify
234
- if (signalSet.has('user_feature_request') || signals.some(function (s) { return String(s).startsWith('user_feature_request:'); })) {
235
- var featureLines = transcript.split('\n').filter(function(l) {
236
- return /\b(add|implement|create|build|i want|i need|please add)\b/i.test(l);
237
- });
238
- if (featureLines.length > 0) {
239
- var featureContext = featureLines[0].replace(/\s+/g, ' ').trim().slice(0, 150);
240
- candidates.push({
241
- question: 'User requested a feature that may benefit from community solutions: ' + featureContext + ' -- Are there existing implementations or best practices for this?',
242
- amount: 0,
243
- signals: ['user_feature_request', 'community_solution_sought'],
244
- priority: 1,
245
- });
246
- }
247
- }
248
-
249
- // Strategy 6: Performance bottleneck -- seek optimization patterns
250
- if (signalSet.has('perf_bottleneck')) {
251
- var perfLines = transcript.split('\n').filter(function(l) {
252
- return /\b(slow|timeout|latency|bottleneck|high cpu|high memory)\b/i.test(l);
253
- });
254
- if (perfLines.length > 0) {
255
- var perfContext = perfLines[0].replace(/\s+/g, ' ').trim().slice(0, 150);
256
- candidates.push({
257
- question: 'Performance bottleneck detected: ' + perfContext + ' -- What optimization strategies or architectural patterns address this?',
258
- amount: 0,
259
- signals: ['perf_bottleneck', 'optimization_sought'],
260
- priority: 2,
261
- });
262
- }
263
- }
264
-
265
- // Strategy 7: Hub search miss with active problem -- no ecosystem solution exists
266
- if (signalSet.has('hub_search_miss_with_problem')) {
267
- var problemCtx = extractErrorContext(transcript, 120);
268
- var problemSignalList = signals.filter(function(s) {
269
- return s === 'log_error' || s === 'test_failure' || s === 'deployment_issue'
270
- || s.startsWith('errsig:');
271
- }).slice(0, 3);
272
- if (!isInfraError(problemCtx) && !isInfraError(problemSignalList.join(' '))) {
273
- candidates.push({
274
- question: 'No matching solution found in ecosystem for active problem (signals: ' + problemSignalList.join(', ') + '). Context: ' + (problemCtx || 'complex multi-signal issue') + ' -- What strategies, patterns, or tools address this class of problem?',
275
- amount: 0,
276
- signals: ['hub_search_miss', 'ecosystem_gap', 'solution_sought'],
277
- priority: 2,
278
- });
279
- }
280
- }
281
-
282
- // Strategy 8: Repair loop -- stuck in repair->fail->repair cycle
283
- if (signalSet.has('repair_loop_detected') || signalSet.has('force_innovation_after_repair_loop')) {
284
- var recentGenes = extractRecentGeneIds(recentEvents, 6);
285
- candidates.push({
286
- question: 'Agent is stuck in a repair loop (repair->fail->repair cycle) with genes: [' + recentGenes.join(', ') + ']. The underlying issue persists despite multiple attempts. What fundamentally different approach could break this cycle?',
287
- amount: 0,
288
- signals: ['repair_loop', 'architectural_help_needed'],
289
- priority: 3,
290
- });
291
- }
292
-
293
- // Strategy 9: Plateau -- consecutive non-improving outcomes
294
- if (signalSet.has('plateau_pivot_required') || signalSet.has('plateau_pivot_suggested')) {
295
- var severity = signalSet.has('plateau_pivot_required') ? 'severe' : 'moderate';
296
- candidates.push({
297
- question: 'Agent evolution has plateaued (' + severity + ' -- no improvement in recent cycles). Current gene pool and mutation strategies are exhausted. What novel approaches, architectural patterns, or paradigm shifts could restart progress?',
298
- amount: 0,
299
- signals: ['evolution_plateau', 'pivot_needed'],
300
- priority: severity === 'severe' ? 3 : 2,
301
- });
302
- }
303
-
304
- return candidates;
305
- }
306
-
307
- // ---------------------------------------------------------------------------
308
- // Urgent strategies (post-solidify, rate-limited by URGENT_INTERVAL_MS)
309
- // These fire when a single cycle produces a bad outcome, without waiting
310
- // for multi-cycle statistical signals.
311
- // ---------------------------------------------------------------------------
312
-
313
- function buildUrgentCandidates(opts) {
314
- var o = opts || {};
315
- var candidates = [];
316
-
317
- // U1: Solidify validation failure -- the patch failed automated checks
318
- if (o.validationFailed) {
319
- var valErrors = String(o.validationErrors || '').slice(0, 200);
320
- var geneId = o.geneId || 'unknown';
321
- if (!isInfraError(valErrors)) {
322
- candidates.push({
323
- question: 'Evolution cycle produced a patch that failed validation (gene: ' + geneId + '). Errors: ' + valErrors + ' -- What is the correct approach to fix this validation failure?',
324
- amount: 0,
325
- signals: ['validation_failure', 'solidify_rejected'],
326
- priority: 3,
327
- });
328
- }
329
- }
330
-
331
- // U2: Low confidence outcome -- solidify scored below threshold
332
- if (o.lowConfidence && Number.isFinite(o.confidenceScore)) {
333
- var score = Math.round(o.confidenceScore * 100) / 100;
334
- var intent = o.intent || 'unknown';
335
- candidates.push({
336
- question: 'Evolution cycle completed with low confidence (score: ' + score + ', intent: ' + intent + '). The change is uncertain and may not be beneficial. What higher-confidence approaches exist for this type of problem?',
337
- amount: 0,
338
- signals: ['low_confidence', 'uncertain_outcome'],
339
- priority: 2,
340
- });
341
- }
342
-
343
- // U3: LLM review rejection -- a second-opinion model rejected the change
344
- if (o.llmReviewRejected) {
345
- var reason = String(o.llmReviewReason || '').slice(0, 200);
346
- if (!isInfraError(reason)) {
347
- candidates.push({
348
- question: 'Proposed code change was rejected by LLM review: ' + reason + ' -- What alternative implementation approach would pass quality review?',
349
- amount: 0,
350
- signals: ['llm_review_rejected', 'quality_concern'],
351
- priority: 3,
352
- });
353
- }
354
- }
355
-
356
- // U4: Zero blast radius after non-trivial attempt
357
- if (o.zeroBlastRadius && o.hadSignals) {
358
- var attemptedSignals = (Array.isArray(o.signals) ? o.signals : []).slice(0, 5).join(', ');
359
- candidates.push({
360
- question: 'Evolution cycle targeting signals [' + attemptedSignals + '] produced zero blast radius (no effective changes). The approach was insufficient. What concrete implementation steps would address these signals?',
361
- amount: 0,
362
- signals: ['zero_blast_radius', 'ineffective_approach'],
363
- priority: 2,
364
- });
365
- }
366
-
367
- // U5: Task completion failure -- claimed a task but couldn't solve it
368
- if (o.taskCompletionFailed) {
369
- var taskTitle = String(o.taskTitle || '').slice(0, 120);
370
- var taskSignals = String(o.taskSignals || '').slice(0, 100);
371
- if (!isInfraError(taskTitle) && !isInfraError(taskSignals)) {
372
- candidates.push({
373
- question: 'Failed to complete claimed task: "' + taskTitle + '" (signals: ' + taskSignals + '). The problem exceeds current capabilities. What approaches, tools, or patterns would solve this?',
374
- amount: 0,
375
- signals: ['task_completion_failed', 'help_needed'],
376
- priority: 3,
377
- });
378
- }
379
- }
380
-
381
- return candidates;
382
- }
383
-
384
- // ---------------------------------------------------------------------------
385
- // Public API
386
- // ---------------------------------------------------------------------------
387
-
388
- /**
389
- * Standard question generation (cycle start). Rate-limited to MIN_INTERVAL_MS.
390
- */
391
- function generateQuestions(opts) {
392
- var o = opts || {};
393
- var signals = Array.isArray(o.signals) ? o.signals : [];
394
- var recentEvents = Array.isArray(o.recentEvents) ? o.recentEvents : [];
395
- var transcript = String(o.sessionTranscript || '');
396
- var memory = String(o.memorySnippet || '');
397
-
398
- var state = readState();
399
-
400
- if (state.lastAskedAt) {
401
- var elapsed = Date.now() - new Date(state.lastAskedAt).getTime();
402
- if (elapsed < MIN_INTERVAL_MS) return [];
403
- }
404
-
405
- var candidates = buildStandardCandidates(signals, recentEvents, transcript, memory);
406
-
407
- // Exploration (healthy-agent) path: add a low-priority proactive question on a
408
- // slower cadence (EXPLORE_INTERVAL_MS) so a smoothly-running agent -- which
409
- // trips none of the problem strategies above -- still seeds organic bounty
410
- // demand. Disable with EVOLVER_EXPLORATION_QUESTIONS=0.
411
- var exploreEligible = process.env.EVOLVER_EXPLORATION_QUESTIONS !== '0';
412
- if (exploreEligible && state.lastExploreAt) {
413
- var exElapsed = Date.now() - new Date(state.lastExploreAt).getTime();
414
- if (exElapsed < EXPLORE_INTERVAL_MS) exploreEligible = false;
415
- }
416
- if (exploreEligible) {
417
- var exploration = buildExplorationCandidate(signals, recentEvents, transcript, memory);
418
- if (exploration) candidates.push(exploration);
419
- }
420
-
421
- if (candidates.length === 0) return [];
422
-
423
- candidates.sort(function(a, b) { return b.priority - a.priority; });
424
-
425
- var recentQTexts = Array.isArray(state.recentQuestions) ? state.recentQuestions : [];
426
- var filtered = [];
427
- for (var fi = 0; fi < candidates.length && filtered.length < MAX_QUESTIONS_PER_CYCLE; fi++) {
428
- if (!isDuplicate(candidates[fi].question, recentQTexts)) {
429
- filtered.push(candidates[fi]);
430
- }
431
- }
432
-
433
- if (filtered.length === 0) return [];
434
-
435
- // Advance the exploration cooldown only if an exploration question actually
436
- // went out, so problem questions never consume the slower exploration budget.
437
- var explorationSent = filtered.some(function (q) {
438
- return Array.isArray(q.signals) && q.signals.indexOf('exploration') !== -1;
439
- });
440
-
441
- var newRecentQuestions = recentQTexts.concat(filtered.map(function(q) { return q.question; }));
442
- if (newRecentQuestions.length > 30) {
443
- newRecentQuestions = newRecentQuestions.slice(-30);
444
- }
445
- writeState({
446
- lastAskedAt: new Date().toISOString(),
447
- lastUrgentAt: state.lastUrgentAt || null,
448
- lastExploreAt: explorationSent ? new Date().toISOString() : (state.lastExploreAt || null),
449
- recentQuestions: newRecentQuestions,
450
- });
451
-
452
- return filtered.map(function(q) {
453
- return { question: q.question, amount: q.amount, signals: q.signals };
454
- });
455
- }
456
-
457
- /**
458
- * Urgent question generation (post-solidify). Bypasses the standard cooldown
459
- * but has its own shorter cooldown (URGENT_INTERVAL_MS). Only fires when
460
- * a single cycle produces a clearly bad outcome.
461
- *
462
- * @param {object} opts
463
- * @param {boolean} [opts.validationFailed] - solidify validation failed
464
- * @param {string} [opts.validationErrors] - error details
465
- * @param {string} [opts.geneId] - gene used in the failed cycle
466
- * @param {boolean} [opts.lowConfidence] - score below threshold
467
- * @param {number} [opts.confidenceScore] - actual score (0-1)
468
- * @param {string} [opts.intent] - cycle intent
469
- * @param {boolean} [opts.llmReviewRejected] - LLM review rejected the change
470
- * @param {string} [opts.llmReviewReason] - rejection reason
471
- * @param {boolean} [opts.zeroBlastRadius] - no effective changes
472
- * @param {boolean} [opts.hadSignals] - had actionable signals
473
- * @param {string[]} [opts.signals] - current signals
474
- * @param {boolean} [opts.taskCompletionFailed] - failed to complete a task
475
- * @param {string} [opts.taskTitle] - task title
476
- * @param {string} [opts.taskSignals] - task signals
477
- * @returns {Array<{ question: string, amount: number, signals: string[] }>}
478
- */
479
- function generateUrgentQuestions(opts) {
480
- var state = readState();
481
-
482
- if (state.lastUrgentAt) {
483
- var elapsed = Date.now() - new Date(state.lastUrgentAt).getTime();
484
- if (elapsed < URGENT_INTERVAL_MS) return [];
485
- }
486
-
487
- var candidates = buildUrgentCandidates(opts);
488
- if (candidates.length === 0) return [];
489
-
490
- candidates.sort(function(a, b) { return b.priority - a.priority; });
491
-
492
- var recentQTexts = Array.isArray(state.recentQuestions) ? state.recentQuestions : [];
493
- var filtered = [];
494
- for (var fi = 0; fi < candidates.length && filtered.length < MAX_URGENT_QUESTIONS; fi++) {
495
- if (!isDuplicate(candidates[fi].question, recentQTexts)) {
496
- filtered.push(candidates[fi]);
497
- }
498
- }
499
-
500
- if (filtered.length === 0) return [];
501
-
502
- var newRecentQuestions = recentQTexts.concat(filtered.map(function(q) { return q.question; }));
503
- if (newRecentQuestions.length > 30) {
504
- newRecentQuestions = newRecentQuestions.slice(-30);
505
- }
506
- writeState({
507
- lastAskedAt: state.lastAskedAt || null,
508
- lastUrgentAt: new Date().toISOString(),
509
- lastExploreAt: state.lastExploreAt || null,
510
- recentQuestions: newRecentQuestions,
511
- });
512
-
513
- return filtered.map(function(q) {
514
- return { question: q.question, amount: q.amount, signals: q.signals };
515
- });
516
- }
517
-
518
- module.exports = { generateQuestions, generateUrgentQuestions };