nervネルフ

Wire reference

Enough to write a peer: the framing, the shapes, the encodings, the version rule and the failure modes. Three transports, two shapes, two encodings.

Three transports

transportframingfor
argvone JSON object on stdout, then exita program that runs once per call. Nothing to keep alive, and a fresh process knows everything the last one did.
pipeone object per line, newline-delimiteda program held for the session, talking to the one that started it.
socketfour bytes of big-endian length, then that many bytesanything that may knock. Self-delimiting, so a peer that dies mid-frame is caught at the length.
An encoding is not a transport. JSON is on all three; naming it as one is how a diagram of this family came to have “argv + json” on an edge.

Two shapes

a call — somebody is waiting
{"call": "<verb>", "args": [ … ]}
{"ok": true, "family": 1, "n": <count>, "result": [ … ]}

an event — nobody is
{"event": "<name>", … }

result is always a list, so one call answers with what the function did. Two ends disagreeing about that fail silently: a client that unpacks reads a bare-value server as having returned nothing at all, so the bug presents as an empty memory rather than as an error.

The version rule

family is the revision of the wire a reply is written in. A newer peer is refused by name; an older one is not. A reply with no family at all is from before the check and is accepted.

The constant is duplicated in each sibling rather than shared. A crate held in common would be a dependency between repositories, and this family has none.

Two encodings

JSONthe default. What every peer understands, and what somebody with socat can read.
CBORthe same shape as bytes, for a caller that is not going to read it.

On a one-shot door, ask with --cbor. On a socket, just send it: the server answers in whatever it was asked in.

how the encoding is read off a body — no handshake, no setting
first non-space byte  '{' or '['   → json
                      0x80..0xBF   → cbor   (a cbor map or array)
                      anything else → json  (so the error message is the useful one)

Refusals

A refused verb is ok: false with exit status zero, and a refusal is a reply: only the transport failing closes anything. That is what lets a caller tell “it said no” from “it is not there”.

faultthe caller loses
refuseda feature. Carry on.
unavailablethe sibling. Carry on without it.
failedthe write. Do not assume it was recorded.
malformednothing yet — but this is a bug to report, not a condition to handle.

Limits

frame16 MiB on magi's own wire; 1 MiB between sessions. A message between instances is a sentence, not a payload — an unbounded read is a way to make a session allocate until it dies.
socket path108 bytes, which is the kernel's limit and not anybody's choice. Long temporary directories are how this is usually met.
identitySO_PEERCRED. A caller the kernel will not identify gets nothing.