@@ -173,6 +173,51 @@ describe("agentsChromeNeedsSticky / linger", () => {
173173 expect ( agentsChromeNeedsSticky ( undefined , NOW ) ) . toBe ( false ) ;
174174 expect ( agentsChromeNeedsSticky ( [ ] , NOW ) ) . toBe ( false ) ;
175175 } ) ;
176+
177+ test ( "interrupted running inside linger is sticky with interrupted tail, not cancelled or cream-live" , ( ) => {
178+ const session = {
179+ agentId : "a" ,
180+ description : "looping" ,
181+ status : "running" as const ,
182+ lifecycleStatus : "interrupted" as const ,
183+ currentToolName : "run_shell" ,
184+ currentToolPreview : "bun test" ,
185+ currentToolStartedAt : NOW - 2_000 ,
186+ startedAt : NOW - 10_000 ,
187+ lastActivityAt : NOW - 2_000 ,
188+ finishedAt : NOW - 1_000 ,
189+ } ;
190+ expect ( agentIsLingering ( session , NOW ) ) . toBe ( true ) ;
191+ expect ( agentsChromeNeedsSticky ( [ session ] , NOW ) ) . toBe ( true ) ;
192+ const rows = formatAgentsPanel ( [ session ] , undefined , NOW ) ;
193+ expect ( rows ) . toEqual ( [
194+ {
195+ label : "● a looping" ,
196+ tail : " · interrupted · bun test still running" ,
197+ stalled : false ,
198+ kind : "lane" ,
199+ status : "interrupted" ,
200+ } ,
201+ ] ) ;
202+ } ) ;
203+
204+ test ( "interrupted running past linger drops even though status stays running" , ( ) => {
205+ const session = {
206+ agentId : "a" ,
207+ description : "looping" ,
208+ status : "running" as const ,
209+ lifecycleStatus : "interrupted" as const ,
210+ currentToolName : "run_shell" ,
211+ currentToolPreview : "bun test" ,
212+ currentToolStartedAt : NOW - 2_000 ,
213+ startedAt : NOW - 10_000 ,
214+ lastActivityAt : NOW - 2_000 ,
215+ finishedAt : NOW - AGENTS_PANEL_LINGER_MS ,
216+ } ;
217+ expect ( agentIsLingering ( session , NOW ) ) . toBe ( false ) ;
218+ expect ( agentsChromeNeedsSticky ( [ session ] , NOW ) ) . toBe ( false ) ;
219+ expect ( formatAgentsPanel ( [ session ] , undefined , NOW ) ) . toBeNull ( ) ;
220+ } ) ;
176221} ) ;
177222
178223describe ( "formatTasksPanel" , ( ) => {
@@ -325,6 +370,69 @@ describe("formatAgentsPanel", () => {
325370 ) . toBeNull ( ) ;
326371 } ) ;
327372
373+ test ( "interrupted linger ranks with terminals, newest finishedAt first" , ( ) => {
374+ const rows = formatAgentsPanel (
375+ [
376+ {
377+ agentId : "live" ,
378+ description : "still going" ,
379+ status : "running" ,
380+ currentToolStartedAt : null ,
381+ startedAt : NOW - 1_000 ,
382+ lastActivityAt : NOW ,
383+ } ,
384+ {
385+ agentId : "done" ,
386+ description : "finished" ,
387+ status : "done" ,
388+ currentToolStartedAt : null ,
389+ finishedAt : NOW - 2_000 ,
390+ } ,
391+ {
392+ agentId : "stopped" ,
393+ description : "cut short" ,
394+ status : "running" ,
395+ lifecycleStatus : "interrupted" ,
396+ currentToolStartedAt : null ,
397+ startedAt : NOW - 5_000 ,
398+ lastActivityAt : NOW - 500 ,
399+ finishedAt : NOW - 500 ,
400+ } ,
401+ ] ,
402+ undefined ,
403+ NOW ,
404+ ) ;
405+ expect ( rows ?. map ( ( r ) => r . status ) ) . toEqual ( [ "running" , "interrupted" , "done" ] ) ;
406+ expect ( rows ?. [ 1 ] ?. tail ) . toBe ( " · interrupted" ) ;
407+ } ) ;
408+
409+ test ( "cancelled linger with lifecycle interrupted paints cancelled, not interrupted" , ( ) => {
410+ const session = {
411+ agentId : "a" ,
412+ description : "cut short" ,
413+ status : "cancelled" as const ,
414+ lifecycleStatus : "interrupted" as const ,
415+ currentToolName : "run_shell" ,
416+ currentToolPreview : "bun test" ,
417+ currentToolStartedAt : NOW - 2_000 ,
418+ startedAt : NOW - 10_000 ,
419+ lastActivityAt : NOW - 2_000 ,
420+ finishedAt : NOW - 1_000 ,
421+ } ;
422+ expect ( agentIsLingering ( session , NOW ) ) . toBe ( true ) ;
423+ expect ( agentsChromeNeedsSticky ( [ session ] , NOW ) ) . toBe ( true ) ;
424+ const rows = formatAgentsPanel ( [ session ] , undefined , NOW ) ;
425+ expect ( rows ) . toEqual ( [
426+ {
427+ label : "● a cut short" ,
428+ tail : " · cancelled" ,
429+ stalled : false ,
430+ kind : "lane" ,
431+ status : "cancelled" ,
432+ } ,
433+ ] ) ;
434+ } ) ;
435+
328436 test ( "a stalled lane uses ! marker and reports silence via the clock" , ( ) => {
329437 const rows = formatAgentsPanel (
330438 [
0 commit comments