Skip to content

v5: socket.yml patch rollout config and filtering - #293

Merged
Mikola Lysenko (mikolalysenko) merged 24 commits into
release/v5-prereleasefrom
v5/socket-yml-patch-config
Sep 29, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 24 commits into
release/v5-prereleasefrom
v5/socket-yml-patch-config

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Work item A of the v5 staged-rollout design (#290, docs/design/staged-rollout.md §9.1). scan reads the repo root's socket.yml and uses it to narrow what it patches. This covers hosted, vendored and agent mode (--dry-run included) and the in-memory engine behind the autopatch bot. The per-run cap (--max-new-patches, work item B) builds on the shared types this PR adds.

What users get

A patches block in the root socket.yml. Keep version: 2 so the scanner and socket-cli keep working; they strip or ignore the block.

# Critical first: widen by editing one line
version: 2
patches:
  minSeverity: critical   # later: high, then low, then remove the key
# One directory of a monorepo first
version: 2
patches:
  includePaths:
    - "/services/payments/"
# One ecosystem, hold one package
version: 2
patches:
  ecosystems: [npm]
  ignorePackages: ["pkg:npm/left-pad"]
# Pause: report only, existing patches stay in place
version: 2
patches:
  enabled: false
  • Keys: enabled, includePaths, ignorePaths, ecosystems, packages, ignorePackages, minSeverity (critical|high|medium|moderate|low) and maxNewPatches. maxNewPatches is validated here and enforced by B.
  • Paths: gitignore patterns with npm ignore semantics, matched against each project's lockfiles. A golden fixture generated from the npm package pins this.
  • Existing scanner key: projectIgnorePaths is now honored too.
  • Test/fixture defaults: test/ tests/ fixtures/ __fixtures__/ testdata/ are skipped by default for discovered roots (scan 'services/*', in-memory detection). This replaces the hard-coded list in the in-memory engine. Re-include one with ignorePaths: ["!/e2e/tests/"], on disk and in memory. A directory you name yourself is always scanned.
  • Flags only narrow further. New --min-severity <level|none> / SOCKET_MIN_SEVERITY beats the file's floor. New --no-socket-yml / SOCKET_NO_SOCKET_YML ignores the file.
  • Narrowing never removes a patch. A package that already has a recorded patch (manifest > hosted pins > vendor ledger) and is now filtered is left byte-identical. It is listed in policy.retained[] with upgradeAvailable. A recorded merged patch below a new floor is kept.
  • Fails closed. A broken file fails scan before any request or write: exit 1, errorCode: socket_yml_invalid (or socket_yml_ambiguous when socket.yml and socket.yaml disagree). The message names the key path, gives a did-you-mean hint, and suggests --no-socket-yml. Example: socket.yml: patches.minSeverty: unknown key (did you mean minSeverity?) ….
  • Reporting. Every successful scan --json gains a top-level policy block:
    "policy": {"source": "file", "path": "socket.yml", "sha256": "…", "enabled": true,
               "minSeverity": {"value": "high", "source": "file"},
               "counts": {"filtered": 3, "retained": 1},
               "filtered": [{"purl": "pkg:npm/qs@6.5.2", "uuid": null, "project": "services/legacy",
                             "reason": "policy_path_excluded", "detail": "/legacy/ (patches.ignorePaths)"}],
               "retained": [{"purl": "pkg:npm/lodash@4.17.20", "project": "", "recordedUuid": "…",
                             "reason": "policy_package_ignored", "detail": "…", "upgradeAvailable": true}]}
    Human output adds Policy (socket.yml): N skipped by filters, M patched packages held. and always names skipped critical/high patches.
  • Commands: get ignores the policy and warns policy_bypassed. A hosted/vendored PATH outside the repo root is exit 2. --global reads no file.
  • In-memory engine: two-phase selection (§7.2).
    • The host fetches the root socket.yml / socket.yaml first and passes it to selectHostedScanPaths as policyFiles: [{path, text} | {path, missing: true}], plus noSocketYml.
    • Selection applies the full path policy, negations included. It returns policyPaths, policySha256 and policyError. An excluded root goes into ignoredSample with its policy_* reason and is not streamed.
    • The session takes noSocketYml, minSeverity, policyPaths and policySha256. It fails socket_yml_invalid if the policy it reads differs from what selection read.
    • The result carries policy, or policyError with no root processed and no file changed.
    • hosted-bundle and index.d.ts have the new fields.

Trust boundary (CLI_CONTRACT.md): socket.yml may narrow or pace, never widen. Keys like apiUrl, apiToken, org, mode or downloadMode are unknown keys and fail validation.

Layout

  • crates/socket-patch-core/src/policy/ holds the frozen §9.0 contract:

    • SelectionPolicy, PolicySource, FilterReason, PolicyError, PolicyFs, Root, Offers;
    • package_spec_matches, moved from the CLI;
    • find_repo_root, repo_relative.

    It also holds the strict parser (socket_yml.rs) and the top-down gitignore matcher (paths.rs).

  • commands/scan/policy.rs, commands/scan/socket_yml_args.rs: disk glue and flags. discover_selected now returns Offers.

  • hosted_memory/select.rs: two-phase policy selection.

  • New deps, exact-pinned: serde-saphyr =1.3.0 and ignore =0.4.33.

  • CI: the test-release timeout goes from 40 to 50 minutes. A docs-only change already takes about 38 minutes, and this PR adds two crates and a test binary.

Decisions where the plan left a gap

These are recorded in docs/design/staged-rollout.md §9.4:

  1. YAML parsing: serde-saphyr's event parser, so aliases are never expanded, and anchors/aliases/merge keys are refused only inside patches/projectIgnorePaths. serde_norway can't refuse them per subtree.
  2. Disk markers match the in-memory lock markers; manifests are not markers. This keeps both engines' path results identical.
  3. Floor vs recorded patch: a ranking-based "keep recorded" rule stands in until B's search_result_supersedes.
  4. enabled: false: recorded packages go to retained[], the rest to filtered[].
  5. In-memory gaps until B's recorded view: there is no retained[] yet, and policy.filtered[] lists only the roots the session received.
  6. Two-phase handshake: §7.2 doesn't say how the session learns what selection saw. It is policySha256, returned by selection and passed to the session; a session that reads a policy file without it fails closed. policyFiles.text must be a lossless decode (Node buffer.toString('utf8'); TextDecoder drops a BOM).
  7. README recipes: R1/R5 (which depend on the cap) are left for B.

Tests

  • Core unit tests:
    • every §4.4 row;
    • BOM/CRLF/UTF-16/NUL, empty and absent files, alias bomb, depth, the both-files rules;
    • lookup with a .git dir, file or none, GIT_CEILING_DIRECTORIES and a foreign owner;
    • symlink inside/outside, directory, FIFO, oversize;
    • the 1377-case npm ignore golden fixture, and this repo's own socket.yml.
  • Disk e2e (tests/e2e_socket_yml_policy.rs, real binary, wiremock catalog, monorepo with npm roots and a gem):
    • filtering by path, ecosystem, package and severity in hosted, dry-run, agent and vendored mode;
    • PATH-glob defaults vs literal PATHs, includePaths, projectIgnorePaths;
    • invalid and ambiguous files (exit 1, no request, no bytes changed), --no-socket-yml;
    • flag/env precedence;
    • retained pins byte-identical in hosted and agent mode;
    • recorded merged patch kept, enabled: false, PATH outside the repo, and get's warning.
  • Parity (hosted_memory_parity.rs, through the real two-phase flow):
    • the same roots and packages are filtered on disk and in memory, and severity floors match;
    • a negation re-includes a default-ignored root, which is fetched and patched byte-identically to disk;
    • a withheld, changed, digest-less, invalid or half-bypassed policy gives policyError;
    • selection fails closed on a missing, symlinked or invalid policy file, and option precedence holds.
  • Parser contract: cli_parse_scan.rs rows for both flags and env vars.
  • Checks: cargo clippy --workspace --all-features --all-targets -D warnings is clean. The policy, in-memory, parity, scan and get suites pass locally.

CI failures inherited from the base (not this PR's)

🤖 Generated with Claude Code


Generated by Claude Code


Note

Medium Risk
Changes what scan patches in all modes and CI, but policy only narrows behavior with fail-closed validation and extensive e2e/parity tests.

Overview
scan now honors repo-root socket.yml to narrow patching across hosted, vendored, agent, dry-run, and the in-memory autopatch engine. A patches block (plus existing projectIgnorePaths) can disable writes, scope by gitignore-style paths/ecosystems/packages, and set a severity floor; existing recorded patches are never removed—filtered packages land in policy.retained[] with reporting via a new top-level policy JSON block and human Policy (socket.yml): … line.

CLI: --min-severity / SOCKET_MIN_SEVERITY and --no-socket-yml / SOCKET_NO_SOCKET_YML; invalid or ambiguous YAML fails scan before network or disk writes (exit 1, socket_yml_invalid / socket_yml_ambiguous). Discovered roots skip test/, tests/, fixtures/, etc. by default (negation supported); get bypasses policy with policy_bypassed warnings. Policy logic lives in new socket-patch-core policy (serde-saphyr, ignore); in-memory flow is two-phase (selectHostedScanPaths → session with policySha256). CI test-release timeout raised 40→50 minutes.

Reviewed by Cursor Bugbot for commit f680990. Configure here.

Adds the design for rolling Socket patches out gradually: a
`patches:` block in socket.yml that narrows what scan may patch
(paths, ecosystems, packages, severity floor, on/off), and a
severity-ordered per-run cap on new patches so each scan lands the
next few most critical fixes.

The plan splits the work into two parallel items with a frozen
interface, lists every hard-coded filter and where it belongs, and
covers the depscan autopatch follow-up. configuration.md now records
that socket-patch reads socket.yml for selection policy only, with
the trust boundary unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Three independent reviews (ambiguity, churn, trust boundary) found
gaps that would have let the two implementations disagree or let a
repo file widen or stall the rollout. The plan now:

- matches paths against marker files with the backend's top-down
  gitignore rules, so projectIgnorePaths means the same everywhere
- uses one data source for severity, supersession and ordering
- spends the budget only on patches the planning pass proves can
  land, and admits nothing new when a lookup failed
- uses the merged recorded view in every mode and engine
- has depscan read the policy from the base commit for PR jobs
- hardens file handling (regular files, aliases, size, encoding,
  trusted repo root) and reports what a policy hides

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A final consistency pass found places where the two work items
would have produced incompatible code: base purls admitted in one
directory being charged again in the next, no defined hand-off of
the unfiltered offers from the severity filter to classification,
no shared repo-relative path helper, and override sources the JSON
must report but the interface could not carry. The shared contract
now defines each of these, and the parity tests match each engine's
budget scope.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The plan said both that the selector returns the shared offers
struct (work item A) and that it returns admitted/deferred rows
(work item B). The selector now returns the offers, and B adds the
rollout stage after it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
New socket_patch_core::policy module: the SelectionPolicy, Offers and
repo-root helpers that the staged-rollout plan freezes as the shared
contract between the socket.yml work and the --max-new-patches work.

It reads the repo root's socket.yml/socket.yaml strictly and fails
closed: bad YAML, a misspelled `patches` block, unknown keys (with a
did-you-mean hint), wrong types, empty allowlists, bad globs and
anchors or aliases inside the keys we read are all errors that name
the key path. Path lists match marker files with npm `ignore`
semantics, walked top-down; a golden fixture generated from the npm
package pins that. The built-in test/fixture ignores become
overridable defaults for discovered roots.

--package matching moves to core so scan and the policy share it.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
scan now reads the repo root's socket.yml before any write and applies
its patches block in hosted, vendored and agent mode, --dry-run
included: path filters on project roots (PATH-glob matches also get
the built-in test/fixture ignores), ecosystem and package filters on
crawled packages, and a severity floor on the patches a package may
receive. An invalid or ambiguous file fails the run with exit 1 and
an errorCode before any request.

Packages that already carry a patch are never removed, upgraded or
replaced by the policy: they are held and reported under
policy.retained. A recorded patch below a new floor stays in place.
patches.enabled: false reports what would be patched and writes
nothing.

New flags: --no-socket-yml / SOCKET_NO_SOCKET_YML and
--min-severity / SOCKET_MIN_SEVERITY. Every successful scan --json
result gains a top-level policy block. A PATH outside the repository
root is a usage error.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
selectHostedScanPaths now streams the root socket.yml/socket.yaml and
returns them as policyPaths; it drops test and fixture trees through
the policy's built-in default ignores instead of a hard-coded segment
list (structural excludes like node_modules and vendor stay fixed).

The session reads the policy before any root is processed: path
filters run before the project limit, ecosystem and package filters
on each root's packages, and the severity floor before selection. A
listed policy file that arrives without content, or an invalid one,
yields policyError with no root processed and no file changed. New
options noSocketYml, minSeverity and policyPaths; the result gains a
policy block. hosted-bundle and index.d.ts carry the new fields.

get now warns policy_bypassed when the repo's socket.yml would have
skipped the package it patches.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CLI_CONTRACT.md gains a "socket.yml patch policy" section (grammar,
precedence, paths, lookup, validation, commands, error codes and the
policy JSON block), the flag and env rows, and the "narrow or pace"
half of the trust-boundary rule. README adds a "Roll out gradually"
section with copyable socket.yml recipes, CHANGELOG lists the new
policy and the breaking scan changes, and the design docs record the
decisions made while building it.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@socket-security

socket-security Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​ignore@​0.4.339810093100100
Addedcargo/​serde-saphyr@​1.3.09610093100100

View full report

@socket-security-staging

socket-security-staging Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​ignore@​0.4.339810093100100
Addedcargo/​serde-saphyr@​1.3.09610093100100

View full report

Fixes from an adversarial self-review of the policy work:

- A non-ASCII package spec no longer panics validation, and error
  text, warnings and verbose lines drop terminal escapes and bidi or
  zero-width characters.
- Ignore lists that fail to compile together are an error instead of
  silently matching nothing, and the policy file is opened by its
  resolved path without following a swapped-in symlink.
- A top-level key that looks like a misspelled `patches` (`patchs`),
  a top-level merge key or an aliased key now fails closed.
- Repo-root lookup follows a `.git` symlink and trusts the checkout
  owner under root and sudo, so CI containers keep the policy.
- The severity floor always reports the patch it held back, report-
  only --json runs report what a floor or `enabled: false` hides, a
  root skipped as a whole is always one entry and no longer prints
  "No packages found", warnings print once per invocation, and the
  policy line is omitted when there is nothing to say.
- policy entries are sorted and use canonical purls on disk and in
  memory; the in-memory engine applies a socket.yml negation of a
  built-in ignore to roots it was given, and policyError carries no
  CLI-only remedy.
- A lockfile-less disk root matches path filters by its manifests.

Tests cover each fix, plus the prune universe, agent path filters, a
vendored package held byte-identical, and tighter oracles; docs are
corrected where they overstated what the human output names.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] CI note: vlt patch compatibility / install-proof (…, vlt 0.0.0-*) fails the same way on both 48f2e78 and faa6ffc. The failing suite is e2e_redirect_vlt_build, with 5 hosted rollback tests:

  • hosted_crlf_lock
  • hosted_idempotence
  • hosted_resave_crlf_rollback
  • hosted_resave_install_rollback
  • hosted_rollback_byte_exact

In each, rollback exits 1 with hosted_wiring_contested / patched_ref_unattributable for a vlt-lock.json that has no lockfileVersion.

This is not caused by this PR. rollback never reads the socket.yml policy, and this diff doesn't touch the rollback or vlt code. The same 5 tests fail identically on #282 (run 36430532691), which only merged the current base (#283), and #279/#281 go red on this workflow too after the same merge.

I don't know of a fix to port yet. I'll re-run the failed jobs once when this run finishes.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] CI note: Poetry patch compatibility / native (macos-latest, 1.8.5) failed on faa6ffc, and failed again on its one re-run.

Which cases fail. Only the hosted cases fail:

  • direct hosted: ERROR, where poetry's own install raises SSLError → ConnectionError "Cannot install urllib3" while fetching from patch.socket.dev.
  • crlf hosted: poetryInstallExit0 and the install checks that depend on it.

The socket-patch side of those cases is fine: the relock keeps the patch, check --lock exits 0, and the VEX run emits 1 statement. The other cases in that job pass.

Why I don't think this PR causes it.

  • In the same run, the same faa6ffc binary passes 27 of the 28 poetry legs. That includes ubuntu-latest, 1.8.5 and every other macOS poetry version.
  • The failing step is poetry 1.8.5's HTTPS download on the macOS runner, and this diff doesn't touch the hosted rewriters or any URL.
  • The same leg passed on 48f2e78 20 minutes earlier.

I can't pull the capture artifact from this sandbox, so I can't prove it further. The re-run is used; I'll keep watching and look again if it shows up on the next push.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] test (windows-latest) fails in one target, -p socket-patch-cli --test covgap_commands_scan_mod. This PR does not change that test file.

This failure comes from the base branch:

No fix exists yet, so I haven't ported one. The job logs cut off before the failing test's name, so I can't propose a patch from here. I won't rerun this job, because the same failure on the base branch already rules out a flake.


