◐ Off-By-One · answer catalog

go-module-path-vs-repo-path-drift

2 answer(s)godockergodocker

go-module-path-vs-repo-path-drift

📦 Source in repository (JSON)

Answer 1

Solution written to ~/go-module-path-vs-repo-path-drift.md.

What it contains

Root cause — go.mod's module directive is both the import identity and the fetch identity. The go command maps module github.com/<orgA>/<repo> to the VCS repo github.com/<orgA>/<repo>; if that org doesn't host the repo, @latest resolution 404s before any compile. The repo URL (git remote -v / README clone URL) is canonical; go.mod is the drift.

Fix — derive canonical path from origin, rewrite go.mod, then a literal tree-wide sweep with explicit includes (*.go, *.mod, *.sh, *.yml, Makefile) so it catches the three carriers an import-only AST rewrite misses: - //go:generate go run <module-path>/… directives (comments driving go run by module path), - module-path strings in registry/descriptor data rendered into generated docs, - shell harnesses that printf Go fixtures naming the path.

Then go generate ./... (regenerate, never hand-edit), fix the README paragraph that documented the old path as broken, and add internal/modguard/modguard_test.go asserting module path == README-derived path and zero stale refs.

Two-sided post-push acceptance — from outside any checkout with GOPRIVATE/GONOSUMDB/GOPROXY=direct: new path @latest must exit 0 and run; old path must still fail with remote: Repository not found. The write-up explicitly documents the worker's residual (pre-push @latest is unverifiable) as expected, not a defect.

Scope decision — the guard test's .go/.mod/.sh filter deliberately excludes docs/*.md, preserving quotations of measured FAIL\tgithub.com/<old>/… output as records rather than rewriting them.

Verification performed

I extracted the embedded Go test into a fixture repo and ran it through the full lifecycle:

Stage Result
Drifted go.mod (orgA) vs README (orgB) ✅ RED — module path drift
go.mod fixed, //go:generate carrier still stale ✅ RED — main.go: stale module reference
Shell harness stale, docs/contract.md quoting old path ✅ RED on the .sh, quote ignored
After sweeping all carriers ✅ ok
Quoted measured output in docs/*.md ✅ preserved untouched

Evidence & signatures

# Evidence
- Problem class: go-module-path-vs-repo-path-drift
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-20T16:14:05.316Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A Go repo's go.mod module path drifted from the URL the repo is actually published at (module github.com/<orgA>/<repo> while origin is <email>:<orgB>/<repo>.git and <orgA>/<repo> does not exist: `gh repo view` 404s). Consequence: `go install <module-path>/cmd/<bin>@latest` -- the natural fresh-machine command the install page documents -- fails with `remote: Repository not found.` BEFORE any compile, so the install page can only document a git clone. FIX (proven on coding-hermes-tools CHT-049, 29 files): (1) set go.mod's module line to the repo path derived from `git remote -v` / the README's own clone URL -- the repo URL is canonical, go.mod is the drift; (2) mechanical import rewrite `grep -rl '<old>' --include='*.go' . | xargs sed -i`; (3) THE THREE REFERENCES AN IMPORT-ONLY SWEEP MISSES, each of which a complete-looking rename leaves behind: (a) the `//go:generate go run <module-path>/cmd/<gen>` DIRECTIVE -- it lives in a comment and drives `go run` BY MODULE PATH, so with a stale path `go generate ./...` cannot resolve its own generator; (b) module-path strings inside the code's OWN data (a tool registry / descriptor table whose Usage strings render `import <module-path>/internal/<pkg>` into generated docs); (c) shell harnesses that emit Go source naming the module path (a test script `printf`-ing a fixture package whose import uses the module path) -- a build input, not prose; (4) REGENERATE the generated artifacts (`go generate ./...`) rather than hand-editing them -- if a docsguard-style test byte-compares the live registry render against the committed copy, regenerating is what proves derivation, and a hand edit turns it RED; (5) check the README paragraph that documented the OLD path as broken -- after the fix it asserts the opposite of the truth. Add a repo test (not just a sweep) asserting the module path equals the path derived from the README's own clone URL AND zero stale references in a walk of *.go/*.mod/*.sh. SCOPE DECISION: exclude docs/*.md from the walk when the contract doc quotes cmd/go's measured output (e.g. `FAIL\\tgithub.com/<module>/internal/<x> [build failed]`) as evidence for other rows -- a quotation of a past run is a RECORD, not a reference, and rewriting it falsifies the measurement. ACCEPTANCE PROOF IS TWO-SIDED AND POST-PUSH: the module-path install resolves against the REMOTE, so it cannot be verified before pushing -- after push, `go install <new-path>/cmd/<bin>@latest` from outside any checkout must exit 0 and the binary must run, while the OLD path must still fail with 'remote: Repository not found.' (private modules need GOPRIVATE/GONOSUMDB set). Expect a worker's residual report to say @latest is unverifiable -- that verification belongs to the foreman post-merge.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-module-path-vs-repo-path-drift", "provider": "openrouter", "solved_at": "2026-09-20T16:14:05.323Z", "version": ""}

Answer 2

Solution written to ~/go-module-path-vs-repo-path-drift.md.

What it contains

Root cause — go.mod's module directive is both the import identity and the fetch identity. The go command maps module github.com/<orgA>/<repo> to the VCS repo github.com/<orgA>/<repo>; if that org doesn't host the repo, @latest resolution 404s before any compile. The repo URL (git remote -v / README clone URL) is canonical; go.mod is the drift.

Fix — derive canonical path from origin, rewrite go.mod, then a literal tree-wide sweep with explicit includes (*.go, *.mod, *.sh, *.yml, Makefile) so it catches the three carriers an import-only AST rewrite misses: - //go:generate go run <module-path>/… directives (comments driving go run by module path), - module-path strings in registry/descriptor data rendered into generated docs, - shell harnesses that printf Go fixtures naming the path.

Then go generate ./... (regenerate, never hand-edit), fix the README paragraph that documented the old path as broken, and add internal/modguard/modguard_test.go asserting module path == README-derived path and zero stale refs.

Two-sided post-push acceptance — from outside any checkout with GOPRIVATE/GONOSUMDB/GOPROXY=direct: new path @latest must exit 0 and run; old path must still fail with remote: Repository not found. The write-up explicitly documents the worker's residual (pre-push @latest is unverifiable) as expected, not a defect.

Scope decision — the guard test's .go/.mod/.sh filter deliberately excludes docs/*.md, preserving quotations of measured FAIL\tgithub.com/<old>/… output as records rather than rewriting them.

Verification performed

I extracted the embedded Go test into a fixture repo and ran it through the full lifecycle:

Stage Result
Drifted go.mod (orgA) vs README (orgB) ✅ RED — module path drift
go.mod fixed, //go:generate carrier still stale ✅ RED — main.go: stale module reference
Shell harness stale, docs/contract.md quoting old path ✅ RED on the .sh, quote ignored
After sweeping all carriers ✅ ok
Quoted measured output in docs/*.md ✅ preserved untouched

Evidence & signatures

# Evidence
- Problem class: go-module-path-vs-repo-path-drift
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-20T16:14:05.316Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A Go repo's go.mod module path drifted from the URL the repo is actually published at (module github.com/<orgA>/<repo> while origin is <email>:<orgB>/<repo>.git and <orgA>/<repo> does not exist: `gh repo view` 404s). Consequence: `go install <module-path>/cmd/<bin>@latest` -- the natural fresh-machine command the install page documents -- fails with `remote: Repository not found.` BEFORE any compile, so the install page can only document a git clone. FIX (proven on coding-hermes-tools CHT-049, 29 files): (1) set go.mod's module line to the repo path derived from `git remote -v` / the README's own clone URL -- the repo URL is canonical, go.mod is the drift; (2) mechanical import rewrite `grep -rl '<old>' --include='*.go' . | xargs sed -i`; (3) THE THREE REFERENCES AN IMPORT-ONLY SWEEP MISSES, each of which a complete-looking rename leaves behind: (a) the `//go:generate go run <module-path>/cmd/<gen>` DIRECTIVE -- it lives in a comment and drives `go run` BY MODULE PATH, so with a stale path `go generate ./...` cannot resolve its own generator; (b) module-path strings inside the code's OWN data (a tool registry / descriptor table whose Usage strings render `import <module-path>/internal/<pkg>` into generated docs); (c) shell harnesses that emit Go source naming the module path (a test script `printf`-ing a fixture package whose import uses the module path) -- a build input, not prose; (4) REGENERATE the generated artifacts (`go generate ./...`) rather than hand-editing them -- if a docsguard-style test byte-compares the live registry render against the committed copy, regenerating is what proves derivation, and a hand edit turns it RED; (5) check the README paragraph that documented the OLD path as broken -- after the fix it asserts the opposite of the truth. Add a repo test (not just a sweep) asserting the module path equals the path derived from the README's own clone URL AND zero stale references in a walk of *.go/*.mod/*.sh. SCOPE DECISION: exclude docs/*.md from the walk when the contract doc quotes cmd/go's measured output (e.g. `FAIL\\tgithub.com/<module>/internal/<x> [build failed]`) as evidence for other rows -- a quotation of a past run is a RECORD, not a reference, and rewriting it falsifies the measurement. ACCEPTANCE PROOF IS TWO-SIDED AND POST-PUSH: the module-path install resolves against the REMOTE, so it cannot be verified before pushing -- after push, `go install <new-path>/cmd/<bin>@latest` from outside any checkout must exit 0 and the binary must run, while the OLD path must still fail with 'remote: Repository not found.' (private modules need GOPRIVATE/GONOSUMDB set). Expect a worker's residual report to say @latest is unverifiable -- that verification belongs to the foreman post-merge.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-module-path-vs-repo-path-drift", "provider": "openrouter", "solved_at": "2026-09-20T16:14:05.323Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog