Six findings from the review of the structured Codex session, all of them
about a session that is live in the map while the thing it names is not:
- A prompt is addressed by its own approval id, not by the tool item it is
about. A shell bridge re-asks per command under one parent item, and the
second ask used to evict the first, leaving that turn blocked on a request
nobody could answer.
- A subagent runs its own thread over the same connection. Its `turn/started`
no longer satisfies the root thread's waiter, and every event now carries the
thread it actually came from.
- Publication is one step at the end of acquire: the process identity is in
hand, the child is still alive, and the attempt still owns the session. A
failure reaps only its own child, so a replacement already published keeps
running.
- Codex talks before its thread is named. Those events wait in the acquisition
window and are delivered in arrival order once the session is published,
instead of being dropped.
- A broken stdin pipe ends the transport rather than one write: the child is
reaped and the owner learns its lease is worthless.
- A death that reaches us through several listeners reports once, keeping the
first cause rather than the generic exit that follows it.
Implements the structured agent-session adapter for Codex: one long-lived
app-server child per session, started or resumed under the lease the host
already reserved, reporting the process identity the lease re-proves and the
provider handle link the journal binds to.
The thread the adapter reports is the one Codex actually opened, never the one
a client declared, and a resume that lands on a different thread is refused
rather than recorded as a resume. A turn is named from the start response when
Codex sends an id there and from the turn-started notification when it acks
first; when neither names it in time the submission settles unknown, which the
journal renders as delivery unconfirmed rather than failure. Only a refusal
Codex actually answered becomes a rejection.
Model, effort, and policy are per-turn overrides — there is no thread-settings
write — so an option set between turns is applied to the next turn/start, and
unlisted keys are refused instead of becoming arbitrary client-controlled
parameters.