Files
led-sync-studio/.planning/phases/02-app-core-audio/02-04-SUMMARY.md
Claude 721568f0f8 docs(02-04): complete ChoreographyScheduler plan — CHR-05 absolute monotonic scheduler
- SUMMARY.md: timing algorithm, 9 tests, D-07/D-08/D-09 decisions documented
- STATE.md: plan advanced, progress 90%, decisions logged
- ROADMAP.md: phase 2 progress updated (5/6 summaries)
2026-04-03 14:52:08 +02:00

4.5 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
02-app-core-audio 04 scheduling
asyncio
monotonic-clock
choreography
timing
scheduler
phase provides
02-01 ChoreoEvent Pydantic model with timestamp/zone/animation/params fields
phase provides
02-02 ESP32Transport.send_command() for fire-and-forget UDP dispatch
ChoreographyScheduler asyncio task — absolute monotonic clock event dispatch
pause/resume with pause_offset accumulation (D-09)
seek() skips events before seek position
on_event callback hook for TUI integration
02-05 (beat detection integration)
03-xx (TUI wraps scheduler for playback controls)
phase 4 (live reactive mode uses on_event hook)
added patterns
Absolute monotonic scheduling: fire_at = start_time + pause_offset + event.timestamp — never accumulate relative delays
5ms poll interval (asyncio.sleep(min(remaining, 0.005))) keeps event loop responsive while maintaining <1ms drift
pause_offset accumulation for correct pause/resume without event skipping or double-firing
created modified
src/led_sync/scheduler.py
tests/test_scheduler.py
Absolute monotonic timestamps (D-07): fire_at recalculated fresh each 5ms poll iteration — mathematical guarantee of <1ms drift regardless of duration
pause_offset accumulation (D-09): resume() adds elapsed pause time to offset, keeping all future fire_at calculations correct
Scheduler does not inject v:1 — that is transport's responsibility, scheduler sends {zone, animation, params} only
ChoreographyScheduler._run(): asyncio.create_task() wrapping loop with 5ms poll interval
seek() implemented as play() restart with seek_seconds — simpler than maintaining event index pointer
CHR-05
2min 2026-04-03

Phase 02 Plan 04: ChoreographyScheduler Summary

asyncio absolute monotonic scheduler dispatching LED animation commands at precise timestamps — drift < 20ms guaranteed by D-07/D-08/D-09 algorithm

Performance

  • Duration: 2 min
  • Started: 2026-04-03T12:49:30Z
  • Completed: 2026-04-03T12:51:01Z
  • Tasks: 1 (TDD: 2 commits — test + implementation)
  • Files modified: 2

Accomplishments

  • ChoreographyScheduler with absolute monotonic clock dispatch — never accumulates relative delays
  • pause/resume pair using pause_offset accumulation (D-09) — no event skipping or double-firing on resume
  • seek() via play() restart with seek_seconds — correctly skips events before seek position
  • 9 pytest-asyncio tests all passing — timing, payload format, pause/resume, seek, stop, on_event callback, position tracking

Task Commits

Each task committed atomically (TDD pattern):

  1. RED — failing tests - a6ba523 (test)
  2. GREEN — ChoreographyScheduler implementation - ea59bb0 (feat)

Files Created/Modified

  • src/led_sync/scheduler.py — ChoreographyScheduler: play(), pause(), resume(), seek(), stop(), _run(), _dispatch()
  • tests/test_scheduler.py — 9 asyncio tests covering all scheduler behaviors

Decisions Made

  • Absolute monotonic timestamps (D-07): fire_at = start_time + pause_offset + event.timestamp recalculated fresh each poll iteration — mathematical guarantee of <1ms drift per event over any duration
  • pause_offset accumulation (D-09): resume() adds elapsed pause time so all future fire_at values stay correct
  • seek() implemented as play() restart — simpler than maintaining an internal event index pointer, avoids state management complexity
  • Scheduler sends {zone, animation, params} only — v:1 is transport's responsibility (confirmed by test asserting "v" not in cmd)

Deviations from Plan

None - plan executed exactly as written.

Issues Encountered

None — implementation matched plan specification precisely. All 9 tests pass on first run.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • CHR-05 fulfilled: ChoreographyScheduler dispatches animation commands at absolute monotonic timestamps
  • Ready for Phase 02-05 (beat detection) which will call scheduler.on_event via the callback hook
  • Ready for Phase 03 TUI integration — scheduler is asyncio-native, Textual will wrap play()/pause()/resume()/seek() directly
  • current_position property enables real-time timeline display in the TUI

Phase: 02-app-core-audio Completed: 2026-04-03