Skip to content

Commit 17e1c79

Browse files
author
evolver-publish
committed
Release v1.80.7
1 parent 9f7b0c5 commit 17e1c79

41 files changed

Lines changed: 328 additions & 40 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

index.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1559,12 +1559,43 @@ async function main() {
15591559
}
15601560

15611561
} else if (command === 'setup-hooks') {
1562-
const { setupHooks } = require('./src/adapters/hookAdapter');
1562+
const hookAdapter = require('./src/adapters/hookAdapter');
1563+
const { setupHooks, resolveConfigRoot, detectPlatform, loadAdapter } = hookAdapter;
15631564

15641565
const platformFlag = args.find(a => typeof a === 'string' && a.startsWith('--platform='));
15651566
const platform = platformFlag ? platformFlag.slice('--platform='.length) : undefined;
15661567
const force = args.includes('--force');
15671568
const uninstall = args.includes('--uninstall');
1569+
const verifyOnly = args.includes('--verify');
1570+
1571+
if (verifyOnly) {
1572+
// Read-only verification: do not touch any files, just report whether
1573+
// the previously-installed hooks/plugin look healthy. Lets users answer
1574+
// "is the plugin actually loaded?" without grepping opencode logs.
1575+
try {
1576+
const platformId = platform || detectPlatform(process.cwd());
1577+
if (!platformId) {
1578+
console.error('[setup-hooks] --verify: could not detect platform. Pass --platform=opencode|cursor|claude-code|codex|kiro');
1579+
process.exit(2);
1580+
}
1581+
const adapter = loadAdapter(platformId);
1582+
if (!adapter || typeof adapter.verify !== 'function') {
1583+
console.error('[setup-hooks] --verify: platform ' + platformId + ' does not support verification yet.');
1584+
process.exit(2);
1585+
}
1586+
const configRoot = resolveConfigRoot(platformId, process.cwd());
1587+
const report = adapter.verify({ configRoot });
1588+
if (typeof adapter.printVerifyReport === 'function') {
1589+
adapter.printVerifyReport(report);
1590+
} else {
1591+
console.log(JSON.stringify(report, null, 2));
1592+
}
1593+
process.exit(report.ok ? 0 : 1);
1594+
} catch (verifyErr) {
1595+
console.error('[setup-hooks] --verify error:', verifyErr && verifyErr.message || verifyErr);
1596+
process.exit(1);
1597+
}
1598+
}
15681599

15691600
try {
15701601
const result = await setupHooks({
@@ -1685,6 +1716,7 @@ async function main() {
16851716
- --platform=cursor|claude-code|codex|kiro|opencode (auto-detect if omitted)
16861717
- --force (overwrite existing config)
16871718
- --uninstall (remove evolver hooks)
1719+
- --verify (read-only: print install health for the chosen platform)
16881720
- asset-log flags:
16891721
- --run=<run_id> (filter by run ID)
16901722
- --action=<action> (filter: hub_search_hit, hub_search_miss, asset_reuse, asset_reference, asset_publish, asset_publish_skip)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evomap/evolver",
3-
"version": "1.80.6",
3+
"version": "1.80.7",
44
"description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
55
"main": "index.js",
66
"bin": {

src/adapters/opencode.js

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ function install({ configRoot, evolverRoot, force }) {
127127

128128
if (!force && isEvolverManagedPluginFile(pluginPath)) {
129129
console.log('[opencode] Evolver plugin already installed. Use --force to overwrite.');
130-
return { ok: true, skipped: true };
130+
printPostInstallNotice(pluginPath);
131+
return { ok: true, skipped: true, plugin_path: pluginPath };
131132
}
132133

133134
fs.mkdirSync(opencodeDir, { recursive: true });
@@ -144,15 +145,147 @@ function install({ configRoot, evolverRoot, force }) {
144145
}
145146

146147
console.log('[opencode] Installation complete.');
147-
console.log('[opencode] opencode auto-loads plugins from .opencode/plugins/ -- restart opencode to activate.');
148+
printPostInstallNotice(written);
148149

149150
return {
150151
ok: true,
151152
platform: 'opencode',
153+
plugin_path: written,
152154
files: [written, agentsMdPath, ...copied],
153155
};
154156
}
155157

158+
function printPostInstallNotice(pluginPath) {
159+
// The opencode TUI "Plugins" tab only lists TUI plugins (registered via
160+
// tui.json with `default export { id, tui }`). Server plugins like ours,
161+
// auto-loaded from .opencode/plugins/, are functional but invisible in
162+
// that tab. This is by opencode design, not a bug. See:
163+
// https://github.com/sst/opencode -> packages/opencode/specs/tui-plugins.md
164+
// Surfacing this proactively here prevents the "is it actually loaded?"
165+
// confusion that motivated EvoMap/evolver issue #531.
166+
console.log('');
167+
console.log('[opencode] Restart opencode for the plugin to take effect.');
168+
console.log('[opencode] Note: this is a SERVER plugin (event hooks). It will NOT appear in');
169+
console.log('[opencode] the TUI "Plugins" tab -- that tab only lists TUI plugins');
170+
console.log('[opencode] (registered via tui.json). The plugin is still loaded and');
171+
console.log('[opencode] running silently in the background.');
172+
console.log('[opencode] To verify the plugin is loaded, run:');
173+
console.log('[opencode] opencode --print-logs --log-level INFO debug config 2>&1 | grep ' + JSON.stringify(pluginPath));
174+
console.log('[opencode] Or run:');
175+
console.log('[opencode] evolver setup-hooks --platform=opencode --verify');
176+
}
177+
178+
// Walk the install state and report what is healthy / what is missing.
179+
// Used by the `--verify` flag to give users a definitive answer to
180+
// "is the plugin actually installed and loadable?". Returns a structured
181+
// result so callers (CLI, future TUI plugin) can format it as they like.
182+
function verify({ configRoot }) {
183+
const opencodeDir = path.join(configRoot, '.opencode');
184+
const hooksDir = path.join(opencodeDir, HOOK_SCRIPTS_DIR_NAME);
185+
const pluginsDir = path.join(opencodeDir, PLUGINS_DIR_NAME);
186+
const pluginPath = path.join(pluginsDir, PLUGIN_FILE_NAME);
187+
const agentsMdPath = path.join(configRoot, 'AGENTS.md');
188+
const expectedScripts = [
189+
'evolver-session-start.js',
190+
'evolver-signal-detect.js',
191+
'evolver-session-end.js',
192+
];
193+
194+
const checks = [];
195+
196+
const pluginExists = fs.existsSync(pluginPath);
197+
checks.push({
198+
id: 'plugin_file_present',
199+
ok: pluginExists,
200+
detail: pluginExists ? pluginPath : 'missing: ' + pluginPath,
201+
});
202+
203+
const managed = pluginExists && isEvolverManagedPluginFile(pluginPath);
204+
checks.push({
205+
id: 'plugin_managed_marker',
206+
ok: managed,
207+
detail: managed
208+
? 'first line contains _evolver_managed: true'
209+
: 'plugin file is not evolver-managed (was it edited or replaced by another tool?)',
210+
});
211+
212+
let pluginLoadable = false;
213+
let pluginLoadError = null;
214+
if (pluginExists) {
215+
try {
216+
// Require the plugin in an isolated module cache slot to confirm it
217+
// parses and exports the expected shape. opencode does an ESM dynamic
218+
// import; CommonJS require here is a strict subset of that, so a
219+
// failure here is a guaranteed failure under opencode too.
220+
delete require.cache[require.resolve(pluginPath)];
221+
const mod = require(pluginPath);
222+
const fn = mod && (mod.Evolver || mod.default);
223+
pluginLoadable = typeof fn === 'function';
224+
if (!pluginLoadable) pluginLoadError = 'no Evolver/default function export';
225+
} catch (err) {
226+
pluginLoadError = (err && err.message) || String(err);
227+
}
228+
}
229+
checks.push({
230+
id: 'plugin_loadable',
231+
ok: pluginLoadable,
232+
detail: pluginLoadable
233+
? 'require() succeeded and exports Evolver()'
234+
: 'require() failed: ' + (pluginLoadError || 'unknown'),
235+
});
236+
237+
const missingScripts = expectedScripts.filter(
238+
(name) => !fs.existsSync(path.join(hooksDir, name))
239+
);
240+
checks.push({
241+
id: 'hook_scripts_present',
242+
ok: missingScripts.length === 0,
243+
detail: missingScripts.length === 0
244+
? 'all 3 hook scripts present in ' + hooksDir
245+
: 'missing: ' + missingScripts.join(', '),
246+
});
247+
248+
let agentsMdHasSection = false;
249+
try {
250+
if (fs.existsSync(agentsMdPath)) {
251+
agentsMdHasSection = fs.readFileSync(agentsMdPath, 'utf8').includes(EVOLVER_MARKER);
252+
}
253+
} catch { /* ignore */ }
254+
checks.push({
255+
id: 'agents_md_section',
256+
ok: agentsMdHasSection,
257+
detail: agentsMdHasSection
258+
? 'AGENTS.md contains evolution memory section'
259+
: 'AGENTS.md is missing or has no evolution section (re-run install)',
260+
});
261+
262+
const allOk = checks.every((c) => c.ok);
263+
264+
return {
265+
ok: allOk,
266+
plugin_path: pluginPath,
267+
hooks_dir: hooksDir,
268+
config_root: configRoot,
269+
checks,
270+
note: allOk
271+
? '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.'
272+
: 'One or more checks failed. Re-run `evolver setup-hooks --platform=opencode --force` to repair.',
273+
};
274+
}
275+
276+
function printVerifyReport(report) {
277+
console.log('[opencode] Verify report');
278+
console.log('[opencode] plugin path : ' + report.plugin_path);
279+
console.log('[opencode] hooks dir : ' + report.hooks_dir);
280+
console.log('[opencode] config root : ' + report.config_root);
281+
console.log('[opencode] Checks:');
282+
for (const c of report.checks) {
283+
console.log('[opencode] ' + (c.ok ? '[OK] ' : '[FAIL]') + ' ' + c.id + ' -- ' + c.detail);
284+
}
285+
console.log('[opencode] ' + (report.ok ? 'All checks passed.' : 'Some checks failed.'));
286+
console.log('[opencode] ' + report.note);
287+
}
288+
156289
function uninstall({ configRoot }) {
157290
const opencodeDir = path.join(configRoot, '.opencode');
158291
const hooksDir = path.join(opencodeDir, HOOK_SCRIPTS_DIR_NAME);
@@ -193,6 +326,8 @@ function uninstall({ configRoot }) {
193326
module.exports = {
194327
install,
195328
uninstall,
329+
verify,
330+
printVerifyReport,
196331
buildPluginSource,
197332
isEvolverManagedPluginFile,
198333
PLUGIN_FILE_NAME,

src/evolve.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/guards.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/pipeline/collect.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/pipeline/dispatch.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/pipeline/enrich.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/pipeline/hub.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/evolve/pipeline/select.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)