Fix global PM probes spawning bare names from the project (#421, #434, #438, #440) - #442
Mikola Lysenko (mikolalysenko) wants to merge 9 commits into
Conversation
Global mode asked npm, yarn, pnpm, bun, gem and composer where their global installs live by spawning the bare tool name. On Windows those tools are .cmd/.bat shims that a bare spawn never finds, so scan -g silently reported nothing to patch. The yarn probe also ran inside the scanned project, where Yarn Berry runs the project's own "global" script and its output picked the directory scanned as global. Probes now resolve the tool through PATHEXT (and never from a relative PATH entry), npm-family global probes run from the home directory, and Composer's home falls back to %APPDATA%\Composer and $XDG_CONFIG_HOME/composer like Composer does. Fixes #421, #434, #438, #440. Assisted-by: Claude Code:claude-opus-5-5
A Windows App Execution Alias (the Store python3.exe) is a reparse point the PATH lookup can't stat, though a bare spawn launches it. The Python probe shares this runner, so fall back to the bare name on Windows when the lookup finds nothing, rather than lose an interpreter that used to be found. Also satisfies clippy's redundant closure lint. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
[agent] Two red checks on
If either fails again on re-run, I'll treat it as real and root-cause it. Generated by Claude Code |
Global Composer discovery now also tries Composer's own defaults, %APPDATA%\Composer and $XDG_CONFIG_HOME/composer. On a Windows runner APPDATA points at a real Composer home, which outranks the ~/.composer and ~/.config/composer candidates these tests stage. Unset both variables there, as the tests already do for HOME and PATH, so they keep exercising the HOME candidates. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
An earlier cargo fmt run over the whole workspace reformatted 125 files this change doesn't touch. Restore them to main so the diff holds only the global-probe fix. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
[burn-down agent] Ready for review on
Note: Slack announcement could not be sent this run (no Slack send tool available in the agent session); next run will retry. Generated by Claude Code |
Union the CHANGELOG Fixed entries from both sides. Co-Authored-By: Claude <[email protected]>
|
bugbot run Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KKwBoKTsqpGR3ZcCAcEyCA
The no-composer and empty-HOME tests still inherited APPDATA and XDG_CONFIG_HOME. Global discovery now probes %APPDATA%\Composer and $XDG_CONFIG_HOME/composer, so a machine with a real Composer home there made both tests see a vendor dir and fail. Unset both variables in these tests too, as the sibling HOME-fallback tests already do. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KKwBoKTsqpGR3ZcCAcEyCA
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 465db05. Configure here.
|
Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KKwBoKTsqpGR3ZcCAcEyCA
LLM Description written by Claude Code:claude-opus-5-5
Fixes #421
Fixes #434
Fixes #438
Fixes #440
Summary
On Windows,
scan -g,get -gandvex -gnow find globally installed npm, yarn, pnpm, bun, RubyGems and Composer packages. Before this change they reported an empty, successful scan. The npm-family global lookups also no longer run inside the scanned project, so a Yarn Berry project's"global"script can't run or choose the directory that gets scanned (and patched) as the global install. Composer's global home also falls back to Composer's own platform defaults.Priority note: the cluster is p1 (npm/yarn/RubyGems) and includes one p2 member (#438, Composer), because they share the same boundary.
Root cause
Global discovery asks each package manager where its global tree lives:
npm root -g,yarn global dir,pnpm root -g,bun pm bin -g,gem env gemdir|gempathandcomposer global config home. Every one of these probes went throughSystemCommandRunner::run(crates/socket-patch-core/src/utils/process.rs), which calledCommand::new(bin)on the bare tool name. That caused two problems:stdonly tries<name>.exe. These tools install asnpm.cmd,yarn.cmd,gem.cmdandcomposer.bat, so every probe returnedNoneand discovery came back silently empty (On Windows (RubyInstaller),scan -g/get -g/vex -gfind no global gems becausegem envis spawned as baregem, which never resolves togem.cmd#421, On Windows,scan -g/get -g/vex -gfind no global npm packages becausenpm root -gis spawned as barenpm, which never resolves tonpm.cmd#434, On Windows, scan -g finds no Composer global packages in the default %APPDATA%\Composer home, so apply -g and vex -g silently do nothing #438).globalcommand and dispatchesyarn global dirto the project's"global"script, whose stdout then picked the "global" directory (scan -ginside a Yarn Berry project runs the project'sglobalpackage.json script and scans whatever directory it prints as a global install #440). A fix for the.cmdresolution alone would have madescan -ginside a Yarn Berry project runs the project'sglobalpackage.json script and scans whatever directory it prints as a global install #440 reproduce on Windows too, which is why these ship together.Fix
SystemCommandRunnerresolves the program with the existingresolve_tool(PATHEXT on Windows, absolute PATH entries only, so a tool planted in the project via.on PATH is never run) and spawns the resolved path throughcommand_for. On Windows, if the lookup finds nothing, it falls back tostd's own.exesearch. That keeps App Execution Aliases such as the Storepython3.exeworking;stdnever searches the cwd on Windows.GlobalProbeRunnerruns the probe from a neutral directory: the user's home (absolute only), otherwise the drive root, and never the project. The npm, yarn, pnpm and bun global probes andcomposer global config homeuse it.gem envkeeps the project cwd on purpose, because rbenv and chruby choose the Ruby from the project's.ruby-version, and local mode uses the same lookup.get_composer_homenow probes Composer's own defaults:%APPDATA%\Composerfirst on Windows, and~/.composer, then$XDG_CONFIG_HOME/composer, then~/.config/composerelsewhere. Relative or empty variables are ignored.APPDATAandXDG_CONFIG_HOME, as they already do forHOMEandPATH. On a Windows runner the real%APPDATA%\Composerotherwise outranks the HOME candidates they stage.Tests
The new suite
crates/socket-patch-core/tests/global_probe_spawn_e2e.rsputs fake tools on PATH the way they install on each OS: an executableshscript on Unix, and a<name>.cmdshim with no.exeon Windows.npm_family_global_probes_find_the_installed_shims(npm/pnpm/bun)test (windows-latest)yarn_global_probe_runs_outside_the_scanned_projectleft: "/tmp/…/proj",right: "/tmp/…/home". On Windows it also fails, because the shim isn't found. Passes on windows-latestglobal_probe_ignores_a_tool_planted_on_a_relative_path_entryleft: Ok("/planted/node_modules")global_gem_paths_come_from_the_installed_gem_shimgem.cmd). Passes on windows-latestcomposer_home_comes_from_the_installed_composer_shimcomposer.cmd). Passes on windows-latestcomposer_home_falls_back_to_xdg_config_home(Unix),composer_home_falls_back_to_appdata_on_windows(Windows)left: []. The APPDATA test passes on windows-latestThere is also a unit test,
neutral_probe_dir_prefers_an_absolute_home_and_never_the_cwd.CI: everything is green on
059b07b, includingtest (windows-latest). Bugbot found no issues on059b07b.Commands run locally (Linux):
cargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --test global_probe_spawn_e2e: 6/6 pass with the fix, 3/6 fail withsrc/stashed (the 3 Linux-observable cases above)utils::processunit tests all pass.cargo test --workspace --all-features --no-fail-fast: everything passes except 12 permission-injection tests (*_write_failure_*,*unremovable*,relax_loop_must_not_traverse_symlinked_root). They fail only because this sandbox runs as uid 0, which ignoreschmod 0o555. The 4 core-lib ones pass when rerun asnobody. None of them touch the probe code. CI runs as non-root.mainisn't rustfmt-clean under the pinned 1.93.1 toolchain, and CI doesn't gate on it. To keep this diff to the 7 files the fix needs, I didn't apply a workspace-widecargo fmt.npm/,pypi/andgem/only dispatch the binary.Follow-ups (not in this PR)
yarn global dirdoesn't exist before yarn 1.1.0, and there's no fallback #437: yarn 1.0.x has noyarn global dir, so it needs a default-folder fallback.vendor-dircascade inside the global home.scan -g/get -g/vex -gfind no global gems becausegem envis spawned as baregem, which never resolves togem.cmd#421 notes that the hard-coded gem fallback list lacks RubyInstaller and XDG dirs. Withgem envworking on Windows, that list is no longer the discovery path there, so it's left as is.🤖 Generated with Claude Code
https://claude.ai/code/session_01KKwBoKTsqpGR3ZcCAcEyCA
Note
Medium Risk
Changes subprocess spawning and global discovery paths used by
scan -g; behavior is safer (neutral cwd, no relative PATH tools) but touches cross-platform CLI resolution where regressions would affect global scans only.Overview
Global mode (
-g) now discovers machine-wide npm, yarn, pnpm, bun, RubyGems, and Composer installs reliably instead of often returning an empty scan.Command spawning for package-manager probes no longer uses bare names:
SystemCommandRunnerresolves tools viaresolve_tool(PATHEXT on Windows fornpm.cmd/gem.cmd/composer.bat, absolute PATH entries only so a project-local fake binary is not run). A newGlobalProbeRunnerruns npm-family and Composer global probes from a neutral directory (absolute home, else drive root), so Yarn Berry cannot answeryarn global dirvia a project"global"script or cwd-sensitive config.Composer global home discovery uses
GlobalProbeRunnerforcomposer global config homeand adds platform fallbacks aligned with Composer:%APPDATA%\Composeron Windows and$XDG_CONFIG_HOME/composer/~/.config/composerelsewhere. Composer e2e tests unsetAPPDATA/XDG_CONFIG_HOMEwhen staging HOME-based fallbacks.New
global_probe_spawn_e2etests cover Windows shims, yarn cwd isolation, relative PATH hardening, gem, and Composer fallbacks;neutral_probe_dirhas a unit test. CHANGELOG documents the fix.Reviewed by Cursor Bugbot for commit 465db05. Configure here.
Generated by Claude Code