From 31e5e232a347a0ca6977f4ac066af095c5d6180a Mon Sep 17 00:00:00 2001 From: Alexgodoroja Date: Tue, 11 Aug 2026 15:07:28 -0700 Subject: [PATCH] fix(openclaw): drop unsupported --force from linked plugin install OpenClaw rejects --force alongside --link ("Linked plugins point at the source path directly"), so `attach --openclaw` aborted on the first of the three CLI steps. Because install, enable and inspect share one try block, the plugin was never registered at all -- while the cpSync above had already populated ~/.pilot/integrations/openclaw-policy, leaving users with plugin files on disk and nothing installed against them. --force was redundant regardless: a linked install points at installedPlugin, which cpSync refreshes on every run, so re-attaching stays idempotent without it. The test stub logged argv and always exited 0, so it accepted a flag pair the real CLI refuses and the bug shipped green. It now mirrors the CLI and rejects the combination, which fails the test if --force is reintroduced. Verified against OpenClaw 2026.7.1-2: install, enable and inspect all succeed, and the plugin reports status "loaded". --- src/setup/harnesses/openclaw.js | 4 +++- test/native-harness-setup.test.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/setup/harnesses/openclaw.js b/src/setup/harnesses/openclaw.js index 0dcdce1..b31146d 100644 --- a/src/setup/harnesses/openclaw.js +++ b/src/setup/harnesses/openclaw.js @@ -21,7 +21,9 @@ export async function configure(options = {}) { mkdirSync(join(home, '.pilot', 'integrations'), { recursive: true }); cpSync(SOURCE_PLUGIN, installedPlugin, { recursive: true, force: true }); try { - await execute('openclaw', ['plugins', 'install', '--link', '--force', installedPlugin], { + // No --force: OpenClaw rejects it alongside --link, and a linked install already + // points at installedPlugin, which the cpSync above just refreshed. + await execute('openclaw', ['plugins', 'install', '--link', installedPlugin], { env: process.env, timeout: 60000, maxBuffer: 1 << 20, }); await execute('openclaw', ['plugins', 'enable', 'pilot-policy'], { diff --git a/test/native-harness-setup.test.js b/test/native-harness-setup.test.js index 4b8ecd9..85fb025 100644 --- a/test/native-harness-setup.test.js +++ b/test/native-harness-setup.test.js @@ -100,7 +100,19 @@ test('OpenClaw setup installs the bundled native policy plugin in one pass', () const log = join(home, 'openclaw.args'); mkdirSync(bin, { recursive: true }); const executable = join(bin, 'openclaw'); - writeFileSync(executable, `#!/bin/sh\nprintf '%s\\n' "$@" >> ${JSON.stringify(log)}\nprintf '%s\\n' -- >> ${JSON.stringify(log)}\n`); + // Mirror the real CLI, which rejects --force alongside --link. A permissive stub is + // what let the unsupported flag pair ship green. + writeFileSync(executable, [ + '#!/bin/sh', + `printf '%s\\n' "$@" >> ${JSON.stringify(log)}`, + `printf '%s\\n' -- >> ${JSON.stringify(log)}`, + 'case " $* " in *" --link "*)', + ' case " $* " in *" --force "*)', + ' echo "--force is not supported with --link." >&2; exit 1;;', + ' esac;;', + 'esac', + '', + ].join('\n')); chmodSync(executable, 0o700); configureInHome('openclaw', home, (dir) => { const target = join(dir, '.openclaw', 'openclaw.json'); @@ -110,7 +122,7 @@ test('OpenClaw setup installs the bundled native policy plugin in one pass', () const installed = join(home, '.pilot', 'integrations', 'openclaw-policy'); assert.equal(existsSync(join(installed, 'openclaw.plugin.json')), true); const calls = readFileSync(log, 'utf8'); - assert.match(calls, /plugins\ninstall\n--link\n--force/); + assert.match(calls, /plugins\ninstall\n--link\n[^\n]*openclaw-policy/); assert.match(calls, /plugins\nenable\npilot-policy/); assert.match(calls, /plugins\ninspect\npilot-policy\n--json/); const manifest = JSON.parse(readFileSync(join(installed, 'openclaw.plugin.json'), 'utf8'));