Files

2.0 KiB

Event Stream Contract

Status

Planned for the next milestone. The Phase 1 web skeleton does not implement the event stream yet.

Intended Endpoint

  • GET /api/events/stream

Transport Choice

  • start with Server-Sent Events rather than websockets
  • keep the stream read-only and cursor-based
  • let the frontend use events to invalidate or refresh TanStack Query caches

Query Parameters

  • after_event_id: optional monotonic cursor
  • run_id: optional run filter for run-scoped pages
  • thread_id: optional thread filter for timeline views

Event Envelope

Each SSE message should carry one JSON object with this shape:

{
  "event_id": 42,
  "event_type": "task_blocked",
  "run_id": "run_web_001",
  "task_id": "T1",
  "thread_id": "thr_123",
  "summary": "Need the API shape",
  "payload": {
    "source": "orch"
  },
  "created_at": "2026-03-20T09:30:00Z"
}

Expected First Event Types

  • task_added
  • task_ready
  • task_dispatched
  • task_running
  • task_blocked
  • task_verifying
  • task_answered
  • task_verification_recorded
  • task_done
  • task_failed
  • thread_claim
  • thread_update
  • thread_reply
  • thread_result
  • council_tallied
  • council_report_persisted

Cursor Rules

  • event_id is the only resume cursor
  • the server should emit events in ascending event_id order
  • reconnect clients should pass the last processed event_id
  • the server should not depend on in-memory subscriptions for correctness

Frontend Usage

  • run detail pages should subscribe with run_id
  • thread views may subscribe with thread_id
  • the client should prefer refetch/invalidate behavior over complex local reducers in the first realtime slice

Backend Notes

  • source data should come from the existing shared events table
  • orchd should treat the stream as a projection over persisted events, not as a separate ephemeral bus
  • if filtering becomes expensive later, move filtering logic into a dedicated query layer without changing the wire contract