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 — Decide vendored-entry liveness through one discovery verdict by mikolalysenko · Pull Request #1050 · 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 §3.B asks one question: is this vendored entry still live? Four separate oracles answer it today: vendor_entry_live, dispatch_in_use_one, scan_vendor_references and the JVM entry_wired. They disagree.

  • B19. dispatch_in_use_one serves the prune GC, scan's ledger supplement and the vendor --check remedy. It only had probes for npm, cargo and the pypi requirements flavor. Every gem, golang, composer, nuget, maven/jvm, uv, poetry, pdm, pipenv and pylock entry answered None and was kept forever:
    • scan --prune could never reclaim one;
    • scan's supplement recreated it as a discovered package and never emitted vendor_ledger_entry_unwired;
    • meanwhile vendor --check and vex already called it dead.
  • B62. vendor --check reported orphaned JVM trees (maven2, gradle, coursier and their indexes, plus the generated sbt file) only when the whole ledger was empty.
  • B61. Legacy Maven and NuGet treated a raw substring as "already wired". A commented-out <repository> or <packageSources> source took the in-sync hot path, so the build resolved the unpatched package.

Change

  • Core: one GC / supplement in-use verdict. Discovery::vendor_entry_in_use(root, entry) -> Option<bool> sits next to vendor_entry_live and is derived from the same discovery:

    • Some(true) in any of these cases:
      • the entry is live;
      • another lock contests its wiring;
      • a file that mentions its uuid had wiring dropped as DIAG_REF_UNATTRIBUTABLE;
      • cargo withheld a relock-pending [patch].
    • Some(false): discovery read and parsed an install-deciding lockfile of the entry's ecosystem, and nothing above holds.
    • None: discovery read no such lockfile, or one of its files could not be read or parsed.
    • JVM entries answer from their own layout (entry_references).
  • An attestation drop is not a liveness verdict. Attestation fails closed by dropping a ref it cannot tie to the one copy that installs. Examples:

    • an unpatched copy in the same lock;
    • npm's legacy dependencies mirror;
    • a non-registry nested copy;
    • vlt's other instances or bundled copies;
    • a yarn git block;
    • a version-less Go replace.

    The GC has to fail safe, by keeping the entry. One rule covers every extractor: keep the entry whenever a file that mentions the uuid carries an unattributable diagnostic. This is deliberately file-grained, so it errs toward keeping. Mentions rejected as DIAG_REF_INVALID are shapes the package manager never installs from, and they still read as unused. Examples: stale bun.lockb pool strings, a vlt edge spec, cargo's leftover [patch] after a hosted takeover.

  • New discovery evidence:

    • Discovery::read: every guarded read, tagged with the reading extractor's ecosystem. A manifest alone (Cargo.toml, pyproject.toml, hatch.toml) is not a lock, so it decides nothing.
    • Discovery::withheld: now only cargo's relock-pending [patch], which cargo reports as invalid rather than unattributable. The earlier npm and bun pushes were removed because the diagnostic rule subsumes them.
  • Routing.

    • run_vendor_gc pass (b) takes every verdict from one discovery snapshot taken before it reverts anything. Before, each probe re-read the files after the previous revert. Reverting one entry never rewires another, so the snapshot only removes ordering effects.
    • vendored_ledger_supplement reads the run's ProjectContext discovery (scan and get pass their context).
    • The vendor --check remedy uses the same verdict.
  • B62. The JVM orphan check fires whenever no ledger entry is a JVM entry:

    • empty ledger: refuses, as before;
    • otherwise: records a failed vendor_ledger_missing artifact event, whose path names the orphan.

    The path list is now one jvm::apply::LEDGER_OWNED_PATHS.

  • B61. Each backend now uses the comment-masking reader its forward writer already uses: find_wireable_anchor for the pom, parse_config_source_keys(blank_comments(..)) for nuget.config.

Duplicates deleted

The GC, supplement and vendor --check remedy oracles go from 5 to 1. Deleted:

  • commands::vendor::dispatch_in_use_one
  • vendor::npm_flavor::vendored_entry_in_use
  • vendor::cargo::vendored_entry_in_use
  • vendor::pypi::vendored_entry_in_use
  • vendor::pypi_requirements::requirements_entry_in_use

Kept on purpose (see Deferred):

  • the pnpm, pnpm-legacy and vlt structural probes (pnpm_entry_in_use, pnpm_legacy_entry_in_use, vlt_entry_in_use). Their revert guards still use them. If one disagrees with the GC verdict, the guard refuses and the entry lands in GC failed, so nothing is reverted unsafely.
  • the two JVM checks. entry_wired (vex, vendor --check) is strict attestation: every half is wired and the Gradle script is intact. entry_references (GC, supplement) asks whether anything still references the tree. Wired implies referenced, so the GC never reverts an entry that vex attests.
  • scan_vendor_references, the raw-text check used by orphan sweeps, repair, rollback and vendor --check's unknown-wiring scan.

JVM orphan path lists: the CLI inline list and coursier_tree::ORPHAN_PATHS become LEDGER_OWNED_PATHS, so 2 lists become 1.

Behaviour changes

  • Newly prunable by scan --prune when an install-deciding lock no longer mentions them: gem, golang, composer, nuget, legacy maven, JVM, and the uv, poetry, pdm, pipenv and pylock pypi flavors.
  • npm. An unknown or mismatched npm flavor, or a v9 lock under a pnpm-legacy entry, used to read as None. Now a lock that resolves nothing for the entry reads as unused.
  • Still undecidable. Lock-less pyproject projects (hatch, or any flavor before its first lock) keep answering None, and the entry is kept. This is now pinned by a test. Earlier wording that listed hatch among the B19 fixes was wrong for the lock-less case.
  • None of this needs a maintainer decision (Decide: one shape for the --json top-level error (scan and get emit both a string and a {code, message} object) #704, Decide: warn on and then remove scan --apply/--vendor, and whether --vex stays embedded #966, Decide: give SOCKET_FORCE per-command names so forcing a self-update doesn't also force apply and vendor #615, Decide: where patch API calls go when a token is set but the org slug can't be resolved #648, C34, E44-E47 are untouched).

Testing

Run locally on macOS. Every cargo command went through heavy-job.sh with CARGO_INCREMENTAL=0 and -j4.

  • cargo test -p socket-patch-core --lib -- vex:: vendor::: 2987 passed, plus the new pyproject test.

  • cargo test -p socket-patch-cli:

    target passed
    --lib 871
    vendor_jvm_cli 30
    covgap_commands_scan_mod 53
    covgap_commands_vendor 54
    scan 118
    repair 126
    rollback 38
    vendor 91
    e2e_vex_lockfile 323
    in_process_vendor 121
    scan_vendor_e2e 37
    scan_vendor_requirements_unwired 3
    vendor_eject 8

    All green on head.

  • cargo clippy -p socket-patch-core -p socket-patch-cli --all-targets: no diagnostics in any file this PR touches. Toolchain 1.93.1 still flags pre-existing lints elsewhere (jvm_jar.rs, python_crawler.rs, redirect/mod.rs, test helpers), and those are on main too.

Keep-side coverage for every newly prunable ecosystem. Each successful, non-dry-run vendor through the vendor::test_support wrappers now asserts that the GC verdict on the entry it just wrote is not Some(false). In vendor::, that ran against real backend output for every ecosystem and flavor, with every verdict Some(true) (count per ecosystem/flavor):

ecosystem / flavor runs
cargo 70
composer 45
gem 76
golang 23
maven 43
nuget 42
jvm 1
npm (package-lock, bun, pnpm, pnpm-legacy, vlt, yarn-berry, yarn-classic) 535
pypi requirements 44
pypi uv 13
pypi poetry 14
pypi pdm 23
pypi pipenv 11
pypi hatch 3
pypi python-lock 3

Regression tests, failing first.

  • vendor::npm_flavor::tests::unattributable_wiring_stays_in_use covers the v2 legacy mirror, a v3 nested git copy and a vlt other instance. With the new rule disabled it fails: left: Some(false), right: Some(true).

  • gc_tests::vendor_gc_keeps_an_entry_whose_wiring_is_only_unattributable: run_vendor_gc keeps a legacy-mirror entry, dry and wet. It fails with the rule disabled.

  • vex::discover::tests::lockless_pyproject_entries_stay_undecidable pins None.

  • Run on the merge-base c5be5d1 (test hunks only, in a throwaway worktree), these three failed as expected:

    • vendor_gc_reclaims_unused_composer_entry_and_keeps_a_wired_one (B19): unused_reverted was [].
    • ledger_supplement_reports_a_bumped_composer_entry_unwired (B19): the entry was resurrected into packages.
    • check_reports_jvm_trees_without_a_jvm_entry_beside_other_entries (B62): no JVM orphan event; only the npm entry's own failure.

    The B62 test now also asserts that the event's path is an existing LEDGER_OWNED_PATHS member.

  • commented_out_repository_is_not_wired and commented_out_source_is_not_wired (B61) fail with the old substring checks restored.

Linux and docker suites are left to CI.

Deferred

  • scan_vendor_references (orphan sweeps, repair, rollback's ledger-less gate, vendor --check's unknown-wiring scan) is still a separate raw-text scan. Scan every vendored-write file for vendored references (#832, #958) #1015 (Vendored-reference scan never sees NuGet or Maven wiring, so the orphan sweep deletes a still-wired unit #832, Vendored-reference scan never reads hatch.toml, so the orphan sweep deletes a wheel that a Hatch environment still installs #958) is extending it now. Retiring it into discovery is the follow-up once Scan every vendored-write file for vendored references (#832, #958) #1015 merges. This PR touches neither repair.rs nor registry.rs.
  • Route the pnpm, pnpm-legacy and vlt revert guards through Discovery::vendor_entry_in_use. The pnpm part needs coordination with Fix 15 open pnpm issues across hosted, vendored and agent modes #1007's owner.
  • Derive the JVM attestation check (entry_wired) from the reference check plus a layout-intact check, together with a single jvm::layout module and per-GAV JVM orphan detection (a tree dir with no matching JVM entry while other JVM entries exist).
  • Lock-less pyproject pypi entries (hatch, or before the first lock) stay undecidable, so they are kept.
  • withheld and the unattributable rule match on uuid and mode. A uuid names one patch, so one package version, so matching on base_purl too would add nothing today.
  • NuGet hosted and vendored still share the socket-patch-<uuid> key. Deciding "ours" by the source value (NuGet scan --mode vendored over a hosted pin skips the takeover (purl case mismatch), keeps the hosted feed wired, writes no vendor ledger and still reports success #553) is not addressed here.
  • ecosystem_in_scope does not map "jvm" to maven (a separate audit finding).

🤖 Generated with Claude Code


Note

High Risk
Changes prune GC, vendor --check, and scan supplement behavior across all ecosystems; incorrect liveness could revert live patches or leave stale ledger entries.

Overview
Unifies vendored-ledger liveness behind Discovery::vendor_entry_in_use, replacing separate per-ecosystem probes (dispatch_in_use_one, npm/cargo/pypi vendored_entry_in_use) so scan --prune, the vendored ledger supplement, and vendor --check share one verdict.

Discovery now records which lockfiles were read (Discovery::read) and cargo relock-pending wiring (withheld), and treats unattributable attestation drops and contested locks as keep (fail-safe) rather than unused. The prune GC loads one discovery snapshot before reverting entries so half-pruned locks cannot skew later probes.

Behavior fixes: Composer and other previously unprobed ecosystems can be reclaimed when install-deciding locks no longer wire them; JVM orphan detection runs when the ledger has no JVM entry (not only when empty); Maven/NuGet commented-out repository/source blocks no longer count as wired for the in-sync vendor path.

Vendor test helpers assert a freshly vendored entry is never Some(false) for the GC verdict.

Reviewed by Cursor Bugbot for commit e9bd805. 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 4 commits October 7, 2026 11:40
@mikolalysenko @claude
Add Discovery::vendor_entry_in_use, the one vendored in-use verdict
8003fba
The prune GC and scan's ledger supplement asked a per-backend probe
(npm, cargo, pypi-requirements only) whether a vendored entry is still
consumed, while vex and vendor --check judge liveness by discovery.
Give discovery the evidence for a tri-state in-use answer for every
ecosystem:

- `Discovery::read` logs every guarded read, tagged with the ecosystem
  whose extractor read it, so "nothing wires it" can mean "unused" only
  once a lockfile of that ecosystem was actually read and parsed.
- `Discovery::withheld` records wiring an extractor withholds as a ref
  although a file still routes through the patch: npm's and bun's
  in-lock contests and cargo copies whose lock lags (another tag, or an
  untagged override). Not attested, but still wiring the GC must keep.
- `vendor_entry_in_use` = live, contested or withheld -> Some(true);
  a read lockfile of the ecosystem and nothing wiring it -> Some(false);
  no lockfile, or one that cannot be read or parsed -> None. JVM
  entries answer from their own layout (`entry_references`).

Audit B19 (§3.B "is this vendored entry live").

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Decide legacy Maven and NuGet "already wired" through the comment-awa…
76562ad
…re readers

The vendored Maven backend treated any occurrence of its repository id
in pom.xml as wiring, and the NuGet backend any occurrence of its source
key in nuget.config, so a commented-out (or profile-scoped) repository
or source took the in-sync hot path and the build resolved the
unpatched package. Use the same masking the forward writers already
use: `find_wireable_anchor` (comments and <profiles> masked) for the
pom, and `parse_config_source_keys(blank_comments(..))` for the
nuget.config <packageSources>.

Audit B61.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Report orphaned JVM trees whenever the ledger has no JVM entry
e9dc502
`vendor --check` reported committed JVM trees (maven2, gradle, coursier,
their indexes, the generated sbt file) as `vendor_ledger_missing` only
when the whole ledger was empty, so a project that also vendors another
ecosystem never noticed a lost JVM half. Fire whenever no ledger entry
is a JVM entry: an empty ledger still refuses as before, otherwise the
orphan is recorded as a failed artifact event beside the other checks.

The path list moves to one `jvm::apply::LEDGER_OWNED_PATHS` (replacing
the CLI's inline list and `coursier_tree::ORPHAN_PATHS`), and the JVM
path tables spell the tree roots through their named constants.

Audit B62.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Route the prune GC, scan's ledger supplement and vendor --check throu…
d872a10
…gh one in-use verdict

`dispatch_in_use_one` answered "is this vendored entry still consumed"
for npm, cargo and the pypi requirements flavor only and kept every
other entry (gem, golang, composer, nuget, maven/jvm, uv, poetry, pdm,
pipenv, hatch, pylock) forever: `scan --prune` could never reclaim them
and scan's ledger supplement resurrected them as discovered packages,
never reporting `vendor_ledger_entry_unwired`, while `vendor --check`
and vex already called them dead.

Every caller now asks `Discovery::vendor_entry_in_use`:
- run_vendor_gc (pass b) takes all verdicts from one discovery of the
  project before it reverts anything;
- vendored_ledger_supplement reads the run's ProjectContext discovery
  (scan and get pass their context);
- vendor --check's "dependency removed" remedy.

Deleted: `dispatch_in_use_one` (CLI) and the per-backend dispatchers
`vendor::npm_flavor::vendored_entry_in_use`,
`vendor::cargo::vendored_entry_in_use`,
`vendor::pypi::vendored_entry_in_use` and
`pypi_requirements::requirements_entry_in_use` (4 in-use oracles -> 1;
the pnpm/vlt structural probes stay for their revert guards). Their
tests now assert the discovery verdict, with lock fixtures carrying the
version an install records.

Audit B19.

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
@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 3 commits October 7, 2026 13:05
@mikolalysenko @claude
Keep vendored entries whose wiring attestation only dropped as unattr…
84b2d90
…ibutable

The prune GC's in-use verdict read every vendored ref that attestation
dropped as unused unless an extractor had recorded it as withheld, and
only npm's in-pair contest, bun and cargo did. Every other unattributable
drop (an unpatched copy in the same lock, npm's legacy `dependencies`
mirror, a non-registry nested copy, vlt's other instances and bundled
copies, a yarn git block, a version-less Go replace) made `scan --prune`
unwire a vendored patch the package manager still installs.

`vendor_entry_in_use` now keeps an entry whenever a file that mentions
its uuid also carries a DIAG_REF_UNATTRIBUTABLE diagnostic. That one rule
covers every extractor, so the npm and bun `withheld` pushes are gone;
cargo's relock-pending record stays because cargo reports that case as
DIAG_REF_INVALID. Mentions rejected as invalid (stale bun.lockb pool
strings, vlt edge specs, cargo's leftover [patch] after a hosted
takeover) still read as unused.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Assert every backend test's fresh vendor reads as in use for the prun…
b3020d2
…e GC

Each successful, non-dry-run vendor through the test_support wrappers now
asks discovery's in-use verdict about the entry it just wrote and fails
on Some(false). Every backend suite (npm flavors, pnpm, yarn, bun, vlt,
cargo, composer, gem, golang, maven, nuget and every pypi flavor) thus
pins the keep side of the GC against its real output.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko @claude
Pin the path the JVM orphan event names
9ff1237
The B62 test now checks that the vendor_ledger_missing event names a
LEDGER_OWNED_PATHS member that exists, not just any maven-tagged event.

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:06
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.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Gradle JVM prune may fail open
    • Created gradle::references_checked that returns Result<bool, String> and fails when files cannot be read, ensuring fail-closed behavior consistent with other JVM backends.
  • ✅ Fixed: Empty-wiring JVM entries skip layout check
    • Modified is_jvm_entry to recognize empty-wiring maven-ecosystem entries with valid maven purls, preventing them from incorrectly falling through to generic maven discovery.

Create PR

Or push these changes by commenting:

@cursor push 002ca36d71
Preview (002ca36d71)
diff --git a/crates/socket-patch-core/src/vendor/jvm/apply.rs b/crates/socket-patch-core/src/vendor/jvm/apply.rs
--- a/crates/socket-patch-core/src/vendor/jvm/apply.rs
+++ b/crates/socket-patch-core/src/vendor/jvm/apply.rs
@@ -36,13 +36,20 @@
 };
 
 /// Whether `entry` was written by this backend: it has wiring and every
-/// record is one of this backend's kinds.
+/// record is one of this backend's kinds, OR it's a maven-ecosystem entry
+/// with a valid maven purl (covers empty-wiring reconstructed entries).
 pub fn is_jvm_entry(entry: &VendorEntry) -> bool {
-    !entry.wiring.is_empty()
+    if !entry.wiring.is_empty()
         && entry
             .wiring
             .iter()
             .all(|w| KINDS.contains(&w.kind.as_str()))
+    {
+        return true;
+    }
+    // Empty-wiring entries (e.g., from repair/reconstruction) that are
+    // maven-ecosystem with valid maven purls should still be treated as JVM entries
+    entry.ecosystem == "maven" && parse_maven_purl(&entry.base_purl).is_some()
 }
 
 /// Offline inputs have not been authenticated by independent registry checksums.
@@ -827,7 +834,7 @@
     }
     let (maven, gradle) = sides(&entry.wiring);
     (maven && maven_reactor::wired_checked(&read, &c).unwrap_or(true))
-        || (gradle && gradle::references(&read, &c))
+        || (gradle && gradle::references_checked(&read, &c).unwrap_or(true))
 }
 
 /// The liveness proof `vex` needs: every half of the entry is wired, and

diff --git a/crates/socket-patch-core/src/vendor/jvm/gradle.rs b/crates/socket-patch-core/src/vendor/jvm/gradle.rs
--- a/crates/socket-patch-core/src/vendor/jvm/gradle.rs
+++ b/crates/socket-patch-core/src/vendor/jvm/gradle.rs
@@ -1197,6 +1197,42 @@
     indexed && applied
 }
 
+/// Checked variant of [`references`] that returns an error when files
+/// cannot be read, for fail-closed GC ([`crate::vex::discover::Discovery::vendor_entry_in_use`]).
+pub fn references_checked(read: ReadFn<'_>, c: &Coords<'_>) -> Result<bool, String> {
+    let gav = format!("{}:{}:{}", c.group_id, c.artifact_id, c.version);
+    let index_bytes = read(INDEX_REL).ok_or_else(|| format!("cannot read {}", INDEX_REL))?;
+    let index_text = String::from_utf8(index_bytes)
+        .map_err(|_| format!("{} is not valid UTF-8", INDEX_REL))?;
+    let rows = index_rows(&index_text)
+        .ok_or_else(|| format!("{} could not be parsed", INDEX_REL))?;
+    let indexed = rows.iter().any(|r| {
+        let cols: Vec<&str> = r.split('\t').collect();
+        cols.first() == Some(&gav.as_str()) && cols.get(3) == Some(&c.uuid)
+    });
+    
+    let wiring = WiringTarget::vendored();
+    let mut applied = false;
+    let mut settings_found = false;
+    for rel in ["settings.gradle", "settings.gradle.kts"] {
+        if let Some(bytes) = read(rel) {
+            settings_found = true;
+            let text = String::from_utf8(bytes)
+                .map_err(|_| format!("{} is not valid UTF-8", rel))?;
+            let dsl = dsl::dsl_of(rel).unwrap_or(Dsl::Groovy);
+            if has_apply_line(&text, dsl, &wiring, "") {
+                applied = true;
+                break;
+            }
+        }
+    }
+    if !settings_found {
+        return Err("cannot read settings.gradle or settings.gradle.kts".to_string());
+    }
+    
+    Ok(indexed && applied)
+}
+
 /// The liveness proof `vex` needs for this layout: `c` is
 /// [`references`]d, the script is ours (line endings aside), and a re-plan
 /// over the committed tree is refused nowhere and degraded nowhere.

