The declared-but-unwired surface from the plugin-deps plan §B item 2:
scan_plugin classified package.json sidecars but nothing executed.
- pm/workspace.install_node_sidecar(): npm ci (with package-lock.json)
or npm install (without) into the plugin's OWN node_modules — never a
global prefix; pm's pinned npm store-first (PATH second, the same
precedence as _uv_binary); lazy-install-gated; returns a reason
string on failure, never raises. Injectable runner for hermetic
tests.
- plugins install flow: a package.json plugin gets its own y/n consent
question; a node-dep failure warns but never blocks the python-dep
path or the install.
tests: 6 hermetic tests (no-package no-op, ci-vs-install selection by
lockfile presence, lazy-off refusal, failure reason surfacing, runner
explosion isolation). Full sweep: 210 passed, 0 failed.