fix(director): the beat speaks from the real program, not an imagined one [spec 04] - #165
Merged
Merged
Conversation
… one [spec 04] A buffered talk beat invented a whole broadcast: songs announced that never played, a kettle heard from the listener's room, an afternoon narrated to its end in five real minutes (.dev/dev.log 2026-08-31 14:06-14:28). The prompt gave the model only a six-hour scene bucket and no music facts, so it filled the silence in. The ContextPack now carries the real clock (formatClock, ICU-free) and the program's live music status (playing / quiet / picking / pickFailed), derived from what the Director actually knows: the on-air segment, the pick slot, the latest search outcome (epoch-guarded against a dropped pick resolving late), and the last track that aired. The talk builders render both plus anti-fabrication red lines (the system announces tracks; never narrate picking, listener-side sounds, or time passing); the respond and steer prompts get the same facts without the beat-shaped rules. A forced MURMUR_SCENE drops the clock line rather than contradict it. Peer review (codex gpt-5.6-sol): 4 findings, 4 applied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MSvKfUaQzE95K77oqaBzDU
wine-fall
force-pushed
the
zachg-0831--beat-music-grounding
branch
from
September 2, 2026 06:48
ea21293 to
3bb7f19
Compare
wine-fall
added a commit
that referenced
this pull request
Sep 2, 2026
…191) The grounding that landed in #165 tells the host the local time to the minute. It still could not tell a Monday from a Saturday: the six-hour scene bucket cannot, and neither could a bare "2:28 pm". `formatClock` now renders the weekday and the zero-padded date before the 12-hour local time, so every prompt that speaks aloud knows which day it is. Spec 04 §3.4 records the field's shape. Taken from #162 by Eis4TY, whose diagnosis this is. Its other half — the on-air track's played/remaining seconds — is left out on purpose: self- initiated beats are composed two deep ahead of air (spec 04 §3.3), so a countdown stamped at compose time is already false by the time it is spoken, and works against the anti-fabrication rules #165 added. Claude-Session: https://claude.ai/code/session_01DnTSsRfAnvPPhcbipAMrgW Co-authored-by: Tianyi <41855716+Eis4TY@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 2, 2026
Closed
wine-fall
added a commit
that referenced
this pull request
Sep 4, 2026
"Say real things" shipped: the off-loop topic pool, weighted by the listener's spoken language and their timezone, landed via #201 and #203. The file's own rule is that a delivered line is deleted rather than archived, so the row and its section go, and spec 13 becomes the record — its two pointers into the deleted section are retargeted at itself. What survives the line is tracked elsewhere: #202 joins the by-ear list, and #44 closes on that issue's first box. Line 0's other half is resolved too, though not the way the file predicted. It called for the parallel clock and grounding work to be reconciled into one change; what actually happened is that #165 landed the grounding, #191 then landed only the weekday-and-date half of #162, and the play-progress half was deliberately dropped because the look-ahead makes a countdown false by the time it airs. Recorded as a decision, not a merge, so nobody re-proposes the progress fields. What is left of line 0 is the dropped first line, unchanged. Two cross-references pointed at the deleted line. #98's eval track is the sharper of them: line 2 shipped a prompt whose whole job is stochastic, and the only thing that caught its first draft getting that wrong was a person reading a dev log — so the eval is overdue, not upcoming. Claude-Session: https://claude.ai/code/session_018KVNGUoCkDfWFdLwkGWsAi Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Fixes the self-initiated talk beat fabricating music state. Evidence (.dev/dev.log 2026-08-31): in the no-song stretch after a 14:06
music.end, beats claimed a track was still playing and ending; during the 14:23–14:28 pick-failure window (dead probe, "nothing suitable found") the beats invented an entire broadcast — a song chosen, put on, heard to its end, the listener's kettle heard boiling — and called the afternoon over at 14:28.Root cause: the talk prompt carried no music facts and no clock — only the six-hour scene bucket — so the model filled the silence in. Beats also air minutes after generation via the spec-04 look-ahead buffer.
Related spec: specs/spec04/04-no-dead-air.md (§3.4 context enrichment — bugfix, spec unchanged per convention).
What changed
ContextPackgainstime(real local clock, ICU-freeformatClock) andmusic— a discriminatedMusicState:playing(the on-air label),quiet(nothing playing, optionally the last track),picking(search in flight),pickFailed(latest search empty). Derived in the Director from the segment, the pick slot, the search outcome, and the last aired track; a wired radio always states a music fact.startTrackannounce path, unchanged); the beat never narrates picking/starting a song, never claims listener-side sounds, never narrates time passing.pickFailed; a forcedMURMUR_SCENEdrops the clock line rather than contradict it.Unchanged by design: mood-driven pick selection (spec 04),
gapSeconds, the announce path.Peer review (codex gpt-5.6-sol, xhigh): 4 findings, 4 applied, 0 dismissed.
Gates: 1012 vitest green, tsc, oxlint. By-ear: whether the beats actually stop fabricating on a real run is a stochastic outcome — worth an ear during the next normal listening session, no dedicated pass owed.
AI coding brief
Original request: Fix the bug of self-initiated talk beats fabricating music state (songs announced that never played, imagined listener-side sounds, time narrated faster than real), with evidence and the fix plan pre-settled in-session: ground the
ContextPackwith real music status + real clock, and add prompt red lines.Manual interventions: None during the build — the invocation carried the full investigation (log evidence, root cause, fix design, constraints), so the session went straight to test-first implementation.
Retro: Front-loading the diagnosis into the /murmur-ship brief (evidence timestamps, named code seams, settled design, explicit non-goals) let the build skip re-investigation entirely; the only additions came from the codex closing review, which the brief correctly left open.
🤖 Generated with Claude Code
https://claude.ai/code/session_01MSvKfUaQzE95K77oqaBzDU