Skip to content

Preserve root-managed OpenClaw runtime during plugin installs#81632

Closed
fuller-stack-dev wants to merge 1 commit into
openclaw:mainfrom
fuller-stack-dev:codex/preserve-host-runtime-plugin-installs
Closed

Preserve root-managed OpenClaw runtime during plugin installs#81632
fuller-stack-dev wants to merge 1 commit into
openclaw:mainfrom
fuller-stack-dev:codex/preserve-host-runtime-plugin-installs

Conversation

@fuller-stack-dev

@fuller-stack-dev fuller-stack-dev commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: plugin npm installs can encounter a root-managed setup where .openclaw/npm/node_modules/openclaw is the active OpenClaw runtime, not disposable plugin peer debris.
  • Why it matters: the stale peer cleanup path could uninstall or scrub that active runtime while installing another plugin, which can leave gateway startup importing missing runtime files.
  • What changed: repairManagedNpmRootOpenClawPeer now detects when the managed-root node_modules/openclaw realpath matches the active host package root and skips cleanup in that case.
  • What did NOT change (scope boundary): stale/transient openclaw peer cleanup still runs when node_modules/openclaw is not the active host runtime.
  • AI-assisted: yes; I understand the changed guard and verified it with focused tests plus real filesystem proof below.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra
  • Plugins / install runtime

Linked Issue/PR

Real behavior proof

  • Behavior addressed: root-managed plugin installs preserve the active openclaw runtime package instead of treating it as stale peer debris.
  • Real environment tested: macOS local OpenClaw checkout on branch codex/preserve-host-runtime-plugin-installs, Node via repo toolchain, temporary real managed npm root under /var/folders/.../T, no mocks and no test runner.
  • Exact steps or command run after this patch: ran a node --import tsx --input-type=module script that created a real managed npm root with package.json, package-lock.json, node_modules/openclaw, .bin/openclaw, and dist/cli/gateway-lifecycle.runtime.js, then called the patched repairManagedNpmRootOpenClawPeer against that active host package.
  • Evidence after fix: Terminal transcript from the real filesystem reproduction:
$ node --import tsx --input-type=module <real-filesystem-proof-script>
script_created_managed_root_with=openclaw package, package-lock, CLI shim, gateway lifecycle runtime file
script_invoked=repairManagedNpmRootOpenClawPeer({ npmRoot, packageRoot: hostRoot })
fixture=/var/folders/04/4nmxfbmn44d21bwf7cqknhgc0000gn/T/openclaw-real-proof-12GcMB
repair_result=false
manifest_openclaw_dependency=2026.5.12-beta.6
lock_openclaw_package_version=2026.5.12-beta.6
host_package_version=2026.5.12-beta.6
bin_still_exists=true
gateway_lifecycle_runtime_still_exists=true
  • Observed result after fix: the repair function returned false, did not invoke npm uninstall/prune, and the active host package, lockfile entry, CLI shim, and gateway lifecycle runtime file remained present.
  • What was not tested: no live Telegram/Discord gateway restart in this proof; the proof isolates the root-managed runtime mutation that caused the gateway startup failure.
  • Before evidence (optional but encouraged): local incident logs from the affected setup showed gateway startup failing with ERR_MODULE_NOT_FOUND for /Users/jason/.openclaw/npm/node_modules/openclaw/dist/cli/gateway-lifecycle.runtime.js after plugin install activity mutated the same managed npm root.

Root Cause (if applicable)

  • Root cause: the managed npm root is used both for installed plugin packages and, in root-managed installs, for the active openclaw package. The stale peer cleanup path assumed any root-level node_modules/openclaw was plugin peer debris.
  • Missing detection / guardrail: cleanup did not compare the root-level node_modules/openclaw realpath with the active OpenClaw package root before uninstalling or scrubbing it.
  • Contributing context (if known): a plugin with a runtime dependencies.openclaw entry can cause npm to materialize or mutate root-level openclaw state during plugin install.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/infra/npm-managed-root.test.ts and src/plugins/install.npm-spec.test.ts.
  • Scenario the test should lock in: active root-managed host package is preserved, while stale non-host openclaw peer packages are still cleaned up.
  • Why this is the smallest reliable guardrail: the bug lives at the managed npm root repair/install seam; these tests exercise that seam without requiring live channel credentials.
  • Existing test that already covers this (if any): existing stale peer cleanup tests covered removal, but not active-host preservation.

User-visible / Behavior Changes

OpenClaw plugin installs are less likely to break the currently running root-managed OpenClaw runtime when a plugin dependency graph references openclaw.

Diagram (if applicable)

Before:
plugin install -> stale peer cleanup sees node_modules/openclaw -> uninstall/scrub -> active runtime files can disappear

