2026-11-02 12:36:32 +00:00
|
|
|
# Runa Protocol
|
|
|
|
|
|
|
|
|
|
`runa-protocol` defines versioned request, response, and event data contracts
|
2026-11-03 14:49:35 +00:00
|
|
|
for clients and the `runa` dispatcher. It is independent of transport
|
|
|
|
|
and runtime implementation. `runa` accepts WebSocket text messages bound to an IPv4 or
|
|
|
|
|
IPv6 loopback address, defaulting to `127.0.0.1:3737` without arguments.
|
|
|
|
|
Clap parses `--listen` / `RUNA_LISTEN` on the server and `--connect` /
|
|
|
|
|
`RUNA_CONNECT` on `runa-cli`; explicit flags override environment variables.
|
|
|
|
|
The listener is unauthenticated and intended only for
|
2026-11-03 14:36:21 +00:00
|
|
|
trusted local development. Both the REPL and VS Code use WebSockets.
|
2026-11-02 12:36:32 +00:00
|
|
|
|
2026-11-03 19:11:39 +00:00
|
|
|
## Version 5
|
2026-11-02 12:36:32 +00:00
|
|
|
|
2026-11-03 17:26:21 +00:00
|
|
|
Every request and response carries `version: 5`. Requests also carry a
|
2026-11-02 12:36:32 +00:00
|
|
|
non-empty `request_id` used to correlate the response. A server must reject
|
|
|
|
|
unsupported versions with `unsupported_version` rather than interpreting a
|
|
|
|
|
request using a different contract. Events carry the protocol version and do
|
|
|
|
|
not have a request ID.
|
|
|
|
|
|
|
|
|
|
Requests have a tagged command object:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
2026-11-03 17:26:21 +00:00
|
|
|
"version": 5,
|
2026-11-02 12:36:32 +00:00
|
|
|
"request_id": "req-1",
|
|
|
|
|
"command": {
|
|
|
|
|
"operation": "send",
|
|
|
|
|
"parameters": {
|
2026-11-02 14:19:25 +00:00
|
|
|
"actor_ref": "xK8_pQ2-Lm5_012345678",
|
|
|
|
|
"message": {
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
"type": "record",
|
|
|
|
|
"data": {
|
|
|
|
|
"op": { "type": "string", "data": "send" },
|
|
|
|
|
"value": { "type": "integer", "data": 9 },
|
|
|
|
|
"target": { "type": "actor_ref", "data": "Hj2_9sM0-pQ4_7aBcD3eF" }
|
|
|
|
|
}
|
2026-11-02 14:19:25 +00:00
|
|
|
}
|
2026-11-02 12:36:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2026-11-03 17:26:21 +00:00
|
|
|
The version 5 operations are source listing/read/write, commit/history/revision
|
2026-11-03 16:01:24 +00:00
|
|
|
retrieval/rollback, actor spawn, send, tick, inspect, actor listing, event
|
|
|
|
|
retrieval, privileged system messages, and cancellation.
|
2026-11-02 12:36:32 +00:00
|
|
|
Migration closures are intentionally excluded: they are host callbacks, not
|
|
|
|
|
portable wire values.
|
|
|
|
|
|
2026-11-03 16:01:24 +00:00
|
|
|
Source paths are extensionless relative paths such as `actors/counter`, not
|
|
|
|
|
behavior aliases. They exclude the `source/` root and `.rn` extension.
|
|
|
|
|
|
|
|
|
|
| Operation | Parameters | Reply kind/data |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `list_sources` | none | `sources`: file array |
|
|
|
|
|
| `read_source` | `path` | `source`: file |
|
2026-11-03 19:28:56 +00:00
|
|
|
| `check_source` | `source` (including unsaved text) | `source_checked`: `{diagnostics}` |
|
2026-11-03 16:01:24 +00:00
|
|
|
| `write_source` | `path`, `expected_source_id` (null to create), `source` | `source`: file |
|
2026-11-03 19:11:39 +00:00
|
|
|
| `rename_source` | `path`, `target`, `expected_source_id`, `update_actors` | `source`: renamed file |
|
|
|
|
|
| `delete_source` | `path`, `expected_source_id` | `acknowledged` |
|
|
|
|
|
| `actor_behavior` | `actor_ref` | `actor_behavior`: `{source_id, source}` |
|
|
|
|
|
| `write_actor_behavior` | `actor_ref`, `expected_source_id`, `source` | `actor_behavior`: `{source_id, source}` |
|
|
|
|
|
| `update_behavior_source` | `actor_ref`, `path`, `expected_source_id`, `temporary_source_id` | `source`: updated original file |
|
2026-11-03 16:01:24 +00:00
|
|
|
| `commit_source` | `path` | `source_committed`: commit |
|
|
|
|
|
| `source_history` | `path` | `source_history`: commit array |
|
|
|
|
|
| `revision_source` | `path`, `revision` | `behavior_source`: `{source}` |
|
|
|
|
|
| `rollback_source` | `path`, `revision` | `source`: restored file |
|
|
|
|
|
| `spawn` | `path`, tagged `state`, positive `mailbox_capacity` | `actor_spawned`: `{actor_ref}` |
|
|
|
|
|
| `system` | `actor_ref`, `message` | `acknowledged` |
|
|
|
|
|
|
|
|
|
|
A file is `{path, source_id, source}` and a commit is
|
|
|
|
|
`{revision, source_id}`. Commits generate readable random revision strings and
|
|
|
|
|
capture working text without compilation. Rollback restores working source
|
|
|
|
|
without appending history. Spawn compiles current working source even when
|
|
|
|
|
uncommitted; compilation failures do not spawn an actor.
|
|
|
|
|
|
2026-11-03 19:11:39 +00:00
|
|
|
Rename preserves history and atomically updates installed/pending actor path
|
|
|
|
|
bindings when `update_actors` is true. In-use paths require that authorization;
|
|
|
|
|
existing destination paths are never overwritten. Delete discards working text
|
|
|
|
|
and history and rejects installed/pending users unless all are failed, with an
|
|
|
|
|
explicit stop-first error. Compiled artifacts are retained.
|
|
|
|
|
|
|
|
|
|
`actor_behavior` reads the existing temporary text, or the actor's loaded
|
|
|
|
|
artifact rather than its current working file. Writing compiles first and
|
|
|
|
|
schedules an actor-local safe-boundary install, retaining state/mailbox and
|
|
|
|
|
leaving shared source/history untouched. A failed actor's implementation may be
|
|
|
|
|
replaced without restarting or acknowledging its failed input. Reload/become
|
|
|
|
|
clear temporary text after successful scheduling; restart retains it; removal
|
|
|
|
|
cleans it up. `update_behavior_source` copies temporary text into shared working
|
|
|
|
|
source without committing. Its original path and both source identities are
|
|
|
|
|
checked before writing. Stale source identities/path bindings return `conflict`.
|
|
|
|
|
|
|
|
|
|
Actor snapshots add `behavior_path` (nullable installed source path),
|
|
|
|
|
`pending_behavior_path` (nullable scheduled source path), and
|
|
|
|
|
`temporary_behavior` (boolean). These are additive v5 metadata fields; older
|
|
|
|
|
v5 snapshots may omit them and clients default to null/false.
|
|
|
|
|
|
2026-11-03 19:28:56 +00:00
|
|
|
### Compilation diagnostics
|
|
|
|
|
|
|
|
|
|
`check_source` compiles a standalone text buffer with the image's native modules.
|
|
|
|
|
It does not execute, save, commit, cache, install, or emit `image_changed`.
|
|
|
|
|
Both invalid and valid source return `source_checked`: compiler errors/warnings
|
|
|
|
|
are validation results; infrastructure failures still use the error envelope.
|
|
|
|
|
|
|
|
|
|
Each diagnostic is `{severity: "error"|"warning", message, range}`. A non-null
|
|
|
|
|
range is `{start: {line, character}, end: {line, character}}`, with zero-based
|
|
|
|
|
lines, UTF-16 code-unit columns, and an exclusive end. Ranges refer to the exact
|
|
|
|
|
submitted text, not the current contents of a source path. `range: null` denotes
|
|
|
|
|
an error without a location in the submitted source. There are no synthetic
|
|
|
|
|
locations inferred from compiler display strings.
|
|
|
|
|
|
|
|
|
|
Compilation failures from spawn/reload/become/temporary behavior writes also
|
|
|
|
|
carry an optional `diagnostics` array in `ProtocolError`, retaining the existing
|
|
|
|
|
`runtime_failure` code and human-readable `message`. This is an additive v5
|
|
|
|
|
field: absent diagnostics deserialize as an empty list and are omitted when
|
|
|
|
|
empty. Source checking is single-file; it does not resolve other image files
|
|
|
|
|
as modules.
|
|
|
|
|
|
2026-11-03 16:01:24 +00:00
|
|
|
System message shape is `{kind: "stop"|"kill"|"restart"|"pause"|"resume"|"reload"}`
|
|
|
|
|
or `{kind: "become", path: "actors/other"}`. This is a trusted host request;
|
|
|
|
|
actor `ctx.send` and `ctx.send_from` accept only ordinary data. Stop runs optional
|
2026-11-03 18:23:43 +00:00
|
|
|
`on_shutdown` after the active handler and removes the actor on success. Kill
|
|
|
|
|
removes the actor immediately without shutdown, including failed actors. Removed
|
|
|
|
|
references return `not_found`; state, mailbox, and retained logs are discarded.
|
|
|
|
|
Failed actors are not automatically removed. A `Stopped` event denotes removal,
|
|
|
|
|
and `image_changed` invalidates actor lists. Restart is independent of stop/kill and
|
|
|
|
|
retains identity, mailbox, the loaded script and state; removed actors cannot be
|
|
|
|
|
restarted. Reload/become defer installation to
|
2026-11-03 16:01:24 +00:00
|
|
|
the next handler boundary. The scheduler still advances only through `tick`.
|
|
|
|
|
|
2026-11-02 12:36:32 +00:00
|
|
|
Responses echo the request ID and carry either a typed reply or a protocol
|
2026-11-03 16:01:24 +00:00
|
|
|
error. Events use a separate versioned envelope. Actor and source snapshots
|
2026-11-02 12:36:32 +00:00
|
|
|
are wire DTOs, not serialized runtime objects; implementation identities are
|
2026-11-02 14:19:25 +00:00
|
|
|
represented by their stable display strings. Public actor identity is a
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
21-character URL-safe NanoID string carried in `actor_ref`. The server maps known service
|
2026-11-02 12:44:33 +00:00
|
|
|
failures to the defined error codes and otherwise uses `runtime_failure`
|
|
|
|
|
rather than claiming a more specific category.
|
|
|
|
|
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
### Portable values
|
|
|
|
|
|
|
|
|
|
Spawn state, send messages, snapshot state/mailbox/reservations, and migration
|
|
|
|
|
event states use the same tagged value shape:
|
|
|
|
|
|
|
|
|
|
| Value | JSON |
|
|
|
|
|
| --- | --- |
|
|
|
|
|
| Null | `{"type":"null"}` |
|
|
|
|
|
| Boolean | `{"type":"bool","data":true}` |
|
|
|
|
|
| Signed 64-bit integer | `{"type":"integer","data":42}` |
|
|
|
|
|
| String | `{"type":"string","data":"hello"}` |
|
|
|
|
|
| List | `{"type":"list","data":[<value>, ...]}` |
|
|
|
|
|
| Record | `{"type":"record","data":{"key":<value>, ...}}` |
|
|
|
|
|
| Actor reference | `{"type":"actor_ref","data":"<21-character-NanoID>"}` |
|
|
|
|
|
|
|
|
|
|
References are distinct from strings. Their shape is validated even when
|
|
|
|
|
nested; existence is checked when a reference is used as a send destination,
|
|
|
|
|
not merely stored as data. The old message envelope and protocol v2 are not
|
|
|
|
|
accepted. The REPL's natural JSON and `$actor`/`$record` conveniences are
|
|
|
|
|
client syntax, not wire encodings.
|
|
|
|
|
|
|
|
|
|
Each state/message permits a maximum nesting depth of 32 (root depth 0),
|
|
|
|
|
4,096 nodes, and 1 MiB of UTF-8 string/key bytes. Requests are also subject to
|
2026-11-03 14:36:21 +00:00
|
|
|
the transport's 1 MiB total message limit, including tags and envelope.
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
Unsupported value tags, malformed references, floats, and out-of-range integers
|
|
|
|
|
fail decoding; well-formed requests exceeding value limits receive
|
|
|
|
|
`invalid_request`. Invalid Rune transition output fails the actor without
|
|
|
|
|
acknowledging the reserved message, changing committed state, or enqueueing
|
|
|
|
|
any of its sends.
|
|
|
|
|
|
2026-11-02 12:44:33 +00:00
|
|
|
`get_events` drains and returns the events currently accumulated by this
|
|
|
|
|
single-worker image. It is not a durable subscription or replayable event log.
|
2026-11-03 14:49:35 +00:00
|
|
|
The transport limits each request to 1 MiB before parsing. Malformed
|
2026-11-03 14:36:21 +00:00
|
|
|
JSON or an oversized message terminates that connection with an error; no protocol
|
2026-11-03 14:49:35 +00:00
|
|
|
response is emitted when a request cannot be decoded. A WebSocket disconnect
|
|
|
|
|
closes only that client connection. The listener
|
2026-11-02 13:50:30 +00:00
|
|
|
allows up to 16 simultaneous clients and serializes each dispatch through the
|
2026-11-03 14:36:21 +00:00
|
|
|
same image. WebSocket response payloads are capped at 1 MiB, with one
|
|
|
|
|
in-flight dispatch per client and a bounded shared dispatch queue. Every local client can use the full development
|
2026-11-02 13:50:30 +00:00
|
|
|
API; loopback binding is not authentication or authorization. Remote access
|
|
|
|
|
must not be enabled until appropriate authentication and authorization exist.
|
2026-11-03 14:49:35 +00:00
|
|
|
The `runa-client` crate validates response protocol versions and request IDs.
|
|
|
|
|
Its `WebSocketClient` connects to
|
2026-11-03 14:36:21 +00:00
|
|
|
loopback endpoints using bounded WebSocket messages and correlation checks,
|
|
|
|
|
validating interleaved notifications while waiting for responses.
|
|
|
|
|
Connection establishment has a 5-second timeout; WebSocket writes and response
|
|
|
|
|
waits have 30-second timeouts. A failed network request invalidates that client connection.
|
2026-11-02 14:57:26 +00:00
|
|
|
No automatic retry is performed: loss of a response does not imply that the
|
|
|
|
|
operation failed to commit.
|
|
|
|
|
|
2026-11-03 14:36:21 +00:00
|
|
|
The interactive REPL uses WebSockets and never owns the image. Disconnecting clients
|
2026-11-03 16:01:24 +00:00
|
|
|
does not stop actors or reset source history; reconnecting clients can
|
|
|
|
|
retrieve them through `list_actors` and `list_sources`. The network executable
|
|
|
|
|
loads `source/actors/counter.rn` on image startup, not on connection.
|
2026-11-03 14:49:35 +00:00
|
|
|
The stdio transport and child-process client have been removed.
|
2026-11-02 12:36:32 +00:00
|
|
|
|
2026-11-03 14:54:07 +00:00
|
|
|
The TypeScript VS Code client issues `list_actors`, `inspect_actor`,
|
2026-11-03 16:01:24 +00:00
|
|
|
source file/version-control operations, `spawn`, `send`, `tick`, and `system`.
|
2026-11-03 16:37:31 +00:00
|
|
|
VS Code automatically displays writable image files under a `source` directory
|
2026-11-03 16:49:04 +00:00
|
|
|
in its dedicated Runa sidebar's source tree, without modifying workspace folders,
|
2026-11-03 16:01:24 +00:00
|
|
|
and caches read-only commit documents by connection, path, and revision.
|
2026-11-03 14:54:07 +00:00
|
|
|
It preserves i64 inputs and bounds the complete outgoing envelope as well as
|
|
|
|
|
incoming messages. It enforces loopback endpoints, bounded UTF-8 text messages,
|
2026-11-03 13:52:28 +00:00
|
|
|
version/request-ID/reply-kind checks, and portable snapshot value validation.
|
|
|
|
|
It decodes JSON integers as `bigint` and prints them losslessly, including
|
|
|
|
|
signed 64-bit state and unsigned 64-bit telemetry. It uses the same 5-second
|
|
|
|
|
connect and 30-second request timeouts, closes on transport/protocol corruption,
|
|
|
|
|
and never retries automatically. A well-formed server error is surfaced without
|
2026-11-03 14:36:21 +00:00
|
|
|
invalidating the stream. Server notifications trigger automatic refreshes of
|
|
|
|
|
the actor tree and open snapshot documents. Manual refresh remains available.
|
|
|
|
|
|
|
|
|
|
## WebSocket transport and notifications
|
|
|
|
|
|
2026-11-03 17:26:21 +00:00
|
|
|
### Actor editing and log subscriptions (v5)
|
|
|
|
|
|
|
|
|
|
- `edit_actor {actor_ref,state,messages}`: `state` is a tagged portable value or
|
|
|
|
|
null to leave it unchanged. `messages` is null to leave the mailbox unchanged,
|
|
|
|
|
or `{reserved,queued}` where reserved is a tagged value or null for no
|
|
|
|
|
reservation, and queued is an ordered array of tagged values. At least one
|
2026-11-03 18:23:43 +00:00
|
|
|
edit is required. Only paused/failed actors with no active execution
|
2026-11-03 17:26:21 +00:00
|
|
|
are editable; values and mailbox capacity are validated atomically.
|
|
|
|
|
- `set_log_level {actor_ref,level}`: level is one of `trace`, `debug`, `info`,
|
|
|
|
|
`warn`, `error`, `fatal`. Both mutations return `acknowledged` and invalidate
|
|
|
|
|
image views. Actor snapshots include `log_level`.
|
|
|
|
|
- `logs {actors,follow,after}`: actors is an array of references (empty means
|
|
|
|
|
all); after is an exclusive u64 sequence cursor. Reply kind `logs` carries
|
|
|
|
|
`{entries,next_sequence,has_more}`, with at most 128 entries per page.
|
|
|
|
|
Each entry is `{sequence,actor_ref,level,message}`. Missing actors are errors.
|
|
|
|
|
History queries are read-only and do not invalidate views.
|
|
|
|
|
- With follow true, the connection registers the filter before history is read.
|
|
|
|
|
Subsequent notification envelopes carry
|
|
|
|
|
`{event:"log",data:{sequence,actor_ref,level,message}}`. Reissuing `logs`
|
|
|
|
|
replaces the filter; follow false unsubscribes. Matching entries newer than
|
|
|
|
|
the reply's cursor are emitted after its reply, allowing history/follow
|
|
|
|
|
deduplication by sequence. Other connections receive no log events.
|
|
|
|
|
Transport and client buffers are bounded at 1,024 entries; lag is an explicit
|
|
|
|
|
connection error, not a guaranteed-delivery stream. Disconnect removes the
|
|
|
|
|
subscription. Image invalidations remain coalescible and independent of logs.
|
|
|
|
|
|
2026-11-03 16:21:41 +00:00
|
|
|
On `quit`, `exit`, Ctrl+C, or end-of-input, the CLI completes the WebSocket close
|
2026-11-03 16:05:29 +00:00
|
|
|
handshake with a 5-second deadline before releasing the connection. A failed
|
|
|
|
|
handshake is reported rather than treating an abrupt reset as a normal close.
|
|
|
|
|
|
2026-11-03 14:36:21 +00:00
|
|
|
Connect to `ws://127.0.0.1:3737/` (or a configured numeric loopback endpoint)
|
|
|
|
|
and offer the `runa-debug` WebSocket subprotocol. The server requires and echoes
|
|
|
|
|
that subprotocol. Plain TCP JSON Lines is no longer accepted by the network
|
2026-11-03 17:26:21 +00:00
|
|
|
listener. The request/response contract is version 5.
|
2026-11-03 14:36:21 +00:00
|
|
|
Each WebSocket text message contains exactly one JSON request, response, or
|
|
|
|
|
notification, without newline framing. Binary messages and malformed requests
|
|
|
|
|
terminate the connection. Fragmented text is supported with a 1 MiB aggregate
|
|
|
|
|
message limit; individual frames are also limited to 1 MiB. Compression is not
|
|
|
|
|
enabled. Upgrade handshakes have a 5-second timeout and writes have a
|
|
|
|
|
30-second timeout so stalled peers do not hold client slots forever.
|
|
|
|
|
|
|
|
|
|
The endpoint accepts only the root path and rejects requests carrying an
|
|
|
|
|
`Origin` header: browser-origin access is not enabled for this unauthenticated
|
|
|
|
|
local API. This is not authentication; local non-browser clients retain full
|
|
|
|
|
development privileges.
|
|
|
|
|
|
|
|
|
|
Every upgraded connection automatically receives non-destructive invalidations:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
2026-11-03 17:26:21 +00:00
|
|
|
"version": 5,
|
2026-11-03 14:36:21 +00:00
|
|
|
"event": {
|
|
|
|
|
"event": "image_changed",
|
|
|
|
|
"data": { "revision": 42 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Successful mutating requests (spawn, send, tick, lifecycle controls,
|
2026-11-03 16:01:24 +00:00
|
|
|
source writes/commits/rollback, and system messages) increment a server-session revision
|
2026-11-03 14:36:21 +00:00
|
|
|
and notify all connected clients, including the initiator. Read-only requests,
|
|
|
|
|
failed mutations, and `get_events` do not generate invalidations. A tick
|
|
|
|
|
invalidates snapshots even when it only advances execution telemetry or causes
|
|
|
|
|
an actor failure. A successful send invalidates mailbox snapshots before any
|
|
|
|
|
handler runs. Notifications may appear between requests and their replies;
|
|
|
|
|
clients must distinguish them from correlated responses.
|
|
|
|
|
|
|
|
|
|
Revisions increase within one server session, not across server restarts.
|
|
|
|
|
Slow subscribers retain only the latest unsent revision; gaps are expected.
|
|
|
|
|
These notifications are hints to re-fetch authoritative data, not individual
|
|
|
|
|
runtime events, a durable log, an atomic snapshot revision, or replay.
|
|
|
|
|
On connection/reconnection, fetch a full listing first. The VS Code client
|
|
|
|
|
coalesces bursts and schedules another refresh if an invalidation arrives
|
2026-11-03 16:01:24 +00:00
|
|
|
during an in-flight read. Refresh never advances the scheduler or calls `get_events`;
|
2026-11-03 14:36:21 +00:00
|
|
|
the REPL's explicit `events` command still drains the separate runtime queue.
|
2026-11-03 13:52:28 +00:00
|
|
|
|
2026-11-02 14:19:25 +00:00
|
|
|
The current validation checks the protocol version, request ID, actor-reference
|
2026-11-03 16:01:24 +00:00
|
|
|
shape, structured-value limits, revision ID shape, non-empty paths, mailbox
|
|
|
|
|
capacity, and instruction budget. Canonical source paths, actor existence,
|
|
|
|
|
expected source identities, mailbox capacity at send time, and all runtime
|
2026-11-02 12:36:32 +00:00
|
|
|
invariants remain authoritative at the application-service boundary.
|