Skip to content

Fix crawlers missing parent dirs under --cwd . (#1902) - #1906

Open
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-crawler-relative-cwd
Open

Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
mainfrom
agent/fix-crawler-relative-cwd

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1902

Summary

If you run socket-patch from a project or workspace member without --cwd, scan, apply and vex now read the config files in parent directories, just as they do with an absolute --cwd. Before this fix, three lookups never looked above the working directory:

Root cause

--cwd defaults to . and reaches the crawlers as typed. Upward config lookups walked Path::ancestors(), which for . yields only . and "". So they never reached a real parent directory. pkg_managers (std::path::absolute) and enclosing_pnpm_modules_yaml_sync (canonicalize) already worked around this. The three lookups above didn't.

Fix

  • utils::relpath::absolute_lexically: makes a path absolute against the working directory and folds ./... It doesn't resolve symlinks, and it treats the empty path (the parent of a bare node_modules) as the working directory. yarnrc_modules_folder and pnpm_layout::modules_dir_setting now walk from it. Both return only a project-relative string, so their output keeps the same spelling.
  • utils::relpath::ancestors_keeping_spelling: a lazy upward walk that pairs each absolute level with a spelling in the start path's own terms. It keeps the lexical ancestors and spells each level above the working directory with .. (./..). relocated_yarn_pnpm_store_sync uses it, so a store found from ./packages/a/node_modules and one found from ./node_modules get the same spelling. The store is still read from the absolute project path.

Why not make --cwd absolute in GlobalArgs::crawler_options, as the issue proposes?

The CLI depends on crawler paths keeping the relative spelling under the default --cwd .. ui::display_copy_path strips the raw cwd prefix to print node_modules/x, and path_scope::BoundScope documents that "crawler paths are NOT absolutized". Absolute crawler paths would change every relative path the CLI prints or matches. Fixing the lookups that walk upward keeps those outputs the same.

Tests

New regression tests in crates/socket-patch-core/tests/crawler_npm_e2e.rs are #[serial] and use a shared CwdGuard, which replaces the inline copy that was there. Each test crawls once with an absolute cwd as a control, then again with . from inside the project:

Case Test Without the fix With the fix
#1902 .yarnrc --modules-folder above cwd parent_yarnrc_modules_folder_is_read_from_a_relative_cwd FAILED: roots [], want ["./deps"] ok
#1902 yarn pnpm store above a member parent_yarn_pnpm_store_is_found_from_a_relative_member_cwd (unix) FAILED: only is-odd, transitive is-number missing ok
same cause: pnpm modulesDir in the root yaml parent_pnpm_modules_dir_is_read_from_a_relative_member_cwd FAILED: [] ok
spelling and laziness of the walk utils::relpath::tests::ancestors_keeping_spelling_climbs_past_the_working_directory (new helper) ok

To get the "without the fix" column, I made absolute_lexically return its input unchanged and reran the tests.

Local runs:

  • cargo fmt --all -- --check: ok
  • cargo clippy --workspace --all-features -- -D warnings: ok
  • cargo test -p socket-patch-core --all-features --no-fail-fast: 7657 passed. 4 failed, all permission-denial tests in other modules (copy_tree, vlt_heal, pypi_poetry, pypi_requirements). They can't fail closed when run as root, which is how this container runs. CI runs them as a normal user.
  • cargo test -p socket-patch-cli --all-features --lib: 940 passed
  • SOCKET_PATCH_NPM_E2E_REQUIRED=1 cargo test -p socket-patch-cli --all-features --test e2e_redirect_npm_build -- --ignored: 9 passed (run on the first commit)
  • The full cargo test --workspace ran out of disk in this container, so CI is the check for the remaining CLI suites.

No wrapper changes are needed: npm/, pypi/ and gem/ only forward --cwd.

Review notes (/code-review high)

Fixed:

  • A store could be reported under two spellings (./store and store). The walk now keeps the lexical spelling.
  • The pnpm modulesDir lookup had the same bug.
  • The cwd-changing tests were in the lib test binary, where other tests read the cwd without serializing. They moved to the integration suite.
  • The walk helpers are now shared and lazy.

Not changed, with reasons:

https://claude.ai/code/session_011f9aeS6qCCCE8PZfZcJW4k


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Run from a project or yarn workspace member without --cwd, scan and
apply never looked above the working directory. A parent .yarnrc
--modules-folder was ignored, so packages installed there were
reported missing. From a member, the root's relocated yarn pnpm store
was never walked, so transitive packages read as not installed.

The npm crawler now walks up from the absolute path while keeping
the relative spelling of the paths it reports. Fixes #1902.

Assisted-by: Claude Code:claude-opus-5-5
Review follow-up. A store reached from two node_modules roots could be
reported under two spellings (./store and store) and walked twice;
the walk now keeps the lexical spelling and only adds .. above the
working directory, so each directory has one spelling.

pnpm's modulesDir lookup had the same bug: from a workspace member
under the default --cwd, the root pnpm-workspace.yaml was never read.
It now walks from the absolute path too.

The helpers move to utils::relpath, and the cwd-changing tests move
to the crawler_npm_e2e suite, which already serializes cwd changes.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review November 1, 2026 03:12
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 378c581. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Nov 1, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Burn-down agent: labeled Ready for review at head 378c581.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does: Under the default --cwd . (or any relative --cwd), three upward config lookups in the npm crawler only walked the lexical ancestors of ., so they never reached a parent directory: a parent .yarnrc --modules-folder, a yarn workspace root's relocated pnpm-linker store, and pnpm modulesDir in the workspace root. This walks them from the absolute path, and keeps the relative spelling of the paths the CLI prints.

Risk: low. The fix is confined to three lookup helpers. With an absolute --cwd they behave as before (the new tests use it as the control), and output paths keep their relative spelling.

Look here

Verified

  • Read the full diff. I traced the spelled walk for ., "", ./packages/a, ../x, a/../b and ./a/.., and the spelled level matches the absolute level in every case.
  • yarnrc_modules_folder's strip_prefix(rc_dir) now compares two absolute paths, so it is consistent. The lookups are per project, not a hot path.
  • The tests change the process cwd only under #[serial] with a restoring guard, like the existing deno test.
  • Ran cargo test -p socket-patch-core --lib relpath and the parent_* tests in crawler_npm_e2e locally: 9 passed (6 relpath lib tests, 3 parent_* e2e tests), 0 failed.
  • CI: 32/32 executed checks green (50 skipped by path filters). Bugbot: success. CHANGELOG.md untouched. No unresolved threads.

Changes I made: none.

Open questions: none blocking. Note that, as with an absolute --cwd today, the walk now reads .yarnrc/.npmrc files above the project (up to /) under --cwd . too. That is the intended parity.

Auto-merge is armed, so approving sends it straight to the merge queue.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

2 participants