fix(plugins): include explicitly enabled plugins in startup plan (DOJ-4055)#1
Merged
lapc506 merged 1 commit intoMay 21, 2026
Conversation
…startup [DOJ-4055]
v2026.5.7 introduced a `shouldConsiderForGatewayStartup` filter in
`resolveGatewayStartupPluginPlanFromRegistry` that builds the list of
`onlyPluginIds` passed to `loadOpenClawPlugins`. The filter accepts a
plugin only when it declares `activation.onStartup === true`, is the
context-engine slot, or is a memory-startup plugin matching the dreaming
or memory-slot configuration.
For tool/hook/route plugins that the operator has explicitly enabled via
`plugins.entries.{id}.enabled = true` (and/or pinned in `plugins.allow`)
but that do NOT also expose a channel/provider/memory contract or declare
`activation.onStartup`, every `canStart*` path returns false and
`shouldConsiderForGatewayStartup` returns false. The plugin id is silently
dropped from `plan.pluginIds`. Downstream, the loader's
`matchesScopedPluginRequest` skips any candidate not in `onlyPluginIds`,
so the plugin module is never `import()`-ed.
Race B's instrumentation in the DojoOS Agent plugin confirmed this empirically:
five `console.error` breadcrumbs at the top of `dist/index.js` (well before
any sub-import) never fired, while the gateway emitted
`http server listening (1 plugin: slack)` and never logged
`DojoOS Agent Plugin registered`. Race D removed `plugins.load.paths` from
the gateway config (eliminating the redundant config-source candidate and
the matching `duplicate plugin id` warning), but the global candidate still
failed to load — because the gateway-startup filter, not duplicate
resolution, was excluding it.
This commit adds a single branch to `shouldConsiderForGatewayStartup`:
for any non-bundled plugin, treat an explicit
`entries.{id}.enabled === true` OR explicit `plugins.allow` membership as
sufficient signal to consider the plugin at gateway startup. Bundled
plugin semantics are unchanged (they keep relying on
`activation.onStartup`, slot configuration, and channel detection).
Tests: `src/plugins/bundled-plugin-metadata.test.ts` continues to pass
(30/30), including the empty-config-startup baseline and the
"starts Bonjour when explicitly enabled" case (Bonjour is bundled, so
it routes through the pre-existing paths; the new branch only widens
non-bundled startup behavior). Full plugin/loader/registry suite passes
(209/209: loader, manifest-registry, setup-registry, plugins-cli.list).
Scope: 21 lines added in a single file
(`src/plugins/gateway-startup-plugin-ids.ts`). No public type changes, no
config-schema additions, no architectural restructuring.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
21-line patch (1 file, +21/-0) to
src/plugins/gateway-startup-plugin-ids.tsrestoring pre-v2026.5.7 behavior for tool/hook/route plugins that declare no capability slot.Problem
The
shouldConsiderForGatewayStartupfilter at line 134 buildsplan.pluginIds(which becomesonlyPluginIdsscope forloadOpenClawPlugins). Pre-patch, the filter only included plugins matching one of:manifest.activation.onStartup === true, context-engine slot, memory slot, channel/root/speech-provider/generation-provider gates, explicit-hook gate, or agent-harness match.The DojoOS Agent plugin (which registers 43 tools, 11 hooks, and 17 HTTP routes via the SDK at module-import time) declares no channel, no provider contract, no memory slot, no
activation.onStartup, and no agent-harness wiring. Every gate returnedfalse. The plugin id was silently dropped fromplan.pluginIds. Downstream,loader.ts:1715(matchesScopedPluginRequest) skipped its discovery candidate before anyimport()ran.5-breadcrumb instrumentation in the plugin (including a
console.error("[DojoOS-plugin] module-loaded")on line 1 ofindex.tsbefore any imports) confirmed: zero breadcrumbs reached Cloud Run logs. The plugin module is never evaluated by Node. The failure is upstream of plugin code, in this resolver.Fix
Adds one branch to
shouldConsiderForGatewayStartup: for non-bundled plugins, treat explicit operator enablement (pluginsConfig.entries[id]?.enabled === trueORpluginsConfig.allow.includes(id)OR membership inactivationSourcePlugins) as sufficient signal to include the plugin in the startup plan.The branch is positioned at the end (after all capability gates) so plugins that ALSO declare a capability slot continue to short-circuit on the gate that fits them. Only plugins that pass NO capability gate but ARE explicitly enabled in config fall through to the new branch.
Bundled plugin behavior is unchanged (
!manifest.bundledguard).Test plan
src/plugins/bundled-plugin-metadata.test.ts: 30/30 ✓src/plugins/loader.test.ts+manifest-registry.test.ts+setup-registry.test.ts+cli/plugins-cli.list.test.ts: 209/209 ✓tsc --noEmit: no new errors (3 pre-existing errors in unrelatedagents/pi-embedded-runner.*.test.tsfiles remain —TS2352casts onAgentMessage, not touched by this PR)pnpm install --frozen-lockfileclean under Node 22.22.2pnpm run build+pnpm run ui:install+pnpm run ui:buildcleannpm packproducesopenclaw-2026.5.7.tgz(24.4 MB, 9,708 files) with SHA2566224c7141406f8fdc52adfe59db12395a0dc58ce43e6f3565c29f2be3803f3a1v2026.5.7-dojo.2dojo-agent-internal-stagingrevision00021-zpm(2026-05-20T23:52:17Z):[gateway] http server listening (2 plugins: openclaw-plugin, slack),[plugins] DojoOS Agent Plugin registered: 43 tools, 11 hooks, 17 routes (shared mode),/api/healthHTTP 200,/api/sessionsHTTP 401Risk assessment
allowvsentries[id].enabledreconciliation: the new branch accepts either as sufficient. The previous semantics didn't have to reconcile because no path reached this code. Explicit by design.tasks.mdT-09. Happy to add in a follow-up commit if the maintainer prefers.Linear
DOJ-4055 — plugin-load regression diagnosis chain (Race B + C + D + E) preserved in the consuming plugin repo's openspec/changes directory:
doj-4055-plugin-load-fix.Created by Claude Code on behalf of @lapc506.
🤖 Generated with Claude Code