Repository navigation
Resolve pnpm modules dirs through one helper for crawler and layout detection (#1129) - #1347
Conversation
Assisted-by: Claude Code:claude-opus-5-5
The npm crawler alone knew where pnpm installs a project when modulesDir is set. Its resolver moves to crawlers::pnpm_layout, which answers for a disk root and for a ProjectView (memory and snapshot), and lists a dir both configured and holding .modules.yaml once. The crawler reads its pnpm roots from there; nothing it finds changes. Refs #1129 Assisted-by: Claude Code:claude-opus-5-5
detect_npm_pkg_manager and the pnpm Plug'n'Play carve-out probed only node_modules/ for pnpm's store. A node-linker=pnp project with modulesDir set keeps it in <modulesDir>/.pnpm, so it was read as yarn berry: apply refused with yarn_pnp_unsupported and the yarn remedy, vendor gave the yarn refusal, and vex read pnpm's loader as yarn's. Both now ask pnpm_layout::installed_store_in, the same modules dirs the crawler crawls, and the literal node_modules probes are gone. Fixes #1129 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review 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 2e2715b. Configure here.
|
[agent] CI: Generated by Claude Code |
|
[agent] Correction to my comment above: Generated by Claude Code |
|
Ready for review at
Labeled Generated by Claude Code |
Assisted-by: Claude Code:claude-opus-5-5
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1129
Summary
"Where does pnpm keep this project's install?" now has one answer:
crawlers::pnpm_layout. Before this PR there were two. The npm crawler honored pnpm'smodulesDir, butdetect_npm_pkg_managerand the pnpm Plug'n'Play carve-out (pnpm_pnp_layout_in) checked only the literalnode_modules/. So anode-linker=pnpproject withmodulesDir: depswas read as yarn berry:applyrefused it withyarn_pnp_unsupportedand told the user to runyarn patch;Why
Leverage: B 1 (#1129), U 0, D 1 (two implementations of pnpm's install location become one), R M. Score 3, P2. This was the top free candidate in the refactor register. The other candidates are blocked by file overlap with open PRs. Register row E92 is in
register/10-audit-ecosystems.md, and the living-document passage is indoc/06-discovery-vex.md.What changed
crawlers/pnpm_layout.rs:configured_modules_dirs(project)is the crawler's formerpnpm_modules_dirs. It resolves themodulesDirsetting and finds child dirs that hold.modules.yaml. It no longer lists a dir twice when that dir is both configured and holds the record.installed_store_in(view)/installed_store(project)check for.modules.yamlor.pnpm/innode_modules/first, and then in the configured dirs.root(), likeyarn_node_linker, so a recording that reaches it is not reused. In memory, only the project's ownpnpm-workspace.yamland.npmrccount.npm_crawler.rs:pnpm_modules_dirs,pnpm_modules_dir_settingandunquote_yaml_scalarare moved out of this file.PNPM_MODULES_YAMLis now the shared constant.resolve_modules_folderbecomespub(super)so the new module can share it.pkg_managers.rs: step 4 ofdetect_npm_pkg_managerandpnpm_pnp_layout_incallpnpm_layout. The hard-codednode_modules/.modules.yaml/node_modules/.pnpmprobes are deleted. The carve-out now checks the cheap lockfile conditions before it looks for the store.Deleted / diff
Production: +191 / −92 (the new module's production half is 171 lines, about 60 of them doc comments). Tests: +213 (the
pnpm_layouttests plus 1 CLI test).Behavior
modulesDir(or in a child dir holding.modules.yaml) is detected as pnpm:applypatches the crawled copies instead of refusing; vendored mode refuses withvendor_pnpm_pnp_unsupportedand the pnpm remedy; andYarnPnpLoader::detectreturnsNone;applyprints the pnpm copy-on-write note instead of nothing.configured_install_rootsalready deduplicated them.Test evidence
e2e_safety_yarn_pnp::pnpm_pnp_with_a_custom_modules_dir_applies(both the.npmrcand thepnpm-workspace.yamlspelling). With main'ssrc/it fails:error.code = yarn_pnp_unsupported, exit 1. On the branch it passes: exit 0 anddeps/dummy/index.jsis patched.pnpm_layout::tests::every_reader_finds_a_store_in_the_configured_modules_dirruns every former reader on 4 layouts and checks each answer: crawler roots,detect_npm_pkg_manager,pnpm_pnp_layout(disk, memory, snapshot),YarnPnpLoader::detectanddetect_npm_lock_flavor. The 4 layouts are.npmrc,pnpm-workspace.yamlplain and quoted, and an unconfigured dir holding.modules.yaml.yarn.locknext to the loader, still detect yarn berry.cargo test -p socket-patch-core --lib -- crawlers:: vendor::npm_flavor vendor::lock_inventory: 890 passed.cargo test -p socket-patch-cli --all-features --test e2e_safety_yarn_pnp: 41 passed.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-core --lib: 6095 passed, 4 failed. The 4 are the known root-sandbox failures that also fail on main (relax_loop_must_not_traverse_symlinked_root,an_unremovable_hidden_lock_keeps_every_store_entry,wire_write_failure_maps_error_and_leaves_lock_untouched,wire_failure_rolls_back_already_written_files) and pass in CI.cargo test -p socket-patch-core --test '*': all passed.spawn_env_hygiene: 12 passed.Risk
Medium-low. The change is limited to layout detection.
detect_npm_pkg_managernow readspnpm-workspace.yaml/.npmrcfrom the project upward, plus one listing of the project root, but only whennode_modules/holds no pnpm store. That happens once perapply/vex, not per package.🤖 Generated with Claude Code
https://claude.ai/code/session_019GNMsU2GoB5YNpiTvAX7ht
Note
Medium Risk
Changes package-manager and PnP classification paths used by apply, scan, and vendored mode; behavior is narrowed to custom pnpm
modulesDirlayouts with broad unit/e2e coverage.Overview
Fixes #1129 by giving the npm crawler and package-manager layout detection a single source of truth for where pnpm installs packages (
crawlers::pnpm_layout).Before: only the crawler respected pnpm’s
modulesDir(and stores under<modulesDir>/.pnpm).detect_npm_pkg_managerand the pnpm-vs-yarn PnP carve-out looked only undernode_modules/, sonode-linker=pnp+ custommodulesDir(e.g.deps/) was treated as yarn berry —applyreturnedyarn_pnp_unsupportedinstead of patching.After:
configured_modules_dirs,installed_store/installed_store_in(disk, snapshot, memory) are shared.pkg_managersstep 4 andpnpm_pnp_layout_inuse them; duplicate logic is removed fromnpm_crawler. pnpm PnP with a custom modules dir is classified as pnpm, crawled, and patched.Tests add unit coverage in
pnpm_layoutand e2epnpm_pnp_with_a_custom_modules_dir_appliesfor.npmrcandpnpm-workspace.yaml.Reviewed by Cursor Bugbot for commit 2e2715b. Configure here.
Generated by Claude Code