# External Interfaces This document is the index and human-authored contract for Cohesix external interfaces: transport selection, target console framing, namespace paths, control files, and non-generated record schemas. It links to generated snippets for compiler-owned values instead of copying them. Manifest schema 1.29 permits at most 512 retained Queen intent outcomes and selects 512 in both QEMU and Pi Release A profiles. Compatibility policy defaults remain 64; the Python projection includes the selected `queen_dedupe_entries`. Exhaustion refuses new identities without eviction or repeated effects. The schema retains the explicitly selected `peft.release` action and WorkerLora receipt code `0x0305`. Its strict arguments are `request_sha256` and optional boolean `recovery_only` (default false); fresh recovery grants restore only the original frozen baseline. Native/controller records and public usage are defined in [Private LoRA release](PRIVATE_LORA_RELEASE.md). The schema retains compiler-selected macOS launchd service maps, exact Xcode/release/endpoint target maps and version-1 actions. Their target, process-identity, refusal and observation contracts are in [MACOS_PROVIDERS.md](MACOS_PROVIDERS.md). No macOS device access or native execution moves into the VM. The schema adds host-only `gateway` protocol controls with `cohesix-agent-protocol-controls/v1` shape. Missing switches resolve false; unknown fields or versions refuse. Master and per-protocol switches are conjoined and do not alter target console, Secure9P or Worker ABIs. Protocol internals belong in [SECURE9P.md](SECURE9P.md), role and ticket policy in [ROLES_AND_SCHEDULING.md](ROLES_AND_SCHEDULING.md), system boundaries in [ARCHITECTURE.md](ARCHITECTURE.md), and operator command usage in [USERLAND_AND_CLI.md](USERLAND_AND_CLI.md). See the [Glossary](GLOSSARY.md) for Cohesix-specific protocol, role, and authority terms. ## Desktop projection [SwarmUI](SWARMUI.md) uses Rust-owned Queen console or Hive Gateway sessions. Editable connections and guided controls project existing console/namespace contracts; installed host forms share the `coh-cli` parser with `coh`. A single-use review binds the exact request and current connection context. Bounded subprocess execution uses argument arrays, never a shell. Timeout means an interrupted controller with unknown remote outcome, not cancellation. `coh evidence story` verifies canonical signed graphs and CAS against separate trust, then returns bounded redacted observations. It does not introduce a new pack, receipt or replay schema. Native file selection and optional acceptance metadata are desktop-local. Offline replay disconnects live authority; reference verification and presentation cannot create readiness or promote a failed run. ## Stability and authority The selected profile manifest, resolved manifest, generated tables, and generated snippets are authoritative for enabled providers, exact capacities, paths, and defaults. Source and fixtures are authoritative for handwritten parsers and response grammar. The following are breaking changes: - a Secure9P request, response, or error-code change; - a target console verb or `OK`/`ERR`/`END` grammar change; - a namespace path, mode, or record-format change; - a role/ticket authority change; or - a generated interface, bound, or default change. Breaking changes require the process in `AGENTS.md`: manifest schema changes where applicable, regenerated artifacts, updated fixtures, tests, and canonical documentation in the same authorized change. ### MCS operator-inspection records The Pi-only verbose `wifi: pair_handoff` v1 diagnostic is additive; its passive ring layout and field semantics are defined in [DRIVERS.md](DRIVERS.md). It changes no runtime-init ABI version, generated authority, console command, authentication/framing, namespace, or REST/SDK/report schema. Absence is unavailable evidence, never a readiness or performance result. Pi `smp mcs` adds five passive `mcs_idle*` rows after its existing 22-row batch. Pi `netstats` emits the seven latest-connection `mcs_session*` v1 rows and, for Wi-Fi, two passive `wifi_ack_admission` / `wifi_ack_last` v1 rows, as specified in [USERLAND_AND_CLI.md](USERLAND_AND_CLI.md). Keeping the session rows outside `smp mcs` preserves its complete physical body and end marker within the existing 69-line body / 72-line total backlog. ACK receipts prove only root dequeue, copied-page publication and child ingress acceptance, never TCP retirement. These records add no scheduling authority. QEMU output, authentication, framing and host-tool/REST/SDK APIs are unchanged. The console provides bare `caps`, bare `smp`, and the first `bi` record plus strict `caps mcs`, `smp mcs`, `[bi:v2]`, `[caps:mcs/v1]`, and `[smp:mcs/v1]`. Every record labels kernel, generated, or runtime authority. Early-console and registry contention are typed unavailable states; generated rows never fabricate live registration, binding, activation, or containment. The shared parser additionally recognizes strict `smp poll-time`. Pi event-pump profiles return eight cached root-poll elapsed-time rows and `OK SMP mode=poll-time`; other profiles return typed unsupported, and bootstrap returns `ERR SMP reason=policy detail=event-pump-required`. Pi physical-console Wi-Fi diagnostics add six explicit `wifi rx-trace <0..5>` pages of retained TCP headers and existing receive timestamps. These bounded diagnostic schemas, numeric bases and missing-evidence semantics are specified in [USERLAND_AND_CLI.md](USERLAND_AND_CLI.md). No payload is retained and the reader has no device authority. Host `cohsh` forwards the shared SMP command; Wi-Fi pages remain physical-console only. This console extension changes no manifest, shared ABI, namespace, authentication, framing, REST/SDK or benchmark schema. `[caps:mcs/v1]` emits one or more independently source-labelled records per runtime or generated scope. Each record is at most 77 bytes so the Pi linked HDMI fallback preserves every field; consumers join records by command, `source`, and `scope` rather than assuming one positional row per scope. ## Pi 4 pre-kernel policy interface The Pi 4 U-Boot menu is a bounded pre-kernel configuration surface, not a new Cohesix protocol or authority path. `scripts/pi4-image-build.sh` generates the executable `boot.cmd`/`boot.scr.uimg` contract. Generic persistent U-Boot environment storage is disabled; only the FAT-side `cohesix.env` file is eligible for Cohesix boot-policy import. The import contract is: - maximum file size: 384 bytes; - text line endings: LF or CRLF; - allowlisted keys only: `coh_net_mode`, `coh_net_interface`, `coh_static_ip`, `coh_static_prefix_len`, `coh_static_gateway`, `coh_wifi_ssid`, `coh_wifi_psk`, and `coh_show_logo`; - coherent network tuples: `dhcp|static` plus `wired|wifi`, with static address and prefix required for static mode and SSID required for Wi-Fi; - logo preference: absent or exactly `0|1`; any other value rejects the saved policy; - absent, empty, oversized, malformed, or incoherent input: clear network overrides and use selected-manifest defaults. File presence and saved-network state are deliberately distinct. A logo-only or cleared `cohesix.env` remains a valid file but produces **Default network settings active** with the **Boot with default settings** action. A coherent imported network tuple produces **Saved network settings loaded** with **Boot with saved settings**. Back/discard transitions reload the file before returning to **Cohesix boot menu**, so working values cannot masquerade as persisted policy. The root menu exposes **Change network settings**, a stateful **Boot logo: On (select to turn off)** / **Boot logo: Off (select to turn on)** action, **Reset saved settings to defaults**, **Save settings and restart**, and **Advanced: Open U-Boot shell**. Reset has a separate **Reset saved settings?** confirmation page; `1` confirms, `0` cancels, and no persistent state changes before confirmation. Cancel is the Enter-key default. A confirmed reset writes a verified default policy rather than requiring deletion of `cohesix.env`. The menu uses an iterative page dispatcher for root, IPv4 configuration, network connection, Wi-Fi, manual IPv4, review, and reset-confirmation pages. Submenus consistently use `0` for **Back** or **Cancel** and `9` for **Advanced: Open U-Boot shell**. Operator-facing choices are **Automatic (DHCP)** / **Manual (static IPv4)** and **Ethernet (wired)** / **Wi-Fi (wireless)**. The review page distinguishes **Boot once without saving** from **Save settings and restart**; discard reloads persisted policy before returning to the root menu. Existing Wi-Fi settings can be kept or changed, and a reset followed by **Change network settings** creates a fresh saved policy for a different Wi-Fi network without a reflash. Credential entry is enabled only on the USB-keyboard/HDMI console. The display explicitly warns that the network name and password are visible on that display while serial output is disabled; temporary replacement variables are not part of the export allowlist. SSIDs are redacted from summaries so untrusted imported text cannot forge terminal or serial evidence. Save and reset operations export into a bounded buffer, write `cohesix.env`, verify its size, privately compare a readback copy, and set success only after exact agreement. Restart is never invoked after a failed export, write, size check, load, or comparison. At boot, selected non-empty overrides are projected into the staged DTB as `/chosen/cohesix,net-mode`, `cohesix,net-interface`, `cohesix,static-ipv4`, `cohesix,static-prefix-len`, `cohesix,static-gateway`, `cohesix,wifi-ssid`, and `cohesix,wifi-psk`. Root-task validates these properties and either selects the DTB-backed policy or reports a bounded rejection and retains the generated manifest defaults. The source manifest is never rewritten by U-Boot. ## Transport matrix | Surface | Wire contract | Authentication and authority | Runtime boundary | | --- | --- | --- | --- | | Host/in-process NineDoor | Bounded Secure9P 9P2000.L subset | `Tattach` selects role/identity and carries the ticket | Host `std` server and tests only; not an in-target listener | | Target serial console | Unframed console lines | Physical serial access, then application `ATTACH` for role/ticket authority | Root-task console | | Target TCP console | Four-byte little-endian length plus one console line | Transport `AUTH `, then application `ATTACH [ticket]` | `console-network-runtime` smoltcp listener; the only permitted in-target TCP listener | | REST, UI, GPU, sidecar, and federation tools | Host-specific projection | Must preserve the underlying ticket and namespace authority | Host only; never a new VM authority path | Secure9P messages are not transported through the target TCP console. A console command such as `CAT` or `ECHO` invokes the target namespace adapter; it does not synthesize a 9P frame on the wire. ### Internal target namespace-service ABI `namespace-service/v1` is an internal, pointer-free ABI between root and the restricted `nine-door-runtime` child. It is not an operator transport, host RPC, or second policy plane. The 32-byte request header carries the ABI and header versions, operation, sequence, supervisor generation, bounded path and payload lengths, and zero-valued reserved fields. Path and payload bytes occupy separate shared frames bounded to 256 and 4096 bytes. The child prepares only the declared `attach`, `tail`, `spawn`, `kill`, `echo`, `cat`, `list`, and `log` operations; absolute paths have at most eight components and reject `.` and `..`. The response repeats the operation, sequence, and generation with a typed status and bounded prepared bytes. Root independently validates that identity before ticket, Queen-policy, or mutation authority is exercised. Unknown labels, operations, error codes, extra capabilities, short replies, stale generations, mismatched bytes, and partial records fail closed. Each direction uses two distinct 4 KiB pages with complementary read/write mappings. Shared records contain no pointers. Root's endpoint capability is Write + GrantReply without Read or Grant; the child's receive capability is Read-only. The selected child image is digest-bound and mapped W^X. The service receives one compiler-budgeted bootstrap scheduling context while suspended. After registry seal, root resumes it, validates one empty parser probe, observes its atomic `ReplyRecv` transition, and removes that scheduling context. Steady-state work runs only on the bounded root-donated Call/Reply chain. Fault or activation failure closes any exact outstanding caller, scrubs and unmaps the shared frames, removes Reply authority, and revokes the retained child anchor before reuse. ### Internal target console-network ABI `console-network-service/v6` is the private ABI of the active-SC `console-network-runtime` child. The child owns target Ethernet/IP/TCP state, frame parsing, transport authentication, and bounded response emission. It is not the passive NineDoor service and is not a second external protocol. The console-network ABI uses four fixed 4096-byte pointer-free, sequence-last pages: - root-produced packet ingress and control, mapped read-only in the child; and - child-produced packet egress and events, mapped read-write in the child. Compact packet and control/event headers plus the validated active payload are authoritative. Inactive tails are not protocol fields. Producers clear commit, write the validated fields and bytes, publish the final sequence with release ordering, and signal only afterward. Consumers accept a record only when the surrounding commit observations agree and all reserved fields are zero. Control kind `SendBatch = 3` carries encoding version 1, one through eight records, exact used length, zero reserved fields, and `1..=256` bytes of valid UTF-8 per record with no CR or LF. Root encodes the complete batch before publication; the child validates the complete copied payload before emitting the unchanged sequence of individually length-prefixed records. Internally, the child may admit consecutive records as one at-most-1,400-byte socket wire train, below the qualified Pi TCP MSS and always ending at a complete record boundary. A maximum eight-record, 256-byte-per-record batch therefore uses exactly two trains of five and three records; smaller records may fit in one. Preparation does not advance the private response cursor. Only a complete socket enqueue commits the next cursor, and that commit must still match the authenticated connection, batch identity, and prepared cursor. Backpressure or stale identity consumes nothing. A partial enqueue is a terminal invariant failure and never advances or retries the cursor. The train is only an internal enqueue unit: it adds no aggregate external frame, changes no four-byte length prefix, and does not change ABI v6 or the public `AUTH`/`ATTACH` and `OK`/`ERR`/`END` grammar. Legacy `SendLine = 1` and Disconnect remain valid controls. Event kind `CommandBatch = 27` carries encoding version 1 and one through eight consecutive authenticated commands for one exact connection. Each record retains its original `now_ms`, exact length, and `1..=2304` UTF-8 bytes. The child batches only records already admitted in FIFO order, stops before the fixed 2368-byte payload bound, and never batches across a lifecycle or connection-identity event. Root validates the complete private copy and reserves capacity for every command before admitting any of them. One batch consumes one publication credit; it does not add capability, scheduling, or command authority. Physical Pi command publications use this existing batch encoding even for one command: the exchange header samples publication start, while each nested record retains command creation time for policy. QEMU keeps its qualified timestamp and single-command representation. On the copied Pi WiFi path, one credited command publication may additionally carry one already-prepared egress packet. The child commits the packet first, then commits the Command/CommandBatch event as the bundle barrier, and signals only the event notification followed by root fan-in. Root may inspect that companion packet level only after accepting the command event; a watermark-only wake cannot consume a partial bundle. It validates the packet generation and sequence, copies both records, and returns one global publication credit only after durable adapter retention. There is no separate packet signal for this bundle, no additional service poll, and no lifecycle-event pairing. Direct GENET and QEMU do not relay a companion packet through root. One complete wire-frame or wire-train commit may retain one following bounded service cycle. A no-progress cycle quiesces; pending state without sendability or capacity does not create an uncredited spin. Publication requires explicit credit returned only after root has validated and durably handled every indicated event and egress record. Duplicate, stale, late, or identity-mismatched acknowledgements fail closed. The generated descriptor supplies target timer frequency, image identity, mappings, capabilities, notifications, scheduling authority, and fault routes. Root policy, role attachment, namespace mutation, and command execution remain outside the child. The public `AUTH`/`ATTACH` and `OK`/`ERR`/`END` contract is unchanged. ABI v6 assigns the descriptor's former `reserved0` field to fixed child slot 6. HAL mints into that slot only a Write-only, badge-1 capability to the additional root-control wake notification; it grants no Read, Reply, Grant, scheduling, packet, or policy authority. After committing a durable child event, standalone packet TX publication, or complete copied command/packet bundle, the child signals the existing component-specific notification first and this fan-in notification second. Both notifications are coalescing scheduling hints. The sequence-last shared record remains authoritative, so root must recheck the exact durable condition before sleeping and must never infer publication or identity from the wake badge alone. The descriptor change does not alter the four shared pages or any public framing or console grammar. On Pi, compiler truth places root-control on core 0 and this child on core 2 at equal priority 200. Direct GENET and mediated WiFi both use the same cross-core handoff: root commits the durable record, executes a release fence, and signals the exact one-hot child notification. Neither backend pre-drains the child SC or calls `SchedContext_YieldTo`. Exact authenticated direct-GENET control or publication-ACK work may bridge the remaining boundary only through the condition-before-block root fan-in after every identity, lifecycle, operator, recovery, containment, and durable-frontier check passes. QEMU direct-VirtIO retains its existing signal-only selector and cannot consume the Pi fan-in. Invalid backend, authentication, lifecycle, core, priority, MCP, SC, badge, or publication state fails closed. The durable record remains work authority; Signal and the fan-in add no work credit, public frame, or child authority. When the selected descriptor sets `direct_virtio`, its sealed extension names one QEMU VirtIO-net MMIO page, the exact IRQHandler slot, two fixed queue pages, and 16 RX plus 16 TX coherent DMA pages. Only the child maps those resources during steady state. It negotiates the required modern/MAC/mergeable RX feature set, rejects multi-buffer or out-of-range completion metadata, and moves at most one bounded frame per public data-path call. Queue saturation is typed backpressure; it cannot allocate, extend a descriptor chain, or fall back to a root-owned adapter. Containment suspends the child, resets the exact device status register, acknowledges no future IRQ, scrubs the admitted DMA pages, and then revokes the child bundle. The compiler derives `direct_genet` only for the exact Pi `bcmgenet-v5` profile; there is no manifest-authored runtime toggle. The sealed ABI v6 extension names one 32-page CPU-only range shared only by the GENET and console child generations. Page 0 is the aligned sequence-last control page, pages 1 through 15 are GENET-to-console RX slots, and pages 16 through 31 are console-to-GENET TX slots. Both children map the pages as cacheable Normal/XN memory. The descriptor conveys no physical address, MMIO, DMA, device-visible, or root-policy authority. Root obtains DHCP through the legacy bounded path, proves every root-mediated GENET command, RX, and TX cursor quiescent, publishes the exact handoff-pending generation, and sends one generation-bound zero-payload `DGHO`. Only the exact `PROGRESS/READY` terminal activates the direct link. During an exact unfaulted `IDLE/QUIESCING` phase only the bounded legacy drain may run; a retry cannot switch while the coordinator or root RX/TX queues retain work. After READY, GENET remains the sole MMIO/DMA/IRQ and private-DMA-ring owner and copies frames to and from the CPU link. Console-network remains the sole smoltcp/TCP/authentication owner. Root retains lifecycle, control-event, and fault supervision but performs no steady packet copy, poll, or GENET packet command. Each direction is a fixed single-producer/single-consumer ring. Producers publish generation-bound monotonic cursor and sequence-last state with release ordering; consumers validate generation, sequence, length, and stable commit with acquire ordering. The reciprocal send-only peer notifications are coalescing wake hints only. Durable cursor state carries work, and both peers perform a final state recheck before waiting. One direct MCS slice handles at most one material TX or RX operation, including retained cursor reconciliation. The GENET owner may retain up to 16 such slices in one dense window; successive slices alternate their first TX/RX choice, an empty side donates its slice, and continuous bidirectional pressure receives an exact eight/eight split. Every slice rechecks the elapsed-time, attempt, progress, command-freshness, and refill guards; a notification does not itself reset that accounting. A final slice with no durable successor blocks before any guard/cap/stalled Yield. Sustained legal work remains bounded by GENET's exact `3,000 us / 10,000 us` SC and is naturally postponed until replenishment; standard, protocol, cursor, DMA, IRQ, and paired-containment faults remain terminal. Runtime-private control snapshots use the exact 320-byte header/cursor prefix through `DirectGenetControlState`. This avoids clearing and copying an unrelated 4-KiB scratch page at every ring visit. `DirectGenetControlPage` still requires the complete 4-KiB mapped-page representation; initialization still scrubs it in full. Both codecs share the same identity, poison, occupancy, sequence and commit validation. This is an additive private-copy API, not a smaller mapping or a wire-layout/version change. Shared acquire/recheck loads, sequence-last cursor publication, final reconciliation and reciprocal wake rules remain at the existing runtime boundaries. Within control page 0, bytes `[0,64)` hold the immutable control header and bytes `[64,320)` hold the four 64-byte RX-producer, RX-consumer, TX-producer, and TX-consumer records. Console-network ABI v6 additionally assigns the formerly reserved bytes `[320,640)` to an optional, separately versioned direct-GENET diagnostic-v6 record. The record is exactly 320 bytes, aligned to 64 bytes, assigns record-relative offset 12 to the maximum measured direct MCS packet-slice duration in microseconds, retains offset 108 for cumulative `dpc_level_adoptions`, and publishes its nonzero sequence last at record-relative offset 312 (control-page offset 632). Offsets 160, 168, and 176 hold cumulative nonzero receive-boundary notification receipts, receipts rejected by the exact GENET badge filter, and the bitwise OR of every received badge. Flag bits 9 through 13 retain whether a command-freshness, elapsed guard, counter fault, attempt cap, or bounded stalled-retry boundary occurred. The duration and reason fields are observational and cannot reset a scheduling window or prove the Pi WCET. The counts are sampled before filtering and grant no DPC, packet, IRQ-acknowledgement, retry, or scheduling authority. Each actual nonzero GENET notification is counted once at the initial ring-aware receive or a later combined poll/wait receive; zero/command wakes, synthetic grants, physical-level adoption, and unrelated local steady waits are excluded. The GENET child is the sole writer. Root accepts only two identical stable commit observations around a bounded copy and an exact match to the live nonzero direct generation; magic, version, length, flags, counter relations, 32-bit badge width, IRQ-mask relation, cursor-validity rules, and sequence/commit must all validate. Older or missing publications remain compatible unavailable evidence rather than authorizing an alternate path. Optional GENET queue timing v3 uses `[640,896)` for the console-owned RX observation and `[896,1152)` for the GENET-owned TX observation. Each 256-byte record commits its independent publication sequence last at offset 248. The remaining control-page tail stays reserved. Packet pages use `[2048,2080)` for a producer stamp before the ordinary packet commit, and `[2112,2160)` for an optional completed Signal observation. These are diagnostic sidecars; runtime ABI v13, console ABI v6, packet and cursor authority remain unchanged. Queue v3 records generation, flow identity, sample count/sum and the first longest producer-stamp-to-stable-copy interval. The peak additionally retains the consumer's last completed blocking receive: entry/return CNTVCT, returned badge and kind (1=Recv, 2=Wait, 3=ReplyRecv). Poll does not replace that record. A separately committed producer Signal receipt must match the exact live generation and packet sequence and have returned before the copy timestamp. Missing, raced or invalid observations are unavailable, never zero-duration CPU evidence and never a reason to accept, reject, retry or retain a packet. Root reads each record between stable commit observations. Receive intervals include kernel and descheduling time; the last receive need not have carried this packet's wake. A packet/Signal interval lying inside that receive can locate a delay at the receive boundary, but cannot alone identify SC refill eligibility versus another kernel scheduling cause. V3 additionally retains the consumer's last completed explicit Yield at words 17--19 (entry, return, reason), independently of the last receive; words 20--30 remain zero. GENET records its existing route flag: `0x200` command freshness, `0x400` elapsed guard, `0x800` counter fault, `0x1000` attempted-slice cap, `0x2000` stalled successor; zero denotes another explicit Yield caller. An all-zero observation is unavailable. A valid interval must end by the packet copy and have zero or one known reason bit. Invalid timing cannot affect packet admission. The console RX record has no explicit Yield observation. A matched interval can attribute wall time to explicit Yield, but does not prove remaining CPU budget or absence of involuntary postponement outside that interval. The optional rows are `genet_queue`, `genet_queue_peak`, `genet_queue_wait` `genet_queue_signal` and `genet_queue_yield`, each with `schema=v3`, direction and the same generation/publication pair. Absent directions emit only `genet_queue schema=v3 dir= present=no`. Timestamps and identifiers are hexadecimal CNTVCT values; packet length is decimal. Host tools, SDK and benchmark workloads retain their existing protocol and report contracts. Diagnostic v6 retains the 128-byte maximum-slice receipt at record offset 184. It retains the first longest valid slice, its counter timestamps after source adoption/reclaim, packet work, IRQ work and the final durable check, plus an optional confirmed RX publication timestamp. Direction and exact RX/TX cursor identify the packet operation; a validated nonfragmented IPv4/TCP header adds addresses, ports, sequence, acknowledgement and flags without payload bytes. Three formerly reserved words now sample peer Signal entry, Signal return, and completion of RX descriptor/index retirement. An exact notification-due flag distinguishes an omitted Signal from a measured call. Receipt-relative offsets 104, 112 and 120 contain `rx_signal_enter_ticks`, `rx_signal_return_ticks` and `rx_retired_ticks`. The bounded final `genet_direct_slice_rx` diagnostic row exposes their values with `notify_due`. These samples remain inside packet elapsed time; Signal placement and physical ordering do not change. Absent stages are zero. Present timestamps must be ordered; RX and TX are mutually exclusive. An invalid observational sample cannot alter driver service or replace a valid maximum. Counter ticks use the generated timer frequency and include descheduling and kernel time. They do not measure wire arrival, consumed SC budget or console admission, and an unrelated TX or empty slice maximum cannot be assigned to a delayed incoming TCP request. The record is not inspected during ordinary direct packet service. One operator `netstats` request may ask the already active GENET owner for one idempotent generation-bound `DGHO` replay, retain the stable pre-replay record, and read the replacement publication before normal post-command idle service. The replay can wake the owner and thereby allow that existing idle service to drain durable RX, so this is a causal probe rather than a passive snapshot. It adds no packet, IRQ-acknowledgement, retry, recovery, polling, or fallback authority and cannot establish throughput or acceptance. A failed handoff, invalid cursor or sequence, stale generation, descriptor drift, peer fault, IRQ completion failure, or containment error poisons the link, signals the peer when possible, and enters coupled containment. Root suspends GENET, removes both reciprocal notification caps, and unmaps and deletes all 32 external console mapping caps before anchor revoke. No fault path may revive root packet mediation or transfer either peer's authority. The exact Pi direct-GENET console image spans 70 PT_LOAD pages. Its generated service inventory is 108 frames (70 image, 32 stack, one IPC buffer, one init frame, and four ordinary ABI pages) and 165 retained root CSpace slots. The speed profile uses three additional executable pages above the former 66-page image; the temporary wake observer adds one further page and its retained mapping cap. Neither change enlarges a data-plane or scheduling budget. The 32 direct pages are reused external GENET frames and therefore add console mapping caps rather than data-plane frame objects or a larger child untyped. These private ABI and resource facts do not change the public TCP framing, console grammar, authentication, attachment, or response schema. Static validation and image construction do not prove Pi boot, READY, packet correctness, latency, throughput, QEMU parity, or acceptance. ## Target TCP console sequence ```mermaid sequenceDiagram participant Client as cohsh participant Tcp as console-network-runtime participant Pump as root-task event pump participant Namespace as NineDoorBridge Client->>Tcp: framed AUTH token alt transport token valid Tcp-->>Client: framed OK AUTH else invalid or timed out Tcp-->>Client: framed ERR AUTH Tcp--xClient: close connection end Client->>Tcp: framed ATTACH role and optional ticket Tcp->>Pump: bounded console command Pump->>Namespace: validate role and attach context alt application authority valid Namespace-->>Pump: attached Pump-->>Tcp: bounded OK ATTACH response Tcp-->>Client: framed OK ATTACH else denied or rate limited Namespace-->>Pump: refusal Pump-->>Tcp: bounded ERR ATTACH response Tcp-->>Client: framed ERR ATTACH end Client->>Tcp: framed TAIL path Tcp->>Pump: bounded console command Pump->>Namespace: authorize and read retained window Namespace-->>Pump: bounded records Pump-->>Tcp: bounded OK TAIL response Tcp-->>Client: framed OK TAIL loop retained records Pump-->>Tcp: bounded response record Tcp-->>Client: framed record end Pump-->>Tcp: bounded END response Tcp-->>Client: framed END ``` The diagram shows protocol order, not a claim that `NineDoorBridge` is a host NineDoor server or that every path is available in every profile. ## Target console contract ### Framing Serial accepts console lines directly. TCP frames every inbound and outbound line with a four-byte little-endian total length that includes the header. - Declared total length must be at least 4 and no greater than the Secure9P implementation cap of 8192 bytes. - The isolated QEMU console admits at most 2304 bytes for one authenticated command frame. The existing `echo` grammar permits at most 2048 payload bytes so one compiler-bounded host-ticket record fits with its verb and path; every other command retains its narrower field-specific bound. Physical serial/local-seat lines remain bounded independently at 256 bytes. - Oversized unauthenticated frames terminate authentication. An authenticated session receives `ERR FRAME reason=invalid-length`; the child drains exactly the complete declared payload across any fragmentation, retains the same authenticated connection, and parses the next frame only after that drain. - The first TCP payload must be exactly `AUTH ` with the configured token length. Invalid, missing, or late authentication closes the session. Transport authentication does not select a namespace role. After `OK AUTH`, the client uses `ATTACH [ticket]`. Queen may omit the ticket; worker roles require a valid ticket and subject identity. Failed application login attempts use the current bounded limiter: three failures within 60 seconds produce a 90-second cooldown. `ATTACH` binds an application session to a role-scoped namespace; it never creates or resumes a task. The selected profiles separately admit executable Heartbeat, GPU, and LoRA roles, but only an authorized `/queen/ctl` lifecycle operation can select one of their already constructed suspended children. The child's durable READY record, not `ATTACH` or the control acknowledgement, publishes its exact namespace identity. An `OK ATTACH` means the target namespace prepare succeeded and both NineDoor and root committed the same local role/ticket session. Audit, logger transport, and boot-tracer observation occur after that authority commit and cannot turn a successful prepare into `ERR ATTACH`. The logger remains UART+EP mirrored at this boundary; an optional later EP-only self-test is transport policy, not application authority. ### Command grammar The compiler-owned command inventory is generated in [cohsh_grammar.md](snippets/cohsh_grammar.md). The parser applies per-field bounds from [`cohsh-core`](../crates/cohsh-core/src/command.rs), including the 2304-byte authenticated network-command limit, 2048-byte `echo` payload limit, bounded paths/tickets/JSON payloads, and a maximum of 256 requested tail lines. Commands are case-insensitive at the verb parser where implemented; arguments remain subject to their command-specific grammar. Unknown verbs, missing arguments, extra arguments on strict commands, oversized values, and invalid numeric fields return `ERR` and produce no documented side effect. ### Acknowledgements and streams - Every accepted command produces `OK ...`; every refused command produces `ERR reason= ...`. - Structured namespace streams such as successful `tail`, `cat`, `ls`, and `log` emit a leading `OK`, zero or more bounded records, and a terminal `END`. - Bounded diagnostic commands may emit their diagnostic records before the terminal `OK`; their checked transcript, rather than the namespace-stream ordering rule, is authoritative. - `PING` responds as `OK PING reply=pong`; it does not emit a bare `PONG`. - `QUIT` and authenticated `REBOOT` have explicit connection/flush behavior; clients must wait for the documented acknowledgement rather than treating a disconnect as success. After exact `OK QUIT`, a TCP client half-closes its write side and requires peer EOF on the same connection within the existing timeout; QUIT is not retried after an ambiguous send or close. The isolated owner drains its application and TCP output before an authenticated root-authorized close. It then waits at most one second for the peer FIN and closes from `CloseWait`, avoiding simultaneous FIN on clean QUIT. A ten-second drain expiry or peer-grace expiry aborts the connection; duplicate Disconnect controls cannot extend either deadline. Authentication rejection and independent peer EOF retain their own close behavior. - An `ERR` is terminal for that command and must not be treated as a successful no-op. Some queued Queen commands acknowledge acceptance before the event pump forwards the work; others validate and apply a bounded provider operation before acknowledging success. Clients must use the command-specific status and observability path rather than infer completion timing from a generic `OK`. Canonical transcripts and negative cases live in [`tests/integration`](../tests/integration) and the root-task tests. ### Restricted memory diagnostics The emergency bring-up `hexdump` command is unavailable in release profiles. When explicitly enabled outside release, HAL restricts it to 1–256 bytes in the immutable root executable code span. Refusals are `ERR EPERM memory-diagnostics-disabled`, `ERR ELIMIT memory-diagnostics-length`, or `ERR EPERM memory-diagnostics-unclassified`; extra arguments return `ERR EINVAL memory-diagnostics-arguments`. A bounded `[audit] memory-read` serial line records admission or range refusal. Normal console grammar and TCP/REST framing are unchanged by this early-shell contract. ## Host Secure9P contract Host NineDoor accepts only `version`, `attach`, `walk`, `open`, `read`, `write`, and `clunk`. It does not accept `stat`, `create`, or `remove`. The current codec caps walk depth at eight and each walk component at 64 bytes. Exact session, batching, fid, offset, and error rules are in [SECURE9P.md](SECURE9P.md). The checked-in default profile uses one frame per batch. Where a selected manifest enables larger batches, host NineDoor encodes responses in request order and preserves response tags. Clients must still correlate by tag. ## Namespace conventions All paths are absolute UTF-8 paths. `..`, NUL, undeclared wildcard expansion, and traversal outside the attached role view are rejected. A path appearing in this catalogue does not guarantee runtime presence: the selected manifest must enable it and the active adapter must implement it. Node modes have these meanings: - **read-only:** clients cannot append or replace content; - **append-only:** writes add one bounded record at the provider's expected offset; random overwrite and truncation are rejected; - **control:** an append-only node whose record is parsed and may cause a bounded side effect; and - **directory:** walk/list only. Host providers and the target `NineDoorBridge` overlap but are not identical. Parity must be established per path: a host-only GPU job, sidecar adapter, or federation relay is not target evidence. Conversely, the target adapter does implement selected bounded GPU publication, UI, and `/host` files, but their presence proves only the namespace projection; operating-system actions and federated delivery still execute in host agents. ## Core namespace | Path | Mode | Contract | | --- | --- | --- | | `/log/queen.log` | Client read stream; system append | Bounded retained Queen/root log. Console `log`, `tail`, and `cat` are projections over this path. | | `/proc/*` | Read-only unless a generated node explicitly says otherwise | Bounded session, lifecycle, pressure, ingest, scheduling, lease, and root-reachability observations. | | `/queen/ctl` | Queen control, JSONL | Root-owned lifecycle control for compiler-selected executable Heartbeat, GPU, and LoRA children plus model-only WorkerBus. A successful spawn/admit write means accepted or queued, never READY; only the exact child's durable READY record publishes its canonical `/shard/