Repository navigation
Fix Go vex of +incompatible module patches (#484) - #1427
Conversation
Assisted-by: Claude Code:claude-opus-5-5
The patch API keys a +incompatible Go module as @v2.0.0%2Bincompatible, but go.mod spells the version with a literal +. vex compared the two spellings as plain strings, so an applied agent-mode Go patch for such a module was never verified: vex said not_applied and exited 1, leaving the patch out of the OpenVEX doc. Match Go purls by release identity (PurlKey) when looking up the manifest record for a go-patches replace, and in the go.work override filter, so a go.work replace that overrides a %2B-keyed patch is still caught and never attested. Fixes #484 Assisted-by: Claude Code:claude-opus-5-5
Follow-up to the +incompatible fix. When go.work overrides a Go patch, or the build selects another version, vex now names the omitted patch by the manifest's own purl (with %2B), not the go.mod spelling, so --json consumers can join omissions to manifest keys. The copy-dir lookup now maps every record spelling of the release, deterministically. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ 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 f63372d. Configure here.
|
Labeled Ready for review at head
Slack announcement not sent this run (Slack send unavailable); the next run will retry. Generated by Claude Code |
Final review briefWhat it does: Fixes #484. The patch API writes a Risk: low. The change only touches Go purl matching in vex, and it fails closed:
Look here
Verified
Changes I made: none. Open questions (non-blocking):
Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #484
Summary
socket-patch vexnow attests an applied agent-mode Go patch for a+incompatiblemodule. Before, it saidnot_appliedand exited 1 becauseit couldn't match the go.mod spelling of the version to the manifest key.
Root cause
The patch API keys a
+incompatibleGo module aspkg:golang/M@v2.0.0%2Bincompatible.vexrebuilds Go purls fromgo.modreplace entries withbuild_golang_purl, which spells the+literally, and then compared that string to manifest keys byte for byte:
synthesize_go_patches(manifest.patches.contains_key(&purl)) missedthe
%2Bkey. The go-patches copy dir was never verified, so vex fellback to the pristine module cache and reported
not_applied. This is theAgent-mode Go vex omits an applied patch for a +incompatible module (not_applied, exit 1) because it looks up the manifest with a literal "+" while the API key spells it %2B #484 symptom.
strip_purl_qualifiers(p) != purl) used thesame exact-string compare. With only the first lookup fixed, a
%2Bpatch whose replace go.work overrides would slip past this filter and be
attested while the build links the user's replacement. A mutation run
confirmed this: reverting only this half makes the new test attest and
fail. Both halves are fixed together, so the change stays fail-closed.
Change (
crates/socket-patch-cli/src/commands/vex.rs)version-not-selected filter are now matched by release identity
(
PurlKey, percent-decoded) instead of by string equality.release (deterministic; it used to be one exact key), and omissions are
reported under the record's own purl (
%2B) so--jsonconsumers canjoin them to manifest keys.
qualified Go key (e.g. `pkg:golang/M@v1?x=y`) to the replace's copy dir,
which the old exact lookup never did. This stays fail-closed: each record is
still verified against its own file hashes, and the copy path comes from
go.mod coordinates, not the key. If a manifest holds both the `+` and
`%2B` spellings, each omitted record gets its own warning, one per spelling.
Tests
New
covgap_commands_vex::go_patches_replace_of_an_incompatible_module_matches_the_encoded_keyis hermetic and needs no Go toolchain. It uses a
%2Bincompatiblemanifestkey, a go.mod
+incompatiblego-patches replace and a hash-matching copy dir:package_not_foundomission (red)not_affectedstatement for the%2Bpurl(go_workspace_override)under the%2Bpurlv2.1.0+incompatible(go_version_not_selected)under the%2BpurlPer-issue checklist:
mainand green with the fixLocal runs (Linux, go 1.24.7):
cargo fmt --all -- --check: okcargo clippy --workspace --all-features -- -D warnings: okcargo test -p socket-patch-cli --all-features --test covgap_commands_vex --test e2e_golang_build --test e2e_golang_workspace_build --test e2e_vex_vendor --test e2e_vex_lockfile -- --include-ignored: 470 passed--lib,e2e_vex,e2e_vex_redirect,vex_terminal_output,e2e_golang: all passcargo test --workspace --all-features --no-fail-fast: 14229 passed, 13 failed. None of the failures are in this diff's path, and all of them come from the sandbox: write-failure-injection tests that usechmod 0o555, which the sandbox's uid 0 ignores (covgap_commands_vendor,repair, core--libwrite-failure tests,in_process_redirect), and one bun test that needspatches-api.socket.dev, which the sandbox proxy blocks. CI runs these as non-root.No wrapper changes are needed:
npm/,pypi/andgem/only dispatch to the binary.Review notes (
/code-review high)Fixed: nondeterministic single-key lookup, omissions named under the
go.mod spelling, the missing version-not-selected coverage, and the
per-element
PurlKeyrecompute.Not changed:
assume_applied/known_stalesets still compare byqualifier-stripped string. Both sides come from the API in the same
spelling, and switching them to
PurlKeywould also change PyPI and NuGetname folding for every ecosystem, which is outside this fix.
Start fix for #484commit is this automation's claim marker.It goes away on a squash merge.
🤖 Generated with Claude Code
https://claude.ai/code/session_01P36de77ifXHcVkDgy5ozXo
Generated by Claude Code