fix(plugins): mirror core root-package deps used by core dist code#74213
Conversation
Greptile SummaryThis PR extends Confidence Score: 5/5Safe to merge — mechanical allowlist extension with all entries verified against root package.json and tests passing. Single-file logic change adds nine entries to a string array constant; all nine packages are confirmed as declared root-level dependencies; the consuming code at line 679–681 already silently skips any entry not found in runtimeDeps; alphabetical ordering is maintained; no control flow or API surface changes. No files require special attention. Reviews (1): Last reviewed commit: "fix(plugins): mirror core root-package d..." | Re-trigger Greptile |
|
Codex review: needs maintainer review before merge. Keep this PR open. Current main still mirrors only Maintainer follow-up before merge: Keep this PR open and review it with #74199. The maintainers should decide whether to land the narrow allowlist expansion plus drift guard, or replace it with a more durable root-package/dist-import derivation. Before merge, require green focused tests and packaged/global-install or Testbox smoke proving the runtime-deps manifest includes the added root deps and a representative staged core path no longer throws Best possible solution: Keep this PR open and review it with #74199. The maintainers should decide whether to land the narrow allowlist expansion plus drift guard, or replace it with a more durable root-package/dist-import derivation. Before merge, require green focused tests and packaged/global-install or Testbox smoke proving the runtime-deps manifest includes the added root deps and a representative staged core path no longer throws Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 68ba1e7180a6. |
175eaf8 to
56297e8
Compare
Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to
also include @agentclientprotocol/sdk, @lydell/node-pty, croner,
dotenv, jiti, json5, jszip, markdown-it, tar, and web-push.
These are all declared as direct dependencies in the openclaw root
package.json and imported by core source code (src/acp/*, src/cron/*,
src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts,
src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs,
src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts,
etc), but the existing collectMirroredPackageRuntimeDeps allowlist only
covered semver and tslog.
The dynamic collectRootDistMirroredRuntimeDeps scan does pick up
imports that have an extension package.json owner (for example
memory-core declares chokidar, matrix declares jiti and markdown-it).
For deps with no extension owner, or for setups where the owning
extension is not enabled, those imports never make it into the
runtime-deps mirror and Node fails to resolve them at runtime, e.g.:
Cannot find package 'chokidar' imported from
.../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js
Also add a static drift guard test that walks src/ for value imports of
root-package runtime deps and fails when one is neither in
MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's
package.json (with an explicit allowlist for known-transitive or
build/type-only imports such as chalk, ipaddr.js, file-type,
proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty
during this change.
Refs openclaw#74199.
56297e8 to
8e7452a
Compare
|
Pushed an update addressing the bot review. What changed since the last commit (
I think that addresses asks #1 (regression test) and #2 (durable static check) from the codex review. The remaining ask #3 (packaged/global-install smoke) needs an environment I can't drive from this PR — happy to add a Testbox follow-up if a maintainer can point me at the right command. |
fabianwilliams
left a comment
There was a problem hiding this comment.
LGTM. Adding the 10 missing root-package runtime deps to MIRRORED_CORE_RUNTIME_DEP_NAMES is the right immediate fix, but the real value here is the drift-guard test — scanning src/ for value imports of root-package deps and failing CI when one isn't in either the mirror allowlist or extension-owned set is the discipline that closes the loop on a class of Cannot find package 'X' bugs (croner, jiti, json5, markdown-it, tar, web-push, etc. were exactly this shape). The KNOWN_UNMIRRORED_BARE_IMPORTS allowlist with per-entry reason comments is the right escape hatch for the deliberate exceptions.
…penclaw#74213) Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to also include @agentclientprotocol/sdk, @lydell/node-pty, croner, dotenv, jiti, json5, jszip, markdown-it, tar, and web-push. These are all declared as direct dependencies in the openclaw root package.json and imported by core source code (src/acp/*, src/cron/*, src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts, src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs, src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts, etc), but the existing collectMirroredPackageRuntimeDeps allowlist only covered semver and tslog. The dynamic collectRootDistMirroredRuntimeDeps scan does pick up imports that have an extension package.json owner (for example memory-core declares chokidar, matrix declares jiti and markdown-it). For deps with no extension owner, or for setups where the owning extension is not enabled, those imports never make it into the runtime-deps mirror and Node fails to resolve them at runtime, e.g.: Cannot find package 'chokidar' imported from .../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js Also add a static drift guard test that walks src/ for value imports of root-package runtime deps and fails when one is neither in MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's package.json (with an explicit allowlist for known-transitive or build/type-only imports such as chalk, ipaddr.js, file-type, proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty during this change. Refs openclaw#74199.
…penclaw#74213) Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to also include @agentclientprotocol/sdk, @lydell/node-pty, croner, dotenv, jiti, json5, jszip, markdown-it, tar, and web-push. These are all declared as direct dependencies in the openclaw root package.json and imported by core source code (src/acp/*, src/cron/*, src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts, src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs, src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts, etc), but the existing collectMirroredPackageRuntimeDeps allowlist only covered semver and tslog. The dynamic collectRootDistMirroredRuntimeDeps scan does pick up imports that have an extension package.json owner (for example memory-core declares chokidar, matrix declares jiti and markdown-it). For deps with no extension owner, or for setups where the owning extension is not enabled, those imports never make it into the runtime-deps mirror and Node fails to resolve them at runtime, e.g.: Cannot find package 'chokidar' imported from .../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js Also add a static drift guard test that walks src/ for value imports of root-package runtime deps and fails when one is neither in MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's package.json (with an explicit allowlist for known-transitive or build/type-only imports such as chalk, ipaddr.js, file-type, proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty during this change. Refs openclaw#74199.
…penclaw#74213) Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to also include @agentclientprotocol/sdk, @lydell/node-pty, croner, dotenv, jiti, json5, jszip, markdown-it, tar, and web-push. These are all declared as direct dependencies in the openclaw root package.json and imported by core source code (src/acp/*, src/cron/*, src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts, src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs, src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts, etc), but the existing collectMirroredPackageRuntimeDeps allowlist only covered semver and tslog. The dynamic collectRootDistMirroredRuntimeDeps scan does pick up imports that have an extension package.json owner (for example memory-core declares chokidar, matrix declares jiti and markdown-it). For deps with no extension owner, or for setups where the owning extension is not enabled, those imports never make it into the runtime-deps mirror and Node fails to resolve them at runtime, e.g.: Cannot find package 'chokidar' imported from .../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js Also add a static drift guard test that walks src/ for value imports of root-package runtime deps and fails when one is neither in MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's package.json (with an explicit allowlist for known-transitive or build/type-only imports such as chalk, ipaddr.js, file-type, proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty during this change. Refs openclaw#74199.
…penclaw#74213) Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to also include @agentclientprotocol/sdk, @lydell/node-pty, croner, dotenv, jiti, json5, jszip, markdown-it, tar, and web-push. These are all declared as direct dependencies in the openclaw root package.json and imported by core source code (src/acp/*, src/cron/*, src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts, src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs, src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts, etc), but the existing collectMirroredPackageRuntimeDeps allowlist only covered semver and tslog. The dynamic collectRootDistMirroredRuntimeDeps scan does pick up imports that have an extension package.json owner (for example memory-core declares chokidar, matrix declares jiti and markdown-it). For deps with no extension owner, or for setups where the owning extension is not enabled, those imports never make it into the runtime-deps mirror and Node fails to resolve them at runtime, e.g.: Cannot find package 'chokidar' imported from .../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js Also add a static drift guard test that walks src/ for value imports of root-package runtime deps and fails when one is neither in MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's package.json (with an explicit allowlist for known-transitive or build/type-only imports such as chalk, ipaddr.js, file-type, proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty during this change. Refs openclaw#74199.
…penclaw#74213) Extend MIRRORED_CORE_RUNTIME_DEP_NAMES from ["semver", "tslog"] to also include @agentclientprotocol/sdk, @lydell/node-pty, croner, dotenv, jiti, json5, jszip, markdown-it, tar, and web-push. These are all declared as direct dependencies in the openclaw root package.json and imported by core source code (src/acp/*, src/cron/*, src/config/*, src/infra/{archive,backup,dotenv,push-web}.ts, src/markdown/ir.ts, src/plugin-sdk/root-alias.cjs, src/plugins/jiti-loader-cache.ts, src/process/supervisor/adapters/pty.ts, etc), but the existing collectMirroredPackageRuntimeDeps allowlist only covered semver and tslog. The dynamic collectRootDistMirroredRuntimeDeps scan does pick up imports that have an extension package.json owner (for example memory-core declares chokidar, matrix declares jiti and markdown-it). For deps with no extension owner, or for setups where the owning extension is not enabled, those imports never make it into the runtime-deps mirror and Node fails to resolve them at runtime, e.g.: Cannot find package 'chokidar' imported from .../plugin-runtime-deps/openclaw-<ver>/dist/qmd-manager-...js Also add a static drift guard test that walks src/ for value imports of root-package runtime deps and fails when one is neither in MIRRORED_CORE_RUNTIME_DEP_NAMES nor declared by any extension's package.json (with an explicit allowlist for known-transitive or build/type-only imports such as chalk, ipaddr.js, file-type, proxy-agent, typescript, qrcode). The guard caught @lydell/node-pty during this change. Refs openclaw#74199.
Summary
Extend `MIRRORED_CORE_RUNTIME_DEP_NAMES` (in `src/plugins/bundled-runtime-deps.ts`) to include the nine root-package runtime dependencies that core dist code imports but that the current allowlist does not mirror into the runtime-deps tree:
Context
Currently `MIRRORED_CORE_RUNTIME_DEP_NAMES` is just `["semver", "tslog"]`. The dynamic `collectRootDistMirroredRuntimeDeps` scan picks up other imports only when an enabled extension's `package.json` declares the dependency (so `chokidar` works in 2026.4.26 because `extensions/memory-core/package.json` declares it; `jiti` and `markdown-it` work when `matrix` is enabled because `extensions/matrix/package.json` declares them).
But these nine packages are imported by core dist code, not by an extension:
For setups where no enabled extension owns the dependency, the imports never get installed into `~/.openclaw/plugin-runtime-deps/openclaw-/node_modules`, and Node fails to resolve them when the corresponding code path runs:
```
Cannot find package 'chokidar' imported from
~/.openclaw/plugin-runtime-deps/openclaw-2026.4.25-.../dist/qmd-manager-FuXCtSYP.js
```
(That specific case was fixed in 2026.4.26 because `memory-core` started declaring `chokidar`. The nine above behave the same way.)
Reproduction
Against a vanilla `npm i -g [email protected]`:
```bash
cd ~/.npm-global/lib/node_modules/openclaw/dist
grep -rh '^import .* from "[^./n]' *.js | grep -oE 'from "[^\"]+"' | sort -u
compare each top-level package against .specs[] of:
~/.openclaw/plugin-runtime-deps/openclaw-/.openclaw-runtime-deps.json
```
The nine listed above appear in dist imports but are not in the manifest `specs`.
Approach
These deps fit the same pattern as the existing `semver` / `tslog` entries: declared in the openclaw root `package.json` and used by core dist code. Adding them to `MIRRORED_CORE_RUNTIME_DEP_NAMES` is the smallest, most consistent fix.
A more durable fix would derive the list from a static analysis of core dist bare-imports during build (or extend `collectRootDistMirroredRuntimeDeps` to treat root `package.json` as a fallback owner) so the allowlist cannot drift as new core deps are added. I left that as a follow-up to keep this PR mechanical and easy to review.
Refs
/appis non-writable #71420 (original locked thread covering the same class of bug; this PR addresses the gap between `MIRRORED_CORE_RUNTIME_DEP_NAMES` and the actual import set)Test plan
🤖 Generated with Claude Code