@@ -23,6 +23,193 @@ a version without a non-empty section in this file.
2323
2424## [ Unreleased]
2525
26+ ## [ 5.1.0] — 2026-11-06
27+
28+ ### Added
29+
30+ - ** RubyGems.**
31+ - ** Agent mode patches gems with native (C) extensions for real.** When
32+ ` apply ` (or ` scan ` / ` get --mode agent ` ) patches a gem whose patch changes
33+ native-extension sources (such as ` ext/**/*.c ` or an ` extconf.rb ` ), it
34+ now rebuilds the gem's extensions with RubyGems' own builder, the step
35+ ` gem pristine --extensions ` runs, using the Ruby that owns the gem home.
36+ Both the copy under ` extensions/<platform>/<abi>/ ` and the copy under the
37+ gem's ` lib/ ` are rebuilt, so Ruby stops loading the stale install-time
38+ ` .so ` / ` .bundle ` . A build that fails puts the original sources and build
39+ back (` native_extension_build_failed ` ), and a copy that can't be rebuilt
40+ in place (a precompiled platform gem, a Bundler git checkout, no matching
41+ Ruby) is refused with ` native_extensions_unsupported ` before anything is
42+ written. Sources an earlier release patched without a rebuild are rebuilt
43+ on the next ` apply ` (` native_extension_rebuilt ` warning). ` vex ` and
44+ ` apply --check ` attest such a patch only once its rebuild is recorded,
45+ and otherwise report ` native_extension_not_rebuilt ` . ` rollback ` and
46+ ` remove ` restore the original build. Callers that compile the extension
47+ themselves can opt out with ` --no-gem-native-rebuild ` (env
48+ ` SOCKET_NO_GEM_NATIVE_REBUILD ` ): the sources are written without a
49+ rebuild, with a ` native_extension_not_rebuilt ` warning, and ` vex ` does
50+ not attest them. Hosted copies are unaffected, since RubyGems compiles
51+ the patched gem itself (#1996 , #1998 ).
52+
53+ ### Fixed
54+
55+ - ** RubyGems.**
56+ - With Bundler 4.1 ` override "other", with: "gem", in: "parent" ` , hosted
57+ ` rollback ` and ` remove ` treat the override target as transitive and give
58+ back the original lock and Gemfile byte for byte, instead of writing a
59+ new exact ` gem "gem", "x.y.z" ` pin that blocked later upgrades (#1989 ,
60+ #1991 ).
61+ - Gemspec directives and development dependencies are read as Ruby code:
62+ ` =begin ` /` =end ` blocks, heredoc bodies and ` __END__ ` data are skipped, so
63+ a commented-out dev dependency no longer adds a bogus requirement and a
64+ heredoc no longer refuses the Gemfile (#1932 , #1936 ).
65+ - A gem declared inside nested ` source … do ` blocks is attributed to the
66+ innermost block, as Bundler reads it, so hosted ` rollback ` and ` remove `
67+ of a pin inside the user's own source block no longer refuse with
68+ ` hosted_wiring_contested ` on Bundler 2.1 and older (#1997 , #1999 ).
69+ - ** npm family.**
70+ - pnpm workspace globs with brace sets and character classes
71+ (` packages/{a,b} ` , ` packages/[ab]* ` ) are read the way pnpm reads them in
72+ every mode instead of being refused or read as every directory; shapes
73+ pnpm reads its own way (extglobs, ` [!a] ` , a ` + ` after a class, stepped or
74+ punctuation-spanning brace ranges) are still refused, and commented
75+ importer lines in ` pnpm-lock.yaml ` are ignored (#1846 , #1863 ).
76+ - Quoted values, YAML escapes and duplicate keys in ` pnpm-workspace.yaml ` ,
77+ ` .yarnrc.yml ` and ` .modules.yaml ` decode one way, as pnpm reads them, so
78+ settings such as ` modulesDir ` or ` lockfileDir ` no longer resolve to
79+ different paths depending on the command (#1918 , #1973 ).
80+ - yarn classic's ` .yarnrc ` is read as yarn 1.22 reads the whole file:
81+ ` --modules-folder 'deps' ` no longer sends the crawler to a folder yarn
82+ never installs into, and a file yarn can't parse sets nothing (#1901 ,
83+ #1915 ).
84+ - A malformed ` package.json ` ` workspaces ` field (a non-string item, ` null ` ,
85+ the wrong type) is judged the same way everywhere; the Bun member walk
86+ falls back to ` bun.lock ` instead of reading no members (#1900 , #1971 ).
87+ - ` apply ` and ` rollback ` no longer touch package copies inside a store
88+ nested in another store's entry, which ` scan ` never reports, and keep
89+ the peer-variant copies of a project that lives under ` ~/.bun ` ,
90+ ` ~/.deno ` or ` ~/.vlt ` (#1899 , #1986 ).
91+ - Hosted npm warns ` redirect_npm_omit_lockfile_registry_resolved ` when any
92+ npm config layer sets ` omit-lockfile-registry-resolved ` , which makes the
93+ next ` npm install ` drop the hosted URL and fail with ` EINTEGRITY ` , and
94+ names where it is set and the remedies (#1871 , #1872 ).
95+ - Hosted vlt scans no longer download every granted patch archive to
96+ check its encoding, and no longer withhold dependencies with
97+ ` redirect_vlt_artifact_unverifiable ` ; a mirror that re-encodes archives
98+ makes ` vlt ci ` fail closed with ` EINTEGRITY ` . The in-memory hosted
99+ engine (the Node addon and ` hosted-bundle ` ) now pins vlt dependencies
100+ instead of withholding them as offline (#2013 ).
101+ - The lock inventory skips Rush subspace locks with unsafe names, as
102+ lockfile discovery already did (#2003 ).
103+ - ** PyPI.**
104+ - A requirements line pinned through an environment variable
105+ (` six==${SIXV} ` ) is refused by ` vendor ` with
106+ ` pypi_requirement_env_templated ` , and ` vendor --check ` and ` vex ` read it
107+ as possibly installing any release, so the patch is no longer attested
108+ while ` pip install -r ` can install the unpatched one (#1873 , #1874 ).
109+ - A hosted scan of a Python project with no lockfile the rewriters read now
110+ warns ` redirect_pypi_no_lockfile ` , naming the files looked for and the
111+ project's own lock command, instead of passing silently (#638 , #1885 ).
112+ - After a hosted rollback, a vendored rollback or ` vendor --revert ` of a
113+ requirements-file pin, the reinstall advisory covers pip and names the
114+ requirements files to reinstall from (#1953 , #1954 ).
115+ - The hosted Pipenv stale-install warning ends with the same runnable
116+ remedy as vendored mode and never prints an option-like package name
117+ into a shell command (#1878 , #1883 ).
118+ - A ` poetry.lock ` in an old format (0, 1.0, 1.1) keeps its "written by
119+ Poetry < 1.4" warnings and refusals even when a hand-merged header claims
120+ a newer Poetry (#1847 , #1865 ).
121+ - Hosted ` rollback ` , ` remove ` and ` scan ` restore the pins hosted mode
122+ writes into uv 0.2 ` [[distribution]] ` locks (uv < 0.2.35) instead of
123+ refusing them (#2014 ).
124+ - ** Go.**
125+ - In a go 1.16 (unpruned) module where a dependency imports a fork that
126+ the root ` go.mod ` replaces with the patched module, ` apply ` ,
127+ ` apply --check ` , hosted mode and ` vex ` read the module graph to tell
128+ whether the patch is really built, instead of reporting it applied
129+ while ` go build ` linked the unpatched code (#1840 , #1843 ).
130+ - ` vex ` reads the ` go.work ` that governs the project (` GOWORK ` , else the
131+ nearest one at or above it, with members anywhere), as hosted and
132+ vendored modes already did, and no longer attests a Socket replace the
133+ workspace keeps out of the build (` go_workspace_override ` ) (#2011 ).
134+ - ** JVM.**
135+ - A Maven 4 root that builds its subdirectories implicitly (model 4.1.0,
136+ ` pom ` packaging, no ` <subprojects> ` ) is treated as a reactor by hosted
137+ mode, ` vex ` and the Maven cache scope, not only by vendored mode, so a
138+ root-only pin is no longer attested while a module keeps its own
139+ version (#1809 , #1886 ).
140+ - Hosted Maven keeps every line of ` .mvn/checksums/checksums.sha256 ` it
141+ doesn't own (single-space or ` * ` sha256sum lines, tabs, comments) and
142+ the file's line endings, instead of silently dropping them (#2016 ).
143+ - Vendored Maven ` vex ` no longer attests a build that may still use the
144+ unpatched jar: an executable classifier copy of the patched artifact,
145+ or a suffixed version left only in a plugin, profile or unused property,
146+ now withholds attestation (#2006 ).
147+ - Vendored Gradle withholds attestation when a ` gradle.lockfile ` locks
148+ the patched artifact at another version
149+ (` gradle_lock_overrides_vendored ` ) or a custom ` lockFile ` location is
150+ used (` gradle_custom_lock_file ` ) (#2004 ).
151+ - sbt: ` vex ` no longer attests a hosted pin that a build reassignment of
152+ ` dependencyOverrides ` or ` resolvers ` , ` sbt.override.build.repos=true ` ,
153+ or newer resolution evidence shows the build doesn't apply
154+ (` vex_sbt_pin_bypassed ` ) (#2030 ), nor a vendored pin without current
155+ sbt resolution evidence or with its vendored tree missing
156+ (` vex_sbt_resolution_unverified ` , ` vex_sbt_vendored_tree_missing ` )
157+ (#2008 ).
158+ - ** NuGet.** When a ` packages.lock.json ` locks a patched package at a
159+ version the writers refuse to wire (another target framework or
160+ project), ` vex ` no longer attests that version
161+ (` vex_nuget_lock_other_version ` ); ` 1.0 ` and ` 1.0.0 ` count as one version
162+ (#2007 ).
163+ - ** Composer.** A ` composer.lock ` with a UTF-8 BOM is read everywhere,
164+ and vendor then ` --revert ` keeps the BOM byte for byte; a revert no
165+ longer deletes a vendored artifact such a lock still installs from
166+ (#2017 ).
167+ - ** Vendoring.**
168+ - Vendored dry runs leave already-vendored patches out of the "Would
169+ download and vendor" headline and list them as skipped, matching the wet
170+ run and the JSON (#1850 , #1856 ).
171+ - Run from a workspace member with no lockfile of its own, a vendored
172+ ` scan ` , ` get ` or ` vendor ` names the lock that installs the member and
173+ where to run from (#1904 , #1913 ).
174+ - npm package-lock packages installed from a URL or git spec, and workspace
175+ members, are refused before their patch is downloaded; dry runs preview
176+ them as refused and they no longer hold a ` --max-new-patches ` rollout
177+ slot (#1976 , #1977 ).
178+ - In a vlt project, ` vendor ` no longer requests service downloads for
179+ packages it then refuses (#1909 , #1947 ).
180+ - Every vendored entry point (` scan ` previews and rollout plans, the
181+ download phase, ` get ` , and ` vendor ` ) applies the same refusals before
182+ any download: a v1 ` package-lock.json ` project, or a hosted pnpm pin
183+ whose takeover would be refused, is refused before its patch is
184+ fetched; ` get <uuid> --mode vendored ` reports every such refusal and
185+ writes nothing; and ` vendor ` refuses before restoring a hosted pin
186+ instead of restoring it and rolling back. Codes and details are
187+ unchanged (#2015 ).
188+ - A vendored revert keeps an artifact the lock still references through
189+ an escaped path spelling (` \/ ` in an older ` composer.lock ` , Windows
190+ backslashes) instead of deleting it (#2022 ).
191+ - ** General.**
192+ - The nested-project remedy quotes its path for the shell it prints for,
193+ including Windows and ` % ` (#1859 , #1884 ).
194+ - Patch and vendor download errors read the same on every path (size
195+ limit, HTTP status with a bounded body excerpt), and artifact downloads
196+ log under ` --debug ` (#1869 , #1870 ).
197+
198+ ### Maintenance
199+
200+ - Code consolidation with no output change: one lock-rewrite driver for
201+ Poetry and PDM (#1898 ) and module sweeps across the CLI and core
202+ (#1855 , #1864 , #1875 , #1884 , #1892 , #1897 , #1903 , #1907 , #1914 , #1920 ,
203+ #1923 , #1929 , #1939 , #1948 , #1967 , #1975 , #1985 , #1990 ).
204+ - Test and CI infrastructure: shared test env guard, docker harness, PTY
205+ runner, ` copy_tree ` and apply fixtures; hermetic children scrub color
206+ variables; failing tests are annotated in CI; offline bun.lockb rollback
207+ mock and a Windows venv layout in the PyPI fixture (#1891 , #1890 , #1905 ,
208+ #1944 , #1955 , #1964 , #1972 , #1978 , #1988 , #1994 , #2000 ); release
209+ workflow artifact steps move off Node 20 actions (#2027 ). A design doc
210+ and line-count budget plan one lock model for every lockfile reader
211+ (#2001 ).
212+
26213## [ 5.0.1] — 2026-10-13
27214
28215### Fixed
0 commit comments