check-binary-fresh in the root Makefile normalized away the -dirty provenance marker before deciding whether the artifact matched source. A shortcut, and printed up to date with source with exit 0 — even though the binary embedded uncommitted code that exists nowhere in the repository.
The checkout at ~/off-by-one was not present in this environment, so I reconstructed a faithful minimal Go monorepo matching the described layout and guard, reproduced all three failure modes on the buggy recipe, applied the fix, and verified all outcomes. The full solution is written to ~/off-by-one-freshness-fix.md and reproduced below.
check-binary-fresh accepts a binary built from a dirty tree (and misreports unstamped builds)check-binary-fresh in the root Makefile normalized away the -dirty provenance marker before deciding whether the artifact matched source. A <rev>-dirty stamp therefore resolved to its clean base commit, took the git diff --name-only <rev> -- <code paths> shortcut, and printed up to date with source with exit 0 — even though the binary embedded uncommitted code that exists nowhere in the repository.
A second, independent defect in the same recipe: an artifact with no revision stamp (default 0.1.0-dev, e.g. from the README's bare go build ./cmd/off-by-one) fell into the byte-comparison branch and was reported as is stale - source changed since it was built, blaming source drift for a missing build stamp.
Live evidence:
$ ./off-by-one --version
off-by-one 08af20f-dirty # built from a dirty tree
$ git rev-parse --short HEAD
25d9cb2
$ make check-binary-fresh
check-binary-fresh: ./off-by-one is up to date with source
$ echo $?
0 # FALSE PASS
The fix detects -dirty before any stripping, rejects unstamped artifacts with their own message, keeps the resolvable-stamp shortcut and the byte-comparison fallback, documents all outcomes above the target, and points the README Quick Start at make build.
The vulnerable recipe did this:
@stamp=$$(./$(BINARY) --version | awk '{print $$2}'); \
stamp=$$(echo "$$stamp" | sed 's/-dirty$$//'); \ # <-- destroys provenance
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
if [ -n "$$(git diff --name-only "$$stamp" -- $(CODE_PATHS))" ]; then \
... stale ...; exit 1; \
fi; \
echo "... is up to date with source"; \ # <-- taken for dirty builds
else \
# byte comparison against a fresh build, reported as source drift
fi
Two failure modes follow:
Dirty marker erased → clean base commit substituted. 08af20f-dirty becomes 08af20f. That commit is resolvable, so the guard takes the git diff --name-only 08af20f -- <code paths> shortcut instead of hashing/rebuilding the artifact. If the working tree at check time has no diff under CODE_PATHS (changes committed elsewhere, reverted, or living in a compiled path outside CODE_PATHS), the guard reports up to date. The artifact still contains the uncommitted code, which may no longer exist anywhere in the repo.
Unstamped artifact borrows the stale verdict. A bare go build leaves main.version = "0.1.0-dev". That is not a git object, so the guard falls to the byte-comparison branch. A fresh make build embeds the real revision, the bytes differ, and the guard prints is stale - source changed since it was built — a false diagnosis of source drift.
The unifying rule: a freshness guard that strips provenance markers is worthless. Never normalize the -dirty/unknown marker away before the identity comparison, and never let an unstamped artifact inherit the stale-source verdict.
| # | State | Old verdict |
|---|---|---|
| A | dirty build; dirty file compiled but outside CODE_PATHS |
up to date with source, exit 0 |
| B | dirty build, then source reverted (dirty code exists nowhere) | up to date with source, exit 0 |
| C | bare go build (unstamped), source untouched |
is stale - source changed since it was built, non-zero |
Makefile — rewritten check-binary-fresh--- a/Makefile
+++ b/Makefile
@@ -9,25 +9,63 @@ CODE_PATHS := ./cmd ./internal go.mod
build:
go build -ldflags "$(LDFLAGS)" -o $(BINARY) ./cmd/off-by-one
+# check-binary-fresh verifies that ./$(BINARY) was produced from the current
+# source tree. There are three distinct outcomes, and they are deliberately
+# kept distinct so that an unstamped or dirty artifact is never blamed on
+# source drift:
+#
+# 1. EXIT 0 - UP TO DATE. The binary carries a resolvable git revision
+# stamp and no path under CODE_PATHS changed since that
+# revision (`git diff --name-only <rev> -- <CODE_PATHS>`).
+# 2. EXIT 1 - DIRTY BUILD. The stamp ends in "-dirty", meaning the binary
+# embeds uncommitted code that may exist nowhere in the repo.
+# The marker is checked *before* any normalisation; we never
+# strip it. Remedy: commit or stash, then `make build`.
+# 3. EXIT 1 - UNSTAMPED. The stamp is not a git revision and is not even a
+# hex object name (e.g. the default "0.1.0-dev" left by a bare
+# `go build`). The artifact was not built by `make build`; this
+# is not source drift.
+# 4. EXIT 1 - STALE. The stamp is resolvable but code changed since it, or
+# the (hex) stamp is unknown to this clone and a fresh build
+# differs byte-for-byte.
.PHONY: check-binary-fresh
check-binary-fresh:
- @stamp=$$(./$(BINARY) --version | awk '{print $$2}'); \
- stamp=$$(echo "$$stamp" | sed 's/-dirty$$//'); \
+ @if [ ! -x "./$(BINARY)" ]; then \
+ echo "check-binary-fresh: ./$(BINARY) not found - run 'make build'"; \
+ exit 1; \
+ fi
+ @raw=$$(./$(BINARY) --version 2>/dev/null | awk '{print $$2}'); \
+ if [ -z "$$raw" ]; then \
+ echo "check-binary-fresh: ./$(BINARY) carries no version stamp (empty) - it was not built by make build"; \
+ exit 1; \
+ fi; \
+ case "$$raw" in \
+ *-dirty) \
+ echo "check-binary-fresh: ./$(BINARY) was built from a dirty tree (stamp '$$raw'); commit or stash your changes, then run 'make build'"; \
+ exit 1 ;; \
+ esac; \
+ stamp="$$raw"; \
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
- if [ -n "$$(git diff --name-only "$$stamp" -- $(CODE_PATHS))" ]; then \
+ changed=$$(git diff --name-only "$$stamp" -- $(CODE_PATHS)); \
+ if [ -n "$$changed" ]; then \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
+ echo "$$changed" | sed 's/^/ changed: /'; \
exit 1; \
fi; \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
- tmp=$$(mktemp); \
- go build -ldflags "$(LDFLAGS)" -o "$$tmp" ./cmd/off-by-one; \
- if cmp -s ./$(BINARY) "$$tmp"; then \
+ case "$$stamp" in \
+ *[!0-9a-fA-F]*) \
+ echo "check-binary-fresh: ./$(BINARY) carries no version stamp ($$stamp) - it was not built by make build"; \
+ exit 1 ;; \
+ esac; \
+ tmpdir=$$(mktemp -d); \
+ trap 'rm -rf "$$tmpdir"' EXIT INT TERM; \
+ $(MAKE) --no-print-directory build BINARY="$$tmpdir/$(BINARY)" >/dev/null; \
+ if cmp -s "./$(BINARY)" "$$tmpdir/$(BINARY)"; then \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
- rm -f "$$tmp"; \
exit 1; \
fi; \
- rm -f "$$tmp"; \
fi
README.md — Quick Start must use make build--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ A small Go service.
## Quick Start
```sh
-go build ./cmd/off-by-one
+make build
./off-by-one --version
make check-binary-fresh
```
-dirty is checked first. The case "$$raw" in *-dirty) arm runs before the stamp is used for anything. There is no sed stripping at all. A dirty artifact can never resolve to its base commit.0.1.0-dev fails the hex test *[!0-9a-fA-F]* and is reported as carries no version stamp (<stamp>) - it was not built by make build, so it can never be blamed on source drift.<rev>, the git diff --name-only <rev> -- $(CODE_PATHS) check still reports is stale when tracked code changed.cmp. The rebuild is written to a mktemp -d directory outside the repo: building a temp artifact inside the work tree flips Go's embedded VCS stamp to vcs.modified=true, making the comparison non-reproducible.Drop-in final recipe:
check-binary-fresh:
@if [ ! -x "./$(BINARY)" ]; then \
echo "check-binary-fresh: ./$(BINARY) not found - run 'make build'"; \
exit 1; \
fi
@raw=$$(./$(BINARY) --version 2>/dev/null | awk '{print $$2}'); \
if [ -z "$$raw" ]; then \
echo "check-binary-fresh: ./$(BINARY) carries no version stamp (empty) - it was not built by make build"; \
exit 1; \
fi; \
case "$$raw" in \
*-dirty) \
echo "check-binary-fresh: ./$(BINARY) was built from a dirty tree (stamp '$$raw'); commit or stash your changes, then run 'make build'"; \
exit 1 ;; \
esac; \
stamp="$$raw"; \
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
changed=$$(git diff --name-only "$$stamp" -- $(CODE_PATHS)); \
if [ -n "$$changed" ]; then \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
echo "$$changed" | sed 's/^/ changed: /'; \
exit 1; \
fi; \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
case "$$stamp" in \
*[!0-9a-fA-F]*) \
echo "check-binary-fresh: ./$(BINARY) carries no version stamp ($$stamp) - it was not built by make build"; \
exit 1 ;; \
esac; \
tmpdir=$$(mktemp -d); \
trap 'rm -rf "$$tmpdir"' EXIT INT TERM; \
$(MAKE) --no-print-directory build BINARY="$$tmpdir/$(BINARY)" >/dev/null; \
if cmp -s "./$(BINARY)" "$$tmpdir/$(BINARY)"; then \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
exit 1; \
fi; \
fi
Verified on a reconstructed Go monorepo (git-stamped main.version, a pkg/ package compiled into the binary but outside CODE_PATHS, guard driven by make check-binary-fresh).
rm -f off-by-one
make build
./off-by-one --version # off-by-one 6194a6d (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one is up to date with source
[exit=0]
sed -i 's/load threshold %d/load threshold=%d/' internal/server/server.go
make build
./off-by-one --version # off-by-one 6194a6d-dirty (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one was built from a dirty tree (stamp '6194a6d-dirty'); commit or stash your changes, then run 'make build'
make: *** [Makefile:34: check-binary-fresh] Error 1
[exit=2]
sed -i 's/const Name = "stable"/const Name = "evil"/' pkg/feature/feature.go
make build
./off-by-one --version # off-by-one 6194a6d-dirty (evil)
git checkout -- pkg/feature/feature.go # dirty code now exists nowhere
make check-binary-fresh
check-binary-fresh: ./off-by-one was built from a dirty tree (stamp '6194a6d-dirty'); commit or stash your changes, then run 'make build'
[exit=2]
go build — names the missing stamprm -f off-by-one
go build ./cmd/off-by-one
./off-by-one --version # off-by-one 0.1.0-dev (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one carries no version stamp (0.1.0-dev) - it was not built by make build
[exit=2]
is stalerm -f off-by-one
make build
sed -i 's/load threshold %d/load threshold:%d/' internal/server/server.go
make check-binary-fresh
check-binary-fresh: ./off-by-one is stale - source changed since it was built
changed: internal/server/server.go
[exit=2]
rm -f off-by-one
make build VERSION=deadbee # hex but not a commit in this clone
make check-binary-fresh VERSION=deadbee
check-binary-fresh: ./off-by-one is up to date with source
[exit=0]
With differing source the same fallback reports is stale (verified).
check-binary-fresh: ./off-by-one not found - run 'make build'
[exit=2]
A freshness guard that normalizes away provenance is worthless. Never strip the -dirty/unknown marker before the identity comparison, and never let an unstamped artifact borrow the stale-source verdict. Give each state — clean match, dirty build, missing stamp, genuine drift — its own explicit message and exit code.
Artifacts: solution at ~/off-by-one-freshness-fix.md; verified reference implementation at ~/off-by-one (fix commit de11cfb, hygiene commit 6194a6d).
# Evidence - Problem class: makefile-binary-freshness-guard-dirty-stamp-false-pass - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-18T13:41:13.625Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Repo ~/off-by-one (Go monorepo). The deploy-freshness guard `check-binary-fresh` in the root Makefile accepts a binary compiled from a dirty working tree. Root cause: the guard parsed the revision stamp out of `./<bin> --version` and ran `sed 's/-dirty$//'` before resolving it, so a `<rev>-dirty` stamp resolved to its base commit, took the `git diff --name-only <rev> -- <code paths>` shortcut and printed 'up to date with source' with exit 0 even though the artifact contained uncommitted code that exists nowhere in the repo. Live evidence: `./off-by-one --version` = 'off-by-one 08af20f-dirty' with HEAD at 25d9cb2 and the guard exiting 0. Second defect in the same recipe: the README Quick Start built with a bare `go build ./cmd/off-by-one` (no -ldflags), so main.version kept the default '0.1.0-dev', the stamp resolved to nothing, and the byte-comparison fallback reported 'is stale - source changed since it was built' for a binary built seconds earlier from exactly HEAD - misattributing an unstamped build as source drift. Fix: detect the `-dirty` marker BEFORE any stripping and fail fast with a message containing the literal 'built from a dirty tree' plus the remedy (commit or stash, then make build); treat an unresolvable non-sha stamp as 'carries no version stamp (...) - it was not built by make build' instead of source drift; keep the resolvable-stamp shortcut and the byte-comparison stale fallback; document the three outcomes in a comment above the target; and make the README Quick Start use `make build`. Verification: clean clone README path exit 0; dirty build exit non-zero with the named message; unstamped build exit non-zero naming the missing stamp; resolvable stamp with a changed code path still exit non-zero 'is stale'; RED proof in a worktree at the parent revision reproduced the false PASS twice (dirty build accepted; dirty build then source reverted also accepted via the code-path shortcut). General rule: a freshness guard that strips provenance markers is worthless - never normalise away the dirty/unknown marker before the identity comparison, and never let an unstamped artifact borrow the stale-source verdict.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "makefile-binary-freshness-guard-dirty-stamp-false-pass", "provider": "openrouter", "solved_at": "2026-09-18T13:41:13.625Z", "version": ""}The checkout at ~/off-by-one was not present in this environment, so I reconstructed a faithful minimal Go monorepo matching the described layout and guard, reproduced all three failure modes on the buggy recipe, applied the fix, and verified all outcomes. The full solution is written to ~/off-by-one-freshness-fix.md and reproduced below.
check-binary-fresh accepts a binary built from a dirty tree (and misreports unstamped builds)check-binary-fresh in the root Makefile normalized away the -dirty provenance marker before deciding whether the artifact matched source. A <rev>-dirty stamp therefore resolved to its clean base commit, took the git diff --name-only <rev> -- <code paths> shortcut, and printed up to date with source with exit 0 — even though the binary embedded uncommitted code that exists nowhere in the repository.
A second, independent defect in the same recipe: an artifact with no revision stamp (default 0.1.0-dev, e.g. from the README's bare go build ./cmd/off-by-one) fell into the byte-comparison branch and was reported as is stale - source changed since it was built, blaming source drift for a missing build stamp.
Live evidence:
$ ./off-by-one --version
off-by-one 08af20f-dirty # built from a dirty tree
$ git rev-parse --short HEAD
25d9cb2
$ make check-binary-fresh
check-binary-fresh: ./off-by-one is up to date with source
$ echo $?
0 # FALSE PASS
The fix detects -dirty before any stripping, rejects unstamped artifacts with their own message, keeps the resolvable-stamp shortcut and the byte-comparison fallback, documents all outcomes above the target, and points the README Quick Start at make build.
The vulnerable recipe did this:
@stamp=$$(./$(BINARY) --version | awk '{print $$2}'); \
stamp=$$(echo "$$stamp" | sed 's/-dirty$$//'); \ # <-- destroys provenance
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
if [ -n "$$(git diff --name-only "$$stamp" -- $(CODE_PATHS))" ]; then \
... stale ...; exit 1; \
fi; \
echo "... is up to date with source"; \ # <-- taken for dirty builds
else \
# byte comparison against a fresh build, reported as source drift
fi
Two failure modes follow:
Dirty marker erased → clean base commit substituted. 08af20f-dirty becomes 08af20f. That commit is resolvable, so the guard takes the git diff --name-only 08af20f -- <code paths> shortcut instead of hashing/rebuilding the artifact. If the working tree at check time has no diff under CODE_PATHS (changes committed elsewhere, reverted, or living in a compiled path outside CODE_PATHS), the guard reports up to date. The artifact still contains the uncommitted code, which may no longer exist anywhere in the repo.
Unstamped artifact borrows the stale verdict. A bare go build leaves main.version = "0.1.0-dev". That is not a git object, so the guard falls to the byte-comparison branch. A fresh make build embeds the real revision, the bytes differ, and the guard prints is stale - source changed since it was built — a false diagnosis of source drift.
The unifying rule: a freshness guard that strips provenance markers is worthless. Never normalize the -dirty/unknown marker away before the identity comparison, and never let an unstamped artifact inherit the stale-source verdict.
| # | State | Old verdict |
|---|---|---|
| A | dirty build; dirty file compiled but outside CODE_PATHS |
up to date with source, exit 0 |
| B | dirty build, then source reverted (dirty code exists nowhere) | up to date with source, exit 0 |
| C | bare go build (unstamped), source untouched |
is stale - source changed since it was built, non-zero |
Makefile — rewritten check-binary-fresh--- a/Makefile
+++ b/Makefile
@@ -9,25 +9,63 @@ CODE_PATHS := ./cmd ./internal go.mod
build:
go build -ldflags "$(LDFLAGS)" -o $(BINARY) ./cmd/off-by-one
+# check-binary-fresh verifies that ./$(BINARY) was produced from the current
+# source tree. There are three distinct outcomes, and they are deliberately
+# kept distinct so that an unstamped or dirty artifact is never blamed on
+# source drift:
+#
+# 1. EXIT 0 - UP TO DATE. The binary carries a resolvable git revision
+# stamp and no path under CODE_PATHS changed since that
+# revision (`git diff --name-only <rev> -- <CODE_PATHS>`).
+# 2. EXIT 1 - DIRTY BUILD. The stamp ends in "-dirty", meaning the binary
+# embeds uncommitted code that may exist nowhere in the repo.
+# The marker is checked *before* any normalisation; we never
+# strip it. Remedy: commit or stash, then `make build`.
+# 3. EXIT 1 - UNSTAMPED. The stamp is not a git revision and is not even a
+# hex object name (e.g. the default "0.1.0-dev" left by a bare
+# `go build`). The artifact was not built by `make build`; this
+# is not source drift.
+# 4. EXIT 1 - STALE. The stamp is resolvable but code changed since it, or
+# the (hex) stamp is unknown to this clone and a fresh build
+# differs byte-for-byte.
.PHONY: check-binary-fresh
check-binary-fresh:
- @stamp=$$(./$(BINARY) --version | awk '{print $$2}'); \
- stamp=$$(echo "$$stamp" | sed 's/-dirty$$//'); \
+ @if [ ! -x "./$(BINARY)" ]; then \
+ echo "check-binary-fresh: ./$(BINARY) not found - run 'make build'"; \
+ exit 1; \
+ fi
+ @raw=$$(./$(BINARY) --version 2>/dev/null | awk '{print $$2}'); \
+ if [ -z "$$raw" ]; then \
+ echo "check-binary-fresh: ./$(BINARY) carries no version stamp (empty) - it was not built by make build"; \
+ exit 1; \
+ fi; \
+ case "$$raw" in \
+ *-dirty) \
+ echo "check-binary-fresh: ./$(BINARY) was built from a dirty tree (stamp '$$raw'); commit or stash your changes, then run 'make build'"; \
+ exit 1 ;; \
+ esac; \
+ stamp="$$raw"; \
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
- if [ -n "$$(git diff --name-only "$$stamp" -- $(CODE_PATHS))" ]; then \
+ changed=$$(git diff --name-only "$$stamp" -- $(CODE_PATHS)); \
+ if [ -n "$$changed" ]; then \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
+ echo "$$changed" | sed 's/^/ changed: /'; \
exit 1; \
fi; \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
- tmp=$$(mktemp); \
- go build -ldflags "$(LDFLAGS)" -o "$$tmp" ./cmd/off-by-one; \
- if cmp -s ./$(BINARY) "$$tmp"; then \
+ case "$$stamp" in \
+ *[!0-9a-fA-F]*) \
+ echo "check-binary-fresh: ./$(BINARY) carries no version stamp ($$stamp) - it was not built by make build"; \
+ exit 1 ;; \
+ esac; \
+ tmpdir=$$(mktemp -d); \
+ trap 'rm -rf "$$tmpdir"' EXIT INT TERM; \
+ $(MAKE) --no-print-directory build BINARY="$$tmpdir/$(BINARY)" >/dev/null; \
+ if cmp -s "./$(BINARY)" "$$tmpdir/$(BINARY)"; then \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
- rm -f "$$tmp"; \
exit 1; \
fi; \
- rm -f "$$tmp"; \
fi
README.md — Quick Start must use make build--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ A small Go service.
## Quick Start
```sh
-go build ./cmd/off-by-one
+make build
./off-by-one --version
make check-binary-fresh
```
-dirty is checked first. The case "$$raw" in *-dirty) arm runs before the stamp is used for anything. There is no sed stripping at all. A dirty artifact can never resolve to its base commit.0.1.0-dev fails the hex test *[!0-9a-fA-F]* and is reported as carries no version stamp (<stamp>) - it was not built by make build, so it can never be blamed on source drift.<rev>, the git diff --name-only <rev> -- $(CODE_PATHS) check still reports is stale when tracked code changed.cmp. The rebuild is written to a mktemp -d directory outside the repo: building a temp artifact inside the work tree flips Go's embedded VCS stamp to vcs.modified=true, making the comparison non-reproducible.Drop-in final recipe:
check-binary-fresh:
@if [ ! -x "./$(BINARY)" ]; then \
echo "check-binary-fresh: ./$(BINARY) not found - run 'make build'"; \
exit 1; \
fi
@raw=$$(./$(BINARY) --version 2>/dev/null | awk '{print $$2}'); \
if [ -z "$$raw" ]; then \
echo "check-binary-fresh: ./$(BINARY) carries no version stamp (empty) - it was not built by make build"; \
exit 1; \
fi; \
case "$$raw" in \
*-dirty) \
echo "check-binary-fresh: ./$(BINARY) was built from a dirty tree (stamp '$$raw'); commit or stash your changes, then run 'make build'"; \
exit 1 ;; \
esac; \
stamp="$$raw"; \
if git rev-parse --verify --quiet "$$stamp^{commit}" >/dev/null 2>&1; then \
changed=$$(git diff --name-only "$$stamp" -- $(CODE_PATHS)); \
if [ -n "$$changed" ]; then \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
echo "$$changed" | sed 's/^/ changed: /'; \
exit 1; \
fi; \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
case "$$stamp" in \
*[!0-9a-fA-F]*) \
echo "check-binary-fresh: ./$(BINARY) carries no version stamp ($$stamp) - it was not built by make build"; \
exit 1 ;; \
esac; \
tmpdir=$$(mktemp -d); \
trap 'rm -rf "$$tmpdir"' EXIT INT TERM; \
$(MAKE) --no-print-directory build BINARY="$$tmpdir/$(BINARY)" >/dev/null; \
if cmp -s "./$(BINARY)" "$$tmpdir/$(BINARY)"; then \
echo "check-binary-fresh: ./$(BINARY) is up to date with source"; \
else \
echo "check-binary-fresh: ./$(BINARY) is stale - source changed since it was built"; \
exit 1; \
fi; \
fi
Verified on a reconstructed Go monorepo (git-stamped main.version, a pkg/ package compiled into the binary but outside CODE_PATHS, guard driven by make check-binary-fresh).
rm -f off-by-one
make build
./off-by-one --version # off-by-one 6194a6d (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one is up to date with source
[exit=0]
sed -i 's/load threshold %d/load threshold=%d/' internal/server/server.go
make build
./off-by-one --version # off-by-one 6194a6d-dirty (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one was built from a dirty tree (stamp '6194a6d-dirty'); commit or stash your changes, then run 'make build'
make: *** [Makefile:34: check-binary-fresh] Error 1
[exit=2]
sed -i 's/const Name = "stable"/const Name = "evil"/' pkg/feature/feature.go
make build
./off-by-one --version # off-by-one 6194a6d-dirty (evil)
git checkout -- pkg/feature/feature.go # dirty code now exists nowhere
make check-binary-fresh
check-binary-fresh: ./off-by-one was built from a dirty tree (stamp '6194a6d-dirty'); commit or stash your changes, then run 'make build'
[exit=2]
go build — names the missing stamprm -f off-by-one
go build ./cmd/off-by-one
./off-by-one --version # off-by-one 0.1.0-dev (stable)
make check-binary-fresh
check-binary-fresh: ./off-by-one carries no version stamp (0.1.0-dev) - it was not built by make build
[exit=2]
is stalerm -f off-by-one
make build
sed -i 's/load threshold %d/load threshold:%d/' internal/server/server.go
make check-binary-fresh
check-binary-fresh: ./off-by-one is stale - source changed since it was built
changed: internal/server/server.go
[exit=2]
rm -f off-by-one
make build VERSION=deadbee # hex but not a commit in this clone
make check-binary-fresh VERSION=deadbee
check-binary-fresh: ./off-by-one is up to date with source
[exit=0]
With differing source the same fallback reports is stale (verified).
check-binary-fresh: ./off-by-one not found - run 'make build'
[exit=2]
A freshness guard that normalizes away provenance is worthless. Never strip the -dirty/unknown marker before the identity comparison, and never let an unstamped artifact borrow the stale-source verdict. Give each state — clean match, dirty build, missing stamp, genuine drift — its own explicit message and exit code.
Artifacts: solution at ~/off-by-one-freshness-fix.md; verified reference implementation at ~/off-by-one (fix commit de11cfb, hygiene commit 6194a6d).
# Evidence - Problem class: makefile-binary-freshness-guard-dirty-stamp-false-pass - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-18T13:41:13.625Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Repo ~/off-by-one (Go monorepo). The deploy-freshness guard `check-binary-fresh` in the root Makefile accepts a binary compiled from a dirty working tree. Root cause: the guard parsed the revision stamp out of `./<bin> --version` and ran `sed 's/-dirty$//'` before resolving it, so a `<rev>-dirty` stamp resolved to its base commit, took the `git diff --name-only <rev> -- <code paths>` shortcut and printed 'up to date with source' with exit 0 even though the artifact contained uncommitted code that exists nowhere in the repo. Live evidence: `./off-by-one --version` = 'off-by-one 08af20f-dirty' with HEAD at 25d9cb2 and the guard exiting 0. Second defect in the same recipe: the README Quick Start built with a bare `go build ./cmd/off-by-one` (no -ldflags), so main.version kept the default '0.1.0-dev', the stamp resolved to nothing, and the byte-comparison fallback reported 'is stale - source changed since it was built' for a binary built seconds earlier from exactly HEAD - misattributing an unstamped build as source drift. Fix: detect the `-dirty` marker BEFORE any stripping and fail fast with a message containing the literal 'built from a dirty tree' plus the remedy (commit or stash, then make build); treat an unresolvable non-sha stamp as 'carries no version stamp (...) - it was not built by make build' instead of source drift; keep the resolvable-stamp shortcut and the byte-comparison stale fallback; document the three outcomes in a comment above the target; and make the README Quick Start use `make build`. Verification: clean clone README path exit 0; dirty build exit non-zero with the named message; unstamped build exit non-zero naming the missing stamp; resolvable stamp with a changed code path still exit non-zero 'is stale'; RED proof in a worktree at the parent revision reproduced the false PASS twice (dirty build accepted; dirty build then source reverted also accepted via the code-path shortcut). General rule: a freshness guard that strips provenance markers is worthless - never normalise away the dirty/unknown marker before the identity comparison, and never let an unstamped artifact borrow the stale-source verdict.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "makefile-binary-freshness-guard-dirty-stamp-false-pass", "provider": "openrouter", "solved_at": "2026-09-18T13:41:13.625Z", "version": ""}