GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Scope project-mode NuGet crawls to the restore's resolved packages (#427) by mikolalysenko · Pull Request #1183 · SocketDev/socket-patch

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 8, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

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

Fixes #427

Summary

A project-mode scan of a restored .NET project used to list every package in the shared NuGet packages folder (~/.nuget/packages, NUGET_PACKAGES, every packageFolders key). Agent mode then patched packages that other projects had left there, and VEX attested them. This PR turns the crawler into a locator for restored projects. When cwd holds a .csproj/.fsproj/.vbproj, and every project under cwd at any depth has a parsed obj/project.assets.json with libraries, the shared roots are no longer walked. They are looked up only for the union of those resolved libraries (type: "package").

Why (leverage)

  • Issue #427 is the NuGet child of tracking issue #595, register row E05 (register). The living document covers it in Part 6, "Cache crawls are not project-scoped".
  • B 1: Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427.
  • U 1: sets the locator shape for the cargo, go, Maven (Maven hosted scan pins, and VEX attests, artifacts the project doesn't depend on (the crawler lists all of ~/.m2) #265) and Deno children.
  • D: one project.assets.json parser (parse_project_assets) serves both packageFolders and libraries.
  • S 3: measured below.
  • R M: project-mode discovery changes on purpose, as Tracking: scope project-mode cache crawls to what the project resolves #595's acceptance criteria ask.

What changed (crawlers/nuget_crawler.rs only)

  • package_roots builds the root list, plus an optional scope. get_nuget_package_paths (same output as before) and crawl_all both use it.
  • is_dotnet_project became dotnet_root, which returns None, Marker (solution, packages.config or NuGet config) or Project. Only Project roots are scoped.
  • parse_project_assets parses one assets file into packageFolders and libraries. It replaces parse_project_assets_package_folders.
  • restore_scope walks the source tree and unions every project directory's libraries. It returns None if any project is uncovered.
  • locate_libraries probes <root>/<id lowercased>/<version lowercased>/ with the same verify_nuget_package and path_safety::is_safe_name_version guards as find_by_purls. It emits the same rows the walk produced for those directories.

Deleted

  • The whole-cache walk of the shared roots for a fully restored project.

Behavior

  • Changed: a fully restored project no longer crawls packages from the shared roots that its restores did not resolve. "Fully restored" means a project file at cwd, and every project file under it has a parsed assets file with libraries. The resolved packages come out with the same name, version, purl and path as before, but in libraries order instead of readdir order.
  • Unchanged:
    • --global / --global-prefix;
    • solution roots without a root project file;
    • any tree where some project at any depth has no assets file or an assets file without libraries;
    • any tree with a directory that can't be fully listed, or more than 10,000 directories;
    • the project-local packages/ folder, which is still walked in full;
    • get_nuget_package_paths and find_by_purls.
  • Remaining for Tracking: scope project-mode cache crawls to what the project resolves #595's NuGet item: the packages.lock.json fallback, and the crawl_unscoped_cache warning. The warning needs CLI_CONTRACT.md, which open PRs change.

Test evidence

  • New unit tests in nuget_crawler.rs:

    • restored_project_crawls_only_its_resolved_packages
    • located_rows_equal_the_walks_rows_for_resolved_packages
    • sub_project_restores_join_the_scope (a restored sub-project two levels down)
    • an_uncovered_sub_project_keeps_the_walk (review fix: an unrestored sub-project two levels down, and an assets file without libraries)
    • project_local_packages_folder_is_still_walked
    • solution_roots_and_unrestored_projects_keep_the_walk
    • global_prefix_crawl_is_not_scoped
  • Red → green:

    • On main, the Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427 tests fail. For example, the Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427 test gets [[email protected], [email protected], [email protected]] where it expects [[email protected]].
    • an_uncovered_sub_project_keeps_the_walk fails on a05d7fc, the head before the review fix.
    • All of them pass on 038042f.
  • cargo clippy --workspace --all-features -- -D warnings is clean.

  • cargo test -p socket-patch-core --lib: 5805 passed on a05d7fc. Its only 4 failures are the known root-only sandbox ones, which also fail on main:

    • copy_tree::relax_loop_must_not_traverse_symlinked_root
    • vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry
    • pypi_poetry::wire_write_failure_maps_error_and_leaves_lock_untouched
    • pypi_requirements::wire_failure_rolls_back_already_written_files

    On 038042f I re-ran only the 40 crawlers::nuget tests, and they pass.

  • crawler_nuget_e2e: 28 passed. CLI e2e_nuget: 21 passed. The NuGet crawler oracle equivalence suite also passes: its trees have no libraries, so they keep the walk.

  • Timing (release build; I used a throwaway bench and removed it before committing). The fixture is a 3,000-package shared folder and a project that resolves 20 of them:

    • main: 58.5 ms per crawl, 3,000 packages;
    • branch: 0.80 ms per crawl, 20 packages.
  • No dotnet in the sandbox, so I didn't run a real restore. The fixtures follow the assets format: libraries keyed "<Id>/<Version>", with type: package|project.

Risk

Medium.

  • The scope walk lists the source tree. It skips hidden, symlinked, bin, obj, packages and node_modules dirs, and gives up after 10,000 directories.
  • Any project the walk finds without a parsed restore, including one with a relocated BaseIntermediateOutputPath, makes the crawl fall back to the whole-cache walk. So a package is dropped only when no project's restore resolves it.
  • A project outside cwd that is referenced by path is covered too, because its packages appear in the referencing project's libraries.
  • The wrappers (npm/, pypi/, gem/) need no change.

🤖 Generated with Claude Code


Generated by Claude Code

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@claude
Start refactor for #427
1cb5b34
Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko Mikola Lysenko (mikolalysenko) added refactor Structural change: duplicated code or logic, missing abstraction, layering, dead code arch-refactor PR opened by the scheduled architecture refactor routine labels Oct 8, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427
Closed
@claude
Scope project-mode NuGet crawls to the restore
a05d7fc
A project-mode scan of a restored .NET project listed every package
in ~/.nuget/packages, so agent mode patched, and VEX attested,
packages other projects left in the shared cache (#427).

When the working directory is a project (.csproj/.fsproj/.vbproj)
whose obj/project.assets.json parses, the shared roots (the global
packages folder and packageFolders) are now looked up for the
restore's resolved libraries instead of walked. Solution roots,
unrestored projects, global mode and the project-local packages/
folder keep the walk. Each assets file is parsed once for both its
package folders and its libraries.

A 3,000-package cache crawl drops from 58 ms to 0.8 ms.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 8, 2026 22:49
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

cursor[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
refactor: run 2026-10-08T2152Z, PR #1183 (#427)
2a8689b
Assisted-by: Claude Code:claude-opus-5-5
cursor[bot]
cursor Bot reviewed Oct 8, 2026
View reviewed changes

@cursor cursor Bot left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Tanmay182003
Tanmay Singla (Tanmay182003) reviewed Oct 8, 2026
View reviewed changes
Comment thread crates/socket-patch-core/src/crawlers/nuget_crawler.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@claude
Scope NuGet crawls only when every project is seen
038042f
The scope only read the root project's restore and the one-level-deep
ones, so a sub-project deeper down (or one whose assets file has no
libraries) lost its packages from the crawl without a warning.

The scope now walks the source tree (skipping hidden, symlinked, bin,
obj, packages and node_modules dirs, up to 10,000 directories) and
unions the libraries of every project directory's restore. Any project
without a parsed restore, an unreadable directory or an exhausted
budget keeps the whole-cache walk, as on main.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

cursor[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cursor[bot]
cursor Bot reviewed Oct 9, 2026
View reviewed changes

@cursor cursor Bot left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

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 038042f. Configure here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

[agent] test (windows-latest, 1) failed on 038042f in vendor::lock_inventory::view::tests::a_read_set_notices_a_changed_file (view.rs:1182, assertion "a replacement"). This PR doesn't touch that code:

  • The test came in with Decide whether a hosted patch is pinned through lockfile discovery alone #1058 and checks the lock-inventory read set, which has no NuGet crawler code.
  • The same job passed on this PR's previous head a05d7fc, and it passes on main (16106b1, 3a54db9, 568214e).

Likely root cause (Windows only). On non-Unix, Stat::of uses the file's creation time as its identity. The test writes a.tmp and renames it over a.lock, with the same length and the same bytes. NTFS file-system tunnelling keeps the old creation time when a file is renamed over a recently deleted name. modified can also tie at timer resolution. When both happen, the fingerprint can't see the replacement, so the result depends on timing.

Proposed fix (outside this PR's scope). On non-Unix, record every read as racy, so unchanged() compares the bytes it read against the file's current bytes. That is the existing racy path. An alternative is the Windows volume serial plus file index, once windows_by_handle is stable. No fix PR exists yet.

I'm re-running the failed job once to confirm.


Generated by Claude Code

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Tanmay182003
Tanmay Singla (Tanmay182003) approved these changes Oct 9, 2026
View reviewed changes
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

[agent] The one re-run of test (windows-latest, 1) failed again on 038042f, but in a different test. lock_inventory::view::tests::a_read_set_notices_a_changed_file passed this time. The failure is now patch::apply_lock::tests::zero_timeout_does_not_sleep_before_held (apply_lock.rs:1106): "non-blocking acquire should not sleep, took 116.2534ms".

This one isn't this PR's either: that test checks wall-clock time for apply-lock acquisition, which this PR doesn't touch, and it passes on main and on this PR's earlier head a05d7fc. So the job has now failed two different timing-sensitive Windows tests in a row, both outside this diff.

Proposed fix (outside this PR's scope). Assert that the acquire never entered the backoff sleep, through a counter or failpoint, instead of comparing elapsed time against a bound. A 116 ms stall on a shared Windows runner doesn't show a sleep. The proposed fix for view.rs is in my earlier comment. No fix PR exists for either yet.

I've used this PR's one re-run, so I'm leaving CI as is. The PR stays watched. A maintainer can re-run the job, or it will re-run with the next push.


Generated by Claude Code

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Oct 9, 2026
Scope the project-mode cargo crawl to the registry crates Cargo.lock resolves #1204
Closed
Scope the project-mode cargo crawl to the crates Cargo.lock resolves (#1204) #1205
Merged
@mikolalysenko
Merge branch 'main' into arch-refactor/427-nuget-project-scope
5ea0f7a
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

[final reviewer] ci-ok was red on 038042f4 from one Windows unit test, patch::apply_lock::tests::zero_timeout_does_not_sleep_before_held (test (windows-latest, 1), run 37862006667, attempt 2): the non-blocking acquire returned the right LockError::Held but took 116 ms against the test's 100 ms limit. That test is unchanged on main and this PR doesn't touch apply_lock.rs (its only file is crawlers/nuget_crawler.rs), so this isn't this PR's failure. The 100 ms limit equals the backoff sleep it guards against, which leaves no room on a busy Windows runner. That is a CI-reliability fix for the janitor, and no fix exists yet.

I merged main into the branch (now 5ea0f7a9, a merge commit only, so the approval on 038042f4 still covers the code) to get a fresh CI run. Locally the 40 nuget_crawler unit tests pass after the merge. Once ci-ok and clippy are green, the next final-review pass sends it to the merge queue.


Generated by Claude Code

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 6f43b99 Oct 9, 2026
326 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the arch-refactor/427-nuget-project-scope branch October 9, 2026 03:13
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 9, 2026
Scope the project-mode Deno crawl to the JSR packages deno.lock records (#1216) #1217
Merged
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 9, 2026
@mikolalysenko @claude
Add #1008, #1183, #1190 and #1205 to the 5.0.0 release notes
4b7a126
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 9, 2026
@claude
refactor: run 2026-10-09T04:25Z (#1221, record #1183/#1205)
16505cb
This was referenced Oct 9, 2026
Bench: benchmark NuGet as a restored project (#1183 scoped crawl) #1250
Merged
Fix project-mode Maven crawl listing all of ~/.m2 (#265) #1361
Merged
Perf regression: nuget/rescan wall +31% (f3c6313a..17793173; #1340/#1341) #1425
Open
This was referenced Nov 4, 2026
NuGet crawler test crawls the host's ~/.nuget/packages and fails on dev machines #2023
Closed
Make NuGet walk tests ignore the host package cache #2037
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@cursor cursor[bot] cursor[bot] left review comments
@Tanmay182003 Tanmay Singla (Tanmay182003) Tanmay182003 approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

arch-refactor PR opened by the scheduled architecture refactor routine refactor Structural change: duplicated code or logic, missing abstraction, layering, dead code

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages)

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@mikolalysenko @Tanmay182003 @claude
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.