You can send follow-ups to the cloud agent here.

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread crates/socket-patch-core/src/vendor/jvm/apply.rs Resolved

Uh oh!

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

Comment thread crates/socket-patch-core/src/vex/discover/mod.rs Resolved

Uh oh!

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

@claude
Keep JVM trees whose Gradle wiring cannot be read
e9bd805
`scan --prune` reverts a JVM ledger entry when `entry_references` answers
false, but the Gradle arm returned `gradle::references` as is: a malformed
gradle-index.tsv, a non-UTF-8 settings file, or a file the reader could
not read (permission error, link out of the checkout) all read as "not
referenced", so the GC could delete a tree that is still wired. The
maven/sbt/scala-cli arms already map undecidable to true.

Add `gradle::references_checked`, which answers None when a file it
decides by exists but cannot be parsed, and have `entry_references` treat
that, and any read error the ProjectReader recorded, as still in use.
`gradle::references` keeps its old answers for revert and attestation.

Also pin with a test that a hand-stripped, empty-wiring `jvm` entry stays
undecidable (None) for the prune GC.

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 e9bd805. Configure here.

Sorry, something went wrong.

Uh oh!

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

All reactions
Tanmay182003
Tanmay Singla (Tanmay182003) approved these changes Oct 7, 2026
View reviewed changes
@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 7, 2026
@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

