Architecture C from expert panel review: add run_turn_to<W: Write>
that writes all output (spinners, markdown, compaction logs) to a
custom writer instead of hardcoding stdout.
In the TUI path, we pass a Vec<u8> buffer. Zero bytes hit the real
terminal during a turn, so nothing bleeds past the conversation pane
boundary into the dashboard. After the turn, the buffer contents are
stripped of ANSI codes and pushed into the conversation pane where
wrap_line() constrains them to the pane width.
Key changes:
- run_turn() is now a thin wrapper: run_turn_to(input, stdout, true)
- run_turn_to<W: Write>(input, out, emit_output) is the real impl
- All println! → writeln!(out, ...), &mut stdout → out
- emit_output=false in TUI mode prevents runtime tool-stream output
- Add strip_ansi() helper for cleaning captured buffer text
- Remove Clear(ClearType::All) from redraw_after_turn (no debris to wipe)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add 'mod tui;' to main.rs (was missing — TUI code was dead)
- Add /tui slash command that switches from the plain REPL to the
split-pane TUI mode at runtime
- Show startup hint: 'Tip: type /tui for the split-pane dashboard view'
- Add run_tui_repl() that manages the TuiApp event loop, captures
assistant output from the session, and feeds it to the conversation pane
- Add update_dashboard() helper that syncs runtime stats (model, session,
turns, provider) into the shared dashboard state
- ProviderSwap and TeamToggle work inside TUI mode
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three fixes for the rendering mess when output goes off-screen:
1. Word-wrap conversation pane lines — long output no longer bleeds
into the dashboard. The wrap_line() function soft-wraps at word
boundaries and hard-breaks long tokens. The viewport math is
updated to count *visual* rows (not logical Line items).
2. Dashboard kv() aligned columns — keys are right-padded to a
fixed 12-char column (KV_KEY_WIDTH) so values line up cleanly
regardless of key length.
3. Context gauge positioned by row tracking, not hard-coded y offset.
The gauge_row counter moves with the section content, so it stays
correct whether git_branch, LSP, or Team sections are shown/hidden.
Also switched dashboard Wrap to trim: false to preserve spacing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Split multi-line user input and system messages on newlines so each
visual line gets its own ConversationLine (same pattern push_output
already used). This fixes text misalignment when Enter is pressed.
- Don't enable Wrap on the conversation Paragraph — the FIFO viewport
counts Line items to fill the pane, so soft-wrapping would throw off
the row count and misalign content.
- Restore non-TUI files from upstream/main to clear conflict artifacts.
- Fix clippy warnings in lsp_client, lsp_process/parse, and trident.
- Add HandlerSwap and TeamToggle match arms in main.rs ReadOutcome.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>