Metadata
| Status | done |
|---|---|
| Assigned | agent-1117 |
| Agent identity | f51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e |
| Created | 2026-04-29T15:18:09.049685662+00:00 |
| Started | 2026-04-29T15:18:38.829164276+00:00 |
| Completed | 2026-04-29T15:58:37.670968473+00:00 |
| Tags | priority-high,bug,tui,pty,regression, eval-scheduled |
| Eval score | 0.79 |
| └ blocking impact | 0.85 |
| └ completeness | 0.80 |
| └ constraint fidelity | 0.70 |
| └ coordination overhead | 0.85 |
| └ correctness | 0.80 |
| └ downstream usability | 0.78 |
| └ efficiency | 0.85 |
| └ intent fidelity | 0.64 |
| └ style adherence | 0.85 |
Description
Description
Regression report from user 2026-04-29 afternoon. Codex chat in wg TUI:
- Real-time animations don't render — spinners / 'thinking...' indicators that worked a few commits ago no longer animate
- Scrolling up repeats the animation text — scrollback contains stacked copies of what should have been transient cursor-overwrite frames
User quote: 'codex chat is shitting the bed. it was fine before but scrollback didn't work. now it doesn't really show realtime animations as it used to a few commits ago? ugh. and then scrolling up is repeating the animation text???'
Likely root cause
Both symptoms = the same bug. Codex emits transient spinners using cursor-overwrite sequences (\r, cursor-up + line-clear, sometimes alt-screen). A correct terminal renders these in-place — the same line gets repainted, the OLD content does NOT enter scrollback.
The current behavior suggests our PTY emulator is treating each animation frame as a NEW row and pushing prior frames into scrollback. Visible effects:
- Live: instead of one animating spinner, you see nothing or a stale frame because subsequent frames go below into scrollback (off-screen if the row falls below the viewport)
- Scrolling: every frame is preserved as a separate scrollback row
Likely culprit commits (regression candidates)
Bisect against:
- ab96a82fd (fix-codex-agent) — explicitly touched codex stream-event parsing in chat tab. May have changed how cursor-overwrite sequences are interpreted.
- e18de347c (fix-pty-scrollback) — initial-render duplication fix. May have changed the scrollback-append logic such that transient lines are no longer recognized.
- 2e11648ab (fix-wg-tui) — CPU fix. May have changed render cadence / event-driven flow such that animation frames are batched into scrollback append.
git log --oneline -10 -- src/tui/ should narrow this. Use bisect if needed.
Repro
pkill -f "wg tui" && wg tui(fresh process on current binary)- Open or create a codex chat
- Send any prompt that triggers codex to show its 'thinking' spinner (e.g. ask it a substantive question)
- Observe: spinner doesn't animate visibly (Bug 1)
- Wait for response, then scroll up through the chat
- Observe: scrollback contains stacked frames of what should have been a single in-place spinner (Bug 2)
Compare against: codex invoked directly in a normal terminal (without wg TUI). Spinner animates in-place; scrollback is clean.
Investigation steps
- Confirm regression range with git bisect against the user's repro
- Identify the change in the suspect commit that broke cursor-overwrite handling
- Ground-truth check: does our PTY emulator correctly handle:
- \r (carriage return without newline → return cursor to column 0, do NOT scroll)
- \x1b[A (cursor up)
- \x1b[2K (erase line)
- DEC mode 2026 (codex's batched-render synchronization protocol)
- Compare with native
codexCLI byte capture (the diagnose-scrollback-corruption task already produced /tmp/codex-tui-long.bin — reuse it)
Validation
- Failing test written first (TDD): replay codex's spinner-emitting byte sequence into the chat-tab emulator; assert the rendered scrollback has ONE spinner line, not N=frames
- Live smoke: open codex chat, ask a substantive question, observe spinner animates in-place; scroll back, observe scrollback contains the response (not stacked spinner frames)
- No regression of fix-pty-scrollback / fix-tui-pty / fix-codex-agent original repros — verify those repros still pass
- If git bisect points at one specific commit, the fix should preserve that commit's intent while restoring cursor-overwrite handling
- cargo build + cargo test pass
- Permanent smoke scenario added: replay a known cursor-overwrite byte stream, assert the resulting cell grid + scrollback are correct (no stacked frames)
- cargo install --path . was run before claiming done
Process note
This is the FIFTH PTY-related fix in 24 hours (fix-tui-pty, fix-pty-scrollback, fix-codex-agent, fix-scrollback-reflow, and now this). The recurring pattern strongly suggests our home-rolled PTY emulator is fighting state it shouldn't be tracking by hand. If this regression turns out to be hard to isolate cleanly, escalate by reopening the architectural reset path (replace-custom-pty was abandoned earlier; reopen it) — switching to alacritty_terminal or wezterm-term solves this entire class of bugs once.
Depends on
Required by
- (none)
Log
- 2026-04-29T15:18:09.035913226+00:00 Task paused
- 2026-04-29T15:18:18.686059964+00:00 Task published
- 2026-04-29T15:18:37.302082687+00:00 Lightweight assignment: agent=Careful Programmer (f5143935), exec_mode=full, context_scope=task, reason=Careful Programmer best matches this PTY regression investigation and fix—requires thorough debugging (git bisect, cursor-overwrite analysis), precision in critical infrastructure (PTY emulator), and rigorous validation against multiple smoke scenarios; 'Careful' tradeoff aligns with the task's need for extensive testing and no regressions after 5 PTY fixes in 24h.
- 2026-04-29T15:18:38.829167142+00:00 Spawned by coordinator --executor claude --model opus
- 2026-04-29T15:18:51.850531629+00:00 Starting investigation - looking at PTY emulator and recent codex changes
- 2026-04-29T15:21:58.277677851+00:00 Reviewing reflow logic in pty_pane.rs - reflow_parser captures rows + wrapped flags, but loses scrolling region, alt-screen, mode state, cursor pos
- 2026-04-29T15:34:18.070755759+00:00 Identified two bugs: (1) chat_pty_mode missing redraw trigger when no input - animations stall at refresh_interval=1Hz; (2) codex sync-mode repaints can scroll content into scrollback when last row triggers \r\n scroll. Will now write TDD tests and fixes.
- 2026-04-29T15:53:44.178689228+00:00 Implementation complete: (1) chat_pty_has_new_bytes() + watermark wired into has_timed_ui_elements; (2) BSU/ESU sync-mode tracking + reflow-based scrollback trim. 54 pty_pane tests pass, 5 new redraw-trigger tests pass, full 3201 test suite green. Smoke scenario added to manifest.
- 2026-04-29T15:57:52.991099927+00:00 Validated: 3202 tests pass (was 3201). New tests cover (a) sync-mode scrollback trim correctness, (b) chat_pty_has_new_bytes redraw signal, (c) end-to-end PTY child running fake codex spinner. Also live-confirmed via standalone reproducer that unmodified vt100 stacks 10 rows for 10 frames; with the trim the bug-shape doesn't manifest.
- 2026-04-29T15:58:29.953735946+00:00 Committed: 88c1851dc — pushed to remote
- 2026-04-29T15:58:37.670975286+00:00 Task pending eval (agent reported done; awaiting `.evaluate-*` to score)
- 2026-04-29T16:01:12.097184793+00:00 PendingEval → Done (evaluator passed; downstream unblocks)