[agent] Ready for review at e9bd80572b5805aa639cc82e19e47447e9dd4d32.

  • CI: required ci-ok green (22:53Z). 529 success / 6 skipped / 0 failing of 563 check runs; 28 non-required macOS/Windows legs still queued on the runner backlog.
  • Bugbot reviewed e9bd80572b; no unresolved review threads.
  • Mergeable, no conflicts. The branch is 8 commits behind main (no overlap reported by GitHub); the merge queue re-tests against main.
  • Reviewer focus: vendored-entry liveness now comes from a single discovery verdict.

Generated by Claude Code

All reactions

Sorry, something went wrong.

Uh oh!

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

@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 7, 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 Mikola Lysenko (mikolalysenko) removed the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 8, 2026
@mikolalysenko @claude
Merge origin/main into arch-fix/vendored-liveness
f7db4b7
Conflicts were main's rustfmt-only reflows of code this branch rewrote
(vendored_ledger_supplement test calls now take a ProjectContext,
dispatch_in_use_one moved behind the shared liveness probe, cargo
vendored_from_patches keeps the relock_pending claim); kept this
branch's versions.

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 @claude
Merge origin/main into arch-fix/vendored-liveness
ec12e37
Pick up #1093 so PR CI runs without the macOS legs.

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 @claude
Merge origin/main into arch-fix/vendored-liveness
a0f1c87
Resolve golden.rs Discovery destructure: keep this PR's read/withheld
fields and main's unwired_copies (#1033).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@mikolalysenko
Mikola Lysenko (mikolalysenko) removed this pull request from the merge queue due to a manual request Oct 8, 2026
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
Read Cargo.toml [package] identity through formats::cargo::manifest (#693) #1110
Merged
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
This was referenced Oct 8, 2026
Carry scan's lockfile-only and vendored-ledger candidates without a fabricated node_modules path #1113
Closed
Tracking: derive scan candidates, lock entries and hosted refs from one project inventory instead of four discovery systems #1112
Open
Lock inventory and the vendored PyPI router disagree on which lock governs when poetry.lock or pdm.lock has no packages #1114
Open
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 8, 2026

Uh oh!

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

Mikola Lysenko (mikolalysenko) and others added 2 commits October 8, 2026 03:29
@mikolalysenko
Merge remote-tracking branch 'origin/main' into arch-fix/vendored-liv…
0987145
…eness
@mikolalysenko @claude
Merge origin/main into arch-fix/vendored-liveness
22a1b60
Brings in #1044 (governing lock table), #1035, #1038, #1083, #724.
Drop the BUN_LOCK/BUN_LOCKB/NPM_LOCKS imports #1044 added to
npm_flavor.rs: their only user, vendored_entry_in_use, is removed by
this PR (liveness now comes from Discovery::vendor_entry_in_use).
This unused import failed clippy in the merge group.

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
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 8, 2026

Uh oh!

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

@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
Fix main's red CI: macOS Composer on PHP 8.4 and the setup-php pin comment #1102
Merged
@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit 18c5f81 Oct 8, 2026
455 checks passed

Uh oh!

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

@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the arch-fix/vendored-liveness branch October 8, 2026 11:20
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 8, 2026
@mikolalysenko @claude
Merge origin/main into arch-fix/jvm-layout
77afc53
Resolve conflicts with #1050 (vendored-entry liveness): keep its
fail-closed Gradle references_checked and ledger-owned orphan check, and
route both through vendor::jvm::layout (LEDGER_OWNED_PATHS replaces
ORPHAN_PATHS there, re-exported from jvm::apply; settings files come from
layout::GRADLE_SETTINGS_FILES).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 8, 2026
@mikolalysenko @claude
Merge origin/main into arch-refactor/973-maven-single-pom-planner
2c6ecbb
maven_repo.rs: keep this PR's deletion of the legacy same-GAV
<repository> backend; #1050's B61 change (comment-aware "already
wired" check via find_wireable_anchor) and its test only touched that
deleted backend.

Co-Authored-By: Claude Opus 5.5 (1M context) <[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
e647108
Resolve the conflicts with main's move of vendored in-use detection
into discovery (#1050) and its PurlKey rename (#1045):

- npm_flavor.rs: drop the branch's vendored_entry_in_use, now that
  Discovery::vendor_entry_in_use replaces it. Bun discovery already
  picks the live lock through bun_text_lock_drives, so the #735
  regression test now runs through the shared in_use helper with a
  minimist entry.
- lock_inventory/tests.rs: keep both sides' new tests.
- vendor.rs: key the Bun reinstall dedupe on PurlKey.

Assisted-by: Claude Code:claude-opus-5-5
This was referenced Oct 8, 2026
Fix open bun issues (#992, #861, #784, #764, #735, #635, #599, #578, #497, #443, #371) #1009
Merged
After bun remove of a vendored package in a bun.lockb project, scan --prune, vendor --revert and remove keep it as "drifted", so vendor --check stays red and its remedy loops #1132
Closed
Cut merge-group CI from ~46 to ~20 min: shard Gradle e2e and test legs, skip test-release in queue, cancel orphaned runs #1133
Merged
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
pip: run 32 ledger (#1050 liveness, hashed include, no new issues)
526e4e8
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KWAYXWPgb6FHP1jeYTCPcA
@mikolalysenko Mikola Lysenko (mikolalysenko) mentioned this pull request Oct 8, 2026
After uv remove of a vendored package, scan --prune, vendor --revert, remove and rollback all keep it as "drifted", so vendor --check stays red and its suggested scan --prune fix loops #1140
Closed
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 8, 2026
@claude
Merge origin/main into agent/fix-npm-open-issues
b8b069b
Resolve the three conflicts by keeping both sides:

- scan/policy.rs: keep the PR's dir_markers/lock_markers split (lock
  markers decide nested roots for #554) and re-apply main's #1032 change
  inside dir_markers: the JVM manifest fallback now reads
  vendor::jvm::layout::JVM_PROJECT_MARKERS, with main's is_file comment.
- vex/discover/mod.rs: Discovery keeps the PR's `shadowed` refs (#828)
  alongside main's `read` and `withheld` evidence (#1050). Shadowed refs
  carry DIAG_REF_UNATTRIBUTABLE, so vendor_entry_in_use already keeps
  their entries through unattributable_mention.
- vex/discover/testing/golden.rs: destructure all three fields.

Co-Authored-By: Claude <[email protected]>
This was referenced Oct 8, 2026
After pipenv uninstall of a vendored package from a named category on Pipenv 2022/2023, scan --prune, vendor --revert, remove and rollback keep it as "drifted", so vendor --check stays red and its scan --prune remedy loops #1142
Closed
Evict failing merge-queue entries ~35 min sooner #1146
Merged
After npm install <pkg>@<other version> moves a vendored npm package off its patched version, scan --prune, vendor --revert, remove and rollback all drift-keep it, so vendor --check stays red and every remedy it names loops #1155
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
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.

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.