codex - 💡(How to fix) Fix TUI loses or misreports the active turn timer after state replay/restore [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#19984Fetched 2026-04-29 06:24:11
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
0
Timeline (top)
labeled ×4commented ×2unlabeled ×1

Root Cause

This works because it separates the durable turn lifecycle state from the transient UI widget state. The status widget becomes a renderer of the active turn timer rather than the owner of the timer. Replaying or restoring UI state can replace the widget, but it no longer changes the underlying turn start time. Completing a turn also becomes deterministic because the separator can use the server/core-reported completed duration when it exists.

RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

0.125.0

What subscription do you have?

Plus

Which model were you using?

No response

What platform is your computer?

Linux

What terminal emulator and version are you using (if applicable)?

No response

What issue are you seeing?

In the TUI, the elapsed "working" timer for an active assistant turn can be reset, lost, or reported incorrectly when the UI restores input/thread state or replays turn events.

The visible symptom is that the status timer and the final "Worked for ..." separator are not consistently based on the original turn start time. In some flows, the UI falls back to the current status widget elapsed value, so restoring/replaying state can make the elapsed time appear shorter than the actual active turn duration, or omit useful elapsed-time information from the separator.

The underlying issue appears to be that the TUI treats the bottom-pane status widget's local timer state as the source of truth. That widget can be reconstructed or refreshed as part of normal UI state handling, so its local elapsed value is not stable enough to represent the lifetime of the active turn.

The active turn itself already has a more durable lifecycle: turn-start notifications can carry a start timestamp, and turn-complete notifications can carry the completed duration. The TUI should use those turn lifecycle values as the source of truth, then render them through the status widget, instead of deriving turn duration from whichever status widget instance is currently mounted.

What steps can reproduce the bug?

One way to reproduce is to start a Codex CLI turn that remains active long enough for the status timer to advance, then trigger a path that restores or replays TUI state while that turn is still in progress, such as resuming/replaying thread state or switching through UI state that reconstructs the bottom pane.

After the restore/replay, observe the active status timer and the final separator inserted when the turn completes. The elapsed time can be based on the reconstructed widget state instead of the original turn start timestamp.

I validated the fix direction locally. The implementation area is the TUI turn lifecycle and status rendering path, specifically:

  • The chat widget should store the active turn's start time as turn state, independent from the bottom-pane status widget.
  • When a turn-start event is received, the TUI should derive the local monotonic start instant from the event's start timestamp when available, and fall back to the current instant only when no timestamp is provided.
  • When thread/input state is captured and restored, the active turn start time should be included with the restored TUI state, so reconstructing the bottom pane does not reset the timer.
  • When the bottom-pane status indicator is recreated or refreshed while a turn is still running, it should receive the preserved start time and continue rendering elapsed time from that original start point.
  • When a turn completes, the final "Worked for ..." separator should prefer the completed turn duration from the turn-complete notification. If that duration is unavailable, it can fall back to elapsed time calculated from the preserved active turn start time.
  • Any separator baseline used to avoid double-counting work across streamed/final message boundaries should be preserved with the same input state, so elapsed-time deltas remain correct after restore.

This works because it separates the durable turn lifecycle state from the transient UI widget state. The status widget becomes a renderer of the active turn timer rather than the owner of the timer. Replaying or restoring UI state can replace the widget, but it no longer changes the underlying turn start time. Completing a turn also becomes deterministic because the separator can use the server/core-reported completed duration when it exists.

With that approach, the timer survives TUI state restore/replay and the final elapsed-time separator reflects the actual turn duration instead of the reconstructed widget's local elapsed value.

What is the expected behavior?

The TUI should preserve the active turn's original start time across restore/replay paths. The status timer should continue from the original start time, and the final "Worked for ..." separator should use the actual completed turn duration when that duration is available.

Additional information

A related display detail is that short completed turns should still be allowed to show elapsed-time information in the final separator. For example, a completed turn with a duration such as 12 seconds can show Worked for 12s instead of suppressing the elapsed-time label. That makes the behavior easier to verify and keeps short turn summaries consistent with longer ones.

No generated source code is included in this report. The intent is to describe the bug, the affected TUI state ownership, and the validated fix direction.

This report was completed with assistance from Codex CLI.

extent analysis

TL;DR

The TUI should use the active turn's start time and completed duration from turn notifications as the source of truth for the elapsed timer and final separator, instead of relying on the bottom-pane status widget's local timer state.

Guidance

  • Store the active turn's start time as turn state, independent from the bottom-pane status widget, to ensure it survives TUI state restore/replay.
  • When a turn-start event is received, derive the local monotonic start instant from the event's start timestamp, and fall back to the current instant only when no timestamp is provided.
  • Include the active turn start time with the restored TUI state when thread/input state is captured and restored, to prevent the timer from resetting.
  • Use the preserved start time to continue rendering elapsed time from the original start point when the bottom-pane status indicator is recreated or refreshed while a turn is still running.

Example

No code example is provided as the issue does not include specific code snippets, but the above guidance points should be implemented in the TUI turn lifecycle and status rendering path.

Notes

The proposed fix direction has been validated locally, and it separates the durable turn lifecycle state from the transient UI widget state, making the status widget a renderer of the active turn timer rather than the owner of the timer.

Recommendation

Apply the workaround by implementing the proposed fix direction, which uses the active turn's start time and completed duration from turn notifications as the source of truth for the elapsed timer and final separator, to ensure accurate and consistent timing information.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix TUI loses or misreports the active turn timer after state replay/restore [2 comments, 2 participants]