After:
plugin install -> cleanup realpath-checks active host -> preserve active runtime -> continue plugin install

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS local development machine
  • Runtime/container: Node repo toolchain, pnpm workspace
  • Model/provider: N/A
  • Integration/channel (if any): plugin install runtime; no live channel credentials used
  • Relevant config (redacted): temporary managed npm root fixture with openclaw@2026.5.12-beta.6 and @xdarkicex/openclaw-memory-libravdb@1.4.69

Steps

  1. Created a temporary root-managed npm layout where node_modules/openclaw is the active host package.
  2. Ran the patched managed-root repair function against that layout and asserted npm cleanup was not invoked.
  3. Ran focused formatter and behavior tests for the changed files.

Expected

  • Active host node_modules/openclaw remains installed.
  • Stale peer cleanup is skipped only for the active host package.
  • Existing stale peer cleanup behavior remains covered by tests.

Actual

  • Real proof output showed repair_result=false, bin_still_exists=true, and gateway_lifecycle_runtime_still_exists=true.
  • pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts passed.
  • OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts passed with 12 infra tests and 33 plugin tests.

Verification

  • pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts
  • OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts
  • Real filesystem reproduction shown in the Real behavior proof section above.

@openclaw-barnacle openclaw-barnacle Bot added size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 14, 2026
@clawsweeper

clawsweeper Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Summary
The PR adds an active-host realpath guard to managed npm root OpenClaw peer repair and adds direct repair plus npm plugin install regression coverage.

Reproducibility: yes. at source level: current main repairs and scrubs npmRoot/node_modules/openclaw before and after non-openclaw plugin installs whenever that path exists. I did not run a live root-managed install in this read-only review, but the PR body includes after-fix real filesystem proof for the guarded path.

Real behavior proof
Sufficient (terminal): The PR body includes after-fix terminal output from a real filesystem managed npm-root fixture showing cleanup was skipped and active runtime files remained present.

Next step before merge
No repair lane is needed; the active PR appears correct with sufficient proof, so the remaining work is maintainer review, merge gating, and overlap reconciliation.

Security
Cleared: The diff adds filesystem realpath checks and regression tests without changing dependencies, workflows, scripts, secrets handling, network calls, or permissions.

Review details

Best possible solution:

Land this focused guard, or fold the same active-host preservation behavior into the broader managed peer-planning work while preserving stale non-host peer cleanup.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main repairs and scrubs npmRoot/node_modules/openclaw before and after non-openclaw plugin installs whenever that path exists. I did not run a live root-managed install in this read-only review, but the PR body includes after-fix real filesystem proof for the guarded path.

Is this the best way to solve the issue?

Yes. The realpath equality guard is a narrow maintainable fix for avoiding active-host deletion while leaving stale non-host peer cleanup intact; the main open question is whether to land it separately or reconcile it with #81450.

Acceptance criteria:

  • pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts
  • OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts

What I checked:

  • Current cleanup path: On current main, repairManagedNpmRootOpenClawPeer treats a manifest dependency, lockfile entry, or node_modules/openclaw directory as stale state, runs npm uninstall/prune, then scrubs the package directory, bin shims, and hidden lockfile. (src/infra/npm-managed-root.ts:579, 256377c029f6)
  • Plugin install call path: Non-openclaw npm plugin installs call the repair helper before and after npm install, so the cleanup path is on the real managed npm plugin install flow. (src/plugins/install.ts:624, 256377c029f6)
  • Documented dependency contract: The dependency-resolution docs say OpenClaw should keep separate registry copies of the host package out of the managed root and reassert plugin-local host peer links after install/update/uninstall. Public docs: docs/plugins/dependency-resolution.md. (docs/plugins/dependency-resolution.md:60, 256377c029f6)
  • PR implementation: The PR head compares the realpath of the active package root with npmRoot/node_modules/openclaw and returns before cleanup when they match; tests cover direct repair and npm install preservation. (src/infra/npm-managed-root.ts:579, d29bd19220a3)
  • Real behavior proof: The PR body includes after-fix terminal output from a real managed npm-root fixture showing repair_result=false and the active runtime package, lock entry, CLI shim, and gateway lifecycle runtime file preserved. (d29bd19220a3)
  • Related overlapping work: fix: plan managed npm peer pins with npm #81450 is still open and changes the same managed npm peer-planning area, so it should be reconciled before landing this focused guard. (94014ff8f930)

Likely related people:

  • shakkernerd: Recent commits touched the central managed npm peer preservation and hardening paths in src/infra/npm-managed-root.ts, src/plugins/install.ts, and npm install coverage. (role: recent area contributor; confidence: high; commits: 18ca285ed6d1, 6e5042cd62e7, f4cb20300f6b; files: src/infra/npm-managed-root.ts, src/plugins/install.ts, src/plugins/install.npm-spec.test.ts)
  • steipete: Authored the merged managed npm OpenClaw peer repair commit, nearby npm-pack install work, and the related broader managed peer-planning PR. (role: feature-history contributor; confidence: high; commits: 8e533490ab0a, 2eaf8ad7126b, 94014ff8f930; files: src/infra/npm-managed-root.ts, src/plugins/install.ts, src/plugins/install.npm-spec.test.ts)
  • vincentkoc: Opened related stale OpenClaw peer install coverage and is co-authored on the merged managed npm peer repair stack, so they are useful context for regression behavior. (role: adjacent regression contributor; confidence: medium; commits: e470574bfc89, 8e533490ab0a; files: src/plugins/install.npm-spec.e2e.test.ts, src/infra/npm-managed-root.ts, src/plugins/install.ts)

Remaining risk / open question:

  • fix: plan managed npm peer pins with npm #81450 changes the same managed npm peer-planning area and should be reconciled before landing.
  • The supplied runtime proof isolates the managed-root filesystem mutation path; it does not show a full live gateway restart after plugin install.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 256377c029f6.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 14, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 14, 2026
steipete added a commit that referenced this pull request May 14, 2026
Plan managed npm peer dependency pins from npm's lockfile planner instead of recursively scanning nested node_modules packages, preserving host peer ranges when npm cannot produce a usable root pin.

Also preserves active root-managed OpenClaw host runtimes during npm plugin installs, folding the active-host guard/test from #81632.

Verification:
- codex-review --full-access
- pnpm check:test-types
- pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts CHANGELOG.md test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts && git diff --check
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts -- --reporter=verbose
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/plugins/install.npm-spec.e2e.test.ts -- --reporter=verbose
- node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts --reporter=verbose
- GitHub current-head checks: 55 completed, 0 failures; remaining Blacksmith-backed jobs capacity-queued at merge decision time.

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
@steipete

Copy link
Copy Markdown
Contributor

Thanks @fuller-stack-dev. I folded the active-host guard and tests from this PR into #81450, which has now landed on main as d9ff8cf.

Contributor credit was preserved with your Co-authored-by trailer on the landed squash commit, and CHANGELOG.md thanks @fuller-stack-dev. Closing this PR as superseded by the landed maintainer repair.

@steipete steipete closed this May 14, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Plan managed npm peer dependency pins from npm's lockfile planner instead of recursively scanning nested node_modules packages, preserving host peer ranges when npm cannot produce a usable root pin.

Also preserves active root-managed OpenClaw host runtimes during npm plugin installs, folding the active-host guard/test from openclaw#81632.

Verification:
- codex-review --full-access
- pnpm check:test-types
- pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts CHANGELOG.md test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts && git diff --check
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts -- --reporter=verbose
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/plugins/install.npm-spec.e2e.test.ts -- --reporter=verbose
- node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts --reporter=verbose
- GitHub current-head checks: 55 completed, 0 failures; remaining Blacksmith-backed jobs capacity-queued at merge decision time.

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
Plan managed npm peer dependency pins from npm's lockfile planner instead of recursively scanning nested node_modules packages, preserving host peer ranges when npm cannot produce a usable root pin.

Also preserves active root-managed OpenClaw host runtimes during npm plugin installs, folding the active-host guard/test from openclaw#81632.

Verification:
- codex-review --full-access
- pnpm check:test-types
- pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts CHANGELOG.md test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts && git diff --check
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts -- --reporter=verbose
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/plugins/install.npm-spec.e2e.test.ts -- --reporter=verbose
- node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts --reporter=verbose
- GitHub current-head checks: 55 completed, 0 failures; remaining Blacksmith-backed jobs capacity-queued at merge decision time.

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
Plan managed npm peer dependency pins from npm's lockfile planner instead of recursively scanning nested node_modules packages, preserving host peer ranges when npm cannot produce a usable root pin.

Also preserves active root-managed OpenClaw host runtimes during npm plugin installs, folding the active-host guard/test from openclaw#81632.

Verification:
- codex-review --full-access
- pnpm check:test-types
- pnpm exec oxfmt --check --threads=1 src/infra/npm-managed-root.ts src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts CHANGELOG.md test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts && git diff --check
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/infra/npm-managed-root.test.ts src/plugins/install.npm-spec.test.ts -- --reporter=verbose
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/test-projects.mjs src/plugins/install.npm-spec.e2e.test.ts -- --reporter=verbose
- node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts test/scripts/mantis-build-telegram-desktop-proof-evidence.test.ts --reporter=verbose
- GitHub current-head checks: 55 completed, 0 failures; remaining Blacksmith-backed jobs capacity-queued at merge decision time.

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants