fix(tui): the clock stops counting past the end of the song [spec 10] - #281
Merged
Merged
Conversation
A coda riding the outro (spec 04 3.3) keeps presence on music after the audio has ended, and the strip advanced its readout on unbounded wall clock: a 2:54 track printed 3:03 while the rail, which clamps, sat full. The two now read the same length. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
wine-fall
force-pushed
the
zachg-0920--progress-clock-clamp
branch
from
September 20, 2026 07:14
7acf55c to
6009de4
Compare
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The now-playing readout could print more time than the song has: a 2:54 track
showing
3:03 / 2:54while the rail beside it sat full.Not the engine running long. The wall clock is right and the audio is right —
the state is what lingers. A coda riding the outro (spec 04 §3.3) deliberately
keeps presence on
musicafter the audio has ended, so the front-end keptadvancing
now - startedAtwith nothing to stop it. The rail already clamped(
clamp01); only the number did not, so the two disagreed on screen.playedSis now the one place that answers "how far into the track are we",bounded by the length when there is one — an absent length is still "unknown"
(no rail), so it keeps counting rather than freezing at
0:00.Evidence from a real session (
~/.murmur/log/murmur-2026-09-20.log):yt-dlp reports 174 s for that track and a full decode yields exactly 174.0 s of
audio; the 15 s is the coda still speaking. Tracks with no riding coda in the
same log read
played == expectedto the second.Implements specs/spec10/10-tui.md §3.3 (the now-playing rail).
Tests
test/tui-progress.test.tsgains four cases forplayedS: it advances on thefront-end's own clock, stops at the track's length (the 174/189 case above, and
the rail agrees), treats an unknown length as no ceiling, and never reads back
before the start. Full suite green (2000), typecheck and oxlint clean.
Peer review (codex gpt-6-astra): 0 findings, Trade-off verdict: acceptable.
AI coding brief
Original request. The user sent a screenshot of the TUI showing
3:03 / 2:54for a song that had just played, saying the duration was being exceeded again.
The why: a readout that outruns its own denominator reads as a broken player,
and it had been seen more than once.
Manual interventions. None on the fix itself. The user's framing ("the
duration is exceeded") was a symptom report; the diagnosis (engine vs. display)
came from the logs, and the wall-clock-vs-audio drift was ruled out by
measurement before any code was written.
Retro. The log line
music.end played=… expected=…was what made this aten-minute diagnosis instead of a guess — it is worth adding that shape of line
wherever a front-end extrapolates from an origin the engine stamped. The one
detour was measuring audio-clock drift and stream scheduling in a scratch
script before noticing
coda rides the outrositting in the same log; readingthe surrounding log lines first would have skipped it.
🤖 Generated with Claude Code