Repository navigation
Fix Go replace for unselected versions (#391, #392, #509) - #1403
Merged
Mikola Lysenko (mikolalysenko) merged 6 commits intoOct 12, 2026
Merged
Conversation
This was referenced Oct 11, 2026
A Go replace names an exact module version. When the build list selects another version (a later go get, or a go 1.16 graph where a transitive dependency asks for a newer one), the replace is ignored and the build links the unpatched module. Agent apply wrote such a replace and reported it applied, apply --check passed it in go 1.16 graphs, vex attested not_affected, and the hosted gate took a go.sum /go.mod-only line as proof the version was built. All four now ask one helper that reads go.mod and go.sum: require for go 1.17+, and for older graphs the highest of require and the go.sum zip-line versions. apply refuses, apply --check flags, vex omits with go_version_not_selected, and hosted warns and skips. Fixes #391, #392, #509. Assisted-by: Claude Code:claude-opus-5-5
The not-in-graph warning now says go.sum has no zip line for the version, since a /go.mod-only line no longer counts. Checked that the old golden still matches with the old wording, so only the message changed. The +incompatible reconcile test now requires the version it applies. Assisted-by: Claude Code:claude-opus-5-5
A go 1.16 go.sum zip line below the patched version now shows that lower version is built, so apply and apply --check catch it again. Vendored mode gets the same build-list gate before it fetches or wires a module. The hosted not-in-graph warning no longer claims go.mod lacks a require it may have, and the zip-line rule lives in one place. Assisted-by: Claude Code:claude-opus-5-5
The download plan has to name exactly the modules vendor asks the service for, so it now skips a version the build doesn't select, as vendor itself does. Adds a regression test for vendoring an unselected version in a go 1.16 graph. Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 11, 2026 23:25
Collaborator
Author
|
BugBot review Generated by Claude Code |
The vendor suite pinned apply exiting 0 when go.mod requires a newer version than the patch, though the replace it wrote was ignored. It now expects the refusal that names the selected version (#392); apply --check still reports the drift. Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
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 598055a. Configure here.
Wenxin Jiang (Wenxin-Jiang)
approved these changes
Oct 12, 2026
Collaborator
Author
|
Ready for review (burn-down agent)
Generated by Claude Code |
This was referenced Oct 12, 2026
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-go-selected-version-gate
branch
October 12, 2026 02:57
This was referenced Oct 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #391
Fixes #392
Fixes #509
Summary
Go keys a
replaceby module and version. When the build listselects a different version, a replace pinned to the patched version is
silently ignored and the build links the unpatched module. Every Go path
used its own partial go.mod/go.sum heuristic to decide whether a version
is built, so each reported a patch as applied or attested when it wasn't:
apply(#392)vendor(#392, vendored variant in a comment)vendor_go_version_not_selectedapply --check(#392, go 1.16)ResolvedVersionMismatchvex(#391)not_affectedfrom the intact copygo_version_not_selected(agent, vendored and hosted replaces)/go.mod-only line counted as "in the graph"redirect_golang_version_mismatchRoot cause and fix
There was no shared answer to "does the build list select
M@v?". The newvendor::go_build_listanswers it offline from go.mod and go.sum, and everycall site above uses it:
requireis authoritative. If the moduleis absent, it is built only if go.sum has its zip line.
godirective):requireholds only lower boundsand leaves out transitive modules. The selected version is the highest of
the required version and the go.sum zip-line versions. A
/go.modline is written for every version MVS reads, so it doesn't count. With
no evidence at or above the patched version (as after
go mod tidydrops a directory-replaced original's lines), the answer is unknown and
nothing is flagged, unless a zip line below the patched version shows
that lower version is built.
member may require the module.
Docs: CLI_CONTRACT.md (golang agent section and the hosted rule) and
docs/ecosystems.md (Go).
Tests (red on
main, green here)Each new regression test was applied to unmodified
origin/mainand failedthere:
golang_local::tests::test_apply_refuses_a_version_the_build_does_not_select: go 1.16 graph, go 1.21requirebump, and a module the project doesn't use. FAILED on main.golang_local::tests::test_verify_flags_go116_transitive_version_mismatch:apply --checkin a go 1.16 graph. FAILED on main.vendor::golang::tests::test_vendor_refuses_a_version_the_build_does_not_select. Added with the vendor gate./go.mod-only line as "in the graph", so on a go 1.16 module it writes an inert replace for an unselected version and VEX attests not_affected #509redirect::tests::golang_go116_go_mod_only_line_is_not_the_selected_version. FAILED on main.go getupgrades the patched module, although the go-patches replace no longer applies and the build links the unpatched code #391covgap_commands_vex::go_patches_replace_for_an_unselected_version_is_not_attested: go 1.21go getbump and the go 1.16 graph are omitted; the selected and unknown controls still attest. FAILED on main.test_apply_go116_selected_version_still_applies, where the selected version applies and stays in sync after tidy. Passes on both.go_build_list::tests).Commands run locally (Linux, go 1.24.7):
cargo fmt --all -- --check: cleancargo clippy --locked --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --all-features --lib -- go: 848 passedcargo test -p socket-patch-cli --all-features --lib: 913 passedcovgap_commands_vex,covgap_commands_rollback,e2e_golang,e2e_vex_vendor,in_process_vendor,e2e_golang_build,e2e_golang_hosted_build,e2e_golang_hosted_state,e2e_golang_workspace_buildande2e_vendor_golang_build(with--include-ignored, real go): all passThe full
cargo test --workspacecouldn't finish locally because the sessionran out of disk, so CI's full matrix is the check for the rest.
tests/equivalence/golang_rewrite.goldenwas re-blessed. To show only thewarning wording changed, I restored the old not-in-graph message and checked
that the old golden still matched.
/code-review highfindings not fixedgo mod tidy): this reads as "the build selects the higher version". Itfails closed: apply refuses,
vexomits, and hosted drops its ownreplace. go.mod and go.sum alone can't tell a stale line from a transitive
requirement.
go mod tidyclears it.replace in place: a failure is the right signal, because the patch isn't
applied, and
apply --checknames the drift. Removing go.mod lines from afailing apply would be a larger behavior change.
project_selectionre-reads go.mod/go.sum per replace entry inapply --checkandvex: there are a handful of entries per project, soI didn't add the extra plumbing.
read_required_versionsis no longer used outside tests: left in placeto keep this PR scoped. Its tests and a discovery guard still reference it.
by the targeted unit tests above instead.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DH6BEwGj8nVAeveDy6x5fc
Note
Medium Risk
Changes fail-closed behavior across apply, vendor, hosted redirect, and VEX for Go patches—users with stale version-pinned replaces may see new refusals or omitted attestations until they re-scan for the selected version.
Overview
Go
replacedirectives are keyed by module and version, so a pin for a version the build list does not select is ignored and the unpatched module is linked. This PR adds shared offline logic ingo_build_list(fromgo.mod/go.sum) and uses it everywhere that used to guess from partial heuristics.Agent apply / vendor now refuse before writing copies or
replacelines when the patched version is not selected (including go 1.16 graphs where selection comes from go.sum zip lines, not/go.mod-only entries).apply --checkflagsResolvedVersionMismatchon the same basis instead of treating “missing from require” as harmless.Hosted redirect applies the same selection rules: version mismatches warn
redirect_golang_version_mismatch; “in graph” checks ignore/go.mod-only lines (#509).vexdrops attestation for socket-owned replaces withgo_version_not_selectedwhen go.mod/go.sum show another version is built.CLI and ecosystem docs describe the behavior; regression tests and updated golang rewrite golden cover apply, vendor, hosted, vex, and the helper.
Reviewed by Cursor Bugbot for commit 598055a. Configure here.
Generated by Claude Code