The CDC substrate has been writing PR events to change_log since the original PR table landed, and migration 0004_scm_observer_schema.sql (lines 95-137) added two more: pr_review_thread_added and pr_review_thread_resolved. PR #101 will add pr_session_changed. All of these are durable in change_log and the broadcaster in backend/internal/cdc fans them out internally, but no HTTP/SSE controller subscribes to them today. The only live consumer is the terminal session-state fan-out (backend/internal/daemon/daemon.go:76 → terminal.NewManager).
Effect: the frontend / ao CLI cannot react to PR state changes in real time even though the substrate is ready. Anything that wants observer output (dashboard, future ambient notifier, status overlays) has to poll the DB.
Acceptance
Why scope this now
Tracker observer (#35) will emit tracker-shaped CDC events when it lands. Designing the SSE shape now (and keeping the typed-event discriminated union out of the transport) saves us a v2 controller later.
Related
- Depends on
cdc package shape — no code change there, just a consumer.
- Upstream design constraint:
backend/internal/cdc/doc.go already documents the "change_log IS the durable, ordered source of truth; clients catch up by reading it from their own offset" contract.
The CDC substrate has been writing PR events to
change_logsince the original PR table landed, and migration0004_scm_observer_schema.sql(lines 95-137) added two more:pr_review_thread_addedandpr_review_thread_resolved. PR #101 will addpr_session_changed. All of these are durable inchange_logand the broadcaster inbackend/internal/cdcfans them out internally, but no HTTP/SSE controller subscribes to them today. The only live consumer is the terminal session-state fan-out (backend/internal/daemon/daemon.go:76→terminal.NewManager).Effect: the frontend /
aoCLI cannot react to PR state changes in real time even though the substrate is ready. Anything that wants observer output (dashboard, future ambient notifier, status overlays) has to poll the DB.Acceptance
GET /api/v1/events(or a name picked during review) streams CDC events using SSE withLast-Event-IDresume semantics — reuse the offset model documented inbackend/internal/cdc/doc.go.cdcPipe.Broadcasterand serializesEvent(backend/internal/cdc/event.go:37-44) per the existing JSON shape.session_*,pr_*,pr_check_recorded,pr_review_thread_added,pr_review_thread_resolved, andpr_session_changed(the latter lands with PR feat: ao session claim-pr + spawn --claim-pr wiring #101).?project=...) — events for other projects must not leak.httptest+ the real CDC pipeline asserts that a row inserted on the DB shows up in the SSE stream.Why scope this now
Tracker observer (#35) will emit tracker-shaped CDC events when it lands. Designing the SSE shape now (and keeping the typed-event discriminated union out of the transport) saves us a v2 controller later.
Related
cdcpackage shape — no code change there, just a consumer.backend/internal/cdc/doc.goalready documents the "change_log IS the durable, ordered source of truth; clients catch up by reading it from their own offset" contract.