Generated by Claude Code

The optimized test job now has to build two more crates and one more
test binary for the socket.yml policy. It ran out of time on its last
40 minutes, about a minute short, and a docs-only change already takes
38. Raise the limit to 50 minutes so it can finish.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in the merged staged-rollout plan (#290), the Windows scan
test fix (#288) and the docs-only design PRs. The plan's late
two-phase memory selection is implemented in the next commit.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The merged plan makes in-memory path selection two-phase: the host
fetches the root socket.yml first and passes its text to
selectHostedScanPaths. Selection now applies the full path policy, so
a negation such as `!/e2e/tests/` brings a test tree back in memory
exactly as on disk. A listed policy file that is missing, symlinked
or invalid returns policyError with nothing selected.

Selection returns policySha256, and the session fails closed when the
policy it reads differs. Roots the policy excludes keep their marker
files presence-only, so the session still lists them as filtered.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Review follow-ups to two-phase selection:

- Roots the policy excludes are reported in ignoredSample instead of
  streamed presence-only, so a repo with many fixture lockfiles no
  longer runs into the session's file limit.
- A session that bypasses socket.yml while selection applied it now
  fails closed instead of processing roots it never fetched.
- The docs say policy text must decode losslessly (TextDecoder drops
  a BOM) and when policySha256 is null.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Merged release/v5-prerelease after #290 landed, and implemented the plan's late change to §7.2 (commit 82f5b00: two-phase in-memory selection).

What changed

  • Two-phase selection: selectHostedScanPaths now takes policyFiles: [{path, text} | {path, missing: true}] and noSocketYml, and applies the full socket.yml path policy, negations included. So ignorePaths: ["!/e2e/tests/"] selects, fetches and patches that tree in memory exactly as on disk, which a new parity test checks against disk.
  • Fail closed at selection: a listed policy file that isn't passed, is passed missing, is symlinked or is invalid returns policyError, and nothing is selected.

Gap decisions (recorded in staged-rollout.md §9.4, item 9)

  • How the session learns what the selector saw: §7.2 doesn't say. Selection returns policySha256 (null with no file, an empty file, or noSocketYml), and the session takes it as an option. A session that reads a policy file with a different digest, or with none, fails socket_yml_invalid. So does a bypassed session that is given a digest.
  • Excluded roots: a root the selector excludes is not streamed. It is reported in ignoredSample with its policy_* reason, so in memory policy.filtered[] lists only the roots the session received. Streaming presence-only markers instead would count every fixture lockfile against maxFiles.
  • Decoding: policyFiles.text must decode losslessly. Use Node's buffer.toString('utf8'); TextDecoder drops a BOM, and the session then sees different content.

Other changes

  • Test job timeout: test-release passed in about 39 minutes on b975913 under the new 50-minute limit.
  • Windows failure: the base-branch failure in covgap_commands_scan_mod should clear now that v5 fix: unblock the e2e tier on the v5 base #288's fix is merged in.

Checks run locally: clippy (--all-features --all-targets) is clean, and the in-memory, parity, socket.yml end-to-end and CLI parse tests pass. The full workspace run has 19 local-only failures: write-failure tests that don't fail as root, and one peak-memory check. None is in code this PR changes.


Generated by Claude Code

Brings in 28cebf7, which fixes the hosted rollback failures the vlt
compatibility legs hit on this branch.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Update on the vlt compatibility failures, now at 4b71112 (base 28cebf7 is merged in):

  • Failing now: three install-proof legs, vlt 0.0.0-1 and 0.0.0-11 (plus the 0.0.0-1 / Node 22.0.0 leg). They fail three tests in e2e_redirect_vlt_build.rs: vlt_pinned_matrix_hosted_crlf_lock, vlt_pinned_matrix_hosted_idempotence and vlt_pinned_matrix_hosted_rollback_byte_exact. Rollback exits 0 but doesn't restore the lock byte for byte.
  • Why this isn't this PR's: the base's own dispatched vlt run on 28cebf7 (run 36454568301) fails exactly these three tests on the same legs. This PR doesn't touch the rollback or vlt code.
  • Fixes merged so far:
  • Remaining fix: none exists for the last three tests yet. I'll merge it here as soon as it lands on the base.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] The yarn-classic legs (1.0.2, 1.7.0, 1.9.4, …) fail in the mode_migration_npm suite. This PR didn't cause it:

  • Cause: mount_registry_from_classic_lock (tests/mode_migration_npm.rs:407) panics with "no integrity in …". Old yarn 1.x releases write a yarn.lock with only resolved and no integrity line. I reproduced it locally with yarn 1.7.0, and it passes with 1.22.22.
  • Not this PR's: this PR doesn't touch that test or scripts/yarn-classic-vex-matrix.sh. PR ci: pin TLS-verified patch hosts on macOS compat legs (fix hosted DNS flake) #295, on the same base with only CI changes, fails the same legs (1.0.2, 1.6.0, 1.7.0, 1.9.4) in run 36455144314. These legs seem to have started running after v5 fix: unblock the e2e tier on the v5 base #288's CI tier change.
  • Fix: none exists yet. The fix belongs in the test helper, which would fall back to the tarball's sha1 from the resolved URL fragment when there's no integrity line. I'm not widening this PR to include it.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#281 landed on release/v5-prerelease as 73c0c4f; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #281 (one lockfile model per ecosystem). No conflicts;
clippy and the policy, memory, parity and scan suites pass.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#279 landed on release/v5-prerelease as f6bdad5; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #279 (setup removed, patch UI streamlined). Conflicts:
- core lib.rs keeps `policy` and drops `setup`.
- scan keeps policy-aware selection (`select_accessible`) and the
  base's `selection_args`, which `get` now uses.
- CLI_CONTRACT exit-code rows take the base's text plus the
  socket.yml rows.

Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The v5 help rules cap each command's short help at about eight
options. `--no-socket-yml` and `--min-severity` pushed `scan -h` to
ten, so they now appear only in `scan --help`, like the other
advanced scan flags.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review September 28, 2026 20:37
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head f680990 is merged up to release/v5-prerelease at f6bdad5 (#279) with no conflicts outstanding. CI results on this head:

  • All workflows pass except the legs the base branch already fails on:
    • CI: 233 jobs; only yarn-classic 1.0.2 / 1.6.0 / 1.7.0 / 1.9.4 fail.
    • vlt: 87 jobs; only the 0.0.0-1 / 0.0.0-11 install-proof legs fail, on the three hosted-rollback tests.
  • f680990 fixes the coverage/test failure on the previous head. v5: remove setup (WS7) + patch UI streamlining (WS8) #279's new help_text_hygiene test caps scan -h at about 8 options, so --no-socket-yml and --min-severity now appear only in scan --help.

Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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.

Fix All in Cursor

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

Comment thread crates/socket-patch-cli/src/commands/scan/mod.rs
Comment thread crates/socket-patch-cli/src/commands/scan/policy.rs
A report-only `scan --json` (`--prune` with no mode) with a severity
floor or `enabled: false` fetches patch details to fill
`policy.filtered[]`. If every query failed it still printed a success
envelope and exited 0. It now reports the error and exits 1, like the
agent and vendored runs.

Human-mode policy warnings now print `Warning: <detail>` like the rest
of `scan`; the code stays in the JSON `warnings[]` entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#282 landed on release/v5-prerelease as 14a9cb0; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #282, which moves the in-memory engine into
socket-patch-core (`hosted::memory`). The two-phase policy selection
moves with it. Conflicts:
- `canon`, `FilteredEntry`, `RetainedEntry` and `policy_block` move
  from the CLI into `socket_patch_core::policy`, so the core engine
  and disk scans share one `policy` block.
- `roots` is now public in core, for disk scans' marker lookup.
- scan reads the ledgers and wiring through the base's
  `ProjectContext`, and keeps loading the recorded view before
  filtering.
- CLI_CONTRACT's hosted-bundle row takes the base's path, plus the
  policy fields.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head 0881dedd merges release/v5-prerelease at 14a9cb07 (#282), with conflicts resolved.

What the merge changed. #282 moved the in-memory engine into socket-patch-core, and the two-phase policy selection moved with it.

This head also includes 65ef71fd, which fixes both Bugbot findings. Those threads are resolved.

CI on 0881dedd. Every workflow is green except the legs the base branch already fails on:


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#291 landed on release/v5-prerelease as f9cb7e1; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #291, which builds the e2e test binaries once and tiers the
package-manager matrix. The only conflict is the `test-release`
timeout: it takes the base's 40 minutes. The 50 minutes here was sized
for the two feature-set builds that #291 removes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head 997a6f50 merges release/v5-prerelease at f9cb7e13 (#291).

  • Conflict: only the test-release timeout. I took the base's 40 minutes, because v5 CI: build e2e binaries once and tier the PM matrix #291 removed the second feature-set build that the 50 minutes here was sized for. test-release now finishes in about 16 minutes on this head.
  • CI on 997a6f50: every workflow passes except the jobs the base branch also fails:
    • CI: 182 jobs; only yarn-classic 1.0.2 / 1.6.0 / 1.7.0 / 1.9.4 fail.
    • vlt: 87 jobs; only the 0.0.0-1 / 0.0.0-11 install-proof legs fail.
  • Reviews: no new review findings. Both Bugbot threads are resolved.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#292 landed on release/v5-prerelease as a7b0d00; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #292, which fixes the partial-stage repair bug and cuts
redundant downloads. No conflicts; clippy and the policy, in-memory,
parity, e2e policy, parser and help suites pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head 0c5a8cd4 merges release/v5-prerelease at a7b0d00e (#292).

  • Merge: clean, with no conflicts. Clippy passes, as do the policy, in-memory, parity, e2e policy, parser and help suites.
  • CI on 0c5a8cd4: every workflow passes except the legs the base branch also fails:
    • CI: 182 jobs; only yarn-classic 1.0.2 / 1.6.0 / 1.7.0 / 1.9.4 fail.
    • vlt: 87 jobs; only the 0.0.0-1 / 0.0.0-11 install-proof legs fail.
  • Reviews: no new review findings.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#296 landed on release/v5-prerelease as 1e3ace6; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #296, which removes dead code and the v3 compatibility
shims. The only conflict is CLI_CONTRACT's exit-code rows: they take
the base's text (no `--detached`, `--one-off` removed) plus the
socket.yml and SOCKET_MIN_SEVERITY rows. Clippy and the policy,
in-memory, parity, e2e policy, parser, help and scan suites pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] test (windows-latest) failed on d9dd0ff in update_notifier_e2e, and every other target passed. The e2e matrix was skipped because it depends on this job. This PR doesn't touch the notifier test or the update code, all 39 notifier tests pass locally on this head, and the job passed on this PR's earlier heads with the same notifier code. It looks like a Windows timing failure (the test has wall-clock budgets, e.g. grace_budget_bounds_command_latency). The failing assertion isn't in the API's 5,000-line log tail, so I can't confirm which test. I've re-run the failed jobs once. If it fails again I'll treat it as real and look into it.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head d9dd0ff merges #296 (base 1e3ace6) with conflicts resolved. CI has finished on this head:

  • The re-run of test (windows-latest) passed, so the earlier update_notifier_e2e failure was a one-off. All three test legs are green, and the e2e matrix ran.
  • The only failures are legs that also fail on the base: yarn-classic 1.0.2/1.6.0/1.7.0/1.9.4, and vlt install-proof ubuntu 0.0.0-1 (Node 22 and default), ubuntu 0.0.0-11 and windows 0.0.0-11.
  • No review threads are open. The PR is not a draft.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

#297 landed on release/v5-prerelease as b97a1c2; please merge origin/release/v5-prerelease again, resolve conflicts, get green, and keep it ready.


Generated by Claude Code

Brings in #297, which groups the CLI tests into one binary per command
and replaces the #257 oracles with golden files. It merges cleanly;
this PR's test binaries stay at the top level, as most still do.
Clippy and the policy, in-memory, parity, e2e policy, parser, help,
scan and get suites pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsyzefGhAnPkYmXCwq3H3
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] ready to land

Head 29674bb merges #297 (base b97a1c2) with no conflicts. CI has finished on this head:

  • CI, vlt, Bun, PDM, pnpm, Poetry, npm and Pipenv all completed. All three test legs and the e2e matrix pass.
  • The only failures are legs that also fail on the base: yarn-classic 1.0.2/1.6.0/1.7.0/1.9.4, and vlt install-proof ubuntu 0.0.0-1 (Node 22 and default), ubuntu 0.0.0-11 and windows 0.0.0-11.
  • No review threads are open. The PR is not a draft.

Generated by Claude Code

@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit b9e106d into release/v5-prerelease Sep 29, 2026
437 of 445 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the v5/socket-yml-patch-config branch September 29, 2026 10:20
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Sep 29, 2026
Brings in #293, the socket.yml rollout config this branch builds on.
This branch already carries every change #293 made, so every conflict
resolves to this branch's side and the tree matches the previous head
exactly. No code changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AvGSu5jGg1z3f3sePc2eHC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants