Summary
The AppLink data-plane frame notation in aidocs/applink/content_transport.md is ambiguous about whether the 1-byte type tag is part of the MessagePack array or a raw prefix byte. The prose and the example notation pull in opposite directions; only the server source disambiguates.
Surfaced while implementing the mobile decoder (aitasks_mobile t14_1, the applink wire codec) — caught during plan verification, but a future implementer reading only the doc could easily get it wrong.
The ambiguity
- §Wire encoding (line 32): "every binary frame starts with a 1-byte type ID … The remainder is MessagePack-encoded." → reads as raw prefix byte + msgpack array of the rest.
- §Frame types (lines ~95, ~109, …): frames are written as a single array literal, e.g.
[0x01, pane_id, frame_id, cols, rows, cursor, [row, ...], osc8?]
→ reads as one msgpack array whose first element is the tag.
These two readings produce different bytes and an incompatible decoder.
Ground truth (from the server encoder)
.aitask-scripts/applink/content.py settles it — every encode_* does:
return bytes([FRAME_KEYFRAME]) + _packb(arr) # e.g. content.py:384
i.e. a raw 1-byte tag prefix followed by a MessagePack array of the body fields only (the tag is NOT an array element). Also confirmed there: osc8 is appended only when non-empty, so the body array is variable length (e.g. keyframe is 6 or 7 elements) rather than carrying a nil placeholder.
Suggested doc fix
In §Frame types, either:
- annotate the notation as logical-not-literal and state explicitly that
0xNN is a raw leading byte, the bracketed remainder is the msgpack array of body fields, and the tag is not an array element; and/or
- show the body array without the tag, e.g.
tag=0x01, then msgpack [pane_id, frame_id, cols, rows, cursor, [rows], osc8?].
Also worth making explicit (both already true in the encoder, easy to miss in the doc):
- the trailing
osc8? is omitted entirely when empty (variable-length array), and
- packed truecolor is a negative int64 (
-((0xFF<<24)|(r<<16)|(g<<8)|b)) that does not fit a signed 32-bit int — decoders must use a 64-bit read.
No behavior change requested — the wire format is correct and frozen; this is purely a documentation-clarity fix so consumers (mobile decoder, future clients) read it the same way the server writes it.
Filed from aitasks_mobile during t14_1; related to the t822 applink work that authored these docs.
Summary
The AppLink data-plane frame notation in
aidocs/applink/content_transport.mdis ambiguous about whether the 1-byte type tag is part of the MessagePack array or a raw prefix byte. The prose and the example notation pull in opposite directions; only the server source disambiguates.Surfaced while implementing the mobile decoder (aitasks_mobile t14_1, the applink wire codec) — caught during plan verification, but a future implementer reading only the doc could easily get it wrong.
The ambiguity
These two readings produce different bytes and an incompatible decoder.
Ground truth (from the server encoder)
.aitask-scripts/applink/content.pysettles it — everyencode_*does:i.e. a raw 1-byte tag prefix followed by a MessagePack array of the body fields only (the tag is NOT an array element). Also confirmed there:
osc8is appended only when non-empty, so the body array is variable length (e.g. keyframe is 6 or 7 elements) rather than carrying a nil placeholder.Suggested doc fix
In §Frame types, either:
0xNNis a raw leading byte, the bracketed remainder is the msgpack array of body fields, and the tag is not an array element; and/ortag=0x01, then msgpack [pane_id, frame_id, cols, rows, cursor, [rows], osc8?].Also worth making explicit (both already true in the encoder, easy to miss in the doc):
osc8?is omitted entirely when empty (variable-length array), and-((0xFF<<24)|(r<<16)|(g<<8)|b)) that does not fit a signed 32-bit int — decoders must use a 64-bit read.No behavior change requested — the wire format is correct and frozen; this is purely a documentation-clarity fix so consumers (mobile decoder, future clients) read it the same way the server writes it.
Filed from aitasks_mobile during t14_1; related to the t822 applink work that authored these docs.