Skip to content

fix(tui): wrap ask_user transcript trace so it can't clip chat history#130

Merged
Fullstop000 merged 2 commits into
masterfrom
worktree-fix-askuser-transcript-wrap
Jun 5, 2026
Merged

fix(tui): wrap ask_user transcript trace so it can't clip chat history#130
Fullstop000 merged 2 commits into
masterfrom
worktree-fix-askuser-transcript-wrap

Conversation

@Fullstop000
Copy link
Copy Markdown
Owner

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_transcript slices the transcript one logical Line per visible row and renders with Wrap { trim: false }. That contract holds only because block_lines pre-wraps every block to the terminal width via wrap_line.

The ask_user branch was the one exception: it did lines.extend(ask_user_resume_trace(entry)) and returned without wrap_line. ask_user_resume_trace packs the full untruncated question and answer into a single Line, 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_user trace through wrap_line like 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 real block_lines → transcript → render_transcript path on a TestBackend and asserts the newest line isn't clipped.

Both verified to fail without the fix and pass with it.

Dogfood

Real-binary /resume comparison (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

@Fullstop000
Copy link
Copy Markdown
Owner Author

Dogfood — real binary, before/after

Built the pre-fix (origin/master) and fixed binaries, crafted a session with a long ask_user question, and resumed it via /resume at cols=72 rows=12 (transcript tighter than content, so auto-follow pins to the bottom). Captured the actual terminal grid with pyte.

Notice (the newest line) visibility across sizes (cols=72):

rows OLD (pre-fix) NEW (fixed)
9 shown shown
10 CLIPPED shown
11 CLIPPED shown
12 CLIPPED shown
13 CLIPPED shown
14 CLIPPED shown

OLD (pre-fix) — newest "Resumed session" line missing (covered by band); wrapped rows ragged at col 0:

  ✓ ask_user · PR #127 green. Two feat: commits since v0.34.0. Add to
[Unreleased], or bump to v0.35.0 and cut a release?: Bump to v0.35.0 and
cut a release now

  ZZZ_NEWEST_REPLY: cutting v0.35.0
                                          <- "Resumed session" notice clipped here
┌ > ───────────────────────────────────────────────────────────────────┐

NEW (fixed) — newest line visible; continuation rows indented under the marker:

  ✓ ask_user · PR #127 green. Two feat: commits since v0.34.0. Add to
  [Unreleased], or bump to v0.35.0 and cut a release?: Bump to v0.35.0
  and cut a release now

  ZZZ_NEWEST_REPLY: cutting v0.35.0

  Resumed session  session-…-shipverify .
┌ > ───────────────────────────────────────────────────────────────────┐

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jun 5, 2026

Codecov Report

❌ Patch coverage is 98.11321% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.94%. Comparing base (126dcfa) to head (e35bd9a).

Files with missing lines Patch % Lines
ignis/src/console/render/blocks.rs 97.05% 2 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Fullstop000
Copy link
Copy Markdown
Owner Author

Follow-up: folded in the CJK / space-less wrap fix

Review flagged (and I confirmed empirically) that wrap_line only broke on ASCII spaces, so a space-less run wider than a row — CJK text, a long URL — stayed over-width and still clipped the newest transcript line. Since that's the bilingual ask_user case, I folded the fix into this PR: wrap_line now hard-breaks an over-width word at the display-column boundary, so the "every committed line ≤ width" invariant holds for all block types.

Verified on the real binary (/resume, pure space-less Chinese question, cols=72 rows=12) — before this commit the newest line was clipped and continuation rows were ragged at column 0; after, continuation rows are indented and the newest line shows:

  否能够在没有空格的情况下正确地按显示宽度断行否则最新的聊天记录就会被底
  部状态栏遮挡住:
  升级到下一个版本并且立即发布一个全新的正式版本不要再等待了

  最新回复哨兵SENTINEL

  Resumed session  session-…-cjk2 .
┌ > ───────────────────────────────────────────────────────────────────┐

New test: wrap_line_hard_breaks_spaceless_run. Per your call, holding under [Unreleased] (no version bump).

@Fullstop000 Fullstop000 closed this Jun 5, 2026
@Fullstop000 Fullstop000 reopened this Jun 5, 2026
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.
@Fullstop000 Fullstop000 force-pushed the worktree-fix-askuser-transcript-wrap branch from db38334 to e35bd9a Compare June 5, 2026 10:49
@Fullstop000 Fullstop000 merged commit 3d79e61 into master Jun 5, 2026
4 checks passed
@Fullstop000 Fullstop000 deleted the worktree-fix-askuser-transcript-wrap branch June 5, 2026 10:55
Fullstop000 added a commit that referenced this pull request Jun 6, 2026
#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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants