Skip to content

fix(codex): don't record a deadline-truncated turn as success - #7

Draft
09473ZH wants to merge 2 commits into
agent/codex-long-sessions-cleanfrom
fix/codex-turn-deadline-terminal-state
Draft

fix(codex): don't record a deadline-truncated turn as success#7
09473ZH wants to merge 2 commits into
agent/codex-long-sessions-cleanfrom
fix/codex-turn-deadline-terminal-state

Conversation

@09473ZH

@09473ZH 09473ZH commented Aug 19, 2026

Copy link
Copy Markdown

Root cause (2026-08-18 premarket plan incident)

codex_app_server_session.py 的 turn-deadline 兜底会在"本 turn 中出现过任何一条已完成的助手消息"时,把超时静默转成成功:中途叙述文本被当成最终回复,cron 记 last_status=ok。08-18 盘前 plan 的新闻归并在 4200s 上限处被截断,终态记成功,下游 plan 消费了一个不存在的新闻终态。

Fix

跟踪 turn 内最后一个有效信号(text | tool_start | tool_done | activity),deadline 兜底只在助手文本是 codex 最后产出的东西时接受(即该兜底原本要修的 turn/completed 丢失 quirk);其余情况一律走超时错误路径(interrupt + should_retire),错误信息带上 last signal 便于诊断。

Verification

  • tests/run_agent/test_codex_app_server_integration.py + test_codex_app_server_lifecycle.py:36 passed
  • 配套:Qortex-Trading-Harness 将把 HERMES_CODEX_TURN_TIMEOUT_SECONDS 4200→7200 并 bump hermes.lock.yaml 到本 PR 合并后的 commit

🤖 Generated with Claude Code

The turn-deadline fallback accepted result.final_text as the terminal
response whenever ANY assistant message had completed earlier in the
turn. A turn truncated mid-flow (hour-scale script or wait cut off by
the ceiling) therefore surfaced as a clean success carrying stale
narration text, and cron recorded last_status=ok for an incomplete run
(2026-08-18 premarket plan: news merge cut at the 4200s ceiling,
recorded ok, downstream plan consumed a nonexistent news terminal
state).

Track the last meaningful signal (text / tool_start / tool_done /
activity) and accept the fallback only when the assistant text is the
LAST thing codex produced — the original protocol-quirk case. Any
other trailing signal now yields the timeout error path (interrupt +
should_retire), with the last signal named in the error for diagnosis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@09473ZH
09473ZH requested a review from corgi-bot August 19, 2026 03:21
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@09473ZH

09473ZH commented Aug 19, 2026

Copy link
Copy Markdown
Author

保留本 PR 的权衡记录(供未来追溯)

它防的剩余暴露面(在 Harness#106 的 2h turn 上限 + 1800s post-tool quiet watchdog 之后依然存在):

  • watchdog 只约束"工具完成后静默",工具运行中(阻塞 wait_agent、长 exec)被 item/started 忙碌信号豁免。一个 turn 串多段长 wait/exec(单次 wait 上限 1h,可串多次)+ 中途发过任何叙述文本 → 撞 2h 上限 → 旧逻辑把中途文本当最终回复、终态记成功——即 2026-08-18 盘前 plan 事故的原始形状,概率降低但未消除。
  • 假成功的真实代价是不告警、不重试:终态 error 才会触发 cron 告警与恢复;假成功时下游(plan 消费链)安静地使用残缺状态。
  • turn 开始即僵死(无任何文本)的场景现有代码本就报诚实超时(接受分支要求 final_text 非空);本 PR 只收紧"有过中途文本"这一种。

不合它的合理理由(已评估)

  • fork 维护成本:codex_app_server_session.py 是 Harness 镜像 overlay 文件之一,本补丁加重上游同步时的 rebase 负担。对冲动作:同一修复已提交上游 NousResearch/hermes-agent(draft),上游合入后本补丁在下次同步时自动消失。
  • 产品层部分兜底:Harness#96 的 exactly-once 审计工件使 plan 链在消费端校验新闻终态,不全信 turn 成功;但审计工件只覆盖 plan 链,positions/review/intraday/交互会话仍依赖 turn 终态的诚实性,且调度层 last_status 的告警语义只能在此处修。

结论:合并本 PR,同步推动上游收编以消除 fork 负担。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant