feat(maestro): daemon WS /api/events for live catalog updates (NAP-248)
ci / rust (push) Failing after 7m28s

New module `local_events::LocalEventBus` (broadcast<RegistryEvent>) with
two publishers:

* `spawn_session_publisher` — translates SessionManager's own session
  events into the matching `RegistryEvent` variants (with daemon_id
  filled in for the SessionRemoved case).
* `CatalogMirror::apply` — re-publishes peer events after applying them
  to the local mirror, so subscribers see the post-apply state.

New `WS /api/events` route on the daemon: subscribes to the bus, sends
an initial `Snapshot` built from manager.snapshot() ∪ catalog state,
then forwards live deltas. `Lagged` follows the registry's convention
(client resyncs via REST).

Revert the REST-seed hack in web/src/events.ts — the WS endpoint now
exists, so `CatalogStore::start()` can go back to just `connect()`.

E2E: subscribe to a daemon's events WS, expect Snapshot then a
SessionAdded after POSTing /api/sessions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:01:08 +00:00
co-authored by Claude Opus 4.7
parent 54b5763871
commit a671e15114
9 changed files with 369 additions and 37 deletions
-5
View File
@@ -16,11 +16,6 @@ export class CatalogStore {
private backoffMs = 500;
start(): void {
// Seed the catalog from REST so the UI renders even when the events WS
// hasn't connected yet (or isn't available — e.g. talking to a daemon's
// local /api surface, which has no /api/events). The WS, when it
// succeeds, takes over with live deltas.
void this.resync();
this.connect();
}