diff --git a/scripts/e2e/parallels/macos-smoke.ts b/scripts/e2e/parallels/macos-smoke.ts index 075e2d2b35a5..062d45e0936d 100755 --- a/scripts/e2e/parallels/macos-smoke.ts +++ b/scripts/e2e/parallels/macos-smoke.ts @@ -970,7 +970,7 @@ config.update = { ...(config.update || {}), channel: "dev" }; fs.mkdirSync(path.dirname(configPath), { recursive: true }); fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\\n"); JS -/usr/bin/env NODE_OPTIONS=--max-old-space-size=8192 OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 OPENCLAW_DISABLE_BUNDLED_PLUGINS=1${devTargetEnv} ${guestOpenClawEntryRunner} update --channel dev --yes --json --no-restart --timeout ${this.updateDevTimeoutSeconds} +/usr/bin/env NODE_OPTIONS=--max-old-space-size=8192 OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1${devTargetEnv} ${guestOpenClawEntryRunner} update --channel dev --yes --json --no-restart --timeout ${this.updateDevTimeoutSeconds} ${guestOpenClawEntryRunner} --version ${guestOpenClawEntryRunner} update status --json`, {}, diff --git a/scripts/e2e/parallels/npm-update-scripts.ts b/scripts/e2e/parallels/npm-update-scripts.ts index 788396fb3185..e5e0ba9aad01 100644 --- a/scripts/e2e/parallels/npm-update-scripts.ts +++ b/scripts/e2e/parallels/npm-update-scripts.ts @@ -142,12 +142,12 @@ if [ "$agent_ok" != true ]; then fi`; } -function windowsUpdateWithBundledPluginsDisabled(input: NpmUpdateScriptInput): string { +function windowsUpdateWithScopedEnv(input: NpmUpdateScriptInput): string { const registryEntry = input.npmRegistry ? `; NPM_CONFIG_REGISTRY = ${psSingleQuote(input.npmRegistry)}` : ""; return `$script:OpenClawUpdateExit = 0 -$updateOutput = Invoke-WithScopedEnv @{ OPENCLAW_DISABLE_BUNDLED_PLUGINS = '1'; OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS = '1'${registryEntry} } { +$updateOutput = Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS = '1'${registryEntry} } { Invoke-OpenClaw update --tag ${psSingleQuote(input.updateTarget)} --yes --json --no-restart 2>&1 $script:OpenClawUpdateExit = $LASTEXITCODE } @@ -285,7 +285,7 @@ wait_for_gateway() { } scrub_future_plugin_entries stop_openclaw_gateway_processes -${posixNpmRegistryEnv(input.npmRegistry)}OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 "$OPENCLAW_BIN" update --tag ${shellQuote(input.updateTarget)} --yes --json --no-restart +${posixNpmRegistryEnv(input.npmRegistry)}OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 "$OPENCLAW_BIN" update --tag ${shellQuote(input.updateTarget)} --yes --json --no-restart ${posixVersionCheck(macosOpenClawCommand, input.expectedNeedle)} start_openclaw_gateway wait_for_gateway @@ -360,7 +360,7 @@ function Stop-OpenClawGatewayProcesses { } Remove-FuturePluginEntries Stop-OpenClawGatewayProcesses -${windowsUpdateWithBundledPluginsDisabled(input)} +${windowsUpdateWithScopedEnv(input)} if ($updateExit -ne 0) { $updateText = $updateOutput | Out-String $stalePostSwapImport = $updateText -match 'ERR_MODULE_NOT_FOUND' -and $updateText -match ${psSingleQuote(windowsStalePostSwapImportRegex)} @@ -429,7 +429,7 @@ wait_for_gateway() { } scrub_future_plugin_entries stop_openclaw_gateway_processes -${posixNpmRegistryEnv(input.npmRegistry)}OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 openclaw update --tag ${shellQuote(input.updateTarget)} --yes --json --no-restart +${posixNpmRegistryEnv(input.npmRegistry)}OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 openclaw update --tag ${shellQuote(input.updateTarget)} --yes --json --no-restart ${posixVersionCheck("openclaw", input.expectedNeedle)} start_openclaw_gateway wait_for_gateway diff --git a/scripts/e2e/parallels/windows-smoke.ts b/scripts/e2e/parallels/windows-smoke.ts index 8340d3bddad3..a74fe7afe0a2 100755 --- a/scripts/e2e/parallels/windows-smoke.ts +++ b/scripts/e2e/parallels/windows-smoke.ts @@ -687,7 +687,7 @@ $config.update | Add-Member -Force -MemberType NoteProperty -Name channel -Value $config | ConvertTo-Json -Depth 100 | Set-Content -Path $configPath -Encoding utf8 ${windowsScopedEnvFunction} $script:OpenClawUpdateExit = 0 -Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS = '1'; OPENCLAW_DISABLE_BUNDLED_PLUGINS = '1'${devTargetEntry} } { +Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS = '1'${devTargetEntry} } { Invoke-OpenClaw update --channel dev --yes --json --no-restart --timeout ${this.updateTimeoutSeconds} $script:OpenClawUpdateExit = $LASTEXITCODE } diff --git a/test/scripts/parallels-npm-update-smoke.test.ts b/test/scripts/parallels-npm-update-smoke.test.ts index cee6f2a7a7bf..f08549a7bd53 100644 --- a/test/scripts/parallels-npm-update-smoke.test.ts +++ b/test/scripts/parallels-npm-update-smoke.test.ts @@ -1177,23 +1177,40 @@ exit 7 ); expect(windowsScript).toContain("Remove-FuturePluginEntries\nStop-OpenClawGatewayProcesses"); expect(script).toContain("scrub_future_plugin_entries\nstop_openclaw_gateway_processes"); - expect(script).toContain("Invoke-WithScopedEnv @{ OPENCLAW_DISABLE_BUNDLED_PLUGINS = '1'"); expect(macosScript).toContain('OPENCLAW_BIN="$(resolve_required_command openclaw)"'); expect(macosScript).toContain("/usr/local/bin:/usr/local/sbin"); - expect(macosScript).toContain( - 'OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 "$OPENCLAW_BIN" update --tag', - ); expect(macosScript).not.toContain("/opt/homebrew/bin/openclaw"); - expect(script).toContain("OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 openclaw update --tag"); + }); + + it("preserves bundled plugin inventory during updates while isolating POSIX gateway stops", () => { + const input = { + auth: TEST_AUTH, + expectedNeedle: "2026.5.3-beta.2", + updateTarget: "2026.5.3-beta.2", + }; + const windowsScript = windowsUpdateScript(input); + const macosScript = macosUpdateScript(input); + const linuxScript = linuxUpdateScript(input); + const updateLines = [windowsScript, macosScript, linuxScript].map((generatedScript) => + generatedScript.split("\n").find((line) => line.includes(" update --tag ")), + ); + + expect(updateLines).not.toContain(undefined); + for (const updateLine of updateLines) { + expect(updateLine).not.toContain("OPENCLAW_DISABLE_BUNDLED_PLUGINS"); + } + expect(windowsScript).toContain( + "Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS = '1'", + ); expect(macosScript).toContain( 'OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 "$OPENCLAW_BIN" gateway stop', ); - expect(script).toContain( + expect(linuxScript).toContain( "OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 OPENCLAW_ALLOW_ROOT=1 openclaw gateway stop", ); }); - it("reenables bundled plugins before Windows post-update verification", () => { + it("limits the Windows update environment to the update invocation", () => { const script = windowsUpdateScript({ auth: TEST_AUTH, expectedNeedle: "2026.5.3-beta.2", @@ -1201,7 +1218,9 @@ exit 7 }); const updateIndex = script.indexOf("Invoke-OpenClaw update --tag"); - const scopedIndex = script.indexOf("Invoke-WithScopedEnv @{ OPENCLAW_DISABLE_BUNDLED_PLUGINS"); + const scopedIndex = script.indexOf( + "Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS", + ); const versionIndex = script.indexOf("Invoke-OpenClaw --version", scopedIndex); const restartIndex = script.indexOf("Invoke-OpenClaw gateway restart"); const agentIndex = script.indexOf("Invoke-OpenClaw agent --local"); @@ -1212,7 +1231,7 @@ exit 7 expect(versionIndex).toBeGreaterThan(updateIndex); expect(restartIndex).toBeGreaterThan(updateIndex); expect(agentIndex).toBeGreaterThan(updateIndex); - expect(script).not.toContain("$env:OPENCLAW_DISABLE_BUNDLED_PLUGINS = '1'"); + expect(script).not.toContain("OPENCLAW_DISABLE_BUNDLED_PLUGINS"); }); it("generates a .NET-safe Windows stale import regex in the update-failure guard", () => { diff --git a/test/scripts/parallels-smoke-model.test.ts b/test/scripts/parallels-smoke-model.test.ts index da0cc150e7db..3fe701d5dfc5 100644 --- a/test/scripts/parallels-smoke-model.test.ts +++ b/test/scripts/parallels-smoke-model.test.ts @@ -2153,7 +2153,15 @@ kill -TERM "$$"`, expect(transports).toContain("launch retry"); }); - it("keeps Windows update-only env flags scoped before verification", () => { + it("preserves bundled plugin inventory during dev updates", () => { + const devUpdateLines = [macos, windows].map((script) => + script.split("\n").find((line) => line.includes("update --channel dev")), + ); + + expect(devUpdateLines).not.toContain(undefined); + for (const updateLine of devUpdateLines) { + expect(updateLine).not.toContain("OPENCLAW_DISABLE_BUNDLED_PLUGINS"); + } expect(powershell).toContain("windowsScopedEnvFunction"); expect(windows).toContain( "Invoke-WithScopedEnv @{ OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS",