fix(codex): derive terminal-idle watchdog from explicit run timeout - #85296
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 24, 2026, 3:38 PM ET / 19:38 UTC. Summary PR surface: Source +11, Tests +19. Total +30 across 3 files. Reproducibility: yes. at source level: current main and Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the focused runtime-budget fix if maintainers accept the split scope, and keep #85242 open for terminal-idle-specific timeout guidance. Do we have a high-confidence way to reproduce the issue? Yes at source level: current main and Is this the best way to solve the issue? Yes for the early-abort half: deriving the wrapper-owned watchdog from the effective run budget is narrower than adding a new config knob or upstream protocol field. The terminal-idle guidance remains a separate follow-up. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against fa6a9509bc95. Label changesLabel justifications:
Evidence reviewedPR surface: Source +11, Tests +19. Total +30 across 3 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
ClawSweeper PR egg ✨ Hatched: 🥚 common Neon Crabkin Hatch commandComment Hatchability rules:
Rarity: 🥚 common. What is this egg doing here?
|
|
This looks like the right narrow fix for the early-abort path: deriving the terminal-idle watchdog from the effective run timeout avoids cutting long scheduled Codex turns back to the internal 30m default. One remaining issue-scope question: #85242 also asks for terminal-idle-specific user guidance. If this PR is meant to fully close the issue, I think the timeout message should name the terminal-idle watchdog and the effective timeout that fired. Otherwise this can land as the runtime fix, with diagnostics tracked separately. |
|
Reviewed the diff and I agree with @ai-hpc's scope note: the runtime fix itself looks narrow and correct, but this should not fully close #85242 as-is. The PR derives So I would either:
|
6ebefb8 to
1f23f29
Compare
|
Thanks @ai-hpc @steipete for the review. Going with the second option: landing this as the focused runtime fix and tracking the diagnostics wording as a separate follow-up. Changes since the review:
Happy to open the diagnostics follow-up separately, or fold it in here if you'd prefer a single PR after all. |
|
@clawsweeper re-review The three failing checks are unrelated to this diff (which only touches extensions/codex/src/app-server: attempt-timeouts.ts, run-attempt.ts, and the colocated test). They are flaky/long-running shards in unrelated subsystems:
None touch the Codex app-server timeout code. Locally the focused suites pass (attempt-timeouts.test.ts and run-attempt.test.ts, Test Files 2 passed). A CI re-run should clear these. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
1f23f29 to
0408304
Compare
Fixes the early-abort half of openclaw#85242. The Codex app-server terminal-idle watchdog used a hardcoded 30-minute default that was not derived from the effective run timeout, so a scheduled turn configured with a longer timeoutSeconds could be aborted early at 30 minutes even with budget left. resolveCodexTurnTerminalIdleTimeoutMs (now in attempt-timeouts.ts after the upstream split) accepts the effective run timeout and, with no explicit override, follows the run budget instead of the 30-minute default: - explicit override always wins (advanced config / tests) - otherwise terminal-idle = max(30min floor, run budget), so a longer run is no longer cut short and existing protection is never shortened - falls back to the 30min default when no run budget is known Reuses the existing resolvePositiveIntegerTimeoutMs helper, matching the neighbouring post-tool resolver. Adds focused unit tests for the derivation. The diagnostic-wording half of openclaw#85242 (naming the terminal-idle watchdog in the surfaced guidance) is left as a separate follow-up.
7159768 to
0cc6afb
Compare
|
Land-ready at The reported bug is valid: an explicitly configured run timeout above 30 minutes could still be cut off by the Codex terminal-idle watchdog at 30 minutes. During review, the original patch was repaired so the watchdog follows only the explicit run-timeout override. Normal runs retain the 30-minute liveness guard, and explicit no-timeout remains bounded by the existing maximum idle watchdog. Evidence:
Direct Codex contract check:
Issue #85242 remains open because this PR fixes timeout behavior, not the broader diagnostic wording request. |
|
Merged via squash.
|
…penclaw#85296) * fix(codex): derive terminal-idle watchdog from effective run timeout Fixes the early-abort half of openclaw#85242. The Codex app-server terminal-idle watchdog used a hardcoded 30-minute default that was not derived from the effective run timeout, so a scheduled turn configured with a longer timeoutSeconds could be aborted early at 30 minutes even with budget left. resolveCodexTurnTerminalIdleTimeoutMs (now in attempt-timeouts.ts after the upstream split) accepts the effective run timeout and, with no explicit override, follows the run budget instead of the 30-minute default: - explicit override always wins (advanced config / tests) - otherwise terminal-idle = max(30min floor, run budget), so a longer run is no longer cut short and existing protection is never shortened - falls back to the 30min default when no run budget is known Reuses the existing resolvePositiveIntegerTimeoutMs helper, matching the neighbouring post-tool resolver. Adds focused unit tests for the derivation. The diagnostic-wording half of openclaw#85242 (naming the terminal-idle watchdog in the surfaced guidance) is left as a separate follow-up. * fix(codex): derive terminal-idle watchdog from effective run timeout * fix(codex): preserve default terminal idle watchdog --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#85296) * fix(codex): derive terminal-idle watchdog from effective run timeout Fixes the early-abort half of openclaw#85242. The Codex app-server terminal-idle watchdog used a hardcoded 30-minute default that was not derived from the effective run timeout, so a scheduled turn configured with a longer timeoutSeconds could be aborted early at 30 minutes even with budget left. resolveCodexTurnTerminalIdleTimeoutMs (now in attempt-timeouts.ts after the upstream split) accepts the effective run timeout and, with no explicit override, follows the run budget instead of the 30-minute default: - explicit override always wins (advanced config / tests) - otherwise terminal-idle = max(30min floor, run budget), so a longer run is no longer cut short and existing protection is never shortened - falls back to the 30min default when no run budget is known Reuses the existing resolvePositiveIntegerTimeoutMs helper, matching the neighbouring post-tool resolver. Adds focused unit tests for the derivation. The diagnostic-wording half of openclaw#85242 (naming the terminal-idle watchdog in the surfaced guidance) is left as a separate follow-up. * fix(codex): derive terminal-idle watchdog from effective run timeout * fix(codex): preserve default terminal idle watchdog --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#85296) * fix(codex): derive terminal-idle watchdog from effective run timeout Fixes the early-abort half of openclaw#85242. The Codex app-server terminal-idle watchdog used a hardcoded 30-minute default that was not derived from the effective run timeout, so a scheduled turn configured with a longer timeoutSeconds could be aborted early at 30 minutes even with budget left. resolveCodexTurnTerminalIdleTimeoutMs (now in attempt-timeouts.ts after the upstream split) accepts the effective run timeout and, with no explicit override, follows the run budget instead of the 30-minute default: - explicit override always wins (advanced config / tests) - otherwise terminal-idle = max(30min floor, run budget), so a longer run is no longer cut short and existing protection is never shortened - falls back to the 30min default when no run budget is known Reuses the existing resolvePositiveIntegerTimeoutMs helper, matching the neighbouring post-tool resolver. Adds focused unit tests for the derivation. The diagnostic-wording half of openclaw#85242 (naming the terminal-idle watchdog in the surfaced guidance) is left as a separate follow-up. * fix(codex): derive terminal-idle watchdog from effective run timeout * fix(codex): preserve default terminal idle watchdog --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commit 4076ba0)
…s not persisted The fork's fallback-no-persist gate (b8e4198) wrapped the whole finalizeCronRun persistence block, so a fallback run also skipped clearCliSession/setCliSessionId maintenance for the CLI provider that actually ran, leaving stale bindings to hijack the next CLI run. Upstream runs binding maintenance unconditionally (only aborted runs skip it); restore that shape and keep the no-persist gate narrowly around setSessionRuntimeModel/contextTokens. Fixes the base regression test 'clears stale CLI bindings when cron CLI replacement is unflushed' (failing on the branch since b8e4198; bisected). Also: repoint the openclaw#98356 test's getCliSessionBinding import to the 6.11 home (src/agents/cli-session.ts), fix three oxlint errors (promise-executor style in the openclaw#85296 test hunk; only-throw-error + no-shadow in the memory-lancedb failover port).
…penclaw#85296) * fix(codex): derive terminal-idle watchdog from effective run timeout Fixes the early-abort half of openclaw#85242. The Codex app-server terminal-idle watchdog used a hardcoded 30-minute default that was not derived from the effective run timeout, so a scheduled turn configured with a longer timeoutSeconds could be aborted early at 30 minutes even with budget left. resolveCodexTurnTerminalIdleTimeoutMs (now in attempt-timeouts.ts after the upstream split) accepts the effective run timeout and, with no explicit override, follows the run budget instead of the 30-minute default: - explicit override always wins (advanced config / tests) - otherwise terminal-idle = max(30min floor, run budget), so a longer run is no longer cut short and existing protection is never shortened - falls back to the 30min default when no run budget is known Reuses the existing resolvePositiveIntegerTimeoutMs helper, matching the neighbouring post-tool resolver. Adds focused unit tests for the derivation. The diagnostic-wording half of openclaw#85242 (naming the terminal-idle watchdog in the surfaced guidance) is left as a separate follow-up. * fix(codex): derive terminal-idle watchdog from effective run timeout * fix(codex): preserve default terminal idle watchdog --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commit 4076ba0)
…s not persisted The fork's fallback-no-persist gate (b8e4198) wrapped the whole finalizeCronRun persistence block, so a fallback run also skipped clearCliSession/setCliSessionId maintenance for the CLI provider that actually ran, leaving stale bindings to hijack the next CLI run. Upstream runs binding maintenance unconditionally (only aborted runs skip it); restore that shape and keep the no-persist gate narrowly around setSessionRuntimeModel/contextTokens. Fixes the base regression test 'clears stale CLI bindings when cron CLI replacement is unflushed' (failing on the branch since b8e4198; bisected). Also: repoint the openclaw#98356 test's getCliSessionBinding import to the 6.11 home (src/agents/cli-session.ts), fix three oxlint errors (promise-executor style in the openclaw#85296 test hunk; only-throw-error + no-shadow in the memory-lancedb failover port). (cherry picked from commit a01b392)
Summary
Refs #85242. Derives the Codex app-server terminal-idle watchdog from an explicit per-run timeout instead of always using the hardcoded 30-minute default.
This addresses the early-abort half of #85242 as a focused runtime fix. The diagnostic-wording half (naming the terminal-idle watchdog and its effective timeout in surfaced guidance) remains a separate follow-up, so this PR uses
Refsrather thanFixes.The resolver lives in
attempt-timeouts.ts. The call site passesparams.runTimeoutOverrideMs, the existing prepared signal for a deliberate cron/CLI timeout, rather thanparams.timeoutMs, which also carries the implicit 48-hour agent default.Real behavior proof
Before this patch, a scheduled Codex turn with an explicit timeout above 30 minutes could still be aborted by the 30-minute terminal-idle watchdog.
After the maintainer repair:
Focused proof on the real resolver and run-attempt call path:
node scripts/run-vitest.mjs extensions/codex/src/app-server/attempt-timeouts.test.ts extensions/codex/src/app-server/run-attempt.turn-watches.test.ts-> 72 passedtbx_01kwej31e1mn30y1ahjqb23pbz:corepack pnpm check:changed-> passedoxfmt --checkon the three changed files -> cleanA live 30- or 45-minute scheduled turn was not waited out end to end; timer selection is exercised through the production resolver and the real
runCodexAppServerAttemptpath. The diagnostic-wording half of #85242 remains intentionally out of scope.