@@ -264,13 +264,19 @@ impl CaptureDisplayEntry {
264264 fn with_file_stats ( capture : & Capture , manager : & CaptureManager ) -> Result < Self > {
265265 let mut entry = Self :: try_from ( capture) ?;
266266
267- if let Some ( stats) = manager. file_changes . get ( & capture. tag ) {
267+ // Prefer cached stats; if absent, compute on the fly (no mutation of manager needed).
268+ let stats_opt = manager
269+ . file_changes
270+ . get ( & capture. tag )
271+ . cloned ( )
272+ . or_else ( || manager. get_file_changes ( & capture. tag ) . ok ( ) ) ;
273+
274+ if let Some ( stats) = stats_opt. as_ref ( ) {
268275 let stats_str = format_file_stats ( stats) ;
269276 if !stats_str. is_empty ( ) {
270277 entry. display_parts . push ( format ! ( " ({})" , stats_str) . dark_grey ( ) ) ;
271278 }
272279 }
273-
274280 Ok ( entry)
275281 }
276282}
@@ -336,29 +342,50 @@ fn expand_capture(manager: &CaptureManager, output: &mut impl Write, tag: String
336342 } ,
337343 } ;
338344 let capture = & manager. captures [ * capture_index] ;
339- let display_entry = CaptureDisplayEntry :: with_file_stats ( capture, manager) ?;
345+ // Turn header: do NOT show file stats here
346+ let display_entry = CaptureDisplayEntry :: try_from ( capture) ?;
340347 execute ! ( output, style:: Print ( display_entry) , style:: Print ( "\n " ) ) ?;
341348
342349 // If the user tries to expand a tool-level checkpoint, return early
343350 if !capture. is_turn {
344351 return Ok ( ( ) ) ;
345352 } else {
346- let mut display_vec = Vec :: new ( ) ;
353+ // Collect tool-level entries with their indices so we can diff against the previous capture.
354+ let mut items: Vec < ( usize , CaptureDisplayEntry ) > = Vec :: new ( ) ;
347355 for i in ( 0 ..* capture_index) . rev ( ) {
348- let capture = & manager. captures [ i] ;
349- if capture . is_turn {
356+ let c = & manager. captures [ i] ;
357+ if c . is_turn {
350358 break ;
351359 }
352- display_vec . push ( CaptureDisplayEntry :: with_file_stats ( & manager . captures [ i ] , manager ) ? ) ;
360+ items . push ( ( i , CaptureDisplayEntry :: try_from ( c ) ? ) ) ;
353361 }
354362
355- for entry in display_vec. iter ( ) . rev ( ) {
356- execute ! (
357- output,
358- style:: Print ( " └─ " . blue( ) ) ,
359- style:: Print ( entry) ,
360- style:: Print ( "\n " )
361- ) ?;
363+ for ( idx, entry) in items. iter ( ) . rev ( ) {
364+ // previous capture in creation order (or itself if 0)
365+ let base_idx = idx. saturating_sub ( 1 ) ;
366+ let base_tag = & manager. captures [ base_idx] . tag ;
367+ let curr_tag = & manager. captures [ * idx] . tag ;
368+ // compute stats between previous capture -> this tool capture
369+ let badge = manager
370+ . get_file_changes_between ( base_tag, curr_tag)
371+ . map_or_else ( |_| String :: new ( ) , |s| format_file_stats ( & s) ) ;
372+
373+ if badge. is_empty ( ) {
374+ execute ! (
375+ output,
376+ style:: Print ( " └─ " . blue( ) ) ,
377+ style:: Print ( entry) ,
378+ style:: Print ( "\n " )
379+ ) ?;
380+ } else {
381+ execute ! (
382+ output,
383+ style:: Print ( " └─ " . blue( ) ) ,
384+ style:: Print ( entry) ,
385+ style:: Print ( format!( " ({})" , badge) . dark_grey( ) ) ,
386+ style:: Print ( "\n " )
387+ ) ?;
388+ }
362389 }
363390 }
364391
0 commit comments