§4 · Ten messages, five operations, no optional fields

JSON over WebSocket, one message per frame, a type field on every message. There is no extension point other than param, and there are no optional features to negotiate — a conformance profile is something an implementation can hide behind.

Message Direction Fields Meaning
ct.hello both v Handshake and version check
ct.ping client → t0 Opens a latency measurement
ct.pong → client t0, t1 Answers a latency measurement
ct.session → client id, anchorEpochMs, bpm, beatsPerBar, ppq The anchor and the tempo for the session
ct.load → client id, material, lengthTicks Which material to fetch, and how long it runs
ct.ready client → ref, readyAtTick The material is loaded and playable
ct.refuse client → ref, reason The material was not loaded, and why
ct.cmd → client id, atTick, slot, op, value, rampTicks One playback or control command
ct.snapshot → client atTick, cmds[] Current state: the commands in force
ct.state client → offsetMs, minRttMs, jitterMs, minLeadTicks, late[], degraded Client telemetry and health

The five operations

The op field of ct.cmd takes these five values. The core operations guarantee interoperability; param is the only extension point, and its namespace belongs to the application.

op What it does value rampTicks
start slot begins playing its material yes
stop slot stops playing yes
gain slot level decibels yes
param application-defined parameter name + value yes
material assigns material to the slot identifier no

material is an instantaneous assignment and takes no ramp. Note that ct.load does not assign material to a slot — it is a content-addressed fetch with no slot, and assignment is slot state and therefore a command.

The material model is deliberately thin: a session has numbered slots, and a slot is either empty or holds material. The protocol does not know what material is musically — no roles, no instruments, no genre.

A material identifier must be of the form sha256:<hex> in lower case. A client must accept and retain a param name it does not recognise; the prefix ct. is reserved for future versions of the protocol and an application must not use it.

See Examples for a complete message flow and for what a snapshot looks like when two commands compete for one slot.

Two rules that make the control plane replayable

N3 · a command is never answered

A command whose atTick has already passed is still applied, and its effect is computed as if it had been applied at atTick. Lateness is reported in telemetry, not negotiated. A command is never discarded for lateness alone.

N8 · state monotonicity

For a given slot and parameter, the command with the highest atTick wins. Application is therefore idempotent and order-independent: two clients receiving the same commands in different orders arrive at the same state. A snapshot is not a special structure — it is the set of winning commands, each with its original atTick.