@evomap/evolver 1.90.0 → 2.0.0-beta.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 (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,326 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { copyHookScripts, removeHookScripts, removeMarkedSection, assertSafeConfigDir } = require('./hookAdapter');
4
-
5
- const HOOK_SCRIPTS_DIR_NAME = 'hooks';
6
- const PLUGINS_DIR_NAME = 'plugins';
7
- const PLUGIN_FILE_NAME = 'evolver.js';
8
- const EVOLVER_MARKER = '<!-- evolver-evolution-memory -->';
9
- // First line of the plugin file. Used to (a) prove the plugin file is one we
10
- // wrote, so uninstall can safely delete it, and (b) skip overwriting if the
11
- // user replaced it with a custom plugin.
12
- const PLUGIN_HEADER = '// _evolver_managed: true (do not remove this line)';
13
-
14
- function buildPluginSource(hooksDirAbsolute) {
15
- // The plugin shells out to the same three Node scripts that every other
16
- // evolver adapter uses, so the runtime behavior stays consistent across
17
- // hosts. opencode loads .js files synchronously at startup and invokes
18
- // the default-exported async factory with a context object.
19
- return `${PLUGIN_HEADER}
20
- // Auto-generated by \`evolver setup-hooks --platform=opencode\`.
21
- // See https://opencode.ai/docs/plugins/ for the plugin API.
22
- //
23
- // This plugin wires opencode events to the three evolver hook scripts:
24
- // session.created -> evolver-session-start.js (inject memory)
25
- // tool.execute.after -> evolver-signal-detect.js (detect signals on writes/edits)
26
- // session.idle -> evolver-session-end.js (record outcome)
27
- //
28
- // Each script is a stdin/stdout JSON filter -- nothing else is shared with
29
- // opencode, so removing this file fully detaches evolver from opencode.
30
-
31
- const { spawnSync } = require('node:child_process');
32
- const path = require('node:path');
33
-
34
- const HOOKS_DIR = ${JSON.stringify(hooksDirAbsolute)};
35
-
36
- function runHook(scriptName, payload, timeoutMs) {
37
- try {
38
- const result = spawnSync('node', [path.join(HOOKS_DIR, scriptName)], {
39
- input: JSON.stringify(payload || {}),
40
- encoding: 'utf8',
41
- timeout: timeoutMs,
42
- });
43
- if (!result || !result.stdout) return {};
44
- try { return JSON.parse(result.stdout); } catch { return {}; }
45
- } catch {
46
- return {};
47
- }
48
- }
49
-
50
- const Evolver = async () => ({
51
- event: async ({ event }) => {
52
- if (!event || typeof event.type !== 'string') return;
53
- if (event.type === 'session.created') {
54
- runHook('evolver-session-start.js', {
55
- session_id: event.properties && event.properties.info && event.properties.info.id,
56
- }, 3000);
57
- return;
58
- }
59
- if (event.type === 'session.idle') {
60
- runHook('evolver-session-end.js', {
61
- session_id: event.properties && event.properties.sessionID,
62
- }, 8000);
63
- }
64
- },
65
- 'tool.execute.after': async (input, output) => {
66
- if (!input || typeof input.tool !== 'string') return;
67
- if (input.tool !== 'write' && input.tool !== 'edit') return;
68
- runHook('evolver-signal-detect.js', {
69
- tool_input: (output && output.args) || {},
70
- tool_response: (output && output.output) || (output && output.result) || {},
71
- }, 2000);
72
- },
73
- });
74
-
75
- module.exports = { Evolver };
76
- module.exports.default = Evolver;
77
- `;
78
- }
79
-
80
- function buildAgentsMdSection() {
81
- return `${EVOLVER_MARKER}
82
- ## Evolution Memory (Evolver)
83
-
84
- This project uses evolver for self-evolution. Hooks automatically:
85
- 1. Run quietly at session start and load recent evolution memory when useful
86
- 2. Detect evolution signals during file edits
87
- 3. Record outcomes at session end
88
-
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
- Signals: log_error, perf_bottleneck, user_feature_request, capability_gap, deployment_issue, test_failure.`;
91
- }
92
-
93
- function appendSectionToFile(filePath, marker, content) {
94
- let existing = '';
95
- try { existing = fs.readFileSync(filePath, 'utf8'); } catch { /* new file */ }
96
- if (existing.includes(marker)) return false;
97
- const separator = existing.length > 0 && !existing.endsWith('\n') ? '\n\n' : '\n';
98
- fs.writeFileSync(filePath, existing + separator + content + '\n', 'utf8');
99
- return true;
100
- }
101
-
102
- function isEvolverManagedPluginFile(filePath) {
103
- try {
104
- if (!fs.existsSync(filePath)) return false;
105
- const raw = fs.readFileSync(filePath, 'utf8');
106
- return raw.includes('_evolver_managed: true');
107
- } catch {
108
- return false;
109
- }
110
- }
111
-
112
- function writePluginFile(pluginsDir, source) {
113
- fs.mkdirSync(pluginsDir, { recursive: true });
114
- const dest = path.join(pluginsDir, PLUGIN_FILE_NAME);
115
- const tmp = dest + '.tmp';
116
- fs.writeFileSync(tmp, source, 'utf8');
117
- fs.renameSync(tmp, dest);
118
- return dest;
119
- }
120
-
121
- function install({ configRoot, evolverRoot, force }) {
122
- const opencodeDir = path.join(configRoot, '.opencode');
123
- const hooksDir = path.join(opencodeDir, HOOK_SCRIPTS_DIR_NAME);
124
- const pluginsDir = path.join(opencodeDir, PLUGINS_DIR_NAME);
125
- const pluginPath = path.join(pluginsDir, PLUGIN_FILE_NAME);
126
- const agentsMdPath = path.join(configRoot, 'AGENTS.md');
127
- assertSafeConfigDir(opencodeDir, '.opencode', { subdirs: [HOOK_SCRIPTS_DIR_NAME, PLUGINS_DIR_NAME] });
128
-
129
- if (!force && isEvolverManagedPluginFile(pluginPath)) {
130
- console.log('[opencode] Evolver plugin already installed. Use --force to overwrite.');
131
- printPostInstallNotice(pluginPath);
132
- return { ok: true, skipped: true, plugin_path: pluginPath };
133
- }
134
-
135
- fs.mkdirSync(opencodeDir, { recursive: true });
136
-
137
- const written = writePluginFile(pluginsDir, buildPluginSource(hooksDir));
138
- console.log('[opencode] Wrote ' + written);
139
-
140
- const copied = copyHookScripts(hooksDir, path.join(evolverRoot, 'src', 'adapters'));
141
- console.log('[opencode] Copied ' + copied.length + ' hook scripts to ' + hooksDir);
142
-
143
- const injected = appendSectionToFile(agentsMdPath, EVOLVER_MARKER, buildAgentsMdSection());
144
- if (injected) {
145
- console.log('[opencode] Injected evolution section into ' + agentsMdPath);
146
- }
147
-
148
- console.log('[opencode] Installation complete.');
149
- printPostInstallNotice(written);
150
-
151
- return {
152
- ok: true,
153
- platform: 'opencode',
154
- plugin_path: written,
155
- files: [written, agentsMdPath, ...copied],
156
- };
157
- }
158
-
159
- function printPostInstallNotice(pluginPath) {
160
- // The opencode TUI "Plugins" tab only lists TUI plugins (registered via
161
- // tui.json with `default export { id, tui }`). Server plugins like ours,
162
- // auto-loaded from .opencode/plugins/, are functional but invisible in
163
- // that tab. This is by opencode design, not a bug. See:
164
- // https://github.com/sst/opencode -> packages/opencode/specs/tui-plugins.md
165
- // Surfacing this proactively here prevents the "is it actually loaded?"
166
- // confusion that motivated EvoMap/evolver issue #531.
167
- console.log('');
168
- console.log('[opencode] Restart opencode for the plugin to take effect.');
169
- console.log('[opencode] Note: this is a SERVER plugin (event hooks). It will NOT appear in');
170
- console.log('[opencode] the TUI "Plugins" tab -- that tab only lists TUI plugins');
171
- console.log('[opencode] (registered via tui.json). The plugin is still loaded and');
172
- console.log('[opencode] running silently in the background.');
173
- console.log('[opencode] To verify the plugin is loaded, run:');
174
- console.log('[opencode] opencode --print-logs --log-level INFO debug config 2>&1 | grep ' + JSON.stringify(pluginPath));
175
- console.log('[opencode] Or run:');
176
- console.log('[opencode] evolver setup-hooks --platform=opencode --verify');
177
- }
178
-
179
- // Walk the install state and report what is healthy / what is missing.
180
- // Used by the `--verify` flag to give users a definitive answer to
181
- // "is the plugin actually installed and loadable?". Returns a structured
182
- // result so callers (CLI, future TUI plugin) can format it as they like.
183
- function verify({ configRoot }) {
184
- const opencodeDir = path.join(configRoot, '.opencode');
185
- const hooksDir = path.join(opencodeDir, HOOK_SCRIPTS_DIR_NAME);
186
- const pluginsDir = path.join(opencodeDir, PLUGINS_DIR_NAME);
187
- const pluginPath = path.join(pluginsDir, PLUGIN_FILE_NAME);
188
- const agentsMdPath = path.join(configRoot, 'AGENTS.md');
189
- const expectedScripts = [
190
- 'evolver-session-start.js',
191
- 'evolver-signal-detect.js',
192
- 'evolver-session-end.js',
193
- ];
194
-
195
- const checks = [];
196
-
197
- const pluginExists = fs.existsSync(pluginPath);
198
- checks.push({
199
- id: 'plugin_file_present',
200
- ok: pluginExists,
201
- detail: pluginExists ? pluginPath : 'missing: ' + pluginPath,
202
- });
203
-
204
- const managed = pluginExists && isEvolverManagedPluginFile(pluginPath);
205
- checks.push({
206
- id: 'plugin_managed_marker',
207
- ok: managed,
208
- detail: managed
209
- ? 'first line contains _evolver_managed: true'
210
- : 'plugin file is not evolver-managed (was it edited or replaced by another tool?)',
211
- });
212
-
213
- let pluginLoadable = false;
214
- let pluginLoadError = null;
215
- if (pluginExists) {
216
- try {
217
- // Require the plugin in an isolated module cache slot to confirm it
218
- // parses and exports the expected shape. opencode does an ESM dynamic
219
- // import; CommonJS require here is a strict subset of that, so a
220
- // failure here is a guaranteed failure under opencode too.
221
- delete require.cache[require.resolve(pluginPath)];
222
- const mod = require(pluginPath);
223
- const fn = mod && (mod.Evolver || mod.default);
224
- pluginLoadable = typeof fn === 'function';
225
- if (!pluginLoadable) pluginLoadError = 'no Evolver/default function export';
226
- } catch (err) {
227
- pluginLoadError = (err && err.message) || String(err);
228
- }
229
- }
230
- checks.push({
231
- id: 'plugin_loadable',
232
- ok: pluginLoadable,
233
- detail: pluginLoadable
234
- ? 'require() succeeded and exports Evolver()'
235
- : 'require() failed: ' + (pluginLoadError || 'unknown'),
236
- });
237
-
238
- const missingScripts = expectedScripts.filter(
239
- (name) => !fs.existsSync(path.join(hooksDir, name))
240
- );
241
- checks.push({
242
- id: 'hook_scripts_present',
243
- ok: missingScripts.length === 0,
244
- detail: missingScripts.length === 0
245
- ? 'all 3 hook scripts present in ' + hooksDir
246
- : 'missing: ' + missingScripts.join(', '),
247
- });
248
-
249
- let agentsMdHasSection = false;
250
- try {
251
- if (fs.existsSync(agentsMdPath)) {
252
- agentsMdHasSection = fs.readFileSync(agentsMdPath, 'utf8').includes(EVOLVER_MARKER);
253
- }
254
- } catch { /* ignore */ }
255
- checks.push({
256
- id: 'agents_md_section',
257
- ok: agentsMdHasSection,
258
- detail: agentsMdHasSection
259
- ? 'AGENTS.md contains evolution memory section'
260
- : 'AGENTS.md is missing or has no evolution section (re-run install)',
261
- });
262
-
263
- const allOk = checks.every((c) => c.ok);
264
-
265
- return {
266
- ok: allOk,
267
- plugin_path: pluginPath,
268
- hooks_dir: hooksDir,
269
- config_root: configRoot,
270
- checks,
271
- note: allOk
272
- ? 'Plugin is installed and loadable. opencode\'s TUI "Plugins" tab will not list it -- that tab only shows TUI plugins. Run `opencode --print-logs --log-level INFO debug config` and grep for the plugin path to confirm opencode loads it at startup.'
273
- : 'One or more checks failed. Re-run `evolver setup-hooks --platform=opencode --force` to repair.',
274
- };
275
- }
276
-
277
- function printVerifyReport(report) {
278
- console.log('[opencode] Verify report');
279
- console.log('[opencode] plugin path : ' + report.plugin_path);
280
- console.log('[opencode] hooks dir : ' + report.hooks_dir);
281
- console.log('[opencode] config root : ' + report.config_root);
282
- console.log('[opencode] Checks:');
283
- for (const c of report.checks) {
284
- console.log('[opencode] ' + (c.ok ? '[OK] ' : '[FAIL]') + ' ' + c.id + ' -- ' + c.detail);
285
- }
286
- console.log('[opencode] ' + (report.ok ? 'All checks passed.' : 'Some checks failed.'));
287
- console.log('[opencode] ' + report.note);
288
- }
289
-
290
- function uninstall({ configRoot }) {
291
- const opencodeDir = path.join(configRoot, '.opencode');
292
- const hooksDir = path.join(opencodeDir, HOOK_SCRIPTS_DIR_NAME);
293
- const pluginsDir = path.join(opencodeDir, PLUGINS_DIR_NAME);
294
- const pluginPath = path.join(pluginsDir, PLUGIN_FILE_NAME);
295
- const agentsMdPath = path.join(configRoot, 'AGENTS.md');
296
- assertSafeConfigDir(opencodeDir, '.opencode', { subdirs: [HOOK_SCRIPTS_DIR_NAME, PLUGINS_DIR_NAME] });
297
-
298
- let changed = false;
299
-
300
- if (isEvolverManagedPluginFile(pluginPath)) {
301
- try { fs.unlinkSync(pluginPath); changed = true; } catch { /* ignore */ }
302
- }
303
-
304
- const scripts = removeHookScripts(hooksDir);
305
- if (scripts > 0) changed = true;
306
-
307
- if (removeMarkedSection(agentsMdPath, EVOLVER_MARKER)) {
308
- changed = true;
309
- }
310
-
311
- console.log(changed
312
- ? '[opencode] Uninstalled evolver plugin and hooks.'
313
- : '[opencode] No evolver plugin found to uninstall.');
314
-
315
- return { ok: true, removed: changed };
316
- }
317
-
318
- module.exports = {
319
- install,
320
- uninstall,
321
- verify,
322
- printVerifyReport,
323
- buildPluginSource,
324
- isEvolverManagedPluginFile,
325
- PLUGIN_FILE_NAME,
326
- };
@@ -1,74 +0,0 @@
1
- // _lockPaths.js
2
- // Single source of truth for the daemon singleton-lock location and lease
3
- // tunables, shared by the daemon (index.js) and the session-start hook's
4
- // auto-restart guard (evolver-session-start.js).
5
- //
6
- // Issue #176: the hook used to replicate this logic inline ("keep index.js
7
- // out of the hook's require graph"), which could silently diverge whenever
8
- // the daemon's lock resolution changed. This module keeps that property —
9
- // it depends only on fs/os/path — while making divergence structurally
10
- // impossible.
11
- //
12
- // Deployed-layout constraint (PR #163): hook scripts are COPIED into the
13
- // host's hooks dir (e.g. `.claude/hooks/`) and run from there, so every
14
- // same-dir helper they require must be a sibling file listed in
15
- // hookAdapter.js's copy/remove lists (enforced by test/adapters.test.js).
16
-
17
- const fs = require('fs');
18
- const os = require('os');
19
- const path = require('path');
20
-
21
- // Round-4 (see the history note above index.js's daemon-lock block): the
22
- // pidfile previously defaulted to __dirname, which differs per install mode
23
- // (global install vs dev clone vs npx cache), so two daemons launched under
24
- // different install modes never saw each other's lock. Default now lives
25
- // under the per-user state dir so all install modes converge.
26
- // EVOLVER_LOCK_DIR still overrides for tests / sandboxed runs — note the
27
- // basename differs from the default in that case (`evolver.pid` vs
28
- // `instance.lock`).
29
- function getLockFilePath(env) {
30
- const e = env || process.env;
31
- if (e.EVOLVER_LOCK_DIR) {
32
- return path.join(e.EVOLVER_LOCK_DIR, 'evolver.pid');
33
- }
34
- // os.homedir() is cross-platform; process.env.HOME is unset on Windows.
35
- return path.join(os.homedir(), '.evomap', 'instance.lock');
36
- }
37
-
38
- // Round-9: lease tunables for the daemon lock. A live daemon refreshes the
39
- // lock mtime every LOCK_REFRESH_MS; a lock whose mtime is older than
40
- // STALE_LOCK_TTL_MS (and that was written by a lease-aware daemon) is
41
- // treated as stale even if its PID happens to be alive — closing the
42
- // "crash + PID reuse -> new daemon silently refuses to start" hole and the
43
- // "SIGKILL leaves a stale lock nobody reclaims" hole. The TTL is well above
44
- // the heartbeat interval (default 6min) so a healthy daemon never trips it.
45
- // On Windows, SIGTERM is implemented as TerminateProcess() (not a catchable
46
- // signal), so the daemon's releaseLock() never runs and the lock file stays
47
- // on disk with the dead PID — hence the shorter Windows TTL, with a 1-min
48
- // refresh (3x margin against transient FS hiccups). Unix: 5 min TTL is
49
- // 2.5x the 2-min refresh cadence.
50
- const STALE_LOCK_TTL_MS = process.platform === 'win32' ? 3 * 60_000 : 5 * 60_000;
51
- const LOCK_REFRESH_MS = process.platform === 'win32' ? 1 * 60_000 : 2 * 60_000;
52
-
53
- // Returns true if the lock was written by a lease-aware daemon AND its
54
- // mtime is older than the stale TTL — i.e. no live owner is refreshing it,
55
- // so it is safe to treat the recorded PID as dead regardless of whether
56
- // process.kill(pid, 0) resolves (the PID may have been reused). Locks
57
- // written by pre-lease daemons (payload.lease !== true) are never judged
58
- // stale by mtime, so we never falsely steal an older daemon's lock.
59
- function lockIsStaleByLease(lockFile, payload) {
60
- if (!payload || payload.lease !== true) return false;
61
- try {
62
- const ageMs = Date.now() - fs.statSync(lockFile).mtimeMs;
63
- return ageMs > STALE_LOCK_TTL_MS;
64
- } catch (_) {
65
- return false;
66
- }
67
- }
68
-
69
- module.exports = {
70
- getLockFilePath,
71
- lockIsStaleByLease,
72
- STALE_LOCK_TTL_MS,
73
- LOCK_REFRESH_MS,
74
- };
@@ -1,35 +0,0 @@
1
- // _memoryFiltering.js
2
- // Shared memory filtering logic for evolver hooks (platform-independent).
3
- //
4
- // Responsibility: Filter evolution memory outcomes to reduce noise in Claude/Codex context.
5
- // - Removes failed outcomes (no learning value)
6
- // - Filters low-confidence outcomes (score < 0.5)
7
- // - Enforces time bounds (< 7 days old)
8
- // - Limits result size (max 3 outcomes)
9
-
10
- const DEFAULT_MIN_SCORE = 0.5;
11
- const DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
12
- const DEFAULT_MAX_OUTCOMES = 3;
13
-
14
- function filterRelevantOutcomes(entries, opts = {}) {
15
- const minScore = opts.minScore !== undefined ? opts.minScore : DEFAULT_MIN_SCORE;
16
- const maxAgeMs = opts.maxAgeMs !== undefined ? opts.maxAgeMs : DEFAULT_MAX_AGE_MS;
17
- const maxOutcomes = opts.maxOutcomes !== undefined ? opts.maxOutcomes : DEFAULT_MAX_OUTCOMES;
18
-
19
- const now = Date.now();
20
-
21
- return entries
22
- .filter(e => {
23
- // Only keep 'success' outcomes (failed ones don't provide learning value)
24
- if (e.outcome?.status !== 'success') return false;
25
- // Only keep high-confidence outcomes
26
- if ((e.outcome?.score ?? 0) < minScore) return false;
27
- // Only keep recent outcomes
28
- const ts = e.timestamp ? new Date(e.timestamp).getTime() : 0;
29
- if (now - ts > maxAgeMs) return false;
30
- return true;
31
- })
32
- .slice(-maxOutcomes);
33
- }
34
-
35
- module.exports = { filterRelevantOutcomes, DEFAULT_MIN_SCORE, DEFAULT_MAX_AGE_MS, DEFAULT_MAX_OUTCOMES };