@@ -192,20 +192,18 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
192192 auto b = body.find (kClose , a);
193193 if (b == std::string::npos) b = body.size ();
194194 out.kind = Kind::GitDiff;
195- // Frozen build keeps the full diff (show_all, painted
196- // once). In the live tail elide to a tail window so the
197- // per-frame split_lines stays O(window) for a large edit
198- // — same discipline as Write's terminal-but-not-frozen
199- // branch.
200- if (building_frozen ()) {
201- out.text = body.substr (a, b - a);
202- out.show_all = true ;
203- } else {
204- out.text = tail_window (
205- std::string_view{body}.substr (a, b - a),
206- kStreamTailLines );
207- out.show_all = false ;
208- }
195+ // Full diff as soon as the edit is terminal — in the live
196+ // tail too, not only the frozen snapshot. The output is
197+ // FINAL the instant the tool settles, so eliding to a
198+ // tail window here just to expand it one tick later (when
199+ // freeze_range rebuilds with show_all) is the visible
200+ // "diff squeezes, then pops to full size" lag. Per-frame
201+ // split_lines over a stable body for the one-or-two
202+ // frames before the freeze handoff is negligible, and the
203+ // frozen snapshot emits the same full body so the handoff
204+ // is seamless (no height jump).
205+ out.text = body.substr (a, b - a);
206+ out.show_all = true ;
209207 out.text_color = text_tertiary;
210208 return out;
211209 }
@@ -225,11 +223,14 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
225223 it != tc.args .end () && it->is_array () && !it->empty ())
226224 {
227225 out.kind = Kind::EditDiff;
228- // show_all only in the frozen snapshot. While streaming
229- // OR sitting in the live tail (re-rendered every frame)
230- // keep the elided per-side/per-hunk preview so the cost
231- // is bounded; the frozen card carries the full diff.
232- out.show_all = !streaming_now && building_frozen ();
226+ // Full diff as soon as the edit is terminal — in the live
227+ // tail too, not only the frozen snapshot. While STREAMING
228+ // keep the elided per-side/per-hunk preview (hunks grow
229+ // line-by-line, would balloon height every frame); once
230+ // settled the hunks are final, so expanding immediately
231+ // avoids the "stub then sudden expand" lag and matches
232+ // what freeze_range will build (seamless handoff).
233+ out.show_all = !streaming_now;
233234 out.is_streaming = streaming_now;
234235 out.hunks .reserve (it->size ());
235236 for (const auto & e : *it) {
@@ -246,7 +247,7 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
246247 if (nt.empty ()) nt = safe_arg (tc.args , " new_string" );
247248 if (!ot.empty () || !nt.empty ()) {
248249 out.kind = Kind::EditDiff;
249- out.show_all = !streaming_now && building_frozen () ;
250+ out.show_all = !streaming_now;
250251 out.is_streaming = streaming_now;
251252 out.hunks .push_back ({std::move (ot), std::move (nt)});
252253 }
@@ -324,15 +325,18 @@ maya::ToolBodyPreview::Config tool_body_preview_config(
324325 out.show_footer_stats = false ;
325326 } else if (!building_frozen ()) {
326327 // Terminal, but sitting in the LIVE tail (run not settled
327- // yet, re-rendered every frame). Elide to a window so the
328- // per-frame split_lines stays bounded; the FROZEN snapshot
329- // built by freeze_range keeps a generous head+tail (painted
330- // once, then blitted). Footer is dropped here too because
331- // its count would reflect the slice; the frozen card
332- // carries the true `N lines · KB`.
333- out.show_all = false ;
334- out.text = tail_window (content, kStreamTailLines );
335- out.show_footer_stats = false ;
328+ // yet, re-rendered every frame). The content is FINAL —
329+ // no more deltas arrive — so show it in full immediately
330+ // instead of waiting for the next Tick's
331+ // freeze_settled_subturns to graduate it into the frozen
332+ // prefix. Waiting caused a visible "card stays a stub for
333+ // a beat after the tool finished, then suddenly expands"
334+ // lag. Per-frame split_lines over a stable body for the
335+ // one-or-two frames before the freeze handoff is
336+ // negligible, and the frozen snapshot reuses the same
337+ // show_all body so the freeze instant is seamless (no
338+ // height pop).
339+ out.text = std::move (content);
336340 } else {
337341 out.text = std::move (content);
338342 }
0 commit comments