fix(runtime): read Codex's 'Implement this plan?' menu as blocked (#24536)

After a Plan-mode turn Codex shows a menu that owns the keyboard, but its Stop
hook has already fired, so a tui-idle wait settled ready and sent text into the
menu. A Codex blocked text anchor now names it an interactive prompt while its
key row ends the tail, written against a new 0.160.0 capture that is replayed
by the readiness census.
This commit is contained in:
Jinwoo Hong
2026-10-02 14:58:49 -04:00
committed by GitHub
parent caa4228e0f
commit 4ea6673dba
5 changed files with 96 additions and 0 deletions
@@ -0,0 +1,9 @@
{
"capturedAt": "2026-10-02T05:46:28.602Z",
"platform": "darwin",
"command": ["codex", "--no-daemon", "-c", "check_for_update_on_startup=false"],
"cols": 120,
"rows": 40,
"note": "codex-cli 0.160.0, isolated HOME/CODEX_HOME with the project pre-trusted. A Plan-mode turn ends in the 'Implement this plan?' menu, which owns the screen until '3' (No, stay in Plan mode) answers it at 70s; cut 25s later at the empty composer.",
"exitCode": 0
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,36 @@
{
"description": "codex recording at 120x40 replayed on the agent pane, one entry per chunk",
"observations": {
"clocked": [
"0-21: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"22-36: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"37-44: now=working edge=working quiet=ready-strong wait=ready@start",
"45-54: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"55-60: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"61-111: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"112-118: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"119-121: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"122-123: now=working edge=working quiet=ready-strong wait=ready@start",
"124-180: now=working edge=working quiet=working wait=pending",
"181-212: now=working edge=working quiet=ready-strong wait=ready@start",
"213-435: now=working edge=working quiet=working wait=pending",
"436-500: now=working edge=working quiet=ready-strong wait=ready@start",
"501-502: now=working edge=working quiet=working wait=pending",
"503-507: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"508-547: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"548-551: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"552-558: now=blocked:agent-interactive-prompt edge=blocked:agent-interactive-prompt quiet=blocked:agent-interactive-prompt wait=blocked:agent-interactive-prompt@start",
"559-596: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"597-601: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start"
],
"clockless": [
"0-36: verdict=pending:closed wait=pending",
"37-44: verdict=working wait=pending",
"45-121: verdict=pending:closed wait=pending",
"122-502: verdict=working wait=pending",
"503-551: verdict=pending:closed wait=pending",
"552-558: verdict=blocked:agent-interactive-prompt wait=blocked:agent-interactive-prompt@start",
"559-601: verdict=pending:closed wait=pending"
]
}
}
@@ -0,0 +1,35 @@
{
"description": "codex recording at 120x40 replayed on the unknown pane, one entry per chunk",
"observations": {
"clocked": [
"0-36: now=pending:open edge=pending:open quiet=pending:open wait=ready@poll",
"37-44: now=working edge=working quiet=ready-strong wait=ready@start",
"45-54: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"55-60: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"61-111: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"112-118: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"119-121: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"122-123: now=working edge=working quiet=ready-strong wait=ready@start",
"124-180: now=working edge=working quiet=working wait=pending",
"181-212: now=working edge=working quiet=ready-strong wait=ready@start",
"213-435: now=working edge=working quiet=working wait=pending",
"436-500: now=working edge=working quiet=ready-strong wait=ready@start",
"501-502: now=working edge=working quiet=working wait=pending",
"503-507: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"508-547: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start",
"548-551: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"552-558: now=blocked:agent-interactive-prompt edge=blocked:agent-interactive-prompt quiet=blocked:agent-interactive-prompt wait=blocked:agent-interactive-prompt@start",
"559-596: now=pending:closed edge=pending:closed quiet=pending:closed wait=pending",
"597-601: now=pending:closed edge=pending:closed quiet=ready-strong wait=ready@start"
],
"clockless": [
"0-36: verdict=pending:open wait=ready@poll",
"37-44: verdict=working wait=pending",
"45-121: verdict=pending:closed wait=pending",
"122-502: verdict=working wait=pending",
"503-551: verdict=pending:closed wait=pending",
"552-558: verdict=blocked:agent-interactive-prompt wait=blocked:agent-interactive-prompt@start",
"559-601: verdict=pending:closed wait=pending"
]
}
}
@@ -3,6 +3,21 @@
"engineVersion": 1,
"profile": { "screenSource": "live" },
"anchors": [
{
"id": "plan_implement_menu",
"why": "A Plan-mode turn ends in this menu after Codex's Stop hook fired, and it owns the keyboard, so text sent to the pane picks a choice. Codex paints it by cell diff, which drops spaces from the text copy, and leaves it in the tail once answered, so the key row must end the tail.",
"when": {
"region": "text",
"find": { "lastOf": "implement this plan?" },
"after": {
"all": [
{ "regex": "no,\\s*stay\\s*in\\s*plan\\s*mode" },
{ "regex": "enter\\s*select\\s*·\\s*esc\\s*back\\s*$" }
]
}
},
"answer": { "state": "blocked", "reason": "agent-interactive-prompt" }
},
{
"id": "ready_header",
"why": "The startup header with its model and directory labels is the stable ready text across versions; Codex prints permissions only in YOLO mode. Its last occurrence counts, so a header repainted after a dialog proves the dialog was answered.",