You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Findings from an in-container investigation (worktree agent container on feat/cmd-aliases, go1.26.4 linux/arm64) into the VCS/worktree build behavior behind the #361/#365 fixes. Verified by controlled experiment; repro scripts at the bottom.
TL;DR
Go's -buildvcs discovery does not recognize a linked worktree's .gitfile — in every topology we use, stamping is either silently absent or actively wrong. The container failure everyone sees (exit status 128) is only the loudest symptom.
The shipped mitigation (GOFLAGS=-buildvcs=false) is correctly scoped: injected only for worktree containers (internal/docker/env.go, if opts.Worktree), overridable via agent.env / instruction env.
CI and release builds are unaffected: no GOFLAGS/buildvcs anywhere in .github/workflows/; the Makefile only appends inherited GOFLAGS (GOFLAGS := -trimpath $(GOFLAGS)), so host/CI builds stamp normally. Release metadata additionally comes from ldflags (build.Version, build.Revision via git rev-parse), which works in worktrees.
The real loss: binaries built in worktree contexts (host worktrees and worktree containers, including the embedded CP/clawkerd binaries when make clawker runs there) carry no vcs.revision/vcs.time/vcs.modified in debug.BuildInfo. ldflags revision is the only metadata they carry.
Verified behavior matrix (go1.26.4)
Topology
What go does
Result
(A) plain repo
anchors at .git dir
stamps correctly
(B) linked worktree outside the parent path (normal host: clawker worktrees live in the XDG data dir)
walks past the worktree's .git file, finds no repo
builds succeed silently unstamped — even with -buildvcs=true (forced mode only errors when a repo is found but unusable)
walks past the .git file up to the parent's .git directory; runs git status --porcelain / git log with cwd = parent root (confirmed via git shim)
stamps the parent checkout's HEAD and dirty state (vcs.modified=true from the parent tree) — wrong metadata, silently
(D) worktree container (= C, parent is a root-owned scaffold with only .git mounted)
same parent-root probe
git status dies with fatal: detected dubious ownership in repository at '<main repo>' → error obtaining VCS status: exit status 128 → build fails unless -buildvcs=false
Important: even if the parent-root git probe were unblocked (chown/safe.directory), case (C) shows the stamp would be wrong (parent HEAD, whole tree dirty). There is no configuration of the current topology in which go stamps a worktree build correctly — the comment in internal/docker/env.go has this right.
Upstream: go.dev/issue/58218 tracks worktree support for build stamping. Observed behavior on go1.26.4 says linked-worktree .git files are still not honored in our layouts; worth re-checking the issue/CL status before assuming a toolchain bump fixes anything.
Why this matters (repro builds / provenance)
We rely on embedded build metadata for reproducible-build verification and general provenance. Current state:
Degraded: anything built in a worktree context ships without vcs.* BuildInfo. Scanners/tooling reading go version -m see no VCS fields. ldflags build.Revision is the only revision carried, and only for Makefile-driven builds (bare go build in a worktree container has neither).
Trap: host-side worktree builds (B) are silently unstamped today — no error, easy to miss.
Constraints on any fix
No blanket behavior changes: the mitigation must stay scoped to topologies where stamping is impossible (worktree containers). Host non-worktree and CI builds must keep full stamping. (Current opts.Worktree scoping satisfies this.)
No chown/safe.directory on the mounted main .git (rejected: footgun, and it would produce wrong stamps anyway per (C)).
Candidate follow-ups
Document ldflags as the canonical metadata path for worktree builds and ensure every build entry point used inside worktree containers goes through the Makefile (or otherwise injects build.Revision), so no artifact is metadata-free.
Track upstream go.dev/issue/58218; when go correctly anchors at the worktree's own gitdir, drop the GOFLAGS injection (it's overridable per-agent already, so opt-in trials are cheap).
Consider a clawker-side guard/lint for the silent host case (B): warn when building from a clawker worktree on the host that binaries will be unstamped.
Re-verify after any toolchain bump: the behavior matrix above is cheap to re-run (scripts below).
Repro
Worktree container (case D):
env GOFLAGS= go build -buildvcs=true ./cmd/gen-docs
# error obtaining VCS status: exit status 128cd /Users/andrew/Code/clawker && git status --porcelain
# fatal: detected dubious ownership in repository at '/Users/andrew/Code/clawker'
Controlled matrix (any machine):
T=$(mktemp -d);cd$T
git init -q main;cd main; git commit -q --allow-empty -m x
mkdir -p cmd;printf'package main\nfunc main(){}\n'> cmd/main.go;printf'module probe\ngo 1.25\n'> go.mod
git add -A; git commit -q -m code
# (B) outside worktree — silently unstamped even when forced:
git worktree add -q $T/wt-out -b wt1 &&cd$T/wt-out
go build -buildvcs=true -o /tmp/pB ./cmd && go version -m /tmp/pB | grep vcs # no output# (C) nested worktree — stamps the PARENT:cd$T/main && git worktree add -q $T/main/sub/wt-in -b wt2 &&cd$T/main/sub/wt-in
go build -buildvcs=true -o /tmp/pC ./cmd && go version -m /tmp/pC | grep vcs
# vcs.revision = parent HEAD, vcs.modified=true from the parent's dirty tree
Shimming git on PATH during (C)/(D) shows every VCS probe runs with cwd = the parent repo root, confirming go never anchors at the worktree's .git file.
Findings from an in-container investigation (worktree agent container on
feat/cmd-aliases, go1.26.4 linux/arm64) into the VCS/worktree build behavior behind the #361/#365 fixes. Verified by controlled experiment; repro scripts at the bottom.TL;DR
-buildvcsdiscovery does not recognize a linked worktree's.gitfile — in every topology we use, stamping is either silently absent or actively wrong. The container failure everyone sees (exit status 128) is only the loudest symptom.GOFLAGS=-buildvcs=false) is correctly scoped: injected only for worktree containers (internal/docker/env.go,if opts.Worktree), overridable viaagent.env/ instruction env.GOFLAGS/buildvcsanywhere in.github/workflows/; the Makefile only appends inherited GOFLAGS (GOFLAGS := -trimpath $(GOFLAGS)), so host/CI builds stamp normally. Release metadata additionally comes from ldflags (build.Version,build.Revisionviagit rev-parse), which works in worktrees.make clawkerruns there) carry novcs.revision/vcs.time/vcs.modifiedindebug.BuildInfo. ldflags revision is the only metadata they carry.Verified behavior matrix (go1.26.4)
.gitdir.gitfile, finds no repo-buildvcs=true(forced mode only errors when a repo is found but unusable).clawkerlocalsetups).gitfile up to the parent's.gitdirectory; runsgit status --porcelain/git logwith cwd = parent root (confirmed via git shim)vcs.modified=truefrom the parent tree) — wrong metadata, silently.gitmounted)git statusdies withfatal: detected dubious ownership in repository at '<main repo>'→error obtaining VCS status: exit status 128→ build fails unless-buildvcs=falseNotes:
safe.directorywas deliberately rejected as a footgun). It only surfaces when something stripsGOFLAGSand go walks to the parent (e.g.sudo go build, deliberately probing withGOFLAGS=). Normal in-container builds, pre-commit hooks,make clawker, andmake testare all green.internal/docker/env.gohas this right.go.dev/issue/58218tracks worktree support for build stamping. Observed behavior on go1.26.4 says linked-worktree.gitfiles are still not honored in our layouts; worth re-checking the issue/CL status before assuming a toolchain bump fixes anything.Why this matters (repro builds / provenance)
We rely on embedded build metadata for reproducible-build verification and general provenance. Current state:
vcs.*BuildInfo. Scanners/tooling readinggo version -msee no VCS fields. ldflagsbuild.Revisionis the only revision carried, and only for Makefile-driven builds (barego buildin a worktree container has neither).Constraints on any fix
opts.Worktreescoping satisfies this.)chown/safe.directoryon the mounted main.git(rejected: footgun, and it would produce wrong stamps anyway per (C)).Candidate follow-ups
build.Revision), so no artifact is metadata-free.Repro
Worktree container (case D):
Controlled matrix (any machine):
Shimming
giton PATH during (C)/(D) shows every VCS probe runs with cwd = the parent repo root, confirming go never anchors at the worktree's.gitfile.🤖 Generated with Claude Code