Streams, lifecycle and compatibility
Refresh coherent state after a gap, restart or project switch.
AlphaStreams carry bounded observations and cursors. They do not make a client an authoritative owner of Core's state.
Observe
Use ObserveProjectAsync for a complete snapshot followed by its cursor-bound stream. The lower-level subscription methods accept a cursor read from the corresponding snapshot or prior event.
Handle subscribed, resync_required, diagnostic gaps and explicit errors. After a replay gap, fetch a new snapshot. Preserve and compare pending UI drafts instead of silently replacing them with the refreshed model.
WebSocket protocol for other languages
Use the discovered endpoint with scheme ws and path /api/v1/streams. Authenticate the upgrade with the negotiated session in the Authorization: Bearer <accessToken> header. Do not use a token query parameter. After connecting, send a UTF-8 JSON text subscription:
{
"type": "subscribe",
"stream": "project",
"cursor": "opaque-cursor-from-the-project-snapshot"
}
Use the actual cursor returned by Core. Never parse, increment or invent it. project uses the project snapshot cursor; shell, runtime, status, diagnostics and logs each have their own snapshot endpoint and permission. One stream's cursor cannot be reused for another.
Read control frames (subscribed, resync_required, gap, error) and event envelopes with stream, event type, Host/project identity and cursor. Inspect ProjectStreamSubscribeDto, ProjectStreamControlDto, ProjectStreamEventDto and HostStreamEventDto through the live schemas for exact fields. The normal client defaults to a 2 MiB maximum message; respect Core's bounded retention and limits too.
Store the last consumed cursor only after processing its event. After a gap, discard that observation cache, obtain a new coherent snapshot and subscribe from its cursor. Do not apply events from a previous Host/project to the new state.
.NET observation helpers
SubscribeProjectAsync, SubscribeShellAsync, SubscribeRuntimeAsync, SubscribeStatusAsync, SubscribeDiagnosticsAsync and SubscribeLogsAsync expose explicit controls and events. ApiStreamMessage.RequiresSnapshot identifies a gap or resync request. A completed enumeration does not silently renew approval or replace UI drafts.
For coordinated project, shell and runtime observations, ApiConnection accepts your reconnect factory. It reads coherent snapshots and moves through Connecting, Syncing, Ready, Lost and Incompatible. The factory should read fresh discovery and reconnect with an approved credential using host.status, project.read and runtime.read. Your application owns credential storage and renewal policy.
Lifecycle
A Core restart replaces Host identity and invalidates old sessions/cursors. A project switch replaces project identity. Stop issuing edits against the previous identity and read current state before continuing.
Dispose hidden/closed observations and join cancellation. A slow client must not stall automation execution; bounded retention means it may need to resynchronize.
Handshake checks contract major, capabilities and permissions. Missing scopes or an incompatible client should produce a clear refusal rather than fallback to a weaker private interface.
See Pairing and Command recovery.