Skip to content

Fix residual-reference keep reported as drift (#1184) - #1311

Merged
Mikola Lysenko (mikolalysenko) merged 6 commits into
mainfrom
agent/v5-vendor-residual-keep
Oct 10, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 6 commits into
mainfrom
agent/v5-vendor-residual-keep

Conversation

@mikolalysenko

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

Copy link
Copy Markdown
Collaborator

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

Fixes #1184

Summary

Since #997, a vendored PyPI revert keeps the wheel and ledger entry while another root project file still installs from it (vendor_revert_residual_reference). The everyday shape is a pipenv requirements > requirements.txt export made after vendoring. The keep itself is correct, but remove / rollback / vendor --revert reported it as drift:

  • vendor_artifact_kept said "undo the drift".
  • remove printed Kept vendored state …: lockfile wiring drifted.
  • The top-level vendor_revert_kept error told the user to "re-run scan --mode vendored to normalize, then remove".
  • rollback gave vendoredKept[].reason: "lockfile wiring drifted…".

Following that remedy loops. The re-vendor re-wires Pipfile.lock, and the next remove keeps the entry again. The hosted takeover lane had the same mislabel ("part of its vendored wiring was edited since vendoring"), and its vendor --revert remedy left the project unpatched.

Root cause

revert_pypi_opts (core vendor/pypi.rs) handled the residual-reference keep through the generic RevertOutcome::keep_artifact, which emits drift wording. The CLI's VendorRevertStep::Kept carried no cause, so every caller printed the drift text and the normalize remedy.

Fix

  • Core: RevertOutcome::keep_artifact_for_reference emits vendor_artifact_kept with the real cause and remedy. kept_for_residual_reference() reports a keep whose only signal is RESIDUAL_REFERENCE_CODE. The residual warning's remedy now names every unwind (vendor --revert, remove, rollback).

  • CLI: VendorRevertStep::Kept(KeepCause::{Drift, Reference}). For Reference, the following all say that a project file still installs from the vendored artifact and give the remedy "point the file named by vendor_revert_residual_reference back at the registry release (or re-export it from the restored lock), then again":

    • remove's warning, skip reason, top-level message and human error line
    • rollback's vendoredKept reason
    • vendor --revert and the manifest-reconcile skips

    The JSON error code stays vendor_revert_kept, so the contract code is unchanged. Drift keeps keep their exact existing wording.

  • Takeover: a refusal whose only cause is a residual reference now names the file. Its remedy is to point that file back at the registry release and re-run scan --mode hosted.

  • CLI_CONTRACT.md vendor_revert_kept row updated.

Tests (per issue)

Red→green: before the fix the first test failed on "reason":"lockfile wiring drifted; vendored state and manifest entry kept" and the normalize error. Both pass now.

Commands run

  • cargo test -p socket-patch-core --lib vendor::: 2498 passed
  • cargo test -p socket-patch-cli --all-features --test cli_remove_silent --test remove --test rollback --test covgap_commands_rollback --test covgap_commands_vendor --test in_process_rollback_vendored --test mode_migration_pypi --test scan_vendor_e2e --test in_process_vendor_pypi_takeover --test e2e_vendor_pypi_build --test vendor --test in_process_vendor --test coverage_fix_scan_hosted_dryrun_vendored: all pass
  • cargo clippy --workspace --all-features -- -D warnings and cargo fmt --all -- --check: clean

Coordination: #1188 rewrites Pipfile.lock writing, and this PR doesn't touch the Pipfile.lock writers. mode_migration_pypi.rs also gets a test from the #477 PR, which appends at the end of the file, so the two may need a trivial rebase.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When a vendored PyPI revert restored its recorded wiring but kept the
wheel because another project file (a `pipenv requirements` export)
still installs from it, `remove` and `rollback` reported the keep as
"lockfile wiring drifted" and told the user to re-run `scan --mode
vendored` to normalize, then remove. That remedy loops: the re-vendor
re-wires Pipfile.lock and the next remove keeps the entry again.

The keep now carries its cause. `vendor_artifact_kept`, the remove
warning, skip reason and top-level error, rollback's vendoredKept
reason and `vendor --revert` / reconcile skips say a project file
still installs from the artifact, and the remedy is to point that file
back at the registry release (or re-export it from the restored lock)
and run the unwind again. A hosted takeover refused for the same
reason names the file instead of a wiring edit. Drift keeps keep their
existing wording.

Fixes #1184

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 9, 2026 18:31
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review

@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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 060e1c2. Configure here.

Comment thread crates/socket-patch-cli/src/commands/scan/hosted/takeover.rs
mode_migration_pypi.rs: both sides appended tests at the end of the
file; keep main's (#479 Hatch pylock, #604 PEP 440 pins, #1138 uv
workspace member) and append this branch's two #1184 tests after them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The refusal leaves the lock vendored, so re-exporting the requirements
file from it would name the wheel again and the next hosted scan would
refuse again. Tell the user to pin the file to <name>==<version> by
hand, re-run the hosted scan, and only then re-export; the takeover
test now follows that remedy through to a completed takeover.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merged via the queue into main with commit 1ead8bb Oct 10, 2026
53 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/v5-vendor-residual-keep branch October 10, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants