Session Projection Contract¶
Open Cowork syncs product state through shared Cloud session event and projection record types. The contract is versioned in packages/shared/src/cloud-session-contract.ts and consumed by Desktop, Cloud Web, and Gateway. OpenCode still owns runtime execution; Open Cowork only normalizes runtime output into durable product events.
Version¶
Current contract version: 1.
Public shared types:
CloudSessionEventRecordCloudSessionProjectionEventRecordCloudSessionEventTypeCloudProjectedSessionEventType
Changing the meaning of an existing event or projection field requires a version bump, a migration or compatibility path for stored projections, and tests proving older snapshots still hydrate safely. Adding a new event type is allowed without a version bump only when older clients can ignore it without losing required chat state.
Event Flow¶
flowchart LR
OpenCode["OpenCode runtime events"] --> Adapter["Cloud runtime adapter"]
Adapter --> Events["CloudSessionEvent contract"]
Events --> Store["Durable event log"]
Store --> Reducer["Shared projection reducer"]
Reducer --> View["SessionView"]
View --> Desktop["Desktop"]
View --> Web["Cloud Web"]
Events --> Gateway["Gateway renderer"] Rules:
- Raw OpenCode SDK events stop at the runtime adapter.
- Cloud workers append only canonical
CloudSessionEventTypevalues. - Projection reducers live in shared code and produce the
SessionViewshape Desktop already consumes. - Gateway renders only event types marked
channelRenderablein the shared contract. snapshot.requiredandchannel.deliveryare control events, not projected session state.
Projected Event Vocabulary¶
Projected events update durable session state:
session.createdsession.importedsession.project_source.boundprompt.submittedassistant.messagetool.calltask.runpermission.requestedpermission.resolvedquestion.askedquestion.resolvedtodos.updatedcost.updatedartifact.createdsession.statussession.idlesession.abortedruntime.error
Control events are delivered over Cloud APIs but do not update the session projection:
snapshot.requiredchannel.delivery
Extension Rules¶
When adding an event:
- Add it to
CLOUD_SESSION_EVENT_CONTRACTwith facets, producers, consumers, channel renderability, and a short description. - If it is projected, update
reduceCloudSessionProjectionEvent. - Add SDK normalization fixtures when it comes from OpenCode.
- Add Desktop/Web/Gateway tests for every surface that consumes it.
- Keep the Gateway renderer on canonical Cloud events. Do not render raw SDK event names in channel providers.
This contract is the compatibility boundary between synced product surfaces. It should grow through typed events and tests, not through surface-specific parsing of runtime internals.