[Bug] 0.1.7-rc.1 no longer heals $DSH_HOME/profiles/node_modules (0.1.6 did) — profiles with locally installed plugins break every child process: run_code and voice input die with "subprocess scope exited before its bootstrap consumed the launch request" #7635
Replies: 3 comments
|
Thanks — this is the most complete report I have read on this seam, and every load-bearing claim in it holds up. I re-derived the mechanism from the released artifacts rather than from your machine (I do not have your state), so what follows is independent evidence plus three additions. Confirming Finding 2 from the published export surfacesDiffing the published
So it is not a lost call site — the whole writer was retired, and the retirement is deliberate:
and the comment sitting next to
That comment is the precise answer to your "#5863's reasoning no longer holds" sentence: the reasoning still holds for the process that mounts plugins, and the retirement assumed the runtime table could stand in for the disk fallback everywhere. It stands in everywhere except where your Finding 3 points. Why the child processes lose it (the carrier inventory)The runtime resolution has exactly two carriers, and both are in-process:
A
So the child resolves the Node way, walks up into the shared fallback, and no carrier is left to make that walk succeed. One addition to Finding 1: there are two sub-cases, not one
Both fail identically, which is why your Finding 4 reproduces from Your workaround is sound, and here is the mechanism that says so
Two notes on the suggested fix
I am tracking this on the plugin side as well — the failure shape is the same as the one in the Windows ACL thread: a working UI sitting on top of a dead execution path, where the only visible symptom is a tool that silently is not there. |
|
The diagnosis above now has a shipped implementation, for anyone who hits this and does not want to change their install:
One-line usage — install it into the profile and mount it: cd ~/.dsh/profiles/<profile> && pnpm add @argszero/cordis-plugin-profile-fallback-advisor# either through Settings → Plugins, or by adding to the profile's cordis.patch.yml
- insert:
- id: profile-fallback-advisor
name: '@argszero/cordis-plugin-profile-fallback-advisor'
config:
repair: falseIt is a stopgap, not the fix — the fix belongs upstream (restore the writer, or tell the child about the resolution). What it does:
The two remedies it hands the user are the ones already in this thread: What it deliberately does not claim, so nobody is surprised later: it does not inject a resolution into the child (every carrier was checked and is closed — Verified with 74 tests across four suites (the classifier's refusals, the walk on a real tree in both sub-cases, the repair's additive invariants, and the mount on a real |
|
Thanks for the teardown — and for the correction on framing. "The writer was retired on purpose, and the runtime table was assumed to cover the disk fallback everywhere" is the accurate statement, and the thing it misses is exactly Two data points that may be useful: 1. $ grep -rl healProfilesModuleFallback <tree>/@deepseek-ai/ # no hits
$ grep -rl symlinkSync <tree>/@deepseek-ai/ # no hits
$ grep -n 'without writing module-resolution' dsh-app-boot/lib/index.js
726: * Compute the runtime resolution without writing module-resolution files.
$ grep -A 5 '^const PROFILE_PNPM_WORKSPACE' dsh-app-boot/lib/index.js
const PROFILE_PNPM_WORKSPACE = `packages:
- .
nodeLinker: hoisted
autoInstallPeers: false
`;So on rc.2 the stopgap is still the only remedy that does not change the install (the alternative being 2. On the residue shape (you flagged it as unverified on your side): I only have my earlier records — that tree was cleaned up during the rc.2 upgrade on this machine, so I cannot add the Confirming your case (b) from the clean room as well: neither of the throwaway |
Uh oh!
There was an error while loading. Please reload this page.
Symptom
On 0.1.7-rc.1, a profile that has plugins installed into the profile (what
dsh plugin add/ Settings → Plugins produces) still works for chat, but every tool call and voice input fails:Voice input fails with the same seam error (
语音识别失败:subprocess scope exited before its bootstrap consumed the launch request).Environment: dsh
0.1.7-rc.1(pnpm global install), nodev24.21.0, pnpm12.3.4, Linux.Profile dependencies:
@deepseek-ai/dsh-base,dsh-web-app,dsh-experimental-agent-team-profile,dsh-experimental-voice-input-bundle.Finding 1 — the shared fallback the peers resolve through is stale
Per #5863,
autoInstallPeers: falseis intentional: profile-local plugins are supposed to resolve peers through the shared installation fallback at$DSH_HOME/profiles/node_modules, via Node's ordinary parent-walk.On this machine that directory exists but is dead — every entry is a symlink into the 0.1.6 pnpm store generation, which the CLI upgrade garbage-collected:
So Node walks up from
<profile>/node_modules/...intoprofiles/node_modules, finds only dangling links, and throws.Finding 2 — 0.1.6 created/healed that fallback; 0.1.7-rc.1 only removes it
dsh-app-boot0.1.6:dsh-app-boot0.1.7-rc.1:What remains is removal and read-only inspection:
removeLinkProjections()(unlinks old.dsh-module-fallbackprojections),linkedProfileRoots(),realModuleDirectory(). MeanwhileinitProfile()still writes the unchangedPROFILE_PNPM_WORKSPACE:Result: nothing maintains the fallback any more, so a profile-local plugin install has no resolvable peers — and #5863's "the peers are not actually missing" reasoning no longer holds for this case.
Finding 3 — why the UI survives and only child processes die
createRuntimeResolution()builds an in-memory resolution map (installation closure + profile closure, installation package names reserved), so plugins load and chat works.run_codeworker and the speech-to-text worker are plainnodeprocesses with no such map.runnerEnvironment()even deletesNODE_*/TSX_*from the environment, soNODE_PATHcannot compensate. Firstimport '@deepseek-ai/cordis'on the profile path kills the process → the scope exits before its bootstrap consumes the launch request.Both affected features go through
ctx.subprocess.spawn(dsh-ptc-runtime-nodeworker;dsh-experimental-speech-to-text-sensevoiceline ~638), which is why the failure is uniform.Finding 4 — clean-room reproduction (no legacy state)
So this is reachable with the official install path alone; the legacy 493-link tree was only masking it.
Workaround that restored the machine (verified)
Set
autoInstallPeers: truein<profile>/pnpm-workspace.yamland runpnpm install(30 peer packages, all0.1.7-rc.1/cordis 4.0.4, same versions as the installation tree). Verified afterwards:nodeprocessdsh-subprocess-localLinux scope + runner bootstrap test succeeds end-to-end (launch request consumed, exit 0, child import OK)dsh --profile web --dump-config: exit 0 / empty stderr; app boots with zero errorsThis does not break the single-instance invariant from #5863:
collectProfileScopePackagespasses the installation package names asreservedtodependencyClosure, so the profile's cordis copy is never put into the main process's resolution map (and both copies are 4.0.4).Suggested fix
Either restore the fallback maintenance that 0.1.6 had (
healProfilesModuleFallback, run while holding the profile writer lock, plus a one-time heal for existing profiles whose links point at a dead store generation), or make the profile install actually install the peers it reports as missing. Right now the removal of the former makesautoInstallPeers: falsefatal for every profile that installs a plugin, including the two official optional bundles.All reactions