playback: one explicit state machine (idle → cooking → holding → playing → ended) #1

Merged
teahubxyz merged 3 commits from playback-state-machine into main 2026-10-21 06:14:05 +00:00
3 Commits
Author SHA1 Message Date
teahubxyzandClaude Fable 5.1 1aeebac6f2 harness: a resume mode (autoplay blocked); docs for the state machine and hooks
tools/harness.sh resume seeds IndexedDB with a station and one rendered
track, resumes it with no user gesture and expects the TAP TO PLAY wait.
IndexedDB needs http, so the page is served from a temp folder; headless
Chrome's virtual time doesn't wait for IndexedDB, so this mode is driven in
real time over the DevTools protocol (tools/harness-cdp.py, stdlib only).
The loop harness now prints state.phase too.

ARCHITECTURE.md describes the machine as implemented; HANDOFF.md lists what
was found and left alone; STORAGE.md gains db.get and the tapes store (the
code already had both); README points at the new files.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
2026-10-21 06:01:48 +00:00
teahubxyzandClaude Fable 5.1 dddf8f0add brain: plug into the page's hooks instead of overriding its functions
hooks.djPrompt, hooks.stationOpened, hooks.jobMade and hooks.reacted carry what
the djPrompt / openStation / makeJob / react reassignments did; same behaviour.
countPlay reads its one row with db.get instead of db.all().

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
2026-10-21 05:58:46 +00:00
teahubxyzandClaude Fable 5.1 eb110e827b playback: one explicit state machine, hooks for brain.js, db.get for single rows
state.phase (idle → cooking → holding → playing → ended) with named transitions
(toCooking, toHolding, toPlaying, startNow, handOver, toEnded, toIdle) replaces
the three overlapping mechanisms (playJob/advance, swapNow, the crackle hold with
state.holding/pendingJob). state.holding is now a read-only view of the phase.
Behaviour unchanged; the harness prints the same state lines before and after.

A `hooks` object (djPrompt, jobMade, stationOpened, reacted) is what brain.js
plugs into instead of overriding page functions by assignment.

db.all() used to find one row becomes db.get(id); tapes go through tapeById
(KEPT is virtual). setSource drops old object URLs but never the crackle's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
2026-10-21 05:57:59 +00:00