Skip to content

fix(tui): start a forked turn at the fork's own prompt - #56080

Open
bercedev wants to merge 1 commit into
anomalyco:devfrom
bercedev:fix/fork-turn-duration
Open

bercedev wants to merge 1 commit into
anomalyco:devfrom
bercedev:fix/fork-turn-duration

Conversation

@bercedev

@bercedev bercedev commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Part of #55368 (the TUI case the bot reproduced)

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

A full-session fork made while the parent is still answering copies the waiting prompt with its original time.created (projectFork). The TUI footer times a turn from the first input after the previous idle marker (inputIndex in routes/session/rows.ts). In the fork, that is the copied prompt, so the first answer to a new question includes all the time the parent spent waiting.

turnDuration now takes the fork's creation time, and inputIndex stops walking back at an input older than the fork once it has found a newer one. Steers inside the fork still count from the fork's first prompt. Sessions that aren't forks don't pass the time, so imported sessions with old timestamps aren't affected.

I left the other case from the report alone: the fork answering the copied prompt itself, with no new prompt. The footer still times that from the copied prompt. Whether it should show compute-since-fork or wall-clock-since-asked is the open product question in the issue. The Web/Desktop timeline already gets the reproduced case right.

How did you verify your code works?

  • New test in packages/tui/test/cli/tui/session-rows.test.ts: a fork with a copied prompt, then a new prompt and a steer, times the answer from the new prompt; with only the copied prompt it still starts there. It fails on dev (Received: 7202000).
  • Ran the bot's steps in the real TUI (tmux, container with no network, a fake OpenAI chat server on 127.0.0.1 that holds the answer to the first question for 40s): ask, /fork → Full session while the turn is running, ask a new question in the fork.
    • dev: Build · m · 20.0s · 69.0 tok/s
    • This branch: Build · m · 42ms · 83.3 tok/s
  • bun test in packages/tui: 1489 pass, 3 fail. The 3 are the Node reloads the local ESM graph tests, which need node and fail in my container on clean dev as well.
  • tsgo -b in packages/tui is clean. Prettier is clean on the changed lines.

Screenshots / recordings

The fork after the new answer, this branch:

  ┃  OLD question asked before the fork
  ┃
  ┃  NEW question asked in the fork
  ┃
     Fork answer to the new question.
     Build · m · 42ms · 83.3 tok/s

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #55368

A full-session fork made while the parent is still answering copies the
waiting prompt with its original timestamp. The TUI footer starts a turn at
the first input after the last idle marker, so the first answer in the fork
was timed from that copied prompt and included the parent's wait.

Stop the walk back at an input older than the fork once a newer input has
been found. A turn made only of the copied prompt still starts there.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks right. I reproduced the inflated footer on the base with opencode-drive and the simulated model: I held the first answer, forked the full session while it was running and asked a new question in the fork. The footer showed 11.5s on the base and 33ms with this change. session-rows.test.ts passes and tsgo -b in packages/tui is clean.

The public API is unchanged: this only touches TUI internals (turnDuration gets an optional trailing parameter).

I found nothing that blocks a merge. Tokens per second adds up each step's own streaming time, so it isn't affected by the turn start. A fork answering only the copied prompt keeps its current timing, as described.

Related: #55368

Before

After

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant