What is wrong
internal/tui3's TestNothingArrivingAfterTheStopIsDrawn compares a whole
rendered frame before and after driving events at a stopped turn
(stopping_test.go:136). The frame includes the header's live wall clock, so
the test fails whenever its two captures straddle a minute boundary.
Caught on a pull-request gate. The two frames were byte-identical except one
field:
was: codeaf tue 3:43am
new conversation ×
─────────────────────────────────────────────────────────
▸ stopped by you at 0.2s · 1 tool call · ctrl+e
· stopped
─ lab · m ───────────────────────────────────── / commands ─
›
$0.00 stopping
now: codeaf tue 3:44am
(… every other line identical …)
3:43am against 3:44am, and nothing else differs.
Mechanism
stoppingApp sets a.turnBegan = a.now(), and newTestApp installs no clock,
so a.now() is time.Now() and the header draws real time. The assertion is a
string comparison of the whole frame, so that field is part of the claim without
meaning to be.
Rate
About 0.75% per run, which is the fraction of a minute the test spends between
its two captures at its 0.45 second duration. Measured independently before the
diff was in hand: 1 failure in 81 runs on one branch and 0 in 21 on the
trunk, across GOMAXPROCS 1, 2 and 4 — indistinguishable rates, which is what
established that no change under test was responsible.
Why this is worth fixing rather than re-running
Two opposite mistakes are both available here and both are expensive.
Re-running until green is how a real defect gets filed as noise. Reading a clock
tick as a regression in the change under test is how a good change gets blamed
and reworked — that is what nearly happened: this failure arrived on a pull
request whose entire internal/tui3 delta is a doc comment, and whose code
cannot reach the path the test drives, since the test uses synthetic events and a
fakeAgent.
The assertion is also stronger than it needs to be in a way that hides its own
weakness: comparing the entire frame catches any drawing after a stop, which is
the point, but it silently includes a field that changes on its own.
Replication a stranger can run
The honest replication is the rate, since the failure is a race with the clock:
go test -count=81 -run '^TestNothingArrivingAfterTheStopIsDrawn$' ./internal/tui3/
Expect roughly one failure. To force it deterministically, pin the app's clock to
a moment 200 milliseconds before a minute boundary and drive the events across
it; that is also the shape of the fix.
Acceptance
newTestApp (or stoppingApp) installs a fixed clock, so the frame's header
cannot move on its own. The repository already prefers a deterministic clock
over real time in tests.
- A test that fails if the frame comparison stops covering the header — so
the fix does not become "exclude the clock from the comparison", which would
also stop the assertion noticing a real header change after a stop.
go test -count=200 -run '^TestNothingArrivingAfterTheStopIsDrawn$' ./internal/tui3/ green, with the count quoted.
Not added to .github/known-red.txt: that ledger burned to zero on 2026-09-12
(#1012) and only shrinks, and a flake with a known cause is a fix rather than a
line.
What is wrong
internal/tui3'sTestNothingArrivingAfterTheStopIsDrawncompares a wholerendered frame before and after driving events at a stopped turn
(
stopping_test.go:136). The frame includes the header's live wall clock, sothe test fails whenever its two captures straddle a minute boundary.
Caught on a pull-request gate. The two frames were byte-identical except one
field:
3:43amagainst3:44am, and nothing else differs.Mechanism
stoppingAppsetsa.turnBegan = a.now(), andnewTestAppinstalls no clock,so
a.now()istime.Now()and the header draws real time. The assertion is astring comparison of the whole frame, so that field is part of the claim without
meaning to be.
Rate
About 0.75% per run, which is the fraction of a minute the test spends between
its two captures at its 0.45 second duration. Measured independently before the
diff was in hand: 1 failure in 81 runs on one branch and 0 in 21 on the
trunk, across
GOMAXPROCS1, 2 and 4 — indistinguishable rates, which is whatestablished that no change under test was responsible.
Why this is worth fixing rather than re-running
Two opposite mistakes are both available here and both are expensive.
Re-running until green is how a real defect gets filed as noise. Reading a clock
tick as a regression in the change under test is how a good change gets blamed
and reworked — that is what nearly happened: this failure arrived on a pull
request whose entire
internal/tui3delta is a doc comment, and whose codecannot reach the path the test drives, since the test uses synthetic events and a
fakeAgent.The assertion is also stronger than it needs to be in a way that hides its own
weakness: comparing the entire frame catches any drawing after a stop, which is
the point, but it silently includes a field that changes on its own.
Replication a stranger can run
The honest replication is the rate, since the failure is a race with the clock:
Expect roughly one failure. To force it deterministically, pin the app's clock to
a moment 200 milliseconds before a minute boundary and drive the events across
it; that is also the shape of the fix.
Acceptance
newTestApp(orstoppingApp) installs a fixed clock, so the frame's headercannot move on its own. The repository already prefers a deterministic clock
over real time in tests.
the fix does not become "exclude the clock from the comparison", which would
also stop the assertion noticing a real header change after a stop.
go test -count=200 -run '^TestNothingArrivingAfterTheStopIsDrawn$' ./internal/tui3/green, with the count quoted.Not added to
.github/known-red.txt: that ledger burned to zero on 2026-09-12(#1012) and only shrinks, and a flake with a known cause is a fix rather than a
line.