Fix PyPI vendored→hosted takeover stranding unreachable pins (#699) - #708
Open
Mikola Lysenko (mikolalysenko) wants to merge 4 commits into
Open
Mikola Lysenko (mikolalysenko) wants to merge 4 commits into
Mikola Lysenko (mikolalysenko) wants to merge 4 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Hosted mode pins only the root requirements.txt, so taking over a vendored pin that lives in a -r include, or a (transitive) line that vendored mode appended, used to revert the vendored patch and then leave the package unpatched. These tests show the wet run and the dry run for both layouts, plus the root-pin control. Assisted-by: Claude Code:claude-opus-5-5
`scan --mode hosted` over a vendored requirements.txt project now refuses to take over a package whose vendored pin is in a -r include or is a (transitive) line. Before, it removed the vendored patch first and then found no root pin to redirect, so the project went back to installing the unpatched release (exit 1). The dry run previewed a clean takeover. The refusal is checked before anything is reverted, on wet and dry runs alike. The package stays vendored and patched, and the run reports redirect_requirements_takeover_unreachable with the steps to switch. Fixes #699 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 3, 2026 16:58
Collaborator
Author
|
BugBot review Generated by Claude Code |
The refusal told users to run `vendor --revert` to switch one package. That command reverts every vendored package in the project, and for a pin in a -r include the user also has to delete the include's pin, or the unpatched pin is still installed alongside the hosted one. The detail and the contract now say both. Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
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 5f291a5. Configure here.
Collaborator
Author
|
Ready for review (burn-down agent).
Generated by Claude Code |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #699
Root cause
scan --mode hostedover a vendored requirements.txt project (vendored_takeoverinscan/hosted.rs) only checks whether the vendored wiring can be reverted. It never checks whether the hosted requirements rewriter can reach the restored entry. That rewriter only edits a pin in the rootrequirements.txt. A vendored pin in a-rinclude, or a vendor-appended(transitive)line, gets reverted first. The rewriter then refuses withredirect_requirements_entry_not_found, which leaves the package unpatched (exit 1). The dry run counts every takeover preview as redirected, so it never predicts this.Change
patch::redirect::preflight_requirements_takeover(&VendorEntry). Arequirements-flavored PyPI entry is reachable only when every wiring record is a rewritten pin in the rootrequirements.txt. Otherwise it returnsredirect_requirements_takeover_unreachable. The detail names where the pin lives and gives the remedy with its full reach:vendor --revertreverts every vendored package in the project, not just this one;(transitive)line add an exact==pin to the root.vendored_takeover'stakeover_refusalruns this gate for PyPI purls. The existing refusal path then skips the purl before any revert, on wet and--dry-runalike, so the vendored wiring, ledger entry and wheel stay byte-identical (exit 0, the package stays vendored and patched).CLI_CONTRACT.md(a takeover paragraph and a warning-table row).npm/,pypi/,gem/only dispatch to the binary).Per-issue checklist
-rinclude or a vendored "(transitive)" line: the wet run reverts it to the unpatched release, while--dry-runpreviews a clean takeover #699,-rinclude pin:include_pin_takeover_is_refused_before_revert(wet),dry_run_predicts_include_pin_takeover_refusal(dry)-rinclude or a vendored "(transitive)" line: the wet run reverts it to the unpatched release, while--dry-runpreviews a clean takeover #699, vendored(transitive)line:transitive_line_takeover_is_refused_before_revert(wet),dry_run_predicts_transitive_line_takeover_refusal(dry)dry_run_previews_root_pin_takeover+ the existingrequirements_vendored_to_hostedpatch::redirect::requirements::takeover_reach_tests(root pins, include pin, root+include, transitive, other flavors/ecosystems, remedy wording)Test evidence
main(commit 9525830, tests only):cargo test -p socket-patch-cli --all-features --test mode_migration_pypigives 13 passed, 4 failed. All four new refusal tests fail the "no takeover over an entry hosted mode cannot pin" assertion: the dry run saysstatus: successwithredirected: 1, and the wet run sayspartial_failurewith the takeover announced, matching the issue.mode_migration_pypi17/17.covgap_commands_scan_hosted50/50,coverage_fix_scan_hosted_dryrun_vendored5/5,mode_migration_bunandmode_migration_vltgreen,socket-patch-cli --lib834/834,takeover_reach_tests5/5.cargo clippy --workspace --all-features -- -D warnings: clean (re-run on 5f291a5).socket-patch-core --lib: 4847 passed, 4 failed.in_process_redirect: 104 passed, 3 failed. All 7 failures are chmod-0o555 write-failure injection tests that can't fail as root (the sandbox runs as uid 0). They're unrelated to this diff, and CI runs them unprivileged.cargo fmt --all -- --checkis not clean onmainitself with the pinned 1.93.1 rustfmt, and CI doesn't run it. The changed files are rustfmt-clean, and no unrelated files were reformatted.Review
vendor --revert's full reach and the step to delete the include pin. Valid, fixed in 5f291a5, and the thread is resolved.Prioritization note
I picked this over older p1 issues because it's a correctness regression (#503) where a documented, previewed migration actively deletes a working vendored patch.
Generated by Claude Code