Skip to content

Fix vendored requirements.txt re-vendoring removed pins (#786) - #787

Open
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
agent/fix-pypi-vendored-in-use-probe
Open

Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
agent/fix-pypi-vendored-in-use-probe

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

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

Fixes #786

Root cause

dispatch_in_use_one (crates/socket-patch-cli/src/commands/vendor.rs) only has lockfile in-use probes for npm and cargo. For pypi it returns None ("can't tell"). The vendor-ledger discovery supplement and the scan --prune GC both treat None as "still wired". So when a user removes or bumps a vendored requirements.txt pin, the next vendored scan rediscovers the ledger entry. It then re-adds the package as a (transitive) line, or refuses with pypi_requirement_not_pinned on every run, and --prune never reverts the entry.

Change

  • vendor::pypi_requirements::requirements_entry_in_use: for the requirements flavor, the requirements tree is the lock pip installs from. The probe reads the root requirements.txt plus every in-root -r include (the same walk the planner and the unwired-revert guard use).
    • Some(true) when a requirement line's code (not its comment) still names .socket/vendor/pypi/<uuid>/.
    • Some(false) when the tree was read and nothing does.
    • None (keep the entry, fail-safe) when no file could be read, or when a reached include exists but is unreadable.
  • vendor::pypi::vendored_entry_in_use routes the requirements flavor to that probe. Every other pypi flavor still returns None. dispatch_in_use_one gains the pypi arm.

Tests (red → green)

Issue Regression test
#786 case A (removed pin re-added as transitive) removed_vendored_pin_is_unwired_and_pruned
#786 case B (bumped pin, exit 1 forever) bumped_vendored_pin_is_unwired_and_pruned

Local verification

Command Result
cargo clippy --workspace --all-features -- -D warnings clean
cargo test -p socket-patch-core --all-features --lib 4845 passed. The 4 that fail as root (permission-denial fixtures: 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) pass when re-run as an unprivileged user
cargo test -p socket-patch-cli --all-features --lib 834 passed
--test scan_vendor_requirements_unwired 3 passed
--test scan_requirements_lock_only 2 passed
--test scan_vendor_e2e 33 passed
--test e2e_vendor_pypi_build -- --include-ignored (uv 0.8.17, real pip) 23 passed
node --test npm/socket-patch/bin/socket-patch.test.mjs passed

I couldn't run the full cargo test --workspace locally: building every test binary exceeds the session's disk allowance. CI runs it.

CI

All 475 checks are green on 580fff7, and Bugbot reviewed 580fff7 with no findings. The first attempt had three compatibility-matrix cells fail on paths this change can't reach, so I re-ran them once and all passed:

  • Bun 1.3.0 preexisting-manifest vendored (refusalCodesExact, an 80s case).
  • PDM 1.15.5 and 2.9.3 agent-mode rescanIdempotent.

The same jobs were green on other open PRs.

Notes

  • The repo isn't cargo fmt-clean on main with the pinned toolchain, and CI has no fmt gate. cargo fmt --all rewrites about 130 unrelated files, so this PR carries only its own hunks, which are rustfmt-clean.
  • Follow-ups (not claimed here): uv / poetry / pdm / pipenv / hatch / python-lock entries, and gem / golang / composer / nuget / maven, still have no in-use probe. They keep the fail-safe None.
  • No wrapper changes are needed (npm/ only dispatches to the binary; the pypi and gem wrappers were dropped in v5).
  • Picked ahead of older p1 issues because it's a correctness bug that silently re-adds a dependency the user removed, and the fix is small and self-contained.

🤖 Generated with Claude Code


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
A vendored requirements.txt entry stayed "in use" forever, because
the in-use probe behind the ledger supplement and `scan --prune` had
no pypi arm. After a user removed a vendored pin, the next vendored
scan re-added the package as a "(transitive)" line. After a bump,
every scan failed with pypi_requirement_not_pinned. `--prune` never
reverted the entry.

The requirements flavor now asks its requirements tree (the root
file plus in-root -r includes) whether any requirement line still
installs the vendored wheel. A removed or bumped pin now gets the
vendor_ledger_entry_unwired warning, and `--prune` reverts it with
exit 0. An unreadable tree still keeps the entry.

Fixes #786

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 4, 2026 14:55
@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 580fff7. Configure here.

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

Copy link
Copy Markdown
Collaborator Author

Ready for review — head 580fff7847e3.

  • CI: 97/97 completed checks green (3 skipped by path filter); branch is up to date with main, no conflicts.
  • Bugbot: reviewed 580fff7 — no findings. No unresolved review threads.
  • Reviewer focus: the new pypi arm in dispatch_in_use_one returns None (keep entry) whenever the requirements tree can't be fully read, so --prune only reverts entries it can prove are unwired.

Generated by Claude Code

This branch has not been deployed

No deployments
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