@@ -59,7 +59,7 @@ vi.mock('@/executor/handlers/pi/babysit-github', async (importOriginal) => {
5959 }
6060} )
6161
62- import { getMaxExecutionTimeout } from '@/lib/core/execution-limits'
62+ import { createTimeoutAbortController , getMaxExecutionTimeout } from '@/lib/core/execution-limits'
6363import {
6464 resolveBabysitExecutionBudgetMs ,
6565 runBabysitPiWithOptions ,
@@ -283,6 +283,37 @@ describe('runBabysitPiWithOptions', () => {
283283 expect ( mockWithPiSandbox ) . not . toHaveBeenCalled ( )
284284 } )
285285
286+ it ( "creates its sandbox against the execution's deadline, not the provider ceiling" , async ( ) => {
287+ mockFetchSnapshot . mockResolvedValue ( snapshot )
288+ mockFetchThreads . mockResolvedValue ( {
289+ actionable : [ ] ,
290+ skipped : [ ] ,
291+ totalUnresolved : 0 ,
292+ latestReview : null ,
293+ } )
294+ mockFetchChecks . mockResolvedValue ( greenChecks )
295+ const { runner } = makeRunner ( { } )
296+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
297+
298+ // Babysit wraps `context.signal` in its own cancellation controller, and the
299+ // deadline is recorded against the executor's signal alone. Resolving the
300+ // lifetime from that wrapper answers "unknown" and silently falls back to the
301+ // provider ceiling — the run still succeeds, it just over-reserves the
302+ // sandbox. This is the longest-lived Pi mode, so that regression matters most
303+ // here and is invisible without an assertion.
304+ const timeout = createTimeoutAbortController ( 6 * 60 * 1000 )
305+ await runBabysitPiWithOptions (
306+ params ( ) ,
307+ { onEvent : vi . fn ( ) , signal : timeout . signal } ,
308+ { roundWaitMs : 0 }
309+ )
310+
311+ const [ { lifetimeMs } ] = mockWithPiSandbox . mock . calls [ 0 ]
312+ expect ( lifetimeMs ) . toBeLessThanOrEqual ( 6 * 60 * 1000 )
313+ expect ( lifetimeMs ) . toBeGreaterThan ( 5 * 60 * 1000 )
314+ timeout . cleanup ( )
315+ } )
316+
286317 it ( 'requests the initial review and waits without consuming a round when the PR starts clean' , async ( ) => {
287318 mockFetchSnapshot . mockResolvedValue ( snapshot )
288319 mockFetchThreads . mockResolvedValue ( {
@@ -293,7 +324,7 @@ describe('runBabysitPiWithOptions', () => {
293324 } )
294325 mockFetchChecks . mockResolvedValue ( greenChecks )
295326 const { runner } = makeRunner ( { } )
296- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
327+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
297328
298329 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } , { roundWaitMs : 0 } )
299330
@@ -325,7 +356,7 @@ describe('runBabysitPiWithOptions', () => {
325356 const { runner } = makeRunner ( {
326357 cloneResult : commandResult ( '' , 'clone failed' , 1 ) ,
327358 } )
328- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
359+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
329360
330361 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
331362
@@ -348,7 +379,7 @@ describe('runBabysitPiWithOptions', () => {
348379 } )
349380 mockFetchChecks . mockResolvedValue ( greenChecks )
350381 const { runner } = makeRunner ( { } )
351- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
382+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
352383
353384 const result = await runBabysitPiWithOptions (
354385 params ( { executionBudgetMs : 2 * 60 * 1000 } ) ,
@@ -375,7 +406,7 @@ describe('runBabysitPiWithOptions', () => {
375406 } )
376407 mockFetchChecks . mockResolvedValue ( greenChecks )
377408 const { runner } = makeRunner ( { } )
378- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
409+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
379410
380411 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } , { roundWaitMs : 0 } )
381412
@@ -409,7 +440,7 @@ describe('runBabysitPiWithOptions', () => {
409440 contextRequirements : new Map ( failures . map ( ( check ) => [ check . key , true ] ) ) ,
410441 } )
411442 const { runner, runCalls } = makeRunner ( { } )
412- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
443+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
413444
414445 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
415446
@@ -489,7 +520,7 @@ describe('runBabysitPiWithOptions', () => {
489520 throw new Error ( `Unexpected read ${ path } ` )
490521 } ) ,
491522 }
492- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
523+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
493524
494525 const result = await runBabysitPiWithOptions (
495526 params ( ) ,
@@ -543,7 +574,7 @@ describe('runBabysitPiWithOptions', () => {
543574 } )
544575 mockFetchChecks . mockResolvedValue ( greenChecks )
545576 const { runner, runCalls } = makeRunner ( { } )
546- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
577+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
547578
548579 await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
549580
@@ -605,7 +636,7 @@ describe('runBabysitPiWithOptions', () => {
605636 roundFile : JSON . stringify ( { threads : [ ] } ) ,
606637 diff : [ 'round-one-diff' , 'round-two-diff' ] ,
607638 } )
608- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
639+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
609640
610641 const result = await runBabysitPiWithOptions (
611642 params ( { reviewMentions : [ '@review-bot' ] } ) ,
@@ -641,7 +672,7 @@ describe('runBabysitPiWithOptions', () => {
641672 const { runner, runCalls } = makeRunner ( {
642673 prepareStdout : `__CUMULATIVE_CHANGED__=.github/workflows/ci.yml\n__CUMULATIVE_DIFF_BYTES__=20\n__CHANGED__=.github/workflows/ci.yml\n__NEW_SHA__=${ NEW_SHA } \n__NEEDS_PUSH__=1\n` ,
643674 } )
644- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
675+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
645676
646677 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
647678
@@ -671,7 +702,7 @@ describe('runBabysitPiWithOptions', () => {
671702 const { runner, runCalls } = makeRunner ( {
672703 prepareStdout : `__CUMULATIVE_CHANGED__=${ unicodePath } \n__CUMULATIVE_DIFF_BYTES__=20\n__CHANGED__=${ unicodePath } \n__NEW_SHA__=${ NEW_SHA } \n__NEEDS_PUSH__=1\n` ,
673704 } )
674- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
705+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
675706
676707 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
677708
@@ -701,7 +732,7 @@ describe('runBabysitPiWithOptions', () => {
701732 const { runner, runCalls } = makeRunner ( {
702733 prepareStdout : `__CUMULATIVE_CHANGED__=${ quotedPath } \n__CUMULATIVE_DIFF_BYTES__=20\n__CHANGED__=${ quotedPath } \n__NEW_SHA__=${ NEW_SHA } \n__NEEDS_PUSH__=1\n` ,
703734 } )
704- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
735+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
705736
706737 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
707738
@@ -721,7 +752,7 @@ describe('runBabysitPiWithOptions', () => {
721752 const { runner } = makeRunner ( {
722753 pushResult : commandResult ( '' , 'rejected by remote' , 1 ) ,
723754 } )
724- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
755+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
725756
726757 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
727758
@@ -747,7 +778,7 @@ describe('runBabysitPiWithOptions', () => {
747778 const { runner, runCalls } = makeRunner ( {
748779 prepareStdout : '__NEEDS_PUSH__=1\n' ,
749780 } )
750- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
781+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
751782
752783 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
753784
@@ -772,7 +803,7 @@ describe('runBabysitPiWithOptions', () => {
772803 } )
773804 mockFetchChecks . mockResolvedValue ( greenChecks )
774805 const { runner, runCalls } = makeRunner ( { } )
775- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
806+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
776807
777808 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } )
778809
@@ -814,7 +845,7 @@ describe('runBabysitPiWithOptions', () => {
814845 } )
815846 mockFetchChecks . mockResolvedValueOnce ( pendingChecks ) . mockResolvedValueOnce ( greenChecks )
816847 const { runner, runCalls } = makeRunner ( { } )
817- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
848+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
818849
819850 const result = await runBabysitPiWithOptions (
820851 params ( { maxRounds : 1 } ) ,
@@ -846,7 +877,7 @@ describe('runBabysitPiWithOptions', () => {
846877 awaitingConfirmation : true ,
847878 } )
848879 const { runner } = makeRunner ( { } )
849- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
880+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
850881
851882 const result = await runBabysitPiWithOptions (
852883 params ( ) ,
@@ -878,7 +909,7 @@ describe('runBabysitPiWithOptions', () => {
878909 } )
879910 mockFetchChecks . mockResolvedValue ( noChecksGreen )
880911 const { runner } = makeRunner ( { } )
881- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
912+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
882913
883914 const result = await runBabysitPiWithOptions (
884915 params ( { reviewMentions : [ '@review-bot' ] } ) ,
@@ -910,7 +941,7 @@ describe('runBabysitPiWithOptions', () => {
910941 } )
911942 mockFetchChecks . mockResolvedValue ( noChecksGreen )
912943 const { runner } = makeRunner ( { } )
913- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
944+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
914945
915946 const result = await runBabysitPiWithOptions (
916947 params ( ) ,
@@ -942,7 +973,7 @@ describe('runBabysitPiWithOptions', () => {
942973 } )
943974 mockFetchChecks . mockResolvedValue ( greenChecks )
944975 const { runner } = makeRunner ( { roundFile : 'not json' } )
945- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
976+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
946977
947978 const result = await runBabysitPiWithOptions (
948979 params ( ) ,
@@ -998,7 +1029,7 @@ describe('runBabysitPiWithOptions', () => {
9981029 failures : [ '@missing-bot' ] ,
9991030 } )
10001031 const { runner } = makeRunner ( { } )
1001- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
1032+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
10021033
10031034 const result = await runBabysitPiWithOptions (
10041035 params ( { reviewMentions : [ '@review-bot' , '@missing-bot' ] } ) ,
@@ -1040,7 +1071,7 @@ describe('runBabysitPiWithOptions', () => {
10401071 ] ,
10411072 } ) ,
10421073 } )
1043- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
1074+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
10441075
10451076 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } , { roundWaitMs : 0 } )
10461077
@@ -1076,7 +1107,7 @@ describe('runBabysitPiWithOptions', () => {
10761107 prepareStdout : '__NO_CHANGES__=1\n' ,
10771108 roundFile : JSON . stringify ( { threads : [ ] } ) ,
10781109 } )
1079- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
1110+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
10801111
10811112 const result = await runBabysitPiWithOptions ( params ( ) , { onEvent : vi . fn ( ) } , { roundWaitMs : 0 } )
10821113
@@ -1126,7 +1157,7 @@ describe('runBabysitPiWithOptions', () => {
11261157 ] ,
11271158 } ) ,
11281159 } )
1129- mockWithPiSandbox . mockImplementation ( async ( callback ) => callback ( runner ) )
1160+ mockWithPiSandbox . mockImplementation ( async ( _options , callback ) => callback ( runner ) )
11301161
11311162 const result = await runBabysitPiWithOptions (
11321163 params ( ) ,
0 commit comments