GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||
GeezerVison is showing github.com — Fix agent apply writing into shared package stores (#332, #361) by mikolalysenko · Pull Request #486 · SocketDev/socket-patch Conversation
|
| Issue | Regression test | Before fix | After fix |
|---|---|---|---|
| #361 (pnpm GVS) | patch::apply::tests::test_apply_refuses_shared_store_package_dir (npm leg), test_apply_refuses_already_patched_shared_store_package_dir, patch::rollback::tests::test_rollback_refuses_shared_store_package_dir (npm leg) |
FAILED | ok |
| #332 (PDM cache) | test_apply_refuses_shared_store_package_dir (pypi leg), test_rollback_refuses_shared_store_package_dir (pypi leg) |
FAILED | ok |
| #332 (PyPI root = site-packages) | shared_store::tests::patch_dirs_find_a_link_below_the_package_root, plus the PyPI legs above, which use the real site-packages + urllib3/index.js shape |
FAILED with a root-only check | ok |
| no regression | test_apply_patches_through_per_project_pnpm_link, shared_store::tests::* (detection tests incl. negatives) |
ok | ok |
Red run on this branch before the guard: 3 failed; 5 passed. With the first, root-only guard, the PyPI-shaped legs still fail (pkg:pypi/[email protected] dry_run=true: must refuse). With 0f84373, everything passes.
Real pnpm 10.28 end-to-end (enableGlobalVirtualStore: true, projects a/b/c sharing one store, hand-staged .socket/ for pkg:npm/[email protected]):
apply in b: failed / apply_failed ("Refusing to patch …/store/v10/links/@/is-odd/3.0.1/…/node_modules/is-odd …"), exit 1. c's index.js is untouched.rollback in a is refused (exit 1) and the shared bytes stay patched, so b and c aren't silently unpatched.node_modules/is-odd -> .pnpm/…) still applies and rolls back normally.Checks
cargo clippy --workspace --all-features -- -D warnings: clean.cargo test --workspace --all-features --no-fail-fast: everything passes except 13 tests in 4 targets. All 13 are permission tests that make a directory read-only and expect a write to fail, and that can't happen when the sandbox runs as root (e.g. copy_tree::relax_loop_must_not_traverse_symlinked_root, the *_state_write_failure_* / *unremovable* tests). All of them are green in CI.cargo fmt --all -- --check: main itself isn't rustfmt-clean under the pinned 1.93.1 rustfmt (it reformats 120+ unrelated files), so I ran rustfmt only on the files this PR changes, and they are clean.pth cache method already fails closed (File not found), and symlink_individual / hardlink are isolated by the file-level rename. Neither needs a change.🤖 Generated with Claude Code
Note
Medium Risk
Changes agent-mode patch/rollback behavior for PDM symlink-cache and pnpm GVS installs (now errors instead of cross-project writes); detection logic must not false-positive on normal per-project layouts.
Overview
Agent-mode apply and rollback now fail closed when a target package directory (or any parent dir touched by the patch keys) resolves into a cross-project shared store, instead of writing through a symlinked package root and affecting every linked project.
A new patch::shared_store module detects PDM’s symlink install cache (packages/…/referrers + lib/) and pnpm’s global virtual store (v<N>/links beside files/). Per-project pnpm layouts are unchanged. Refusal messages name the store and suggest remediation (e.g. disable GVS, pdm config install.cache_method hardlink) or hosted/vendored mode. Rollback skips the check when everything is already original (no write). CHANGELOG and docs/ecosystems.md document the behavior; regression tests cover apply/rollback for both ecosystems and PyPI site-packages roots.
Reviewed by Cursor Bugbot for commit 3628931. Configure here.
Generated by Claude Code
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Assisted-by: Claude Code:claude-opus-5-5
PDM's symlink install cache and pnpm's global virtual store link a package directory into a store every project on the machine uses. Agent apply renamed the patched file inside that directory, so other projects were patched too, and a rollback in one project silently unpatched the rest. Apply now refuses a package whose real location is such a store, and rollback refuses whenever it would write there. The error names the store and how to get a private copy. Per-project stores reached through a symlink (node_modules/.pnpm, workspace links) are patched as before. Fixes #332, #361. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem 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.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
A PyPI patch is rooted at site-packages with file keys like urllib3/response.py, so the PDM cache link sits below the root and the first guard, which only looked at the root, never saw it. Apply and rollback now classify the directory of every patched file, so a PDM symlink-cache package is refused as intended. Refs #332. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem 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.
There was an error while loading. Please reload this page.
|
Burn-down agent: ready for review at
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Reviewed No actionable correctness or security regressions found. Shared-store detection covers the package root and nested file-parent directories, including PyPI site-packages layouts. Apply refuses even already-patched shared copies; rollback permits an already-original no-op and refuses writes. Ordinary per-project store paths retain their existing behavior. Validation: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Final merge check for |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Resolve the CHANGELOG conflict by keeping both Fixed entries. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01L5H2ijb6wThkigkiW7vRr7
|
[agent] Merged Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem 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 3628931. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[agent] Bugbot reviewed the merge head Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Re-reviewed The update merges Fresh validation: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
Agent-mode apply and rollback on a pnpm project with enableGlobalVirtualStore patch (and unpatch) every other project that shares the store Agent mode writes the patch into PDM's shared install cache when PDM 2.0–2.12 installs packages as directory symlinks (install.cache + symlink)
There was an error while loading. Please reload this page.