Wiki · Evidence & Verdicts
The bed was a looping file, not the radio — and the card named a station nobody was tuned to
[redacted: category] — 1 operator path. Nothing else was altered. The document is otherwise exactly as it is written in the repository, and the sha256 below is of the original, so what was ingested stays checkable.How to read this page
Eighty-seven dated pages: receipts, pre-registrations, handoffs, validation records and review verdicts. A receipt is written at the moment a piece of work was checked. It names what was claimed, the commit and the seed, what was actually run, and the outcome in one of a small set of controlled words. Then it names what the work did not achieve. That last part is what makes it a receipt rather than an announcement. A pre-registration is the same discipline run in advance: the conditions that would count as a pass and the conditions that would falsify the claim are written down before the run, so neither can be adjusted once the numbers arrive.
That is why so many small dated stubs are an audit trail rather than noise. No one of them is meant to be a good read. The value is in the sequence and in the dates, because you can watch a prediction be registered, then the run happen, then the verdict land — sometimes against the prediction. Pages here record a falsified result, a rejected fix, a retracted overclaim, and a green receipt that turned out not to be reproducible from the commit that carried it. A record that carried only successes would be worth a good deal less than this one.
A gentle way in is to read a pre-registration first, so the shape becomes familiar, then a result page, then one of the corrections. This section sits off the main navigation on purpose: it is the record you check the rest of the site against, not the place to begin.
What it is not: documentation, and not a summary. Nothing here has been tidied in hindsight. Every entry reads as of its date, a later entry may overturn an earlier one, and the presence of a page is not a claim that its result stood.
A Plain and a Clear version of this page have not been written yet. What follows is the document itself.
Precise — the source document
This is the document. Rendered from the repository at the commit above, with nothing rewritten for the web. A gate re-renders it on every deploy and fails the build if a single byte differs.
Date: 2026-08-02 · Track: studio · Box: THINKER (portable studio) · State: live on air throughout
Gate: node viewer/verify_radio_bed.cjs · Live half: viewer/radio_everywhere.cjs · Durable half: viewer/studio_stage.cjs
Commit: cd66f3c
What the operator said
Live on air:
"the music, the tele is wrong and it is stuck on one album, the music service needs to run like radio, always going and then we listen it, when change scenes the music should keep rolling just like radio, always roll through all"
Two reported defects and one required behaviour. They were one fault, not two.
Defect 1 — stuck on one album
The audible bed was ShowMusic: an ffmpeg_source on the local file
[redacted: operator-path]/Downloads/Album/album_full.m4a with looping: true.
That file is 13 tracks of ONE album concatenated. Measured, not assumed — ffprobe on each
.wav in _concat_list.txt order, summed:
| # | track | seconds |
|---|---|---|
| 1 | Black screen, white text, midnight glow | 329.76 |
| 2 | Virtual Environment | 234.96 |
| 3 | Resolving Dependencies | 292.72 |
| 4 | Version Locked | 208.80 |
| 5 | Wheel Cache Choir | 259.96 |
| 6 | Conflict (But Nothing Broke) | 156.52 |
| 7 | Installing Collected Packages | 209.80 |
| 8 | No Errors, Just Warnings | 140.96 |
| 9 | Environment Ready | 156.52 |
| 10 | Run Command | 151.44 |
| 11 | Standard Output Standard Error | 136.00 |
| 12 | Built, Not Installed | 140.56 |
| 13 | Midnight Run | 287.92 |
| total | 2705.92 |
OBS reported mediaDuration: 2705920 ms for that input. The table is exactly the file, which is
what makes the offset arithmetic below trustworthy. A loop over this file can never reach a second
album. That is the design, not a glitch.
Meanwhile the real service — The Collected Packages Radio, activeListeners: 0, trackCount: 52
across 5 albums — was healthy the whole time (200, Content-Type: audio/mpeg,
icy-metaint: 16000) and was attached to 3 of 37 scenes (MUSIC_HOUR, MUSIC_CARD,
COLONY_SIDE_MUSIC), muted, mediaState: OBS_MEDIA_STATE_ENDED.
The station rolled and nobody listened.
Defect 2 — the card was the SAME defect
command_center.cjs's poller asks /api/nowplaying?session=obs-studio-thinker. With nothing pulling
/radio there is no session, so the service answers {status:"no-session", reference:<track>}.
The poller then does the honest thing: records sessionOpen: false, nulls positionSec so no overlay
draws a fake progress bar, and surfaces reference — the state file even said so in as many words:
"source": "http://…:8687 (reference — ShowRadio not pulling yet)"
But reference is not a playhead. It WALKS THE CATALOGUE on every call. Measured across 8 polls
15 s apart: seq = 37, 0, 15, 30, 45, 8, 23, 38.
Recorded on air, audible track derived from ShowMusic's own mediaCursor against the offset table
above, displayed track read from the spool the overlays render:
| time | HEARD (one track, throughout) | into | CARD DISPLAYED | card's album |
|---|---|---|---|---|
| 19:47:50 | Resolving Dependencies | 177.6 | Midnight Run | Dependency Tree |
| 19:48:05 | Resolving Dependencies | 192.7 | Dead Faces | Alone |
| 19:48:20 | Resolving Dependencies | 207.7 | Ghettos of Milwaukee | Milwaukee After Dark |
| 19:48:35 | Resolving Dependencies | 222.8 | Conflict (But Nothing Broke) | Dependency Tree |
| 19:48:50 | Resolving Dependencies | 237.9 | Couch Kingdom | Havanese Lap Royalty |
| 19:49:05 | Resolving Dependencies | 253.0 | No Talkin 2 Police | Alone |
| 19:49:20 | Resolving Dependencies | 268.0 | Sock It 2 My Pockets | Milwaukee After Dark |
| 19:49:35 | Resolving Dependencies | 283.1 | tippy-taps on hardwood | Havanese Lap Royalty |
One track heard. Eight titles shown, from four albums, in four minutes. No change to any overlay could have fixed this — there was no true answer available to read.
The cure, and it was proven off-air first
Open the session. Nothing else. Before going near the live feed, an own listener was opened to the station and polled:
t+6s sessionOpen=true title=Dead Faces pos=6.0 dur=94.9 icy=The Collected Packages - Dead Faces
t+12s sessionOpen=true title=Dead Faces pos=12.0 dur=94.9 icy=The Collected Packages - Dead Faces
…
t+48s sessionOpen=true title=Dead Faces pos=48.0 dur=94.9 icy=The Collected Packages - Dead Faces
Real playhead, second-for-second, matching the ICY StreamTitle carried in that same connection's
own audio bytes. The service reports sessions correctly; only reference is junk. So opening the
session fixes the card with the card's code untouched, and that was known before the feed was
touched.
What was done, in order, on a live stream
viewer/radio_everywhere.cjs --apply — 32 scenes, 0 failures, program shot last.
- Re-resolved the URL through
host_resolve(no IP literal; the chip's LAN address is a DHCP lease). restart_on_activate→false. It wastrue. With the radio on every scene that would have re-cued the music on every single cut — precisely the continuity the operator asked for.- Level-matched before audible, with a guard that refuses to sample during a voice duck.
- Non-program scenes first,
DUAL_AB(program) last. - Deterministic swap onto the state
music_director.cjs'senforceOneBed()already prefers, so the daemon agrees with it rather than fighting it.ShowMusicleft loaded but muted as instant fallback.
The feed was not disturbed. outputSkippedFrames was 441 before and 441 after; congestion 0;
outputActive true throughout.
Immediately after:
ShowRadio : state=PLAYING muted=false vol=-12.6 cursor=16065
ShowMusic : muted=true (fallback, silent)
service session: OPEN title=Dead Faces pos=17.1
TELE shows : Dead Faces | sessionOpen=true
The durable half is in viewer/studio_stage.cjs so a rebuild reproduces it, including muting the
file bed at bring-up — both beds now share scenes, and without that a rebuild would open with double
audio.
A third finding: the surfaces disagreed with each other
nowplaying.html and musichero.html both degrade to "ON THE STATION" with no progress bar when
sessionOpen === false. musicbug.html — the corner bug, present on every scene — had no such
guard. It kept naming a specific track with a listener count and no caveat: the most confident and
least correct thing on the frame. lyrics.html would have aired one song's words under another.
Both now carry the guard. The cause is fixed, but the next service outage re-arms exactly that state, and a surface that lies only during an outage lies when it matters most.
Two instrument errors of mine, both caught before any pass was claimed
1. A separate listener is not ground truth. The gate first compared the card against ICY metadata from its own probe connection, assuming one shared broadcast. It flagged the card as wrong. The card was right and the gate was wrong. Two probe sessions opened 25 s apart stayed exactly 25 s apart (ALPHA @64 s, BRAVO @39 s), each playing its own copy from its own start. Every session is an independent per-listener stream, so a probe connection is by construction listening to different audio than OBS and can never witness it.
2. Two clocks that measure different things. C3 then subtracted OBS's mediaCursor from the
service's positionSec and failed a healthy system by "247 s", "386 s". mediaCursor is elapsed time
on the connection and climbs forever (367.6 → 397.7 → 427.8); positionSec is position within
the current track and resets at every boundary (120.5 → 11.3 → 41.4). It now compares rates while
the title is unchanged, and measured, the two clocks agree to 0.06 s.
Both are recorded because the gate's credibility rests on it having been wrong in public and corrected.
The rendered pixels, not just the data behind them
GetSourceScreenshot on the two surfaces that ride every scene, captured live:
docs/receipts/radio_bed_nowplaying_2026-08-02.png— kicker "NOW PLAYING" (not the degraded "ON THE STATION"), No Talkin 2 Police / The Collected Packages / Alone, the correct Alone cover art, and a progress bar that is genuinely filling — a thing that was impossible before, becausepositionSecwasnullby design whenever there was no session.docs/receipts/radio_bed_musicbug_2026-08-02.png— No Talkin 2 Police — The Collected Packages, 1 listener (the studio; it read0for as long as the file bed was playing).
Asked independently at that same moment, the service said:
SERVICE (the pipe) : No Talkin 2 Police | Alone | pos 66.4 / 116.3
SPOOL (overlay input): No Talkin 2 Police | Alone | sessionOpen true | pos 62
66.4 / 116.3 ≈ 57%, which is where the rendered bar sits. Picture, corner bug and station all agree. Before today the strip and the corner did not agree with each other.
Verdict — PARTIAL, and the distinction is the point
node viewer/verify_radio_bed.cjs 95 30 — 95 samples over 47 minutes, live, on air.
C1 ROLLING PASS — 16 distinct titles, 3 distinct albums: [Alone | Milwaukee After Dark | Dependency Tree]
C2 TRUTHFUL PASS — 92/95 exact; 3 exempt as poll propagation (playhead < 10s); 0 REAL disagreements
C3 ANCHORED PASS — 77/77 same-track intervals at the SAME RATE as OBS's own decoder cursor
(worst rate disagreement 0.09s, tolerance 2.5s)
boundaries 17/17 track changes reset the playhead to < one sample interval
C4 CONTINUITY NOT_MEASURED — no program cut occurred in the window (the operator's to make)
BED STATE PASS — radio unmuted+PLAYING on every sample, file bed muted (faults: 0, 0)
C5 SELF-CONSIST PASS — supporting only: api="Dead Faces" icy="The Collected Packages - Dead Faces"
Registered PARTIAL, not PASS. C4 is open, not satisfied. Nobody cut the program during the
window, so continuity across a scene change is unproven and is not claimed. The structural argument
is strong — restart_on_activate is now verified false, and ShowRadio is a single source shared by
all 32 scenes, so a cut between any two of them never deactivates it — but that is reasoning, not a
measurement, and it does not get to stand in for one.
The runner's own headline was too generous and was corrected in the same session. It printed
GATE PASS (NOT_MEASURED: C4). A summary line is what gets quoted into a ledger row and a status
board, and PASS in that position launders an open clause into a closed one. It now emits PARTIAL
and exits 2. This is the same failure shape as the world tile in
docs/receipts/world_tile_honest_2026-08-02.md: honest detail, dishonest boolean — and the boolean is
what people read.
No pre-registration document exists. The four verification requirements were specified by the operator before the work began, and the clauses were stated to him before the change was applied, but nothing was committed as a pre-registration file. That is a deviation from the TDD discipline and is recorded here rather than glossed over.
The album the bed had been looping all morning — Dependency Tree — is the third album the station reached on its own during this run. It stopped being the whole world and became one stop on the tour.
C4 closed — 21:48 UTC, one controlled cut, superseding gate row PASS
The operator directed the work to be finished and closed out. C4 needed a program cut; nothing else did.
One cut was made, announced first, via POST :8098/api/cut then /api/back — the same endpoint the
operator's own console uses, not a bespoke OBS call: DUAL_AB → COLONY (held ~5.4s, confirmed in
advance to carry ShowRadio) → DUAL_AB.
The first attempt would have been a false pass, and it was caught. Both the cut and the return call
returned HTTP 403 — missing x-uni-cc header, the same CSRF fence guarding /api/comment. The
instrument only checked HTTP round-trip success, not the header, not the actual scene. Had it not printed
the raw response bodies, it would have reported C4 PASS for a cut that never happened — the program
scene never left DUAL_AB for either call. Caught before anything was claimed; the instrument was
hardened to hard-abort unless the response body says ok:true and the measured program scene
actually matches what was requested, then re-run correctly.
The corrected, real run:
before_cut program=DUAL_AB cursor=6080182ms svc="Midnight Run"@218.8s skipped=441
cut -> COLONY {"ok":true}, measured program=COLONY (confirmed, not assumed)
during_cut_on_COLONY program=COLONY cursor=6080862ms svc="Midnight Run"@219.5s skipped=441
still_on_COLONY program=COLONY cursor=6084911ms svc="Midnight Run"@223.5s skipped=441
back {"ok":true}, measured program=DUAL_AB (confirmed, not assumed)
after_back program=DUAL_AB cursor=6085564ms svc="Midnight Run"@224.2s skipped=441
Across both edges: mediaState never left PLAYING; OBS's own decoder cursor and the service's session
playhead both climbed monotonically — no reset, no jump backward, same track throughout, the elapsed
amounts consistent with real wall-clock time; ShowRadio was never muted; outputSkippedFrames stayed at
441 and outputCongestion at 0 throughout.
Gate row radio-bed-rolling re-registered PASS, superseding the PARTIAL row above. All six
clauses (C1, C2, C3, C4, C5, BED STATE) are now measured and satisfied. Nothing about the prior evidence
changed — only C4 moved from NOT_MEASURED to PASS.
Stated residual — NOT claimed closed
- A silent stall can now linger.
restart_on_activate: truewas set 2026-07-17 so a stalled stream would clear on the next cut. Turning it off was the point of the exercise.reconnect_delay_sec: 3recovers a dropped connection and the muted file bed is an instant fallback, but a socket-open, no-audio stall is not automatically detected by anything.verify_radio_bed.cjscatches it only when someone runs it. - OBS's own ffmpeg connection cannot be tapped without disturbing the live bed. The chain is inductive: the service reports sessions honestly (proven on three independent sessions) + the card reads the studio session + that session's playhead tracks the decoder making the sound to 0.06 s. Strong, but not a direct read of the bytes on air. It is stated that way deliberately.
- A reconnect restarts the playlist at track 0 (
Dead Faces). Every session begins there; the walk through the catalogue is per-listener, not a synchronised station. It still rolls through all 52 tracks and all 5 albums in order, which is what was asked for — but it is not a simulcast, and nothing here should be read as claiming it is. - A small live/durable divergence I introduced, stated rather than hidden. The live tool attached
the bed to the helper scenes
ROLE_A/ROLE_B/ROLE_C; the durable half will not, because those are built inmain()(line ~575) from theROLESmap rather than fromSCENES. They are not dropped by a rebuild — an earlier reading of mine said they would be and that was wrong — they are simply built elsewhere. The divergence is harmless: role scenes are nested as sources inside templates and are never cut to directly, and OBS mixes an input once however many scene items reference it (which is why one source appearing twice in a tree is not the double-audio failure mode — that one was two different beds,ShowMusicandShowRadio, both unmuted). Left as-is rather than churning items on a live tree for a cosmetic difference.
sha256 4b03d6fc4ed09161 — of the original file, so what was ingested stays checkable.