When multiple /notify calls arrive in quick succession, they now queue up
and display one at a time rather than clobbering each other. Each notification
plays for its full duration before the next is promoted.
- /notify returns `queued: true` and `notify_queue_size` when buffered
- Cleanup thread auto-advances the queue when the playing notification expires
- /clear on the playing notification promotes the next immediately
- /clear on a queued (not-yet-playing) notification removes it from the queue
- /clear-all also drains the queue
- Status response includes `notify_queue_size` for frontend awareness
Bump to v2.3.3. Update OpenAPI spec, README, TODO.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add GET /stream SSE endpoint to aggregator.py; state is pushed
instantly on every change instead of fetched every 2s
- Replace setInterval polling in index.html with EventSource;
onerror shows the ( ?.?) face and auto-reconnect is handled by
the browser natively
- Fix ModuleNotFoundError in detectors: inject project root into
PYTHONPATH when launching subprocesses from kao.py
- Update openapi.yaml, CLAUDE.md, README.md with /stream endpoint
- Remove completed SSE item from TODO.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kao is a display, not a monitor — external systems push events via REST
rather than Kao polling things itself. Update CLAUDE.md to reflect this:
- New Design Philosophy section making the REST-first approach explicit
- Architecture diagram updated to show external systems as the push source
- Detectors section demoted to "Legacy Detectors" with a note to prefer push
- TODO.md added with planned REST API improvements (SSE, notify queue,
sticky notifications, named presets, batch notify, /history endpoint)
and display improvements (brightness curve, scrolling ticker)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>