GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||
GeezerVison is showing github.com — fix(scan): surface hosted redirect state in report-only scan --json and list by mikolalysenko · Pull Request #220 · SocketDev/socket-patch Conversation
|
| Container | bundler | report-only scan --json |
list --json |
|---|---|---|---|
| gem-b1 | 1.17 | exit 0, zero hosted/redirect/warning fields | exit 1 manifest_not_found |
| gem-b2 | 2.7 | exit 0, zero hosted/redirect/warning fields | exit 1 manifest_not_found |
| gem-b4 | 4.0 | exit 0, zero hosted/redirect/warning fields | exit 1 manifest_not_found |
Root cause (at d9afb08, unchanged on main): hosted_wiring_retained is pushed to the scan JSON envelope only inside the --apply branch and the post-apply text path; the read-only path loads redirect_state but never emits it. And hosted mode records its patches only in .socket/vendor/redirect-state.json — it never writes .socket/manifest.json — so list hard-failed on a purely hosted project while its patches were demonstrably live. A hosted-wired project's report-only scan --json was byte-identical to a never-touched project's.
This closes the long-open "hosted-mode JSON gap" residual (scan/mod.rs review 2026-07-04); #207 surfaced the adjacent cross-mode warnings but not these two surfaces.
scan --json — new top-level redirectState block. Every non-hosted-mode, non-vendored-mode envelope (report-only, --mode agent/--apply/--sync, and the zero-discovery path) carries it whenever the redirect ledger holds ≥ 1 record:
"redirectState": { "mode": "hosted", // constant label (a legacy ledger's own mode string may say "redirect") "ledger": ".socket/vendor/redirect-state.json", "records": [ // every ledger record, sorted { "purl": "pkg:gem/[email protected]", // canonicalized — string-joins with wiringLive "ledgerKey": "pkg:gem/[email protected]", // the ledger's verbatim key (may be %-encoded / ?qualified) "uuid": "…" } ], "wiringLive": [ "pkg:gem/[email protected]" ] // purls this run counted whose live lock still proves hosted wiring }
It is a descriptive state block, not a warning — a healthy hosted project's every scan must not read as an anomaly (the #207 hosted_wiring_retained warning stays exactly where it was: the agent-flow conversion-incomplete diagnostic, unchanged and now accompanied by the block). records are the ledger's word; wiringLive is the live lock's proof, computed ONCE per run by the same hosted_wiring_live gate as the #207 warning and scoped to this run's post---ecosystems-filter counted purls — a record with no proof means unwound wiring, an unreadable lock, or a purl this run did not cover, never "still live". Error envelopes (offline refusal, all-batches-failed) are deliberately minimal and never carry the block. Hosted-mode runs keep their redirect sub-object and vendored runs their takeover warnings; both can mutate the ledger mid-run, so neither duplicates a pre-run snapshot that could go stale.
list / list --json — hosted records fold in. Redirect-ledger records are listed alongside manifest entries, labeled apart: details.mode: "hosted" + details.ledger on the events (additive, absent on manifest entries; the constant mode name, whatever opaque mode string a pre-rename ledger carries), a Mode: hosted (recorded in .socket/vendor/redirect-state.json) line on the human path. Global purl sort, manifest entry before the hosted record on a tie — when both stores hold a purl, both are shown. Exit semantics: records found (either store) → exit 0; manifest_not_found still fires when neither store has a record (an edits-only ledger asserts no patches); a present-but-broken manifest still reports manifest_invalid/manifest_unreadable regardless of ledger records — corruption is never masked. A malformed ledger degrades to "nothing to consult" with a stderr warning, muted by --silent (the read-only consumer posture load_redirect_state documents; the hosted write path hard-errors instead). Both stores always come from the SAME project: with --manifest-path the ledger resolves against the root the resolved manifest path implies, never the local cwd. The patch_listed telemetry metric keeps its pre-hosted meaning (patches_count = manifest patches only).
redirectState) paragraph; the read-only sentence now names the block.list row mentions the hosted ledger.manifest_not_found row: list's hosted-only behavior + the never-masked corruption rule.list's details.mode/details.ledger keys.tests/scan_invariants.rs (+4, mirroring fix(scan): surface cross-mode state — hosted wiring retained, vendored ownership, berry vendored-entry refusal #207's fixtures): report-only block presence with records + live proof and no conversion warning; omission for edits-only/no ledger; records-vs-wiringLive split on a registry-clean lock; agent runs carry block + warning together.tests/cli_parse_list.rs (+6 subprocess tests): hosted-only exit 0 with labeled events (JSON + human); manifest+ledger coexistence incl. a same-purl tie; edits-only ledger still manifest_not_found; corrupt manifest never masked; --silent suppression.redirect_state_json gates/shape (scan), envelope labeling + hosted-only envelope (list).Gates: cargo fmt --check on touched files, cargo clippy --workspace --all-features -- -D warnings (the exact CI invocation) clean, and the full scan_invariants, cli_parse_list, in_process_scan, in_process_redirect, in_process_redirect_pnpm, in_process_vendor, cli_parse_scan, cli_scan_silent, mode_migration_npm, mode_migration_cargo, repair_invariants, e2e_vex_redirect, e2e_safety_yarn_pnp, cli_parse_main suites plus the lib unit tests green. No rewriter touched, so the redirect goldens are unaffected.
An adversarial review produced convergent findings; all were reproduced RED-first and fixed:
redirectState on !hosted alone, so scan --mode vendored --json over an empty crawl carried the block. Gate fixed to !hosted && !vendor; omission now pinned for hosted AND vendored envelopes on both the zero-discovery and ≥1-package paths (hosted_mode_envelopes_omit_redirect_state, vendored_mode_envelopes_omit_redirect_state).--silent violations — the malformed-ledger degradation warnings (list + both scan consults) ignored --silent; all three now flow through one shared load_redirect_state_lenient(cwd, silent) (this also silent-gates the pre-existing main-path scan warning, per "errors only").records[] kept verbatim API-spelled ledger keys while wiringLive was canonical, so a live redirect of a %40scope%2F-encoded or ?platform=-qualified purl read as "wiring unwound" under the documented string-compare join. records[].purl is now canonicalized to wiringLive's spelling; the raw key is preserved as records[].ledgerKey.list --manifest-path store mixing — the ledger was resolved against cwd unconditionally, interleaving two projects' stores and letting a local ledger suppress the flagged project's manifest_not_found. The ledger now resolves against the project root the resolved manifest path implies.patch_listed.patches_count had silently become "listed entries" (manifest + hosted, double-counting shared purls); restored to manifest-only, pinned by a wiremock body capture.redirectState.--ecosystems-filter scanned set; "purl not covered this run" documented as the third silent cause (GC prune deliberately keeps its pre-filter set).redirect_state_json is sync and takes the precomputed proof, its records gate being the block's single presence decision.HOSTED_MODE_LABEL; a legacy "redirect" ledger now still labels "hosted" on both surfaces), list exit predicate derived from entry emptiness, envelope-doc sort ownership fixed, manifest_envelope test helper, redirect-ledger fixture writer promoted to tests/common/mod.rs.scan --json is similarly thin on vendored ownership (which packages the vendor ledger owns) — a separate observed gap, deliberately not addressed to keep the surface additive and reviewable.list, vex, and scan's updates[] each fold manifest + redirect-ledger records with their own collision policy — real, but a core-level refactor.remove/repair hosted-awareness asymmetry: repair has a redirect_only_project skip while remove still errors manifest_not_found on hosted-only projects.🤖 Generated with Claude Code
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…nd list Live-verified defect (gem live-matrix D3, 2/2 per cell on bundler 1.17/2.7/4.0 vs production): after `scan --mode hosted` + install, the hosted state was invisible to both read-only surfaces a user would check — * report-only `socket-patch scan --json` (exit 0) contained ZERO hosted/redirect/warning fields (byte-identical to a never-touched project's envelope): the `hosted_wiring_retained` warning rides only the agent-mode apply branch, and the `redirect` sub-object only a hosted-mode run's; * `socket-patch list --json` exited 1 `manifest_not_found` — hosted mode records its patches ONLY in the redirect ledger and never writes `.socket/manifest.json`. This matches the long-open "hosted-mode JSON gap" residual from the 2026-07-04 scan/mod.rs review; PR #207 surfaced the adjacent cross-mode warnings but not these two surfaces. Fix (both additive/MINOR per CLI_CONTRACT.md): * scan --json: every non-hosted-mode, non-vendored-mode envelope (report-only, agent, and the zero-discovery path) now carries a top-level `redirectState` block whenever the redirect ledger holds records: `{ mode, ledger, records: [{purl, uuid}], wiringLive }`. It is a descriptive STATE block, not a warning — records are the ledger's word, `wiringLive` the live lock's proof (the same `hosted_wiring_live` gate as the #207 warning). Hosted-mode runs keep their `redirect` sub-object and vendored runs their takeover warnings (both can mutate the ledger mid-run, so a pre-run snapshot would go stale). * list / list --json: hosted redirect-ledger records fold into the listing, labeled (`details.mode: "hosted"` + `details.ledger`; a `Mode: hosted` line on the human path), purl-sorted with the manifest entry first on a tie. A hosted-only project now exits 0 with its records; `manifest_not_found` still fires when NEITHER store has a record (an edits-only ledger asserts no patches), and a present-but-broken manifest still reports manifest_invalid / manifest_unreadable — corruption is never masked. A malformed ledger degrades to "nothing to consult" with a stderr warning (read-only consumer posture per load_redirect_state's contract). Test-first: tests/scan_invariants.rs (4 new, mirroring the #207 fixtures) and tests/cli_parse_list.rs (6 new subprocess tests) were RED against the old binary; plus in-module unit tests for the block builder and the list envelope labeling. CLI_CONTRACT.md updated (scan section, subcommands table, manifest_not_found row, list action-matrix row). Co-Authored-By: Claude Fable 5 <[email protected]>
There was a problem 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.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit cd7519a. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
…rfaces Adversarial-review round on the redirectState/list-hosted work (PR #220), all defects reproduced RED-first: * vendored zero-discovery leak: the empty-crawl early-return gated the redirectState insertion on `!hosted` alone, so `scan --mode vendored --json` over an empty crawl carried the block the main path (and the contract) exclude — now `else if !vendor`, with omission tests pinning hosted AND vendored envelopes on both the zero-discovery and ≥1-package paths. * --silent violations: the malformed-ledger degradation warnings (list + both scan consults) ignored --silent; all three now flow through one shared crate::commands::load_redirect_state_lenient(cwd, silent). * records↔wiringLive join: records[] kept the ledger's verbatim API-spelled keys (percent-encoded scoped npm names, ?platform= qualifiers) while wiringLive was canonical — a live redirect read as "wiring unwound" under the contract's documented string-compare join. records[].purl is now canonicalized to wiringLive's spelling with the raw key preserved as records[].ledgerKey. * list --manifest-path store mixing: the ledger was always resolved against cwd, interleaving two projects' stores and letting a LOCAL ledger suppress the flagged project's manifest_not_found — the ledger now resolves against the project root the RESOLVED manifest path implies (.socket parent's parent, else the manifest's directory). * telemetry: patch_listed's patches_count had silently become "listed entries" (manifest + hosted, double-counting shared purls); restored to manifest patches only, pinned by a wiremock body capture. * wiringLive scope: the probes now use the post---ecosystems-filter scanned set (a filtered-out purl is "not covered this run", never "unwound"); contract documents the third silent cause. GC prune deliberately keeps the pre-filter set. * efficiency/structure: the live-wiring probe (full lockfile-inventory parse) runs once per run behind a new no-I/O gate and is shared by the block and the agent warning; redirect_state_json is now sync and takes the precomputed proof; the block's records gate is its single presence decision. * one mode-label owner: crate::commands::HOSTED_MODE_LABEL feeds both scan's block (previously echoed the ledger's opaque mode string — a legacy "redirect" ledger now still labels "hosted") and list's details. * list simplifications: exit predicate derived from combined_entries emptiness; build_list_envelope doc reflects the sort ownership; manifest_envelope test helper replaces the copy-pasted call sites. * test fixture promoted: tests/common/mod.rs::write_redirect_ledger, used by cli_parse_list. * contract: redirectState paragraph rewritten (canonical purl + ledgerKey, constant mode label, post-filter wiringLive + third silent cause, error envelopes excluded, --silent-gated degradation warning); list row gains the --manifest-path same-project scoping. Co-Authored-By: Claude Fable 5 <[email protected]>
There was an error while loading. Please reload this page.
…lass-split fallback-home failure semantics Review-round fixes for the two verified Bugbot findings on #222. Finding 1 (Medium): the containment guard's `gem_bundle_config_path_ignored` was a bare eprintln inside the crawler — it never reached any --json `warnings[]` and printed under --silent, violating the repo-wide warning conventions (#219/#220 + the #223 omnibus silent fixes). The crawler is now print-free: the refusal is RECORDED on `BundleStoreDiscovery.skipped_config_path`, and a shared `config_path_ignored_warning(value)` builder feeds the CLI channels — scan pushes it onto the same run-level channel as the PnP layout refusals (JSON `warnings[]` on both the zero-package and >=1-package envelopes; one stderr line gated on !json && !silent), and apply carries it in its Envelope `warnings[]` plus one gated stderr line. Scoped like the crawl that hit it: local mode, gem in --ecosystems/manifest scope. Finding 2 (High, with nuance): with an env/config bundle root, get_gem_paths appends the gem-env fallback homes and the multi-copy fan-out patched EVERY copy with per-copy loud-fail — so a gem present in both the bundle store and a shared home (rvm @global, root-owned system dir) failed the WHOLE run on a permission failure or variant mismatch THERE, even though the copy bundler loads patched fine. Patching a shared home's copy is not itself wrong (plain apply always patched GEM_HOME when no store existed); the defect was failure semantics crossing store classes. Fix: discovery's store list is exposed (`RubyCrawler::discover_bundle_stores`, fs-probes only) and apply's gem fan-out classes each copy — bundle-path store copies stay PRIMARY (loud-fail, unchanged); gem-env fallback-home copies become BEST-EFFORT once at least one store copy applied: a variant mismatch or write failure there is a per-copy non-fatal Skipped event (`gem_fallback_home_skipped`, detail names the path and reason; gated stderr twin), never a run failure. Parity edge kept: with NO bundle-store copy (the historic fallback-only layout, and every --global run) the home copy IS primary and keeps loud-fail exactly as pre-#218 apply. TDD evidence (red -> green on the rebased tip): scan/apply --json missing the warnings[] entry and the --silent leak (3 tests, in_process_gem_config_warning.rs); mismatched-home-copy exit 1 and Failed-event-on-strict-refusal (in_process_gem_fallback_home.rs), with fallback-only loud parity and both-copies-patched pinned green throughout. CLI_CONTRACT.md documents the copy classes and the warning channels. Gates: touched files rustfmt-clean; cargo clippy --workspace --all-features -D warnings clean; core --lib 2535, cli --lib 436; crawlers::ruby 50, crawler_ruby_e2e 25; gem+npm multicopy 2+2; apply_network 11, apply_invariants 4, cli_gem_variant_mismatch_policy 6, cli_apply_silent 2, e2e_gem hermetic 8 (6 shown +cache selftests), e2e_scan, cli_scan_silent, docker_e2e_gem — all green. Co-Authored-By: Claude Fable 5 <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.