@@ -3252,6 +3252,40 @@ describe("Telemetry installments (idle/shutdown flush)", () => {
32523252
32533253 expect ( captureTaskCompletedSpy ) . not . toHaveBeenCalled ( )
32543254 } )
3255+
3256+ it ( "does not re-flush when lastMessageTs is recent even after a prior flush" , ( ) => {
3257+ // Regression guard for the Math.max(lastMessageTs, lastTelemetryFlushAt) fix.
3258+ // Without it, once lastMessageTs is set it never advances after a flush, so
3259+ // the idle check would fire on every 5-minute tick for the rest of the task's
3260+ // life even with no new activity.
3261+ vi . useFakeTimers ( )
3262+ const task = createTask ( )
3263+ task . recordToolUsage ( "read_file" )
3264+
3265+ // First idle flush fires after 31 min.
3266+ vi . advanceTimersByTime ( 31 * 60 * 1000 )
3267+ expect ( captureTaskCompletedSpy ) . toHaveBeenCalledTimes ( 1 )
3268+ captureTaskCompletedSpy . mockClear ( )
3269+
3270+ // New activity arrives 1 min after the flush.
3271+ vi . advanceTimersByTime ( 1 * 60 * 1000 )
3272+ task . lastMessageTs = Date . now ( )
3273+ task . recordToolUsage ( "write_to_file" )
3274+
3275+ // Only 10 min since the new activity — should not flush again yet.
3276+ vi . advanceTimersByTime ( 10 * 60 * 1000 )
3277+ expect ( captureTaskCompletedSpy ) . not . toHaveBeenCalled ( )
3278+
3279+ // 35 min since the new activity (past the 30-min threshold and the next
3280+ // 5-min interval tick) — should flush the new delta now.
3281+ vi . advanceTimersByTime ( 25 * 60 * 1000 )
3282+ expect ( captureTaskCompletedSpy ) . toHaveBeenCalledWith (
3283+ task . taskId ,
3284+ { write_to_file : { attempts : 1 , failures : 0 } } ,
3285+ { user : 0 , assistant : 0 } ,
3286+ "idle" ,
3287+ )
3288+ } )
32553289 } )
32563290
32573291 describe ( "dispose" , ( ) => {
0 commit comments