7. Frame Types
All frames are JSON objects with a type field (string). Implementations MUST silently ignore frames with unrecognised type values to allow forward compatibility.
| Type | Layer | Gated | Fields |
|---|---|---|---|
| handshake | 2 | No | nodeId (string), name (string), version (string), extensions (string[]) |
| state-sync | 2/3 | No | h1 (float[]), h2 (float[]), confidence (float) |
| cmb | 3/4 | SVAF | timestamp (int), cmb (object: { key, createdBy, createdAt, fields, lineage }) |
| message | 2 | No | from, fromName, content, timestamp |
| xmesh-insight | 6 | No | from, fromName, trajectory (float[6]), patterns (float[8]), anomaly (float), outcome (string), coherence (float), timestamp |
| peer-info | 2 | No | peers: [{ nodeId, name, wakeChannel?, lastSeen }] |
| wake-channel | 2 | No | platform (string), token (string), environment (string) |
| error | 2 | No | code (int), message (string), detail? (string) |
| ping | 2 | No | (no additional fields) |
| pong | 2 | No | (no additional fields) |
All cognitive content — observations, decisions, feedback, directives — MUST be sent as cmb frames. Only cmb frames enter SVAF evaluation, produce anchor weights, and modulate CfC state.
7.2 Error Frame
When a node encounters a protocol-level error, it SHOULD send an error frame before closing the connection (if applicable). Error frames are informational — the receiving node MUST NOT treat them as commands.
| Code | Name | Action | Description |
|---|---|---|---|
| 1001 | VERSION_MISMATCH | Close | Peer version is incompatible |
| 1002 | DIMENSION_MISMATCH | Reject frame | h1/h2 vector dimension mismatch |
| 1003 | FRAME_TOO_LARGE | Close | Frame exceeds MAX_FRAME_SIZE |
| 1004 | HANDSHAKE_TIMEOUT | Close | No handshake within deadline |
| 1005 | DUPLICATE_NODE | Close | nodeId already connected |
| 2001 | SVAF_REJECTED | None | Memory-share rejected by SVAF (informational) |
Codes 1xxx are connection-level (close connection). Codes 2xxx are evaluation-level (informational). Error frames MUST NOT contain sensitive information.
7.3 Frame Type Registry
Frame types are identified by their type string value.Core types (this specification) MUST NOT be redefined by extensions.Extension types MUST use <extension>-<name> format.Vendor types MUST use x-<vendor>-<name> format and MUST be silently ignored by non-supporting nodes.
Q&A
Why MUST nodes silently ignore unknown frame types?
Without this rule, you can never add new features to the protocol. If a node crashes or rejects unknown frame types, then deploying a new extension (like mesh groups) requires upgrading every node on the mesh simultaneously — impossible in a peer-to-peer system. Silent ignore means old nodes and new nodes coexist: a node running a new extension sends its frames, and nodes that don’t support the extension simply ignore them. No crash, no error, the mesh keeps working. When a node adds support later, it handles the frame. No coordinated upgrade needed. This is the same principle used by HTTP (unknown headers ignored), TCP (unknown options skipped), and HTML (unknown tags ignored). Every successful protocol is evolvable because of this rule.
What happens if a relay receives an unknown frame type?
The relay forwards it. The relay is a dumb transport pipe — it wraps the payload in a { from, fromName, payload } envelope and sends it to the target or broadcasts it. It never inspects the payload type. This means extension frames (group, vendor, future types) flow through the relay without any relay changes. The intelligence is at the endpoints, not the transport.
Can an extension frame break an existing node?
No, if the node follows Section 7. The frame handler switches on msg.type. Unknown types fall through with no match and no action. The node’s cognitive state, memory, and coupling are unaffected. This is a hard requirement — implementations that reject or error on unknown types are non-conformant.