From 5344b6434260dd5b3c5a496ba4809f166deae1a6 Mon Sep 17 00:00:00 2001 From: Austin Brace Date: Sat, 1 Aug 2026 09:23:05 -0500 Subject: [PATCH] docs(agents): stop asserting a `go` shim that is not present on every host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AGENTS.md's Build Cache Conventions told agents to "just run `go build` / `make` — do NOT set `GOCACHE` yourself" on the stated grounds that "the host `go` shim already routes the default `GOCACHE` to a shared on-disk cache (~/.cache/go-build) and pins compile/link temp to disk (GOTMPDIR=/var/tmp/gotmp)", concluding that a warm shared cache "is never corrupted by a normal build". Every factual clause is false on an unshimmed developer machine. Verified on the macOS host this repo is developed on: which -a go -> /usr/local/bin/go (one entry, a plain Homebrew symlink to ../Cellar/go/1.26.5/bin/go — no shim) go env GOCACHE -> /Users//Library/Caches/go-build, not ~/.cache/go-build ~/.cache/go-build -> absent go env GOTMPDIR -> "" (empty; linker scratch follows $TMPDIR unpinned) df /tmp -> APFS disk, not the "size-capped RAM-backed tmpfs (61G)" the same section warns about The shim is a fleet-provisioning artifact; nothing in this repo installs it. The section now says so up front and gives the two commands that settle it, rather than stating the shimmed configuration as universal fact. The costly half is the "never corrupted by a normal build" conclusion. It is true only for a build with the project's normal flags — and diagnosing a broken build is exactly when an agent varies CGO_CPPFLAGS, CGO_CXXFLAGS, or tags. Following this instruction, two agents nine hours apart wrote CGO_CXXFLAGS-only go-icu-regex archives into the shared cache (e9a0aecd748d 03:52:20Z, f2cb903213fb 13:06:44Z, both 2026-08-01; gcy-lcs). Each needed manual nm verification and surgical deletion, because nothing detects a poisoned entry — the resulting failure names the flags, never the cache. Added the rule that was missing: diagnostic and flag-varying builds get a throwaway GOCACHE, via the isolated-build recipe already documented a few lines below. The hard ban on `go clean -cache`, the /tmp guidance, and the isolated-build recipe are unchanged in substance; the /tmp paragraph is now scoped to fleet executors, where its tmpfs premise actually holds. The recipe's `mktemp -d -p /var/tmp` was checked for portability and works on macOS. Refs: gcy-2o1, gcy-lcs, gcy-ajv --- AGENTS.md | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9c3d0551bd..6f84a0fd46 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -395,6 +395,19 @@ becoming more useful as models improve — it becomes LESS useful instead. ## Build Cache Conventions +Much of this section describes **fleet Linux executors**, which are provisioned +with a `go` shim and a tmpfs `/tmp`. A developer machine generally has neither, +and nothing in this repo installs them. Verify before relying on any of it: + +```bash +which -a go # a shim appears ahead of the real toolchain +go env GOCACHE GOTMPDIR # shim: ~/.cache/go-build and /var/tmp/gotmp +``` + +If `go` is a single plain symlink and `GOTMPDIR` is empty, you are on an +unshimmed host: the defaults described below are not in force, `/tmp` is +probably ordinary disk rather than tmpfs, and cache hygiene is yours to manage. + **Hard ban: never run `go clean -cache`** in any script, hook, or agent session. Running `go clean -cache` against a shared `GOCACHE` (the default when @@ -404,15 +417,24 @@ full rebuild, and any that calls `go clean -cache` mid-flight invalidates all the others' in-progress caches. The incident (vp-g96b, 2026-06-13) produced ~10 cascading cache-miss errors across the executor pool. -**Just run `go build` / `make` — do NOT set `GOCACHE` yourself.** The host `go` -shim already routes the default `GOCACHE` to a shared **on-disk** cache -(`~/.cache/go-build`) and pins compile/link temp to disk -(`GOTMPDIR=/var/tmp/gotmp`). A warm shared cache is faster and is never -corrupted by a normal build. - -**Never point `GOCACHE` (or `TMPDIR`) at `/tmp`.** `/tmp` is a size-capped -RAM-backed tmpfs (61G) shared by the whole fleet — including the harness's -tool-output capture dir. A bare `mktemp -d` (no `-p` dir) resolves against the +**Just run `go build` / `make` — do NOT set `GOCACHE` yourself for an ordinary +build.** Where the shim is present it routes the default `GOCACHE` to a shared +**on-disk** cache (`~/.cache/go-build`) and pins compile/link temp to disk +(`GOTMPDIR=/var/tmp/gotmp`). A warm shared cache is faster than a cold private +one, and a build using the project's normal flags will not corrupt it. + +**A diagnostic build is not a normal build — give it a throwaway `GOCACHE`.** +Any build that varies `CGO_CPPFLAGS`, `CGO_CXXFLAGS`, `-tags`, or the toolchain +can leave objects that a later correct build silently reuses, and diagnosing a +broken build is precisely when those get varied. Two agents nine hours apart +poisoned the shared cache this way with `CGO_CXXFLAGS`-only go-icu-regex +archives (gcy-lcs); each needed `nm` verification and surgical deletion, because +nothing detects a poisoned entry — the resulting failure names the flags, never +the cache. Use the isolated-build recipe below for anything exploratory. + +**Never point `GOCACHE` (or `TMPDIR`) at `/tmp`.** On a fleet executor `/tmp` is +a size-capped RAM-backed tmpfs (61G) shared by the whole fleet — including the +harness's tool-output capture dir. A bare `mktemp -d` (no `-p` dir) resolves against the unset `$TMPDIR`, which defaults to `/tmp` — one cold cache built there is 2-3GB, and a concurrent build wave fills tmpfs and ENOSPCs every agent on the host (incident gm-tkz1r / ga-x9k9b9, 2026-07). The shim deliberately