Skip to content

Fix hosted uv unwind deleting user override pins (#411) - #1331

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/v5-uv-override-ownership
Oct 9, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/v5-uv-override-ownership

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 #411

Summary

A hosted rollback / remove (and the hosted → vendored takeover, which runs the same upstream restore) of a uv project deleted the user's own [tool.uv] override-dependencies = ["six==1.16.0"] pin, the lock's [manifest] overrides record of it and the emptied [tool.uv] table, then warned upstream_uv_override_removed as if hosted mode had added it. The next uv lock --upgrade moved six past the release the user had pinned.

Root cause

v5 hosted mode keeps no ledger, so pushed_override in patch/redirect/upstream/uv.rs decided ownership by spelling alone: any <name>==<version> override of a transitive dependency counted as the one the rewrite adds. The hosted rewrite (utils/python_script.rs rewrite_sources) reuses a user's identical override rather than adding one, so after the scan the two cases were byte-identical.

Fix

  • The hosted rewrite now writes the override entry it adds on its own line under a comment, # socket-patch hosted: pins a patched transitive dependency; rollback removes it (HOSTED_OVERRIDE_MARK). That comment is the ownership evidence. A new array is laid out multi-line. When the array already exists, only the new element is added, and removing it brings back the original bytes. Only the hosted (ArtifactSource::Url) lane is marked. Vendored script wiring is unchanged, because its ledger records the originals.
  • pushed_override matches only a marked entry. A user's unmarked pin is kept, restore_metadata reports no removal (so no upstream_uv_override_removed), and the lock's [manifest] overrides entry gets its specifier back from the declaration instead of being dropped.
  • CLI_CONTRACT.md (hosted unwind coverage, warning table) and docs/testing/uv-compatibility.md describe the marker.

Note: v5 is unreleased, so no released build wrote unmarked hosted overrides. Under this rule, an unmarked entry left by a pre-release main build is kept (fail-safe). The lock and pyproject stay consistent.

Tests (red → green)

Issue Test Before fix After
#411 pyproject + PEP 723 script upstream::uv::tests::restore_keeps_a_user_authored_override_of_the_patched_release (hosted rewrite → restore round-trips a user override byte-for-byte, in three array spellings and a script) FAILED ok
#411 uv.lock [manifest] overrides upstream::uv::declaration_tests::manifest_override_of_a_user_pin_is_restored_not_dropped FAILED ok
guard: hosted-added override still removed upstream::uv::tests::restore_removes_the_override_the_rewrite_added (new array, existing single-line and multi-line user arrays, script) – ok

Red was verified by reverting only the ownership check in pushed_override. Updated: four python_script rendering tests that pin the hosted output, and the python_lock_rewrite golden (re-blessed; only output digests of cases that add an override changed).

Commands run

  • cargo test -p socket-patch-core --lib: 6112 passed
  • SOCKET_PATCH_UV_E2E_REQUIRED=1 cargo test -p socket-patch-cli --test e2e_redirect_uv_build -- --ignored hosted_uv_transitive_override_manifestless_vex hosted_uv_script_lock_manifestless_vex (real uv 0.11.19): both ok. The fresh install is patched, a plain uv sync keeps the lock, and the transitive revert restores the upstream registry entry.
  • cargo fmt --all -- --check (my files clean; upstream/mod.rs diff is pre-existing on main) and cargo clippy --workspace --all-features -- -D warnings: clean

🤖 Generated with Claude Code

Empty commit to open the draft PR.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A hosted rollback, remove or vendored takeover of a uv project deleted
the user's own `[tool.uv] override-dependencies = ["six==1.16.0"]`
pin (plus the lock's `[manifest] overrides` record and the emptied
`[tool.uv]` table) and blamed hosted mode for adding it. The next
`uv lock --upgrade` then moved six past the release the user had held
back.

Hosted mode keeps no ledger, so the restore guessed ownership from the
entry's spelling. The hosted rewrite now puts a `# socket-patch
hosted: ...` comment line above each override entry it adds, and the
restore removes only a marked entry. A user's own pin of the same
release (which the rewrite reuses instead of adding a second one) is
kept, and its lock record gets its specifier back. Vendored mode is
unchanged: its ledger records the originals.

Fixes #411

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 17:25
@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.

✅ 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 6eefaf2. Configure here.

@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 9, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 9, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Ready for review at 084a093e1c1b.

  • CI: required checks ci-ok and clippy green; 6 check suites succeeded. 1 superseded workflow run(s) show as cancelled; the required gates passed on this head.
  • Mergeable against main, no CHANGELOG.md change.
  • Bugbot reviewed this head; no unresolved review threads.

Labeled Ready for review by the burn-down agent. Slack announcement pending (connector unavailable this run).


Generated by Claude Code

@mikolalysenko
Mikola Lysenko (mikolalysenko) removed this pull request from the merge queue due to a manual request Oct 9, 2026
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit c7f2f4e Oct 9, 2026
5 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/v5-uv-override-ownership branch October 9, 2026 21:56
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 10, 2026
Resolve python_script.rs by keeping both sides: the PR's
refuse_direct_reference (PEP 508 direct-ref refusal, #767) and main's
hosted override-dependencies marking (HOSTED_OVERRIDE_MARK,
is_hosted_override, push_hosted_override, #411/#1331). The two were
independent additions at the same spot.

Re-bless tests/equivalence/python_lock_rewrite.golden with
SOCKET_PATCH_BLESS_GOLDEN=1. Per-case dumps of all 1500 seeds from
base, PR, main and merge: 1226 unchanged, 140 match main, 100 match
the PR, 28 changed by both resolve to the PR's refusals plus main's
marked override layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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

Development

Successfully merging this pull request may close these issues.

Hosted uv rollback and remove delete a user-authored override-dependencies = ["<pkg>==<ver>"] pin that hosted mode never added

2 participants