5e51381b7a
Add src/app/events.go: a sealed Event interface with three concrete types (JobChanged, RunRecorded, SchedulerStateChanged), an Observer interface plus ObserverFunc adapter, and Subscribe/emit on the Service. This replaces the scheduler's single onChange callback with typed events the UI can exhaustively type-switch over. Dispatch is serialized by a dedicated dispatchMu (separate from the state lock): observers never run concurrently, emit must be called without holding s.mu so observers can read Service state, and observers must not re-enter an emitting method. emit is wired to mutating ops in T3.3. Adds tests for ordered multi-observer delivery, empty-observer no-op, and observer-reads-state-without-deadlock. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>