Files
openclaw/src/plugins
Leonidas Lux 0f01930c8e fix(plugins): discover config load.paths plugins when index has entries (#99196)
* fix(plugins): discover config load.paths plugins when index has entries

Installing a managed npm plugin populates the persisted plugin index.
Once the index has entries (index.plugins.length > 0),
loadPluginManifestRegistryForInstalledIndex is used instead of the
full discovery path. This path only processes plugins that already
exist in the index — if workspace plugins from config plugins.load.paths
are missing from the index, they are silently dropped from the manifest
registry, producing 'plugin not found (stale config entry ignored)'
warnings on gateway startup and in CLI commands.

Fix: after converting index records to plugin candidates, also
discover plugins from config plugins.load.paths and merge any
candidates that are not already represented in the index-based
list. This ensures config-origin workspace plugins are always
included in the manifest registry regardless of index completeness.

Fixes #99185

* fix(plugins): address clawsweeper review — config-only scope, pluginId scoping, regression tests

- P1: Limit extra discovery scope to config-origin candidates only
  (filter by origin === 'config') instead of full discoverOpenClawPlugins
- P2: Preserve pluginId scoping for load-path candidates
  (filter extra candidates by pluginIdSet when present)
- Add 3 regression tests: load.paths discovery, empty-load no-op,
  pluginId scoping preservation
- Add L2 real behavior proof with direct function call evidence

🦞 diamond lobster: L2 evidence (real function call + objects)

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): replace discoverOpenClawPlugins with config-only discoverFromConfigPaths

P1: The installed-index fallback previously called discoverOpenClawPlugins,
which scans bundled/global/workspace roots and returns their diagnostics.
This allowed unrelated shared-root diagnostics to leak into the
installed-index config validation surface.

Replace it with discoverFromConfigPaths — a new helper that scans only
the user-configured plugins.load.paths entries via discoverFromPath
directly, producing zero bundled/global candidates or diagnostics.

P2: pluginId scoping is preserved for load-path candidates.

Added discoverFromConfigPaths to src/plugins/discovery.ts to keep the
config-only discovery path reusable and explicit.

🦞 diamond lobster: L2 evidence (terminal output from real dev build)

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): preserve bundled-load-path alias filtering in discoverFromConfigPaths

P2: The new discoverFromConfigPaths helper (added in Round 1 to fix the
P1 full-discovery issue) bypassed normal discovery's bundled-load-path
alias guard. If a user had a bundled plugin directory in their
plugins.load.paths, the installed-index fallback would treat it as a
valid config-origin candidate and potentially override/duplicate bundled
plugins.

Add resolvePackagedBundledLoadPathAlias check in discoverFromConfigPaths
before calling discoverFromPath, so bundled paths are skipped with a
warning diagnostic matching normal discovery behavior.

Add P2 regression test verifying bundled plugin load paths are ignored
on the installed-index path while real workspace load paths still work.

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): forward load-path diagnostics unconditionally in installed-index path

Previously, diagnostics from discoverFromConfigPaths were only forwarded
when at least one extra candidate survived filtering. Configs whose
plugins.load.paths contained only bundled aliases, missing paths, duplicates
already in the index, or scoped-out entries silently lost the normal
discovery warning or doctor hint.

Now extraDiagnostics is assigned outside the extraCandidates.length > 0
guard, so every config load-path diagnostic reaches the caller regardless
of whether a new candidate is merged.

Adds a focused regression test verifying that a bundled-only load path
still surfaces the expected alias-guard warning diagnostic.

🦞 diamond lobster: P2 fix, no new L2 evidence needed (regression test
covers the diagnostic-forwarding contract directly)

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): preserve requiresPlugins diagnostics for load paths in installed-index path

- [P2] Export addMissingRequiredPluginDiagnostics from discovery.ts for reuse
- [P2] Call addMissingRequiredPluginDiagnostics on combined index + load-path candidates before passing to loadPluginManifestRegistry
- [P2] Add regression tests: warns when load-path plugin requires missing plugin, does not false-warn when required plugin is already in index

🦞 diamond lobster: L2 + test coverage

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): add missing discovery.js mock exports for addMissingRequiredPluginDiagnostics

plugin-install.test.ts mocks discovery.js but the mock didn't include the
newly exported addMissingRequiredPluginDiagnostics, causing CI failures in
tests that exercise loadPluginManifestRegistryForInstalledIndex.

Also add discoverFromConfigPaths to the mock (already imported but was
only latent because the mock's code path wasn't triggered with load paths).

Ref. https://github.com/openclaw/openclaw/pull/99196

* fix(plugins): rebuild stale configured plugin indexes

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 02:01:00 -07:00
..
2026-06-04 04:54:37 -04:00
2026-06-04 04:29:53 -04:00
2026-06-04 04:15:33 -04:00