Expose a privacy-minimal output-only human-input lifecycle from codex-core
What variant of Codex are you using?
Codex App, IDE Extension, and CLI.
What feature would you like to see?
Please expose an optional, output-only lifecycle for the moments when Codex is
actually waiting for a human permission decision or supported user input.
The lifecycle should be produced once in codex-core, so App, IDE Extension,
and CLI clients share the same semantics. It should emit only:
permission pendingand a matchingresolved;question pendingand a matchingresolved.
Pending should be emitted only after policy, cached approvals, hooks,
automated review, and other automatic routing have finished and the request
will actually be shown to a human.
Resolved should be emitted exactly once, without the decision or answer,
when the owning client receives a response or the request is cleared by
decline, cancellation, replacement, interruption, turn completion, abort, or
session shutdown.
This should cover permission requests as well as blockingrequest_user_input and MCP elicitation questions.
The observer must remain strictly notification-only. It must have no protocol
or code path to approve, reject, select an option, or submit text. The user
continues to respond only in the Codex client that owns the request.
Privacy and authority boundary
The output should contain only a generic kind and an internally generated
opaque request ID. It should never contain request content, filesystem paths,
approval reasons, question text, options, tool input, model output, user
answers, or approval outcomes. Lifecycle data should not be written to
telemetry or long-lived logs.
An optional local transport should be output-only from Codex. Observer input
must never be read and must not be able to influence Codex behavior.
Deterministic cleanup
The lifecycle needs bounded source identity, monotonic sequencing, a heartbeat,
and an authoritative reconnect snapshot containing only requests that are
still active.
EOF, an unknown version or event, a sequence gap, a collision, process loss,
or restart should clear pending state by default. Reconnect must not replay
historical notifications. A still-active request should retain its opaque
request ID across a fresh transport source so a receiver can restore visual
state without replaying sound for the same unresolved request.
Why existing surfaces are not sufficient
App Server exposes typed requests and matching resolution on the owning client
transport, but a separate read-only observer cannot attach to every existing
App, IDE, and CLI task.
PermissionRequest hooks run before the final human-routing decision, so a
hook invocation does not prove that Codex is waiting for a person. They also
do not provide the matching generic resolution needed to remove a notification
deterministically.
A one-shot notification event cannot reliably clear stale pending state when
the Codex process or observer disappears.
Additional information
This is related to #28833, which requests a post-routing approval signal for
passive notifications. This request additionally covers paired no-outcome
resolution, supported blocking questions, shared core ownership, reconnect,
and deterministic source-loss cleanup.
A software-only reference prototype has validated the feasibility of the
core-owned lifecycle and a strict downstream receiver, including permission
and question round trips, privacy boundaries, duplicate and replay handling,
reconnect, restart, observer loss, collision handling, and stale cleanup.
Technical design and test details can be provided privately if useful.
The feature can be disabled by default and should not change existing approval
flows or require UI scripting, keyboard automation, or accessibility
automation.