Skip to content

fix(tui): the clock stops counting past the end of the song [spec 10] - #281

Merged
wine-fall merged 1 commit into
mainfrom
zachg-0920--progress-clock-clamp
Sep 20, 2026
Merged

wine-fall merged 1 commit into
mainfrom
zachg-0920--progress-clock-clamp

Conversation

@wine-fall

Copy link
Copy Markdown
Owner

The now-playing readout could print more time than the song has: a 2:54 track
showing 3:03 / 2:54 while 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 music after the audio has ended, so the front-end kept
advancing now - startedAt with nothing to stop it. The rail already clamped
(clamp01); only the number did not, so the two disagreed on screen.

playedS is 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):

11:20:05 now playing: World Where the Sun Never Rises — Aimer
11:22:49 coda rides the outro
11:23:15 music.end played=189s expected=174s

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 == expected to the second.

Implements specs/spec10/10-tui.md §3.3 (the now-playing rail).

Tests

test/tui-progress.test.ts gains four cases for playedS: it advances on the
front-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:54
for 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 a
ten-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 outro sitting in the same log; reading
the surrounding log lines first would have skipped it.

🤖 Generated with Claude Code

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
wine-fall force-pushed the zachg-0920--progress-clock-clamp branch from 7acf55c to 6009de4 Compare September 20, 2026 07:14
@wine-fall
wine-fall merged commit d875c30 into main Sep 20, 2026
3 checks passed
@wine-fall
wine-fall deleted the zachg-0920--progress-clock-clamp branch September 20, 2026 07:15
@wine-fall wine-fall mentioned this pull request Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant