awslabs / awslabs/cli-agent-orchestrator

[Bug] Codex startup never completes when the TUI shows an account notice bullet (codex-cli 0.153.2)

Open
#739 1 comment 0 reactions 1 assignee Claimed by @mastash3ff View on GitHub
Dominant language
Python
Stars
1.3k
Forks
267
Avg merge
1d 23h
Merged PRs (30d)
70

Description

Found against a **live `codex-cli 0.153.2`** under tmux, driven with CAO's own launch flags and read back through `get_backend().get_history()` — not a synthetic fixture.

`CodexProvider.initialize()` never concludes that Codex has started, and fails with `TimeoutError("Codex initialization timed out after 60 seconds")`, on a pane that is visibly idle and ready to accept input.

## What the pane actually looks like

```
╭──────────────────────────────────────────────────────────╮
│ >_ OpenAI Codex (v0.153.2) │
│ model: gpt-5.6-sol /model to change │
│ directory: /tmp/.../work │
│ permissions: YOLO mode │
╰──────────────────────────────────────────────────────────╯

Tip: Use /copy or press Ctrl+O to copy the latest agent response as Markdown.

• You have 1 usage limit reset available. Run /usage to use one.

› Ask Codex to do anything

gpt-5.6-sol default · /tmp/.../work
```

That is a fully started Codex sitting at its idle composer. Measured through CAO's own capture path:

```
_has_startup_idle_composer(real capture) -> False # initialize() polls until it times out
get_status(real capture) -> completed # before any task was ever submitted
```

## Cause

Codex prints **account/product notices as `•` bullets**, and CAO cannot tell those from agent output.

**1. The readiness veto fires on a notice.** `_has_startup_idle_composer` rejects the frame when `STARTUP_ACTIVITY_PATTERN` (`^\s*•[^\S\n]+\S`) matches anywhere in the bottom `STARTUP_PROMPT_BOTTOM_LINES`. The matching text here is:

```
STARTUP_ACTIVITY_PATTERN vetoes readiness: True -> '\n• Y'
```

`• You have 1 usage limit reset available. Run /usage to use one.` — Codex telling the user about their plan, not activity. The other two vetoes (`WAITING_PROMPT_PATTERN`, `STARTUP_BLOCKING_INPUT_PATTERN`) are both False, so this is the sole reason readiness is refused. Every subsequent poll sees the same line, so the loop can only end in the 60s timeout.

**2. The same line reads as a model reply.** `_find_assistant_marker` returns that bullet, and with no user marker below the footer cutoff `get_status` takes the "long-running response whose `›` marker was evicted" branch and returns `COMPLETED` — for a worker that has never been given a task. The code's own comment calls a false COMPLETED "the dangerous case — it tells the conductor the agent is free."

The placeholder itself is fine: `STARTUP_IDLE_PLACEHOLDER_PATTERN` already lists `Ask Codex to do anything`, and `TUI_FOOTER_PATTERN` matches the `model · path` footer via its `·\s+[~/]` alternative. Neither of those is the problem.

## Impact

Any Codex account whose TUI shows a notice bullet within the bottom 15 lines cannot launch a Codex worker at all: `initialize()` raises after 60s, and on the deferred-init path `_schedule_deferred_init` then notifies the caller and tears the worker down. The trigger is account state (a usage-limit notice, a tip promoted to a bullet), so it will look intermittent across machines and accounts while being fully deterministic on any one of them.

## Suggested direction

The readiness veto should key on **evidence of work in progress**, not on the bullet glyph. Codex marks actual activity with the progress spinner — `TUI_PROGRESS_PATTERN`, the `(s • esc to interrupt)` shape — which is what "still starting" really looks like; a bare bullet with no spinner is a printed line, not a busy TUI. Narrowing `STARTUP_ACTIVITY_PATTERN` to that shape fixes readiness without loosening any of the blocking-dialog checks, which are matched separately.

The `get_status` half is the same root cause and wants the same discrimination: a notice bullet emitted before any user turn should not satisfy the assistant-marker search that produces COMPLETED.

I have the raw byte streams and rendered captures for the startup, pasted-unsubmitted, and accepted-turn phases if they would help whoever picks this up. Happy to take it myself — flagging first rather than sending a PR into an area with active review traffic.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.