GeezerVison is showing github.com — Make the vendored-to-hosted takeover atomic by mikolalysenko · Pull Request #1039 · SocketDev/socket-patch
Conversation
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):
- 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.
- 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, 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.
- 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.
--dry-run runs the same steps and drops the overlay instead of committing, so it reports the wet outcome (B37).
- 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.
- 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.
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]>
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]>
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]>
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]>
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]>
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]>
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]>
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]>
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]>
#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]>
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
cursor
Bot
left a comment
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…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]>
cursor[bot] reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
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.
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]>
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]>
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]>
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Oct 8, 2026
Mikola Lysenko (mikolalysenko)
pushed a commit
that referenced
this pull request
Oct 8, 2026
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
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]>
Mikola Lysenko (mikolalysenko)
pushed a commit
that referenced
this pull request
Oct 8, 2026
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
Mikola Lysenko (mikolalysenko)
added a commit
that referenced
this pull request
Oct 9, 2026
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
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
Milestone
No milestone
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.
|