Codex Parsing Contract¶
Codex-specific parsing lives in backends/codex_shadow.py. The parser is responsible for one-snapshot interpretation of captured pane output and returns CodexSurfaceAssessment plus CodexDialogProjection.
For the concrete on-screen cues currently used by the maintained tracked-TUI workflow, see Codex Signals.
Codex-Specific Surface Vocabulary¶
Codex extends the shared ui_context vocabulary with these provider-specific values:
normal_promptselection_menuslash_commandapproval_prompterror_bannerunknown
The provider reuses the shared availability, business_state, and input_mode values:
- availability:
supported,unsupported,disconnected,unknown - business state:
idle,working,awaiting_operator,unknown - input mode:
freeform,modal,closed,unknown
approval_prompt is the main Codex-specific distinction: it captures approval or trust flows that are similar in behavior to Claude’s trust prompt, but with Codex-specific text and menu shapes.
What The Codex Parser Detects¶
The Codex parser uses signals for:
- supported output families
- idle prompt lines
- processing or progress signals
- selection menus
- approval or trust prompts
- slash-command UI
- error banners
- disconnected states
- visible assistant output in both label-style and TUI-style layouts
As with Claude, runtime derives submit_ready only when the surface is supported, business_state = idle, input_mode = freeform, and no blocking UI context is active.
Codex Parser State Transition Graph¶
Codex parser-state transitions are also evaluated across ordered snapshots. The parser owns the transition facts, while runtime decides what those facts mean for turn lifecycle.
stateDiagram-v2
[*] --> Unsupported
state "idle + freeform" as IdleFreeform
state "idle + modal" as IdleModal
state "working" as Working
state "awaiting_operator" as AwaitingOperator
state "unknown" as Unknown
state "unsupported" as Unsupported
state "disconnected" as Disconnected
Unsupported --> IdleFreeform: evt_supported_surface<br/>+ evt_prompt_freeform
Unsupported --> IdleModal: evt_supported_surface<br/>+ evt_prompt_modal
Unsupported --> Working: evt_supported_surface<br/>+ evt_processing_started
Unsupported --> AwaitingOperator: evt_supported_surface<br/>+ evt_operator_blocked
Unsupported --> Disconnected: evt_surface_disconnected
IdleFreeform --> Working: evt_processing_started
IdleFreeform --> AwaitingOperator: evt_operator_blocked
IdleFreeform --> IdleModal: evt_prompt_modal
IdleFreeform --> Unknown: evt_unknown_entered
IdleFreeform --> Unsupported: evt_surface_unsupported
IdleFreeform --> Disconnected: evt_surface_disconnected
IdleModal --> Working: evt_processing_started
IdleModal --> AwaitingOperator: evt_operator_blocked
IdleModal --> IdleFreeform: evt_prompt_freeform
IdleModal --> Unknown: evt_unknown_entered
IdleModal --> Unsupported: evt_surface_unsupported
IdleModal --> Disconnected: evt_surface_disconnected
Working --> IdleFreeform: evt_prompt_freeform
Working --> IdleModal: evt_prompt_modal
Working --> AwaitingOperator: evt_operator_blocked
Working --> Unknown: evt_unknown_entered
Working --> Unsupported: evt_surface_unsupported
Working --> Disconnected: evt_surface_disconnected
AwaitingOperator --> IdleFreeform: evt_prompt_freeform
AwaitingOperator --> IdleModal: evt_prompt_modal
AwaitingOperator --> Working: evt_processing_started
AwaitingOperator --> Unknown: evt_unknown_entered
AwaitingOperator --> Unsupported: evt_surface_unsupported
AwaitingOperator --> Disconnected: evt_surface_disconnected
Unknown --> IdleFreeform: evt_prompt_freeform
Unknown --> IdleModal: evt_prompt_modal
Unknown --> Working: evt_processing_started
Unknown --> AwaitingOperator: evt_operator_blocked
Unknown --> Unsupported: evt_surface_unsupported
Unknown --> Disconnected: evt_surface_disconnected
The graph shows parser-state transitions only. It does not mean a turn is complete when Codex returns to idle + freeform; completion remains a runtime monitor concern described in Runtime Lifecycle.
Codex State Meanings¶
| State | Meaning | Main Codex signals |
|---|---|---|
idle + freeform |
Codex looks idle and exposes a normal prompt | idle prompt line is visible and no stronger blocking or processing signal applies |
idle + modal |
Codex is idle, but the active surface is still slash-command or another constrained prompt | active slash-command surface is visible |
working |
Codex is actively processing or generating | processing signal or progress output is present |
awaiting_operator |
Codex is blocked on explicit user approval, trust, selection, or login/setup | selection menu, approval prompt, or login/setup block is visible |
unknown |
Codex output is still supported, but not classifiable into a safer stronger state | supported surface with no ready, working, or waiting evidence |
unsupported |
snapshot does not match a supported Codex output family | supported-output-family detector fails |
disconnected |
terminal appears detached or unavailable | disconnected signal is present |
Codex uses the same high-level business-state priority as Claude, but the concrete prompts and output families differ, especially around approval prompts and label-style versus TUI-style dialog.
Codex Transition Events¶
| Event | Detection | Codex-specific interpretation |
|---|---|---|
evt_supported_surface |
availability becomes supported |
a supported Codex output family is recognized |
evt_surface_unsupported |
availability becomes unsupported |
parser no longer trusts the snapshot shape |
evt_surface_disconnected |
availability becomes disconnected |
detached or disconnected Codex surface is visible |
evt_processing_started |
business_state changes to working |
Codex processing or progress signal appears |
evt_prompt_freeform |
business_state is idle and input_mode is freeform |
idle prompt becomes visible without a blocking menu or approval prompt |
evt_prompt_modal |
business_state is idle and input_mode is modal |
slash-command UI is active |
evt_operator_blocked |
business_state changes to awaiting_operator |
selection menu, approval prompt, or login/setup block appears |
evt_unknown_entered |
business_state changes to unknown while availability=supported |
Codex surface is still recognized but no safe stronger state matches |
evt_context_changed |
ui_context changes across snapshots |
for example normal_prompt to approval_prompt or slash_command |
evt_normalized_text_changed |
DialogProjection.normalized_text changes across snapshots |
the closer-to-source visible Codex snapshot text changed |
These events describe parser observations, not runtime lifecycle decisions. The runtime monitor consumes the shared parser outputs from this page; current completion evidence keys off normalized shadow text after pipeline normalization rather than dialog_text.
Preset And Version Selection¶
Codex is also version-aware. Preset selection uses this order:
HOUMAO_CAO_CODEX_VERSION- banner detection from Codex version strings
- latest known preset fallback
Current preset milestones in code are:
| Version floor | Preset id | Notes |
|---|---|---|
0.1.0 |
codex_shadow_v1 |
label-style and prompt/waiting baselines |
0.98.0 |
codex_shadow_v2 |
adds supported TUI bullet-style assistant output |
Unknown newer versions use floor lookup and record the shared version anomaly in parser metadata.
Supported Output Families¶
The Codex parser explicitly supports more than one visible transcript family:
codex_label_v1codex_tui_bullet_v1codex_waiting_approval_v1codex_prompt_idle_v1
This matters because Codex may present assistant content either as labeled transcript lines or as TUI bullet output. The parser contract promises support for both families when they match the supported preset range.
Projection Boundaries¶
Codex dialog projection removes UI chrome such as:
- ANSI styling
- prompt and footer chrome
- progress/spinner lines
- shortcut/footer lines
- menu framing that does not belong in projected dialog
Projection preserves visible dialog content such as:
- label-style assistant output
- bullet-style assistant output
- visible user prompt text that remains on screen
- approval/menu text when Codex is blocked on user input
The result is still projected visible dialog, not authoritative answer association.
The current runtime lifecycle monitor does not use dialog_text as its post-submit diff surface. It keys change evidence off normalized shadow text and keeps dialog_text for human-facing transcript views and caller-owned extraction patterns.
Codex-Specific Blocking And Drift Cases¶
Codex commonly blocks in two ways:
selection_menu: menu-style selection UI is visibleapproval_prompt: Codex is asking for approval or directory trust
slash_command should only apply while the current editable Codex prompt is still inside slash-command interaction. Historical /model output or other command results that remain visible in projected dialog must not keep a later recovered normal prompt in a blocked slash-command state.
The parser also handles both historical label-style output and newer TUI-style bullet output, which makes variant detection especially important when Codex changes its visible UI.
As with Claude, baseline shrinkage sets baseline_invalidated = true for diagnostics.
What Codex Must Not Claim¶
The Codex parser must not claim that visible assistant text is automatically the authoritative answer for the last prompt. Its responsibilities stop at:
- state assessment
- dialog projection
- parser metadata and anomalies
- provider-specific evidence
Anything stronger belongs in a caller-owned association layer.