From 7fef9197655a17258e85d183f946f98eabbbbdf8 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Wed, 10 Jun 2026 15:57:08 -0700 Subject: [PATCH] =?UTF-8?q?fix(tui):=20compact=20tool-call=20transcript=20?= =?UTF-8?q?rendering=20=E2=80=94=20suppress=20boilerplate=20(#3031)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three targeted changes to reduce low-value detail in the default compact/Live transcript view: 1. ExecCell: suppress "(no output)" line in Live mode. The success header already conveys the outcome; Transcript mode keeps it for exports/clipboard/pager. 2. ExecCell: suppress sub-second timing in Live mode. Calls under 1s show no timing line; Transcript mode always shows exact timing. 3. render_preserved_output_mode: suppress "(no output)" for empty output in Live mode. Same rationale — the header carries the signal. Full command text, complete output, and exact timing remain available in Transcript mode (pager, clipboard export, Alt+V detail view). --- crates/tui/src/tui/history.rs | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/crates/tui/src/tui/history.rs b/crates/tui/src/tui/history.rs index 9ca7fb54..08f461ce 100644 --- a/crates/tui/src/tui/history.rs +++ b/crates/tui/src/tui/history.rs @@ -961,7 +961,12 @@ impl ExecCell { Style::default().fg(palette::TEXT_MUTED), width, )); - } else if self.status != ToolStatus::Running { + } else if self.status != ToolStatus::Running + && mode == RenderMode::Transcript + { + // #3031: Suppress "(no output)" in compact/Live mode; + // the success header is enough signal. Transcript still + // records it for exports/clipboard/pager. lines.push(Line::from(Span::styled( " (no output)", Style::default().fg(palette::TEXT_MUTED).italic(), @@ -970,13 +975,17 @@ impl ExecCell { } if let Some(duration_ms) = self.duration_ms { - let seconds = f64::from(u32::try_from(duration_ms).unwrap_or(u32::MAX)) / 1000.0; - lines.extend(render_compact_kv( - "time", - &format!("{seconds:.2}s"), - Style::default().fg(palette::TEXT_DIM), - width, - )); + // #3031: Suppress sub-second timing in compact mode. + // Transcript mode always shows exact timing. + if mode == RenderMode::Transcript || duration_ms >= 1000 { + let seconds = f64::from(u32::try_from(duration_ms).unwrap_or(u32::MAX)) / 1000.0; + lines.extend(render_compact_kv( + "time", + &format!("{seconds:.2}s"), + Style::default().fg(palette::TEXT_DIM), + width, + )); + } } wrap_card_rail(lines) @@ -2840,10 +2849,15 @@ fn render_preserved_output_mode( ) -> Vec> { let mut lines = Vec::new(); if output.trim().is_empty() { - lines.push(Line::from(Span::styled( - " (no output)", - Style::default().fg(palette::TEXT_MUTED).italic(), - ))); + // #3031: In compact/Live mode, suppress "(no output)" — the tool + // header already carries the success/failure status. Transcript + // mode still records it for exports/clipboard/pager. + if mode == RenderMode::Transcript { + lines.push(Line::from(Span::styled( + " (no output)", + Style::default().fg(palette::TEXT_MUTED).italic(), + ))); + } return lines; }