GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Make the vendored-to-hosted takeover atomic by mikolalysenko · Pull Request #1039 · SocketDev/socket-patch

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 7, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

Problem

Architecture audit B03: scan/get --mode hosted over a vendored package (the vendored→hosted takeover) reverted the vendored wiring on disk first and only then planned the hosted pin. When the hosted rewriter refused (a lock-level refusal, a missing berry checksum, unavailable wheel metadata, a Poetry 0.x lock, a uv pin-down, ...), the package was left unpatched in both modes. Hand-copied pre-gates for bun, berry, classic, vlt, Gradle, pypi platform wheels and requirements tried to predict those refusals, and they drifted from the rewriters they copied (the root cause behind #945, #723 and the closed #699). The hosted→vendored direction is already atomic (#963).

  • B14: hosted writes were non-transactional. Files were written one by one, and an error exit after the takeover still said "nothing was written".
  • B37 (takeover part): the dry run counted every takeover as redirected without running the rewriter.
  • B15 (takeover list): the disk flow took over cargo/npm/golang/pypi/Gradle maven, but the in-memory engine refused only cargo/npm/golang.

Change

The takeover now runs inside the run's GroupCommit (commands/scan/hosted/takeover.rs):

  1. Each vendored revert is staged in the overlay under a savepoint. A revert that fails or keeps drifted wiring is rolled back and refused, as before.
  2. The hosted rewrite reads the overlay, so it plans against the reverted project.
  3. A staged purl the rewrite does not pin is retracted. The overlay goes back to its pre-revert state, the purl stays vendored byte for byte, the rest are staged again and the rewrite runs again. Each pass drops at least one purl, so the loop ends. The retracted purl is skipped with its cause (an existing skip reason, the rewriter warning that names it, redirect_requirements_takeover_unreachable, the rewriter's lock-level refusal, or redirect_takeover_not_pinned), followed by the new redirect_takeover_kept_vendored warning. Exit 0.
  4. The hosted pins and the vendored ledger go into the same overlay and are committed once (journaled). Reverted artifacts are deleted only after the commit (GroupCommit::defer_removals; the per-unit revert removal goes through remove_tree_and_prune, bun workspace tarballs through remove_mirror, and the JVM revert's Gradle/Maven tree files through group_commit::defer_removal). The JVM-owned .gitattributes files and the derived maven-metadata.xml files are now in the captured set, so the Gradle revert's writes stay in the overlay too.
  5. --dry-run runs the same steps and drops the overlay instead of committing, so it reports the wet outcome (B37).
  6. A hosted run with no takeover also stages its writes, but commits them unjournaled (commit_unjournaled) because hosted mode writes nothing under .socket/vendor/. If one replacement fails, the files already replaced are put back (B14). The few files the group does not capture (the Gradle hosted index and script under .socket/gradle/) are written just before the commit and put back if a later step or the commit fails.
  7. B15: hosted::takeover::in_reach is the one predicate both engines use.

Duplicate copies deleted

  • Takeover pre-gates that copied rewriter logic: 9 → 0 (bun text/binary, berry lock, berry dep, classic, vlt, Gradle takeover_refusal, pypi platform wheel, requirements reach). preflight_requirements_takeover only explains a retraction now. Review found the Gradle gate was not yet safe to remove, because the JVM revert deleted the vendored tree straight from disk. That is fixed in this PR (see below), so the count stands. preflight_yarn_classic_hosted is now private. After merging main's Fix yarn berry project gates drifting between modes (#628, #629) #657, which moved the berry project gates into the shared formats/yarn/berry_gates, the takeover again checks yarn-berry entries against those gates on the pre-revert project. It calls the rewriter's own preflight_yarn_berry_hosted once per staging pass, so no logic is copied. This is needed because the berry revert re-renders package.json in its majority line ending, so after the revert the rewriter could no longer see the mixed manifest that Hosted yarn berry rewrites a mixed-line-ending package.json that vendored mode refuses #628 refuses. Copied pre-gates: 9 → 0. Shared-gate call sites: 1.
  • Takeover-capable lists: 2 → 1 (stages.rs closure + hosted.rs closure → hosted::takeover).
  • Dry-run takeover preview path: the engine's TakeoverPreview install-policy preview and the CLI's withheld-and-counted preview are deleted. The dry run is the real rewrite now.
  • Stranded-takeover reporting (redirect_takeover_unpatched, partial_failure, unrecorded) is deleted, because a takeover can no longer strand.
  • The cargo/golang revert removal copies (remove_tree + prune_empty_vendor_levels) now use the shared remove_tree_and_prune.

Behavior changes (documented in CLI_CONTRACT.md)

  • A takeover the rewriter would not pin keeps the package vendored with exit 0. Before, it was stranded with exit 1.
  • A failed write or commit changes nothing and exits 1 with "nothing was changed". Before, the takeover and earlier locks were already on disk.
  • A dry run over a vendored pnpm project now previews trustLockfile as written to a new pnpm-workspace.yaml, which is what the wet run does: the revert removes the vendor-created file. The old preview said "merged into the existing" one.
  • With a yarn-offline-mirror, the yarn classic hosted rewriter no longer also warns redirect_yarn_classic_berry_migration_risk, because the mirror refused every pin and nothing was pinned. That warning came from Fix hosted yarn classic pins missing berry warning (#907) #917 on main. Without this fix, a retracted classic takeover reported the berry warning as its cause instead of redirect_yarn_classic_offline_mirror.
  • A vlt takeover over a BOM'd lock is refused by the staged revert itself (vendored_revert_failed) instead of the deleted vlt pre-gate. The state stays the same.

Testing

All commands were run in the worktree with CARGO_INCREMENTAL=0 through the shared limiter, -j4, on the branch after merging origin/main (431b818, head 830726e):

  • cargo test -p socket-patch-core --lib: 5608 passed, plus the new mirror test.

  • cargo test -p socket-patch-cli --lib: 869 passed.

  • cargo test --no-fail-fast -p socket-patch-cli with --test set to each of: coverage_fix_scan_hosted_dryrun_vendored, e2e_golang_hosted_state, covgap_commands_scan_hosted, in_process_redirect, hosted_memory_engine, mode_migration_pypi, in_process_vendor, in_process_vendor_bun_takeover, in_process_vendor_npm_v1_takeover, in_process_vendor_pnpm_takeover, in_process_vendor_pypi_takeover, vendor_eject, vendor_jvm_cli, contract_gradle_codes, gradle_agent_cli, e2e_sbt_vendor, e2e_scala_cli_vendor, covgap_commands_vendor, covgap_commands_vex, e2e_vex_redirect, e2e_redirect_gradle_build, e2e_vendor_gradle_build. All passed. The real-Gradle tests are #[ignore]d.

  • After the second merge and the berry gate: --lib, in_process_vendor (121, including Fix yarn berry project gates drifting between modes (#628, #629) #657's berry_takeovers_refuse_before_reverting_the_old_mode), mode_migration_npm (19, real yarn), mode_migration_pypi, mode_migration_cargo, mode_migration_bun, mode_migration_vlt, in_process_alternate_installers, remove, repair, e2e_redirect_gem_stale_install and the takeover files above all passed.

  • mode_migration_cargo::vendored_then_hosted_takeover_leaves_pure_hosted (real cargo) and mode_migration_npm::{berry,classic}_vendored_then_hosted_takeover_leaves_pure_hosted (real yarn): passed.

  • cargo clippy -p socket-patch-core -p socket-patch-cli --all-targets -- -D warnings: no findings in code this PR changed, but it fails on 20 pre-existing lints in files this PR does not touch, or in lines it did not write (checked with git blame against the merge-base):

    • python_crawler.rs:2760 unused unix_default, and :5375
    • patch/apply.rs:3736
    • jvm_jar.rs (8 × from_ref)
    • redirect/mod.rs:10292 (test)
    • upstream/uv.rs:2097
    • bun_binary.rs:1051
    • maven_repo.rs:2503
    • nuget_feed.rs:2005
    • pnpm_lock.rs:3877
    • yarn_berry_lock.rs:1483
    • yarn_layering_tests.rs:1023,1028
    • The CLI test helpers prebuilt_common/common (module loaded twice, needless borrows).

    With -A unused_variables so the core library compiles, the CLI src/ has no findings.

  • Not run locally: the real-Gradle leg e2e_redirect_gradle_build -- --ignored gradle_hosted_ (including gradle_hosted_takeover_refusal_keeps_vendored). This machine has no JDK, so it is left to the Gradle CI leg. The same staged revert is covered in-process by the new core test below.

New or flipped regression tests (each fails without its fix):

  • vendor::jvm::gradle::tests::a_staged_revert_changes_nothing_until_its_group_commits covers the review blocker. It vendors a Gradle patch, with and without a sibling version that shares maven-metadata.xml, then stages the real revert in a defer_removals group. Dropping the group (the dry run) or rolling it back (the retracted takeover) leaves the full tree byte-identical, and committing lands exactly the plain revert. Before the fix, the drop case deleted the jar, pom, marker, metadata and both .gitattributes.
  • Full-tree snapshots (.socket/ and the vendored artifacts included) now wrap the dry-run takeover in coverage_fix_scan_hosted_dryrun_vendored (pnpm, package-lock, vlt), e2e_golang_hosted_state::hosted_takeover_of_vendored_module_removes_vendored_state (golang, via get --dry-run) and mode_migration_cargo::vendored_then_hosted_takeover_leaves_pure_hosted (cargo). Bun (mode_migration_bun, assert_unchanged) and uv (uv_takeover_without_wheel_metadata_keeps_the_package_vendored, which includes the wheel) already compare the whole state.
  • patch::redirect::tests::yarn_classic_offline_mirror_refusal_skips_the_berry_risk_warning. It fixes in_process_vendor::classic_vendored_to_hosted_takeover_refuses_with_offline_mirror, which failed after merging main's Fix hosted yarn classic pins missing berry warning (#907) #917.
  • From the first round: mode_migration_pypi::uv_takeover_without_wheel_metadata_keeps_the_package_vendored, a_crash_inside_the_takeover_commit_is_finished_by_the_next_run, ledger_update_failure_changes_nothing, covgap_commands_scan_hosted::ledger_save_failure_after_successful_revert_fails_closed, in_process_redirect::partial_lockfile_write_failure_exits_1_and_writes_no_ledger, hosted_memory_engine::vendored_pypi_takeover_is_refused_like_the_disk_flow, group_commit::tests::deferred_unit_removals_wait_for_the_commit.

mode_migration_npm::berry_vendored_then_hosted_takeover_leaves_pure_hosted now expects a hosted resolutions entry in package.json instead of a pristine one. I checked it on origin/main (431b818, real yarn) in a detached worktree, and it already fails there at mode_migration_npm.rs:1223 ("the berry resolutions entry must be reverted"). Since #465, main's hosted berry pin writes resolutions into package.json. So the old assertion was stale, and this PR does not change that behavior.

Deferred

  • B30 (hosted meeting vendored: one pre-rewrite decision for Composer in-place rewrite and the NuGet key collision, mod.rs:5525,5552 vs nuget_feed.rs:219) is not in this PR. Composer/NuGet are not takeover ecosystems, and that decision needs C34.
  • Poetry 0.x vendored → hosted takeover un-vendors the package before hosted mode refuses the lock, while --dry-run previews a clean takeover (redirected: 1, exit 0) #945 / uv vendored → hosted takeover strands a package that vendored mode pinned to a different version than uv.lock: the wet run reverts to the unpatched release (exit 1), while --dry-run previews a clean takeover #723 (uv pin-down, Poetry 0.x) should now be retracted generically instead of stranded, but this PR has no fixtures for them. They are not claimed, are not in the agent-status block, and are left to Fix PyPI hosted takeover un-vendoring before refusal (#723, #945) #946.
  • The per-ecosystem dry-run snapshot covers pnpm, package-lock, vlt, bun, uv, golang and cargo through the CLI, and Gradle only in-process. yarn classic/berry and the other pypi flavors are still checked on the lock and ledger only. Audit of the in-reach reverts: every artifact deletion in npm-family, pypi, cargo, golang and bun goes through remove_tree_and_prune or remove_mirror (both deferring). JVM was the only backend deleting uncaptured .socket/ files directly.
  • Residuals:
    • A crash inside the journaled commit leaves the reverted artifact as an orphan. The next run finishes the commit but does not delete the artifact; vendor --revert's sweep does.
    • The Gradle hosted index and script (.socket/gradle/hosted-index.tsv, socket-patch.hosted.settings.gradle) stay outside the captured set. They are written just before the commit and put back on failure, but a crash in that window leaves them on disk; the captured settings line is what makes them live.
    • The rollout budget can count a takeover that is later retracted.
  • Exit policy (Decide: one shape for the --json top-level error (scan and get emit both a string and a {code, message} object) #704) is unchanged: a failed commit keeps the existing hosted error envelope.

🤖 Generated with Claude Code


Note

Medium Risk
Changes core hosted-mode lockfile and vendor-ledger mutation paths and exit/status contracts; behavior is safer when redirects fail but regressions could affect multi-package takeovers or crash recovery.

Overview
Vendored → hosted takeover is now staged and committed atomically instead of reverting vendored wiring on disk before planning hosted pins. Hosted scan/get open a GroupCommit, run takeover logic in new hosted/takeover.rs, stage each revert under savepoints, plan the hosted rewrite against the overlay, and retract any package the rewriter would not pin (overlay rolled back; package stays vendored with redirect_takeover_kept_vendored, exit 0). Successful runs commit vendored reverts, lockfile redirects, and ledger updates in one step; artifact deletes are deferred until after commit.

Hosted writes are transactional: takeover runs use a journaled commit; hosted-only runs use commit_unjournaled with rollback on partial failure. --dry-run runs the same pipeline and drops the overlay, so previews match wet runs without touching disk.

Removed the stranded-takeover path (redirect_takeover_unpatched, partial_failure exit 1) and ecosystem-specific takeover pre-gates copied from rewriters; hosted::takeover::in_reach is shared with the in-memory engine. CLI_CONTRACT.md documents staged takeover, new skip/warning codes, and updated failure semantics (e.g. ledger save failure leaves the project unchanged).

Tests add full-tree dry-run snapshots and flip expectations for ledger/commit failures and partial lock writes.

Reviewed by Cursor Bugbot for commit 406e111. Configure here.


Generated by Claude Code

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Mikola Lysenko (mikolalysenko) and others added 3 commits October 7, 2026 11:01
@mikolalysenko @claude
Let a group commit hold vendored artifact deletions until it lands
1ce0099
A group commit can now defer the vendored artifact deletions a revert
makes (GroupCommit::defer_removals): every per-unit revert removal goes
through remove_tree_and_prune (cargo and golang now too, instead of their
own remove_tree + prune copies) and the bun workspace tarball removal
through remove_mirror, and both queue the deletion for after the commit
when the open group asks for it. A rollback_to forgets the queued
deletions and a dropped group never makes them, so a staged revert can be
undone with its artifact intact.

Also:
- commit_unjournaled: the all-or-nothing replace without the crash
  journal, for runs that must write nothing under .socket/;
- a journal that had to create .socket/vendor/ prunes it again;
- group_commit::exists is public, for overlay-aware existence checks.

Audit B03/B14 groundwork.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Share one takeover-reach predicate between the hosted engines
2593960
The disk flow took over cargo, npm, golang, pypi and Gradle maven
entries, while the in-memory engine refused only cargo, npm and golang,
so a vendored PyPI package reached the Python rewriters in memory. Both
now use hosted::takeover::in_reach (audit B15).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Make the vendored-to-hosted takeover staged and atomic
bfb893d
scan/get --mode hosted reverted a vendored package's wiring on disk
first and planned the hosted pin afterwards. When the rewriter then
refused (a lock-level refusal, a missing berry checksum, unavailable
wheel metadata, a Poetry 0.x lock, ...), the package was left unpatched
in both modes, and only six hand-copied per-ecosystem pre-gates tried to
predict those refusals. The dry run counted every takeover as redirected.

The takeover now runs inside the run's group commit:
- each vendored revert is staged in the overlay under a savepoint (a
  failing or drift-keeping revert is rolled back and refused);
- the hosted rewrite reads the overlay, so it plans against the
  reverted project;
- a staged purl the rewrite does not pin is retracted: the overlay goes
  back to its pre-revert state, the purl stays vendored byte for byte
  (redirect_takeover_kept_vendored, skipped with the cause), and the
  rest are staged and rewritten again;
- the hosted pins and the vendored ledger are written into the same
  overlay and committed once (journaled); artifacts go after the commit.
A dry run does the same and drops the overlay, so it reports the wet
outcome. A hosted run without a takeover commits its files unjournaled,
putting back the ones replaced if one fails.

Deleted: the bun, berry (lock and dep), classic, vlt, Gradle, pypi
platform-wheel and requirements pre-gates (9 copies of rewriter logic ->
0; the requirements reach check only explains a retraction now), the
dry-run TakeoverPreview path in the engine, and the stranded-takeover
reporting (redirect_takeover_unpatched), which can no longer happen.

Audit B03, B14, B37 (takeover part).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko Mikola Lysenko (mikolalysenko) added the arch-refactor PR opened by the scheduled architecture refactor routine label Oct 7, 2026
Mikola Lysenko (mikolalysenko) and others added 6 commits October 7, 2026 12:13
@mikolalysenko @claude
Keep a staged Gradle takeover from deleting the vendored tree
5b96496
The staged vendored-to-hosted takeover runs the real revert inside a
group commit and relies on the overlay plus deferred removals to undo
it. The JVM revert deleted the tree files under .socket/vendor/gradle
and .socket/vendor/maven2 directly, and wrote or deleted the owned
.socket/gradle/.gitattributes, .socket/vendor/.gitattributes and the
derived maven-metadata.xml files straight to disk. A dry run, or a
takeover the hosted Gradle planner refused and retracted, therefore
deleted the vendored jars while the restored wiring still named them.

Capture the owned .gitattributes files and the derived metadata in the
group overlay, and route the tree-file deletions through
group_commit::defer_removal so they happen only after the commit. A
new test stages the revert (with and without a sibling version sharing
the metadata) and checks that dropping or rolling back the group leaves
the project byte-identical and that committing lands the plain revert.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Put back direct hosted writes when the hosted commit fails
d4edf4d
commit_hosted_writes writes the files the group does not capture (the
Gradle hosted index and script under .socket/gradle/) straight to disk
before the commit. When writing a later file, saving the vendored
ledger or the commit itself failed, the error said nothing was changed
while those files stayed on disk. Record their previous bytes and put
them back on every failure path except an interrupted journaled
commit, which the next locked command finishes.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Check that dry-run takeovers leave the whole tree byte-identical
2ed2870
Snapshot every project file, .socket/ and the vendored artifacts
included, around the dry-run vendored-to-hosted takeover for pnpm,
package-lock, vlt, golang and cargo (bun and the uv retract test
already compare the artifact). Rewrite the stale CLI_CONTRACT Gradle
paragraph that still described the deleted takeover_refusal pre-gate,
and the real-Gradle refusal test's doc comment.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Make the yarn hosted preflights private to the redirect module
6da1ec4
The takeover pre-gates that called preflight_yarn_classic_hosted and
preflight_yarn_berry_hosted from outside are gone. The classic one is
now private and the berry one pub(crate) (upstream/npm.rs still uses
it).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Merge origin/main into arch-fix/takeover-atomic
8601853
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Skip the yarn berry risk warning when an offline mirror refused the pins
bde572b
With a yarn-offline-mirror configured the classic hosted rewriter
refuses every entry, so nothing is pinned, yet it still warned that a
berry install would drop the hosted pins (#907's warning counted the
refused entries as pinned). The staged takeover reports a retracted
purl's first rewrite warning as its cause, so a vendored classic
project with a mirror was skipped as redirect_yarn_classic_berry_
migration_risk and the real refusal, redirect_yarn_classic_offline_
mirror, was never reported (in_process_vendor's
classic_vendored_to_hosted_takeover_refuses_with_offline_mirror failed
once main's #917 landed beside the staged takeover).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 7, 2026
Decide whether a hosted patch is pinned through lockfile discovery alone #1058
Merged
Mikola Lysenko (mikolalysenko) and others added 2 commits October 7, 2026 13:04
@mikolalysenko @claude
Merge origin/main into arch-fix/takeover-atomic
6803a10
Resolves the conflicts with #657: the berry takeover pre-gate it
extended stays deleted in hosted.rs, preflight_yarn_berry_hosted takes
main's manifest argument, preflight_yarn_berry_hosted_dep stays
deleted (its only caller was the deleted pre-gate), and the contract
keeps main's root package.json line-ending sentence.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Keep a yarn berry takeover vendored when the project gates refuse it
830726e
#657 (merged on main) made the hosted and vendored modes refuse a mixed
root package.json, and gated the vendored-to-hosted takeover before its
revert. The staged takeover dropped that pre-gate and let the hosted
rewriter judge the reverted project, but the berry revert re-renders
package.json in its majority line ending, so a mixed manifest passed
the rewriter's check after the revert and the takeover went ahead
(in_process_vendor berry_takeovers_refuse_before_reverting_the_old_mode
failed after the merge).

Judge the berry project gates once per staging pass, on the pre-revert
overlay, through the rewriter's own preflight_yarn_berry_hosted (the
shared berry_gates set, no copied logic). A refused yarn-berry entry is
skipped with the gate's code, followed by redirect_takeover_kept_vendored.
preflight_yarn_berry_hosted is public again for this caller.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 7, 2026 17:07
Tanmay182003
Tanmay Singla (Tanmay182003) approved these changes Oct 7, 2026
View reviewed changes
@claude
Merge remote-tracking branch 'origin/main' into arch-fix/takeover-atomic
172bc83
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cursor[bot]
cursor Bot reviewed Oct 7, 2026
View reviewed changes

@cursor cursor Bot left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for 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.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread crates/socket-patch-cli/src/commands/scan/hosted/takeover.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread crates/socket-patch-cli/src/commands/scan/hosted/takeover.rs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@claude
Keep landed-pin advisories and scope suffixes out of takeover skip re…
406e111
…asons

When a staged takeover is retracted and no rewriter warning names the
package, explain() fell back to the rewrite's first warning as the
lock-level cause. That warning can be a success advisory from a pin that
did land (redirect_npm_allow_remote, redirect_pnpm_trust_lockfile,
redirect_yarn_classic_berry_migration_risk), so the skipped purl and
redirect_takeover_kept_vendored reported the wrong code. Skip those
advisories when picking the fallback; with nothing else left the reason
is NOT_PINNED.

names_package accepted `/` as a left boundary unconditionally, so an
unscoped name like `node` matched inside `@types/node` and a retracted
takeover could inherit another package's warning. A `/` now counts as a
boundary only after a path segment, not after an `@scope`.

Co-Authored-By: Claude <[email protected]>
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

cursor[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cursor[bot]
cursor Bot reviewed Oct 7, 2026
View reviewed changes

@cursor cursor Bot left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

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 406e111. Configure here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@mikolalysenko @claude
Merge origin/main into arch-fix/takeover-atomic
c166766
Resolve conflicts with main's #946 (PyPI takeover pre-gate), #1042
(containment helper) and #1077 (classic berry-migration warning):

- hosted.rs: keep this PR's staged takeover; main's new
  `preflight_pypi_takeover` pre-gate inside the deleted
  `vendored_takeover` is dropped. The staged takeover's `explain` now
  calls `preflight_pypi_takeover` (instead of only the requirements
  check), so a retracted uv pin-down (#723) or Poetry 0.x (#945)
  takeover is still skipped with `redirect_uv_takeover_version_unreachable`
  / `redirect_poetry_lock_unsupported`, as main's tests expect.
- socket_dir.rs: use main's `containment::ensure_unlinked` guard, then
  this PR's deferred removal.
- redirect/mod.rs: take main's `pinned_any` (a mirror-refused entry
  counts only when it already carries our hosted pin), which subsumes
  this PR's mirror fix.
- CLI_CONTRACT.md: describe the uv/Poetry cases as retractions.
- mode_migration_pypi.rs: keep both sides' tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) closed this Oct 8, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a manual request Oct 8, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) reopened this Oct 8, 2026
@mikolalysenko
Mikola Lysenko (mikolalysenko) enabled auto-merge October 8, 2026 03:16
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 8, 2026
@mikolalysenko @claude
Merge origin/main into arch-fix/takeover-atomic
34b12c1
Resolve CLI_CONTRACT.md: keep this PR's staged-takeover wording and add
#1060's redirect_gem_version_not_locked code.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Merge origin/main into arch-fix/takeover-atomic
47deaea
Adopt #1032's jvm::layout module: group_commit captures through
layout::CAPTURED_FILES (now also listing the Gradle script and vendor
.gitattributes this PR captures) plus the derived maven-metadata paths;
drop this PR's duplicate VENDOR_TREES for layout::VENDOR_TREES; the
takeover reach check uses layout::LEDGER_ECOSYSTEM.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit 823810a Oct 8, 2026
558 of 561 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the arch-fix/takeover-atomic branch October 8, 2026 14:55
This was referenced Oct 8, 2026
Delete the vendored and hosted-vlt helpers left without a production caller by the v5 consolidation #782
Open
Delete the dead hosted-vlt redirect-ledger helpers (#782) #1141
Merged
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 8, 2026
@mikolalysenko @claude
Merge main into arch-fix/ui-text-cycles
36f5021
scan/hosted.rs: add main's takeover module (#1039) and keep this branch's
vlt_heal alias in place of scan/hosted/vlt.rs.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
Vendored mode in a Pipenv project wires only Pipfile.lock and silently leaves a sibling requirements.txt unpatched, and the hosted → vendored takeover reverts that file's hosted pin to plain PyPI #612
Closed
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge origin/main into arch-refactor/966-remove-legacy-spellings
ac6d56a
Resolve two CLI_CONTRACT.md conflicts by keeping main's new text (the
atomic vendored-to-hosted takeover wording from #1039 and the
gem_lock_unsupported warning from #768) while re-applying this PR's
migration away from the removed spellings: `scan --apply` becomes
`scan --mode agent`, and `--apply`/`--vendor` in the lockfile
supplement become agent mode / vendored mode.

Co-Authored-By: Claude <[email protected]>
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge origin/main into arch-fix/pinned-check
b31b5bf
Main's #1039 made the vendored-to-hosted takeover staged in the run's
group commit (reverts live in an overlay until one commit, an unpinned
takeover is retracted and stays vendored, dry runs stage too). The PR's
attribution gate is re-applied on that structure:

- RewriteOptions::takeover_uuids is the staged takeovers' uuids
  (Takeover::staged_uuids), in wet and dry runs alike: the rewriters'
  verdict decides them and main's retract loop handles an unpinned one.
- Scan's prior discovery is reused only when no takeover is staged: its
  re-stat sees the disk, not the overlay holding the reverts.
- done.unattributed joins `skipped` after the retract loop, from the
  final rewrite.
- The writes go through main's commit_hosted_writes; the paths created
  for discovery_after_writes are taken before the commit (written paths
  not yet a regular file on disk, plus takeover files the overlay
  creates or removes), and a takeover's reverts count as writes when
  choosing the post-write discovery.
- engine::rewrite drops the TakeoverPreview argument main deleted;
  docs and CLI_CONTRACT describe the staged takeover.

Co-Authored-By: Claude <[email protected]>
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
Evict failing merge-queue entries ~35 min sooner #1146
Merged
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge origin/main into agent/fix-npm-open-issues
9b29774
Picks up the atomic vendored-to-hosted takeover (#1039); merges cleanly
on top of the earlier main merge.

Co-Authored-By: Claude <[email protected]>
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge main into agent/fix-bun-open-issues
aa03736
main's #1039 (atomic vendored-to-hosted takeover) dropped the
takeover_previews parameter from hosted::engine::rewrite. The merge
itself is clean, but this branch's bun.lockb rewrite test still passed
`&[]` for it, so the merge queue failed to compile socket-patch-core's
tests. Drop the stale argument.

Assisted-by: Claude Code:claude-opus-5-5

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TSx4W4Qfb8hsBhw4NEvkv9
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge origin/main into agent/fix-pnpm-open-issues
894fd33
Main's #1039 made the vendored-to-hosted takeover atomic: it moved the
takeover into scan/hosted/takeover.rs and dropped dry-run takeover
previews. Take main's hosted.rs; the branch's pnpm gitBranchLockfile
takeover gate is now covered by the staged takeover's retract path,
since the hosted rewrite emits redirect_pnpm_git_branch_lockfile and
leaves the purl vendored. Keep the branch's per-member and Rush lock
arguments to pnpm_trust and its governing-lock gate, minus the
takeover_previews plumbing main removed.

Co-Authored-By: Claude <[email protected]>
This was referenced Oct 8, 2026
Lower merge-queue check timeout from 360 to 120 min #1149
Closed
Vendored pnpm 12 with packageManager set: the two-document pnpm-lock.yaml makes vendor refuse, and vendor --revert, rollback and the hosted takeover half-revert the project and break frozen installs #466
Closed
A vendored-to-hosted takeover interrupted after its commit journal is written leaves the vendored artifact directory behind for good: recovery finishes the files but not the deferred deletions, and no GC can reclaim it once the ledger is gone #1157
Closed
Vendored→hosted takeover on yarn classic un-patches a vendored npm: alias copy when a direct copy is pinned, instead of retracting the takeover #1158
Closed
Vendored yarn classic rollback can't undo a block yarn has merged with another range (left-pad@^1.1.0, left-pad@^1.3.0:): it reports the block as gone, exits 1 forever and leaves the lock wired #692
Closed
Decide: keep the in-memory hosted engine and napi addon as a supported product, or delete them #1200
Open
Hosted yarn classic offline-mirror refusal misses a mirror set in a workspace member's .yarnrc, so installs run from that member fail the integrity check while the scan reports success and VEX attests #1115
Closed
Upstream restore sends every public-registry lookup at once; the registry_concurrency cap has no caller #1220
Closed
CI performance dashboard #1182
Open
After a vendored-to-hosted takeover is interrupted once its commit journal is written, the next rollback replays the journal, then exits 0 having restored nothing, and the project stays hosted-patched (remove says "No patch found") #1241
Closed
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 9, 2026
@mikolalysenko @claude
Test cargo takeover over unrewritable deps
e18a8af
A vendored cargo crate whose Cargo.toml spelling the hosted rewriter
refuses (dotted keys, a single-quoted literal, registry = "crates-io")
must stay vendored when scan --mode hosted runs over it, and the dry
run must preview that refusal instead of a takeover. The atomic
takeover from #1039 already does this; pin it with a real-cargo e2e so
the crate can never again land in neither mode (#1020).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This was referenced Oct 9, 2026
Test cargo takeover over unrewritable deps (#1020) #1314
Merged
Cargo vendored → hosted takeover un-vendors a crate before hosted mode refuses its Cargo.toml spelling (dotted keys, single quotes, registry = "crates-io"), leaving it unpatched, while --dry-run previews redirected: 1 #1020
Closed
A bare scan or get on a project holding both vendored packages and hosted pins silently converts every hosted pin to vendored (exit 0, no warning), so it undoes a partial hosted takeover #1437
Closed
Fix bare scan/get converting hosted pins (#1437) #1440
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@cursor cursor[bot] cursor[bot] left review comments
@Tanmay182003 Tanmay Singla (Tanmay182003) Tanmay182003 approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

arch-refactor PR opened by the scheduled architecture refactor routine

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Vendored → hosted takeover strands a requirements.txt pin that lives in a -r include or a vendored "(transitive)" line: the wet run reverts it to the unpatched release, while --dry-run previews a clean takeover

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@mikolalysenko @Tanmay182003 @claude
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.