go test ./... is red on unmodified dev for internal/smt, while the same test passes in isolation. Found during mission iteration 151 while verifying an unrelated sprint (#601) outside the codex sandbox; it is not caused by that change.
Measurement
Two controlled arms, run on both the main checkout at 263df3df8 (unmodified) and a sprint worktree:
| Arm |
Command |
Result |
| Full suite |
go test ./... |
rc=1 — FAIL internal/smt |
| Isolated test |
go test ./internal/smt -run TestSolve_HardTimeout_FakeSolverIgnoringT |
rc=0 |
| Whole package |
go test -count=1 ./internal/smt |
rc=0 |
The full-suite arm was also run with no other load and still failed, so this is not an artifact of my running two suites concurrently.
Failure:
--- FAIL: TestSolve_HardTimeout_FakeSolverIgnoringT (3.00s)
solver_timeout_test.go:42: read child pid: open /tmp/.../TestSolve_HardTimeout_FakeSolverIgnoringT.../001/child.pid: no such file or directory
Cause
internal/smt/solver_timeout_test.go:19 calls Solve with Timeout: time.Second against a fake solver script that writes its PID to a file and then sleeps. readChildPID (line 42) then reads that pidfile.
The test assumes the child process gets scheduled and writes its pidfile before the 1s solver timeout kills it. Under the parallel load of a full go test ./..., that assumption can lose: the child is killed before the write lands, the pidfile never exists, and readChildPID fails. Nothing in the test waits for the pidfile to appear.
This is a defect in the test, not in the hard-timeout mechanism it covers — Solve behaved correctly in every observed run (the status/elapsed/error assertions above line 42 all passed).
Why CI is green
CI runs the identical go test -timeout 300s ./... (.github/workflows/ci.yml:98) and dev is green at 263df3df8, so the runners' load profile happens to stay on the winning side of the race. That makes this a latent CI flake rather than a purely local annoyance — the same class the just-closed M-CI-FLAKE-SYSTEMIC-FIX sprint (#591–#600) was about, and it is a survivor of it.
Suggested fix
Poll for the pidfile with a bounded deadline instead of assuming it exists by the time the solver timeout fires — or have the fake solver write its pidfile before doing anything else and have the test wait on that file with a bounded retry, failing loudly on expiry. internal/testutil's bounded helpers (added in #591) are the natural home for the wait.
Related: TestSolve_HardTimeout_FakeSolverIgnoringT is also one of the two tests already known to fail from a /tmp-rooted checkout, so it is sensitive to both tmp location and timing.
🤖 Generated with Claude Code
go test ./...is red on unmodifieddevforinternal/smt, while the same test passes in isolation. Found during mission iteration 151 while verifying an unrelated sprint (#601) outside the codex sandbox; it is not caused by that change.Measurement
Two controlled arms, run on both the main checkout at
263df3df8(unmodified) and a sprint worktree:go test ./...FAIL internal/smtgo test ./internal/smt -run TestSolve_HardTimeout_FakeSolverIgnoringTgo test -count=1 ./internal/smtThe full-suite arm was also run with no other load and still failed, so this is not an artifact of my running two suites concurrently.
Failure:
Cause
internal/smt/solver_timeout_test.go:19callsSolvewithTimeout: time.Secondagainst a fake solver script that writes its PID to a file and then sleeps.readChildPID(line 42) then reads that pidfile.The test assumes the child process gets scheduled and writes its pidfile before the 1s solver timeout kills it. Under the parallel load of a full
go test ./..., that assumption can lose: the child is killed before the write lands, the pidfile never exists, andreadChildPIDfails. Nothing in the test waits for the pidfile to appear.This is a defect in the test, not in the hard-timeout mechanism it covers —
Solvebehaved correctly in every observed run (the status/elapsed/error assertions above line 42 all passed).Why CI is green
CI runs the identical
go test -timeout 300s ./...(.github/workflows/ci.yml:98) anddevis green at263df3df8, so the runners' load profile happens to stay on the winning side of the race. That makes this a latent CI flake rather than a purely local annoyance — the same class the just-closedM-CI-FLAKE-SYSTEMIC-FIXsprint (#591–#600) was about, and it is a survivor of it.Suggested fix
Poll for the pidfile with a bounded deadline instead of assuming it exists by the time the solver timeout fires — or have the fake solver write its pidfile before doing anything else and have the test wait on that file with a bounded retry, failing loudly on expiry.
internal/testutil's bounded helpers (added in #591) are the natural home for the wait.Related:
TestSolve_HardTimeout_FakeSolverIgnoringTis also one of the two tests already known to fail from a/tmp-rooted checkout, so it is sensitive to both tmp location and timing.🤖 Generated with Claude Code