78 lines
1.9 KiB
Markdown
78 lines
1.9 KiB
Markdown
# 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:
|
|
|
|
```json
|
|
{
|
|
"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_answered`
|
|
- `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
|