build: the oldest compiler this module admits is the one CI builds with - #70
Merged
Conversation
The "go" line in go.mod was a floor of 1.26.5 while CI and the toolchain line both said 1.27.0. A floor is the only one of those the compiler enforces, so the gap was reachable: GOTOOLCHAIN=go1.26.8 built this module, the binary answered 0.3.0-rc1, wrote 0.3.0-rc1 into every manifest, and produced different bytes for png, docx and targz than the release of that name. Go 1.27 changed compress/flate, which is why - eleven of the fifty one pinned cases and all seven pinned standard library paths moved when this project went to 1.27.0. The diagnosis was already there and works: a manifest records the toolchain under tool.go, so two runs that disagree can be told apart. Nothing made anybody look. Raising the floor means Go itself refuses that build. The cost is stated rather than hidden, in go.mod and in the changelog: nobody on Go 1.26 can build this from source any more. Downloadable binaries and "go install" are unaffected. There is no toolchain directive left to compare against, and that is measured rather than overlooked. Go refuses a module whose toolchain directive is not newer than its go directive, so once the floor met the pin the build answered "updates to go.mod needed" until the directive came out. The thirty nine lines recording four toolchain decisions moved above the go line instead - the directive was never the valuable part. The pin now lives in GO_VERSION in the three workflows, and the new guard holds the floor against every one of them and against the sentence in README.md, which is the copy somebody reads before they have the repository. Bytes were checked rather than assumed, because go mod tidy moved three modules from the indirect block to the direct one: the module graph is identical at 69, the package set cmd/tfg links is identical at 200, go.sum is untouched, and the three byte stability guards are green. Two mutations, both caught. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Stability report finding T3, accepted in full. The owner decided on 2026-09-06 to take the compatibility cost.
What was wrong
go.moddeclaredgo 1.26.5as a floor while CI and the toolchain line both said1.27.0. The floor is the only one of those the compiler enforces, so the gap was reachable:That binary writes
0.3.0-rc1into every manifest and produces different bytes for png, docx and targz than the release of that name, because Go 1.27 changedcompress/flate- eleven of the fifty one pinned cases and all seven pinned standard library paths moved when this project went to 1.27.0.The diagnosis was already in place and works: a manifest records the toolchain under
tool.go, so two runs that disagree can be told apart afterwards. Nothing made anybody look.What changed
Raising the floor makes Go itself refuse that build. The cost is real and stated rather than hidden, in
go.modand in the changelog: nobody on Go 1.26 can build from source any more. Downloadable binaries andgo installare unaffected.There is no
toolchaindirective left to compare against, and that is measured rather than overlooked. Go refuses a module whose toolchain directive is not newer than its go directive - once the floor met the pin, the build answeredupdates to go.mod neededuntil the directive came out. Verified in three runs: floor plus directive refuses, directive removed builds, comment survives either way. The thirty nine lines recording four toolchain decisions moved above thegoline, because the directive was never the valuable part.The pin now lives in
GO_VERSIONin the three workflows, and the new guard holds the floor against every one of them and against the sentence inREADME.md- the copy somebody reads before they have the repository.Bytes were checked, not assumed
go mod tidymoved three modules from the indirect block to the direct one, so this was measured rather than reasoned about:go list -m all)cmd/tfglinksgo.sumTestStandardLibraryOutputHasNotDrifted,TestOurOwnGeneratorsHaveNotDriftedandTestGeneratingTwiceGivesTheSameBytesare all green. D11 holds.Guard
TestTheBuildFloorIsThePinnedToolchainAndTheReadmeSaysSo- proven red on the real defect before the fix, then green after. Two mutations, both caught: the README going back to an older floor, and CI building with a compiler older than the floor.It asks for equality rather than "the floor is at least the pin", deliberately: comparing versions means arithmetic on version strings, and that is exactly where this class of defect hides.
What it does not prove: that
1.27.0is a good version or that it exists. It proves only that three places name the same one.Full suite green,
preflight --quickgreen on all 12 checks.🤖 Generated with Claude Code