fix(tui): wrap ask_user transcript trace so it can't clip chat history#130
Conversation
Dogfood — real binary, before/afterBuilt the pre-fix ( Notice (the newest line) visibility across sizes (cols=72):
OLD (pre-fix) — newest "Resumed session" line missing (covered by band); wrapped rows ragged at col 0: NEW (fixed) — newest line visible; continuation rows indented under the marker: |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #130 +/- ##
==========================================
+ Coverage 76.62% 76.94% +0.31%
==========================================
Files 66 66
Lines 17575 17671 +96
==========================================
+ Hits 13467 13597 +130
+ Misses 4108 4074 -34 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Follow-up: folded in the CJK / space-less wrap fixReview flagged (and I confirmed empirically) that Verified on the real binary ( New test: |
The ask_user resume trace packed the full question + answer into one Line and bypassed wrap_line, unlike every other block. render_transcript slices one logical line per row but renders with Wrap, so an over-wide trace line re-wrapped at render and pushed the newest rows off the bottom — the running status band appeared to cover the chat history. Route the trace through wrap_line like the other blocks.
wrap_line only broke on ASCII spaces, so a space-less run wider than the row (CJK text, a long URL) stayed over-width, re-wrapped at render, and clipped the transcript — the same bug for bilingual ask_user questions. Hard-break such runs at the column boundary so the "every line <= width" invariant holds for all blocks. Add the [Unreleased] changelog entry.
db38334 to
e35bd9a
Compare
#130 added a regression test asserting an over-wide ask_user trace stays visible via the old transcript auto-follow render path, which inline rendering removed. Re-target the same regression at the inline path: block_lines must hard-break over-wide words so every row fits the width (insert_before blits rows verbatim, so an over-width row would be truncated).
Problem
While the agent is running, the status band at the bottom appeared to cover the newest chat-stream history — the freshest transcript lines vanished at the boundary with the status bar.
Root cause
render_transcriptslices the transcript one logicalLineper visible row and renders withWrap { trim: false }. That contract holds only becauseblock_linespre-wraps every block to the terminal width viawrap_line.The
ask_userbranch was the one exception: it didlines.extend(ask_user_resume_trace(entry))and returned withoutwrap_line.ask_user_resume_tracepacks the full untruncated question and answer into a singleLine, so a normal one-sentence question produces a line far wider than the terminal. That one logical line re-wraps into several rows at render time while still being counted as a single row — the slice then renders taller than the area, ratatui clips the bottom, and the newest lines disappear behind the band.Measured: that trace line was 156 cols on a 40-col terminal.
Fix
Route the
ask_usertrace throughwrap_linelike every other block type, restoring the "every committed line ≤ width" invariant. Bonus: wrapped continuation rows are now correctly indented instead of ragged at column 0.Tests
ask_user_trace_lines_fit_width— pins the width invariant.long_ask_user_trace_keeps_newest_line_visible— drives the realblock_lines → transcript → render_transcriptpath on aTestBackendand asserts the newest line isn't clipped.Both verified to fail without the fix and pass with it.
Dogfood
Real-binary
/resumecomparison (old vs new, cols=72 rows=12): the old binary clips the newest line behind the status band; the fixed binary shows it. Screenshots in a comment below.Gates
cargo fmt --check✓ ·cargo clippy -D warnings✓ ·cargo test --workspace(588) ✓ ·cargo build --release✓