fix(codex): JSONL parser initializes its state vars in both modes

challenge-mode initialized turn_completed_count but tested turn_failed via
'in dir()'; consult-mode initialized neither and rebuilt the counter with
a dir() conditional per event. Both parsers now init turn_completed_count
and turn_failed up front and use plain checks — same semantics, no
module-globals introspection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-01 16:07:31 +00:00
co-authored by Claude Fable 5
parent 6b2cde38c1
commit 5a7a42fc24
4 changed files with 14 additions and 8 deletions
+2 -1
View File
@@ -38,6 +38,7 @@ TMPERR=${TMPERR:-$(mktemp "$TMP_ROOT/codex-err-XXXXXX")}
_gstack_codex_timeout_wrapper 600 codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
import sys, json
turn_completed_count = 0
turn_failed = False
for line in sys.stdin:
line = line.strip()
if not line: continue
@@ -68,7 +69,7 @@ for line in sys.stdin:
except: pass
# Fix 2: three-way completeness check (#2671) — a STATED failure is a failure,
# not a network problem; only silence with no terminal event is a disconnect.
if 'turn_failed' in dir():
if turn_failed:
print('[codex] turn.failed received — the turn errored (reason above), not a disconnect.', flush=True, file=sys.stderr)
elif turn_completed_count == 0:
print('[codex warning] No turn.completed event received — possible mid-stream disconnect.', flush=True, file=sys.stderr)
+2 -1
View File
@@ -36,6 +36,7 @@ TMPERR=${TMPERR:-$(mktemp "$TMP_ROOT/codex-err-XXXXXX")}
_gstack_codex_timeout_wrapper 600 codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' {{CODEX_WEB_SEARCH_FLAG}} --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
import sys, json
turn_completed_count = 0
turn_failed = False
for line in sys.stdin:
line = line.strip()
if not line: continue
@@ -66,7 +67,7 @@ for line in sys.stdin:
except: pass
# Fix 2: three-way completeness check (#2671) — a STATED failure is a failure,
# not a network problem; only silence with no terminal event is a disconnect.
if 'turn_failed' in dir():
if turn_failed:
print('[codex] turn.failed received — the turn errored (reason above), not a disconnect.', flush=True, file=sys.stderr)
elif turn_completed_count == 0:
print('[codex warning] No turn.completed event received — possible mid-stream disconnect.', flush=True, file=sys.stderr)
+5 -3
View File
@@ -80,6 +80,8 @@ fi
# Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper)
_gstack_codex_timeout_wrapper 600 codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' -c 'web_search="cached"' --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
import sys, json
turn_completed_count = 0
turn_failed = False
for line in sys.stdin:
line = line.strip()
if not line: continue
@@ -102,7 +104,7 @@ for line in sys.stdin:
cmd = item.get('command','')
if cmd: print(f'[codex ran] {cmd}', flush=True)
elif t == 'turn.completed':
turn_completed_count = 1 + (turn_completed_count if 'turn_completed_count' in dir() else 0)
turn_completed_count += 1
usage = obj.get('usage',{})
tokens = usage.get('input_tokens',0) + usage.get('output_tokens',0)
if tokens: print(f'\ntokens used: {tokens}', flush=True)
@@ -113,9 +115,9 @@ for line in sys.stdin:
except: pass
# Three-way completeness check (#2671; consult previously had NONE): a STATED
# failure is a failure, not a network problem; only silence is a disconnect.
if 'turn_failed' in dir():
if turn_failed:
print('[codex] turn.failed received — the turn errored (reason above), not a disconnect.', flush=True, file=sys.stderr)
elif 'turn_completed_count' not in dir():
elif turn_completed_count == 0:
print('[codex warning] No turn.completed event received — possible mid-stream disconnect.', flush=True, file=sys.stderr)
"
# Fix 1: hang detection for Consult new-session (mirrors Challenge + resume)
+5 -3
View File
@@ -78,6 +78,8 @@ fi
# Fix 1: wrap with timeout (gtimeout/timeout fallback chain via probe helper)
_gstack_codex_timeout_wrapper 600 codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="medium"' {{CODEX_WEB_SEARCH_FLAG}} --json < /dev/null 2>"$TMPERR" | PYTHONUNBUFFERED=1 "$PYTHON_CMD" -u -c "
import sys, json
turn_completed_count = 0
turn_failed = False
for line in sys.stdin:
line = line.strip()
if not line: continue
@@ -100,7 +102,7 @@ for line in sys.stdin:
cmd = item.get('command','')
if cmd: print(f'[codex ran] {cmd}', flush=True)
elif t == 'turn.completed':
turn_completed_count = 1 + (turn_completed_count if 'turn_completed_count' in dir() else 0)
turn_completed_count += 1
usage = obj.get('usage',{})
tokens = usage.get('input_tokens',0) + usage.get('output_tokens',0)
if tokens: print(f'\ntokens used: {tokens}', flush=True)
@@ -111,9 +113,9 @@ for line in sys.stdin:
except: pass
# Three-way completeness check (#2671; consult previously had NONE): a STATED
# failure is a failure, not a network problem; only silence is a disconnect.
if 'turn_failed' in dir():
if turn_failed:
print('[codex] turn.failed received — the turn errored (reason above), not a disconnect.', flush=True, file=sys.stderr)
elif 'turn_completed_count' not in dir():
elif turn_completed_count == 0:
print('[codex warning] No turn.completed event received — possible mid-stream disconnect.', flush=True, file=sys.stderr)
"
# Fix 1: hang detection for Consult new-session (mirrors Challenge + resume)