@@ -137,8 +137,9 @@ fn refuse(
137137}
138138
139139/// The apply lock for a WET hosted run: the same `<manifest dir>/apply.lock`
140- /// `apply`/`rollback`/`remove`/`vendor` hold, so the takeover pre-reverts,
141- /// the ledger merge and the lockfile writes never race them. `acquire`
140+ /// `apply`/`rollback`/`remove`/`vendor` hold, so the takeover pre-reverts
141+ /// (lockfiles + the vendored ledger) and the lockfile writes never race
142+ /// them. `acquire`
142143/// creates a missing `.socket/` and the guard's drop unlinks the lock file
143144/// and prunes an otherwise-empty `.socket/`, so a run that ends up writing
144145/// nothing leaves no residue. Contention / IO failures render through the
@@ -299,11 +300,10 @@ async fn installed_stale_positive_evidence(
299300/// refuses as a write root is still READ here
300301/// (`verification_only_gem_paths`): bundler installs into it.
301302/// * Records are found BY UUID (the fetch key, stable across purl
302- /// spellings): this run's fetched records first, then the redirect
303- /// ledger's persisted ones — a re-scan whose `/patches/view` fetch failed
304- /// transiently still re-fires from the ledger instead of silently
305- /// dropping the warning (`record_fetch_failed` covers the fetch failure
306- /// itself). Record availability is part of the candidate filter, and the
303+ /// spellings) among this run's fetched records; v5 keeps no hosted
304+ /// ledger to fall back on, so a uuid whose `/patches/view` fetch failed
305+ /// is not judged (`record_fetch_failed` surfaces that failure). Record
306+ /// availability is part of the candidate filter, and the
307307/// probe returns before any crawler work (or `gem env` subprocess spawn)
308308/// when no judgment is possible.
309309/// * PATCHED means [`verify_patch_record`] `Ok` — the one shared oracle
@@ -326,8 +326,7 @@ async fn gem_stale_install_warnings(
326326 global : bool ,
327327 global_prefix : Option < std:: path:: PathBuf > ,
328328 confirmed : & [ ( String , String ) ] ,
329- // This run's fetched records MERGED with the ledger's persisted ones
330- // (the caller hands the post-merge ledger map).
329+ // This run's fetched records, by uuid.
331330 records : & std:: collections:: BTreeMap < String , socket_patch_core:: manifest:: schema:: PatchRecord > ,
332331 gem_artifact_shas : & std:: collections:: BTreeMap < ( String , String ) , String > ,
333332) -> StaleInstallOutcome {
@@ -629,20 +628,20 @@ pub(super) async fn run_redirect(
629628/// ([`socket_patch_core::hosted::engine`], over a
630629/// [`ProjectView::Disk`](socket_patch_core::vendor::lock_inventory::ProjectView));
631630/// what stays here is what needs the host: reference grants and the other
632- /// network fetches, the apply lock (wet runs with a grant), the redirect
633- /// ledger load, the vendored→hosted takeover pre-revert (symlink-checked
634- /// first), the `pipenv --version` probe, the symlink guard, the ledger
635- /// merge-then-persist and the file writes, the gem / Python / vlt
631+ /// network fetches, the apply lock (wet runs with a grant), the
632+ /// vendored→hosted takeover pre-revert (symlink-checked first), the
633+ /// `pipenv --version` probe, the symlink guard, the file writes, the gem /
634+ /// Python / vlt
636635/// stale-install probes, and the optional VEX. Shared VERBATIM by `scan
637636/// --mode hosted` (its `--json` arm through the `run_redirect` wrapper, its
638637/// human arm through [`boxed_run_redirect_selected`] in `scan/mod.rs`; both
639638/// select via `discover_selected`, with no prompt) and by `get --mode
640639/// hosted` (which pins the advisory-resolved uuid), so all produce
641- /// identical on-disk results for the same selection. The redirect ledger
642- /// is loaded HERE, under the apply lock whenever this run holds one (never
643- /// handed in pre- loaded: a copy read before the lock could merge over a
644- /// concurrent writer's edits); a dry run or a zero-grant run reads it
645- /// strictly but writes nothing, quarantine included .
640+ /// identical on-disk results for the same selection. v5 hosted mode keeps
641+ /// no ledger ( the lockfiles are the only record); the VENDORED ledger the
642+ /// takeover needs is loaded HERE, under the apply lock whenever this run
643+ /// holds one (never handed in pre-loaded: a copy read before the lock could
644+ /// be saved over a concurrent writer's edits) .
646645///
647646/// `scan_result` must be `Some` exactly when `common.json` is set (the
648647/// human/JSON split keys on `common.json`; a `--json` caller passing `None`
@@ -1091,10 +1090,10 @@ pub(crate) async fn run_redirect_selected(
10911090 std:: collections:: BTreeMap :: new ( ) ;
10921091 let mut record_warnings: Vec < socket_patch_core:: patch:: redirect:: RewriteWarning > = Vec :: new ( ) ;
10931092
1094- // SYMLINK GUARD (see `engine::guard`) — before the ledger and before any
1095- // write, dry runs included, so a dry run predicts the refusal. The
1096- // revert side (replay.rs ) already refuses linked files, so the write
1097- // side must too.
1093+ // SYMLINK GUARD (see `engine::guard`) — before any write, dry runs
1094+ // included, so a dry run predicts the refusal. The revert side (the
1095+ // hosted → upstream restore's staged flush ) already refuses linked
1096+ // files, so the write side must too.
10981097 if let Some ( refusal) = engine:: guard ( & view, & done, & candidates) {
10991098 return refuse ( common, scan_result. take ( ) , & refusal) ;
11001099 }
@@ -1176,8 +1175,8 @@ pub(crate) async fn run_redirect_selected(
11761175 // the writes so the warning describes the project as this run leaves it.
11771176 // Idempotent re-scans re-confirm and re-probe, so the warning keeps
11781177 // firing until the stale materialization is actually gone. Skipped
1179- // EXPLICITLY on --dry-run: the probe's ledger-record fallback would
1180- // otherwise judge state the run did not (re)create.
1178+ // EXPLICITLY on --dry-run: nothing was written, so the probe would
1179+ // judge state the run did not (re)create.
11811180 let gem_stale: StaleInstallOutcome = if common. dry_run {
11821181 StaleInstallOutcome :: default ( )
11831182 } else {
@@ -1330,7 +1329,7 @@ pub(crate) async fn run_redirect_selected(
13301329 // Stale-flagged purls are EXCLUDED from assume_applied: the same-run
13311330 // envelope carries a redirect_gem_stale_install warning proving the
13321331 // installed materialization unpatched, so attesting that purl from
1333- // the ledger would contradict the run's own warning. Excluded purls
1332+ // this run's records would contradict the run's own warning. Excluded purls
13341333 // fall back to `vex`'s normal installed-tree verification.
13351334 // A confirmed uuid whose bundled instance the rewriter had to skip
13361335 // (#469) leaves that copy unpatched, so it too is verified, never
@@ -1745,8 +1744,8 @@ async fn vendored_takeover(
17451744 None
17461745 } ;
17471746 // Yarn berry twin of the bun gate: the berry rewriter's project-level
1748- // refusals (mixed line endings, cacheKey, `.yarnrc.yml`
1749- // compressionLevel) must be known before the takeover reverts a
1747+ // refusals (mixed yarn.lock / package.json line endings, cacheKey,
1748+ // `.yarnrc.yml` compressionLevel) must be known before the takeover reverts a
17501749 // vendored berry purl, or the revert strips the live vendored patch
17511750 // and the rewriter then refuses the lock. Only entries the
17521751 // vendor ledger wired through the yarn-berry backend are gated (the
@@ -1768,8 +1767,14 @@ async fn vendored_takeover(
17681767 )
17691768 . await
17701769 . ok ( ) ;
1770+ let manifest = socket_patch_core:: utils:: fs:: read_regular_to_string (
1771+ & common. cwd . join ( "package.json" ) ,
1772+ )
1773+ . await
1774+ . ok ( ) ;
17711775 socket_patch_core:: patch:: redirect:: preflight_yarn_berry_hosted (
17721776 & lock,
1777+ manifest. as_deref ( ) ,
17731778 yarnrc. as_deref ( ) ,
17741779 )
17751780 . err ( )
@@ -3382,8 +3387,8 @@ mod tests {
33823387
33833388 /// Probe invocation with the default surface (project-local discovery,
33843389 /// no artifact shas) — tests override the knobs they exercise.
3385- /// `records` is the merged map production hands over ( this run's
3386- /// fetched records plus the ledger's persisted ones) .
3390+ /// `records` is the map production hands over: this run's fetched
3391+ /// records, by uuid .
33873392 async fn probe (
33883393 cwd : & std:: path:: Path ,
33893394 confirmed : & [ ( String , String ) ] ,
@@ -3712,25 +3717,22 @@ mod tests {
37123717 ) ;
37133718 }
37143719
3715- /// RE-FIRE guarantee: when this run's record fetch failed (no fresh
3716- /// records), the merged map the caller hands over still carries the
3717- /// redirect ledger's PERSISTED record under whatever purl key the
3718- /// ledger used — and the probe's uuid lookup judges from it, so a
3719- /// transient /patches/view failure cannot silently retire the warning
3720- /// while the stale materialization is still there.
3720+ /// The probe links a record to a confirmed purl by uuid alone: a
3721+ /// record keyed under the API's qualified purl spelling (not the
3722+ /// confirmed purl) must still judge the stale materialization.
37213723 #[ tokio:: test]
3722- async fn gem_stale_probe_judges_from_persisted_ledger_records ( ) {
3724+ async fn gem_stale_probe_matches_records_by_uuid_not_purl_key ( ) {
37233725 let stale = tempfile:: tempdir ( ) . unwrap ( ) ;
37243726 materialize_gem ( stale. path ( ) , GEM_UPSTREAM ) ;
3725- // Persisted under the API's qualified spelling, not the confirmed
3727+ // Keyed under the API's qualified spelling, not the confirmed
37263728 // purl: only the uuid links them.
3727- let mut ledger_only = std:: collections:: BTreeMap :: new ( ) ;
3728- ledger_only . insert ( format ! ( "{GEM_PURL}?platform=ruby" ) , gem_record ( ) ) ;
3729- let out = probe ( stale. path ( ) , & one_confirmed ( ) , & ledger_only ) . await ;
3729+ let mut qualified = std:: collections:: BTreeMap :: new ( ) ;
3730+ qualified . insert ( format ! ( "{GEM_PURL}?platform=ruby" ) , gem_record ( ) ) ;
3731+ let out = probe ( stale. path ( ) , & one_confirmed ( ) , & qualified ) . await ;
37303732 assert_eq ! (
37313733 out. warnings. len( ) ,
37323734 1 ,
3733- "the ledger records must keep the warning firing across flaky fetches "
3735+ "a record keyed under another purl spelling must still match by uuid "
37343736 ) ;
37353737 }
37363738
0 commit comments