Appendix B — Reserved ranges
The reserved-discriminant ranges for future protocol extensions: which message-ID slots are earmarked for which categories (lifecycle, hot path, control...
Full source summary
The reserved-discriminant ranges for future protocol extensions: which message-ID slots are earmarked for which categories (lifecycle, hot path, control plane, events, L1 lifecycle), the command-tag allocations within the lifecycle range, and the enum-allocation discipline for PhysicalKey and ErrorCode. Implementers extending the protocol pick from these ranges via PR.
1. Reserved message-ID ranges
For implementers extending the protocol:
WORKLOAD_RESPONSE = 0x04andWORKLOAD_CHALLENGE = 0x84are allocated to the endpoint-neutralphux-workload/v1profile (workload-auth.md);0x05..=0x0Fand0x85..=0x8Fremain open for connection lifecycle.0x14is allocated,0x15is retired,HISTORY_REQUEST = 0x16andINPUT_TERMINAL_REPLY = 0x17are allocated, and0x18..=0x1Fremain open.0x91is permanently retired.BOOTSTRAP_BEGIN..BOOTSTRAP_TOMBSTONE = 0x93..=0x97,HISTORY_TOMBSTONE = 0x98, andHISTORY_REJECTED = 0x99are allocated;FRAME_COMPRESSED = 0x9A(proto.md §6.4) is allocated from the hot-path reserve, which it belongs in: it wraps the hot path’s largest frames.0x9B..=0x9Fremain open for hot-path messages.- Message IDs
0x24..=0x2Fand0xA3..=0xAF: reserved for further L1 Terminal lifecycle / per-pane control frames (0x22..=0x23C→S and0xA1..=0xA2S→C are taken; ADR-0056 allocatedMOVE_RESOURCE = 0x2AandRESOURCE_MOVED = 0xA8). TheSPAWN_PROCESS/KILL_PROCESS/PROCESS_SPAWNED/PROCESS_CLOSED/PROCESS_OUTPUTfamily once pencilled into0x24..=0x25/0xA3..=0xA5, and theFORWARD_PORT/CLOSE_PORT_FORWARD/PORT_FORWARD_STATUSfamily into0x28..=0x29/0xA6, are subsumed byResourceKind(L1.md §1.1): a non-PTY process or a forwarded port is a kind served through the existing spawn / output / close frames, not a parallel frame family. Those discriminants stay unallocated. - Message IDs
0x31..=0x3Fand0xC2..=0xCF: reserved for control plane. - Message IDs
0x41..=0x4Fand0xB3..=0xBF: reserved for events (SUBSCRIBE_EVENTS = 0x41C→S andEVENT = 0xB3S→C are taken;0x42..=0x4Fand0xB4..=0xBFremain open). - Message IDs
0x50..=0x5Fand0xD0..=0xDF: L3 (L3.md §1).0x50..=0x55C→S and0xD0..=0xD3S→C are allocated (the metadata verbs, and theLIST_DIRECTORY/DIRECTORY_LISTINGhost query of L3.md §4);0x56..=0x5Fand0xD4..=0xDFremain open. There is no L2 tier, so no L2 range is carved out of this block.
2. Command-tag allocations
Commands ride the generic COMMAND envelope (L1.md §1) and carry
their own one-byte tag inside it. Allocated tags:
| Tag | Command | Owner | Status |
|---|---|---|---|
0x07 | GET_SCREEN | L1.md | shipped |
0x08 | ROUTE_INPUT | L1.md | shipped |
0x09 | KILL_RESOURCES | L1.md | shipped |
0x0c | GET_TERMINAL_STATE | L1.md | shipped |
0x0d | SUBSCRIBE_RESOURCE_EVENTS | L1.md | shipped |
0x0e | UPGRADE | L1.md | shipped |
0x0f | ACQUIRE_INPUT | L1.md | shipped |
0x10 | RELEASE_INPUT | L1.md | shipped |
0x11 | SIGNAL_TERMINAL | L1.md | shipped |
0x12 | REPORT_ASKED | L1.md | shipped |
0x13 | DETACH_CLIENTS | L1.md | shipped |
0x14 | APPLY_INPUT | L1.md | shipped |
0x15 | PUT_FILE | L1.md | shipped |
0x16 | SHUTDOWN | L1.md | shipped |
0x17 | REPORT_AGENT_STATE | L1.md | shipped |
0x18 | GET_PERF | L1.md | shipped |
0x19 | TRANSCRIBE | L1.md | shipped |
0x1a | APPEND_RESOURCE_OUTPUT | L1.md §5.5 | shipped |
0x1b | KILL_RESOURCE_IF | L1.md §5.2.1 | shipped |
KILL_RESOURCES at tag 0x09 reuses the slot freed by the removed
CREATE_SESSION command. Per
ADR-0030
(option B), the leaked session/collection lifecycle verbs are withdrawn and
their tags are freed:
0x09— formerlyCREATE_SESSION; reallocated toKILL_RESOURCES.0x0a— formerlyRENAME_SESSION; freed, reserved, not reallocated. Rename is now an L3 metadataSETonphux.session.name/v1(L3.md §3).0x0b— formerlyKILL_COLLECTION; freed, reserved, not reallocated. Group teardown isKILL_RESOURCES.
A freed tag SHALL NOT be reallocated to an unrelated command without a
PROTOCOL_VERSION bump, so that an old client speaking a withdrawn verb
fails loudly rather than invoking new behavior.
3. Reserved enum ranges
PhysicalKey enum values and ErrorCode enum values are allocated
sequentially. Implementers proposing new values open a PR against
this document.
ErrorCode = 5 is permanently reserved for the withdrawn OUT_OF_TIER
proposal and is never reused. CODEC_UNAVAILABLE = 6 is allocated by ADR-0070.
WRONG_RESOURCE_KIND = 208, NOT_PRODUCER = 209, RECORD_INVALID = 210,
and OVERFLOW = 211 are allocated by the resource model
(proto.md §9; L1.md §1.1, §5.5).
PRECONDITION_FAILED = 212 is allocated by ADR-0109 (L1.md §5.2.1).
KILL_RESOURCE_IF condition bits (L1.md §5.2.1) allocate upward
from 0x01: 0x01 UNATTACHED_SINCE_SPAWN is taken. A decoder keeps a bit it
does not know, and a server refuses a kill that carries one with
PRECONDITION_FAILED, so a new condition is additive and never ignored.
SpawnError (L1.md §3.1) allocates sequentially from 0x00:
0x00..=0x03 are the group / spawn / satellite codes and 0x04 UNSUPPORTED_KIND, 0x05 PARENT_NOT_FOUND, 0x06 PARENT_KIND_MISMATCH are
the resource-binding codes (L1.md §1.2). ResourceKind allocates
TERMINAL = 0 and AGENT_SESSION = 1; a tag once allocated is never reused,
and a decoder maps an unallocated tag to Unknown { tag } (L1.md §1.1).
BootstrapCodec (L1.md §4.3) allocates 0 (synthesized VT v1),
1 (native, followed by the engine version byte), and 3
(AgentEventsJsonlV1); 2 is skipped so the codec tag never shares a value
with the native v2 version byte that follows tag 1 in a dump.
CloseReason (L1.md §1.2) allocates sequentially from 0 —
0..=3 are taken — and follows the DetachReason decode rule below: an
absent field and an unallocated value both read as an unstated reason.
DetachReason (proto.md §7.2) allocates sequentially from 0
— 0..=7 are taken, with workload-auth values 5..=7 still spec-only — and
255 is permanently reserved for INTERNAL_ERROR.
It differs from the enums above in how an unallocated value decodes: a
consumer MUST read one it does not recognise as an unstated reason rather
than as a decode error, because DETACHED is the termination signal and
failing it would both hide the ending and make each new value a fleet-wide
break. New values are therefore additive and need no version bump.
(Earlier drafts of the SPEC reserved a DiffOp tag range here; per
ADR-0013, Terminal
content is now a VT byte stream and DiffOp no
longer exists as a wire concept.)
L2 — Reserved, no collection tier
There is no L2 collection tier. The L2 discriminant range is reserved on the wire but unused, and SHALL NOT be allocated for a collection lifecycle service.
Wire-protocol changelog
Wire-format change log for the phux protocol; the top entry's version must match PROTOCOL_VERSION in phux-protocol. CI gate spec-version-sync enforces this.