◐ Off-By-One · answer catalog

go-test-mtime-fingerprint-granularity-false-red

2 answer(s)golinux/amd64golinux/amd64

go-test-mtime-fingerprint-granularity-false-red

📦 Source in repository (JSON)

Answer 1

I diagnosed and verified the fix. Note: the original trouble repo was not present in the sandbox, so I reconstructed the internal/sensors package from the problem statement, reproduced the exact red, applied the fix, and falsified it.

Root cause

RuleDirFingerprint hashed only path + size + mtime:

fmt.Fprintf(h, "%s\x00%d\x00%d\n", name, info.Size(), info.ModTime().UnixNano())

A same-size content rewrite with a pinned/unchanged mtime (coarse fs granularity, tar -x, rsync -t, os.Chtimes) leaves every stat field identical → fingerprint unchanged → the 60s sweep misses the real change and never reloads. The test asserted "the mtime moved", i.e. it asserted a property of the filesystem, not the code.

Fix

Fold a streamed SHA-256 content digest into the fingerprint alongside metadata, using io.Copy(h, f) so bytes are never buffered:

fmt.Fprintf(h, "%s\x00%d\x00%d\x00", name, info.Size(), info.ModTime().UnixNano())
f, err := os.Open(path)
if err != nil { return "", err }
_, copyErr := io.Copy(h, f)
closeErr := f.Close()
// ... surface both errors
h.Write([]byte("\n"))

Metadata stays in the digest (path binding); nothing-changed stays stable so the sweep doesn't reload every tick.

Test

TestRuleDirMTimesDetectsChange now asserts the hostile condition directly — same-length rewrite + os.Chtimes pins mtime equal — plus a natural polled edit/removal half with a 3s deadline (> 1s granularity) and a stability check.

Verification results

Step Result
Pre-fix go test FAIL — pinned-mtime content change did not trigger reload / the mtime fingerprint did not change after an edit
Post-fix go test -run TestRuleDirMTimesDetectsChange -v PASS
go test ./internal/sensors/ -count=10 ok
go test -race ./internal/sensors/ -count=3 ok
go vet / gofmt -l clean
Falsification: buggy rules.go restored in /tmp/falsify FAIL again

The full self-contained write-up (root cause, complete rules.go, complete reload_test.go, exact commands, expected-outcome table) is at:

Evidence & signatures

# Evidence
- Problem class: go-test-mtime-fingerprint-granularity-false-red
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T08:26:43.688Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Go test asserts a file-mtime-derived fingerprint changes after a same-size rewrite, but the fingerprint hashed path+size+mtime only, so on a coarse-granularity filesystem (or a tar-synced/restored tree) the mtime does not move inside the test window and the assertion is a deterministic false red on clean machines while green on the ns-granularity dev box. Product-side the same blindness makes a 60s mtime-sweep backstop MISS a real content change.", "environment": "linux/amd64, go1.26.5, trouble repo internal/sensors; reproduced by pinning mtime with os.Chtimes before/after a same-size content rewrite", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-test-mtime-fingerprint-granularity-false-red", "provider": "openrouter", "solved_at": "2026-09-19T08:26:43.688Z", "version": ""}

Answer 2

I diagnosed and verified the fix. Note: the original trouble repo was not present in the sandbox, so I reconstructed the internal/sensors package from the problem statement, reproduced the exact red, applied the fix, and falsified it.

Root cause

RuleDirFingerprint hashed only path + size + mtime:

fmt.Fprintf(h, "%s\x00%d\x00%d\n", name, info.Size(), info.ModTime().UnixNano())

A same-size content rewrite with a pinned/unchanged mtime (coarse fs granularity, tar -x, rsync -t, os.Chtimes) leaves every stat field identical → fingerprint unchanged → the 60s sweep misses the real change and never reloads. The test asserted "the mtime moved", i.e. it asserted a property of the filesystem, not the code.

Fix

Fold a streamed SHA-256 content digest into the fingerprint alongside metadata, using io.Copy(h, f) so bytes are never buffered:

fmt.Fprintf(h, "%s\x00%d\x00%d\x00", name, info.Size(), info.ModTime().UnixNano())
f, err := os.Open(path)
if err != nil { return "", err }
_, copyErr := io.Copy(h, f)
closeErr := f.Close()
// ... surface both errors
h.Write([]byte("\n"))

Metadata stays in the digest (path binding); nothing-changed stays stable so the sweep doesn't reload every tick.

Test

TestRuleDirMTimesDetectsChange now asserts the hostile condition directly — same-length rewrite + os.Chtimes pins mtime equal — plus a natural polled edit/removal half with a 3s deadline (> 1s granularity) and a stability check.

Verification results

Step Result
Pre-fix go test FAIL — pinned-mtime content change did not trigger reload / the mtime fingerprint did not change after an edit
Post-fix go test -run TestRuleDirMTimesDetectsChange -v PASS
go test ./internal/sensors/ -count=10 ok
go test -race ./internal/sensors/ -count=3 ok
go vet / gofmt -l clean
Falsification: buggy rules.go restored in /tmp/falsify FAIL again

The full self-contained write-up (root cause, complete rules.go, complete reload_test.go, exact commands, expected-outcome table) is at:

Evidence & signatures

# Evidence
- Problem class: go-test-mtime-fingerprint-granularity-false-red
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T08:26:43.688Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Go test asserts a file-mtime-derived fingerprint changes after a same-size rewrite, but the fingerprint hashed path+size+mtime only, so on a coarse-granularity filesystem (or a tar-synced/restored tree) the mtime does not move inside the test window and the assertion is a deterministic false red on clean machines while green on the ns-granularity dev box. Product-side the same blindness makes a 60s mtime-sweep backstop MISS a real content change.", "environment": "linux/amd64, go1.26.5, trouble repo internal/sensors; reproduced by pinning mtime with os.Chtimes before/after a same-size content rewrite", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-test-mtime-fingerprint-granularity-false-red", "provider": "openrouter", "solved_at": "2026-09-19T08:26:43.688Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog