Skip to content

fix(update): prune stale local bundled plugin shadows#84863

Merged
scoootscooob merged 2 commits into
openclaw:mainfrom
fuller-stack-dev:fix/stale-local-official-plugin-shadows
May 21, 2026
Merged

fix(update): prune stale local bundled plugin shadows#84863
scoootscooob merged 2 commits into
openclaw:mainfrom
fuller-stack-dev:fix/stale-local-official-plugin-shadows

Conversation

@fuller-stack-dev

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

Copy link
Copy Markdown
Member

Summary

  • Add a version-aware stale local bundled-plugin install-record detector for official bundled plugin IDs.
  • Prune those stale records during post-core update convergence before repair/smoke checks run.
  • Teach openclaw doctor --fix to warn on and remove stale local bundled install-record shadows while preserving current, same-version, versionless, source-checkout, and arbitrary local path records.
  • Add a changelog entry and explicit sort comparators so the lint shard accepts the new deterministic iteration.

Verification

  • node scripts/run-vitest.mjs src/plugins/stale-local-bundled-plugin-install-records.test.ts src/cli/update-cli/post-core-plugin-convergence.test.ts src/commands/doctor-plugin-registry.test.ts
    • 3 files passed, 31 tests passed.
  • node scripts/run-oxlint-shards.mjs --threads=8
    • core/extensions/scripts all reported 0 warnings and 0 errors.
  • ./node_modules/.bin/oxfmt --check --threads=1 CHANGELOG.md src/plugins/stale-local-bundled-plugin-install-records.ts src/commands/doctor-plugin-registry.ts
    • all matched files use the correct format.
  • git diff --check

Real behavior proof

Behavior addressed: A stale persisted path install record for an official bundled plugin can make old compiled bundled output, such as old-checkout/dist/extensions/discord, shadow the current bundled plugin after an update. This patch removes only stale compiled bundled path records so the current bundled plugin wins again.

Real environment tested: Local OpenClaw source checkout on macOS with the PR branch checked out at 97e2080a85b1c2df15465b038947f1c68b54bba6, isolated temporary HOME and OPENCLAW_STATE_DIR, and a temporary trusted bundled plugin root containing a current discord plugin at 2026.5.20-beta.1 plus a stale compiled discord path record at 2026.5.4-beta.3.

Exact steps or command run after this patch: Ran a local terminal command with node --import tsx --input-type=module that created the temporary OpenClaw setup, loaded the plugin registry before pruning with the stale install record, called pruneStaleLocalBundledPluginInstallRecords, then loaded the plugin registry again with the pruned records.

Evidence after fix: Copied terminal output from the hermetic runtime command:

{
  "before": [
    {
      "id": "discord",
      "origin": "global",
      "version": "2026.5.4-beta.3"
    }
  ],
  "staleRemoved": [
    {
      "pluginId": "discord",
      "recordPathField": "installPath"
    }
  ],
  "remainingInstallRecords": [],
  "after": [
    {
      "id": "discord",
      "origin": "bundled",
      "version": "2026.5.20-beta.1"
    }
  ]
}

Observed result after fix: Before pruning, discord resolved from the stale global path at 2026.5.4-beta.3. After pruning, the stale installPath record was removed, no install records remained for discord, and the registry resolved discord from the current bundled plugin at 2026.5.20-beta.1.

What was not tested: Full end-to-end updater restart on a packaged beta install was not run locally; the post-core convergence and doctor repair call paths are covered by the targeted tests listed above.

The helper keeps non-stale local overrides covered by tests: current bundled paths, same-version compiled paths, versionless compiled paths, source-checkout extensions/<id> paths, and arbitrary local plugin paths are not pruned.

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes commands Command implementations size: L triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 21, 2026
@clawsweeper

clawsweeper Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The branch adds a helper to detect version-mismatched path install records pointing at packaged bundled plugin output and wires it into post-core update convergence plus doctor registry repair with focused tests.

Reproducibility: yes. at source level, not via a live run: current main preserves path install records while existing bundled-shadow cleanup only covers managed npm/clawhub-style records, so the stale compiled path shadow is credible from code inspection.

PR rating
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🐚 platinum hermit
Summary: The implementation looks focused and reviewable, but the external-PR proof gate is not met yet.

Rank-up moves:

  • Add redacted after-fix terminal or log output for openclaw doctor --fix or post-core convergence against a real stale dist/extensions/<id> path record.
  • Show the observed before/after install-record state, including that source-checkout and arbitrary local path records remain preserved.
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Real behavior proof
Needs real behavior proof before merge: The PR body has assertions and test commands but no redacted after-fix terminal/log/screenshot/artifact; the contributor should add proof, update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.

Risk before merge

  • The PR changes upgrade/doctor behavior by removing persisted version-mismatched local path records that point at old packaged bundled output; that is likely correct for stale shadows but can surprise anyone intentionally pinning an old compiled bundled plugin directory.
  • The contributor has not supplied after-fix real behavior proof, so reviewers cannot yet verify the actual user-path registry mutation outside unit tests and stated expectations.

Maintainer options:

  1. Require upgrade proof first (recommended)
    Ask for redacted terminal or log proof from a real stale dist/extensions/ record showing the record is pruned and preserved override cases are not touched.
  2. Accept the cleanup policy
    Maintainers can intentionally accept that old compiled bundled output paths are stale shadows and rely on the focused tests for the preservation boundary.

Next step before merge
Human review should wait on contributor real behavior proof and consciously accept the local compiled-path cleanup compatibility boundary.

Security
Cleared: No concrete security or supply-chain regression was found; the diff adds TypeScript logic and tests without new dependencies, workflows, secret handling, or artifact execution.

Review details

Best possible solution:

Land the narrow pruning path only after a redacted real upgrade or doctor run proves stale compiled bundled path records are removed while source-checkout and arbitrary local overrides remain untouched.

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

Yes at source level, not via a live run: current main preserves path install records while existing bundled-shadow cleanup only covers managed npm/clawhub-style records, so the stale compiled path shadow is credible from code inspection.

Is this the best way to solve the issue?

Yes, mostly: the PR follows the existing bundled-shadow cleanup direction and narrows removal to version-mismatched packaged bundled output paths, but merge should wait for real upgrade or doctor proof.

Label changes:

  • add P2: This is a normal update/doctor bug fix with limited but real upgrade-state impact.
  • add merge-risk: 🚨 compatibility: Merging changes persisted install-record cleanup and can remove an existing local path record during update or doctor repair.
  • add rating: 🧂 unranked krab: Current PR rating is 🧂 unranked krab because proof is 🧂 unranked krab, patch quality is 🐚 platinum hermit, and The implementation looks focused and reviewable, but the external-PR proof gate is not met yet.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body has assertions and test commands but no redacted after-fix terminal/log/screenshot/artifact; the contributor should add proof, update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.

Label justifications:

  • P2: This is a normal update/doctor bug fix with limited but real upgrade-state impact.
  • merge-risk: 🚨 compatibility: Merging changes persisted install-record cleanup and can remove an existing local path record during update or doctor repair.
  • rating: 🧂 unranked krab: Current PR rating is 🧂 unranked krab because proof is 🧂 unranked krab, patch quality is 🐚 platinum hermit, and The implementation looks focused and reviewable, but the external-PR proof gate is not met yet.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body has assertions and test commands but no redacted after-fix terminal/log/screenshot/artifact; the contributor should add proof, update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.

What I checked:

  • Current post-core convergence does not prune path shadows on main: Current main passes baselineInstallRecords directly into repairMissingConfiguredPluginInstalls, so a path install record can survive into repair and smoke-check unless another existing path removes it. (src/cli/update-cli/post-core-plugin-convergence.ts:70, e42726204490)
  • Existing main cleanup only handles managed package shadows: Current main has doctor cleanup for managed npm packages shadowing bundled plugins and missing-config repair for npm/clawhub install records matching bundled packages; it does not handle source:'path' records pointing at old packaged bundled output. (src/commands/doctor-plugin-registry.ts:95, e42726204490)
  • PR adds bounded stale path detection: The PR helper only lists source:'path' records when the bundled plugin id is known, both record and bundled versions exist and differ, the path differs from the current bundled path, and the record path looks like dist/extensions or dist-runtime/extensions for that plugin. (src/plugins/stale-local-bundled-plugin-install-records.ts:52, ed744adc9d4f)
  • PR preserves local override classes in tests: The added tests cover pruning stale compiled bundled output while preserving the current bundled path, same-version compiled paths, versionless compiled paths, source-checkout extensions/ paths, and arbitrary local plugin paths. (src/plugins/stale-local-bundled-plugin-install-records.test.ts:51, ed744adc9d4f)
  • Related live context supports the problem class: GitHub search found merged feat(agents): support per-agent local model lean mode #84073 whose real behavior proof said a stale external bundled-plugin install record made the local Discord plugin resolve through old output until doctor --fix removed it, which aligns with the failure mode this PR targets.
  • Proof gap: The PR body lists unit/build commands and describes expected outcomes, but the Real behavior proof section does not include redacted terminal output, logs, screenshots, recordings, or linked artifacts from an after-fix real setup. (ed744adc9d4f)

Likely related people:

  • steipete: Recent commits on post-core plugin repair and compatibility host handling touch the same update/doctor install-record path this PR changes. (role: recent area contributor; confidence: high; commits: aa687a08cda4, 2e389b6a46a0, 1fdeee380e75; files: src/cli/update-cli/update-command.ts, src/cli/update-cli/post-core-plugin-convergence.ts, src/commands/doctor/shared/missing-configured-plugin-install.ts)
  • Dallin Romney: Git blame attributes the current post-core convergence and doctor registry baseline in this shallow checkout to the grafted current-main commit. (role: current implementation carrier; confidence: medium; commits: 447a3643c69b; files: src/cli/update-cli/post-core-plugin-convergence.ts, src/commands/doctor-plugin-registry.ts)
  • Ayaan Zaidi: Recent plugin discovery cache work touched the discovery path used by resolveBundledPluginSources, which the new helper relies on to identify current bundled plugin roots. (role: adjacent plugin discovery contributor; confidence: medium; commits: 9da4d5f5df5d; files: src/plugins/discovery.ts, src/plugins/bundled-sources.ts)

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

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels May 21, 2026
@clawsweeper

clawsweeper Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@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 21, 2026
@scoootscooob

Copy link
Copy Markdown
Member

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@scoootscooob
scoootscooob force-pushed the fix/stale-local-official-plugin-shadows branch from 97e2080 to 706ee3f Compare May 21, 2026 07:41
@scoootscooob
scoootscooob force-pushed the fix/stale-local-official-plugin-shadows branch from 706ee3f to 8bcbf68 Compare May 21, 2026 07:44
@scoootscooob
scoootscooob merged commit 4a360ac into openclaw:main May 21, 2026
98 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes commands Command implementations merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants