Summary
In a long TUI session, the final assistant response appeared twice in the transcript, with one copy directly above the other.
This was observed once and could not be reproduced afterward, including with copied long-session fixtures. The session data contains only one persisted copy of the assistant response, so the symptom appears to be presentation-only rather than session corruption or duplicate provider output.
Affected session
- Session ID:
daf7e5f695fb4c0ca3dd25ac52cff3ac
- Session name:
Vultr Serverless Document Ranking
- Tau version at observation:
0.2.3
- Assistant entry inspected:
88a84f137ace4b799d8c1b33e2e0e77e
The active branch projected to roughly 367 transcript items, exceeding the TUI's 200-item mounted window. The affected response contained both thinking and text blocks, so it used structured assistant finalization.
Observed behavior
The completed assistant response was visibly rendered twice in the transcript.
Expected behavior
Each completed assistant response should remain visible exactly once throughout streaming, finalization, redraws, and transcript-window paging.
Investigation
The durable JSONL contains the affected assistant response once. The normal session event pipeline also appears to yield one assistant MessageEndEvent.
One concrete transient was reproduced independently: TranscriptView._redraw() schedules remove_children() and immediately mounts replacement widgets. Textual prunes removed children asynchronously, so old and replacement rows can coexist in the DOM for a frame.
The relevant areas are:
src/tau_coding/tui/app.py: assistant MessageEndEvent handling and structured finalization
src/tau_coding/tui/widgets.py: TranscriptView._redraw() and finish_structured_assistant_message()
- Long-transcript windowing introduced in commit
4d7c9824
A duplicate assistant row was not reproduced by replaying a synthetic long transcript with thinking and text, nor while manually testing copied long sessions.
Direction tested
Draft PR #424 tried hiding stale transcript rows before Textual completed asynchronous pruning. The initial approach touched every mounted row and appeared to make long sessions less smooth. It was narrowed to the trailing visible boundary row, but the original reported symptom still could not be reproduced, so the PR was closed rather than merging an unvalidated workaround.
Suggested next steps
- Add temporary diagnostics around assistant finalization and transcript reconciliation:
- assistant message/event identity
- canonical
ChatItem identities
- mounted widget identities
- transcript window bounds
- active streaming widget identities
- Assert or log when multiple visible widgets represent the same canonical assistant item.
- Capture whether a full redraw, structured finalization, window shift, resize, or duplicate end event immediately preceded the symptom.
- Prefer an awaited or serialized DOM reconciliation if asynchronous pruning is confirmed as the cause, rather than applying visibility changes across the transcript window.
Reproduction status
Not currently reproducible. Keep this issue open for additional reports or diagnostics from a future occurrence.
Summary
In a long TUI session, the final assistant response appeared twice in the transcript, with one copy directly above the other.
This was observed once and could not be reproduced afterward, including with copied long-session fixtures. The session data contains only one persisted copy of the assistant response, so the symptom appears to be presentation-only rather than session corruption or duplicate provider output.
Affected session
daf7e5f695fb4c0ca3dd25ac52cff3acVultr Serverless Document Ranking0.2.388a84f137ace4b799d8c1b33e2e0e77eThe active branch projected to roughly 367 transcript items, exceeding the TUI's 200-item mounted window. The affected response contained both thinking and text blocks, so it used structured assistant finalization.
Observed behavior
The completed assistant response was visibly rendered twice in the transcript.
Expected behavior
Each completed assistant response should remain visible exactly once throughout streaming, finalization, redraws, and transcript-window paging.
Investigation
The durable JSONL contains the affected assistant response once. The normal session event pipeline also appears to yield one assistant
MessageEndEvent.One concrete transient was reproduced independently:
TranscriptView._redraw()schedulesremove_children()and immediately mounts replacement widgets. Textual prunes removed children asynchronously, so old and replacement rows can coexist in the DOM for a frame.The relevant areas are:
src/tau_coding/tui/app.py: assistantMessageEndEventhandling and structured finalizationsrc/tau_coding/tui/widgets.py:TranscriptView._redraw()andfinish_structured_assistant_message()4d7c9824A duplicate assistant row was not reproduced by replaying a synthetic long transcript with thinking and text, nor while manually testing copied long sessions.
Direction tested
Draft PR #424 tried hiding stale transcript rows before Textual completed asynchronous pruning. The initial approach touched every mounted row and appeared to make long sessions less smooth. It was narrowed to the trailing visible boundary row, but the original reported symptom still could not be reproduced, so the PR was closed rather than merging an unvalidated workaround.
Suggested next steps
ChatItemidentitiesReproduction status
Not currently reproducible. Keep this issue open for additional reports or diagnostics from a future occurrence.