@@ -15,6 +15,7 @@ import { getErrorMessage } from '@sim/utils/errors'
1515import { sleep } from '@sim/utils/helpers'
1616import { recordCheck } from './check-report'
1717import {
18+ answerShellDialog ,
1819 type FixtureCall ,
1920 FixtureSim ,
2021 launch ,
@@ -37,6 +38,9 @@ import {
3738 * BACKGROUND_EXECUTOR_REPORT_PATH as it finishes.
3839 */
3940
41+ /** Sim's window for a device to claim an offered call (DESKTOP_TOOL_PICKUP_GRACE_MS in Sim). */
42+ const SIM_PICKUP_GRACE_MS = 15_000
43+
4044const CHAT_A = 'chat-browser-a'
4145const CHAT_B = 'chat-terminal-b'
4246const CHAT_C = 'chat-idle-c'
@@ -89,6 +93,7 @@ test.describe('background executor', () => {
8993 await window . goto ( `${ sim . origin } /workspace/${ WORKSPACE } /chat/${ CHAT_C } ` )
9094
9195 const marker = join ( userData , 'terminal-marker.txt' )
96+ const releaseCommands = join ( userData , 'release-commands' )
9297 const readable = join ( userData , 'notes.txt' )
9398 writeFileSync ( readable , 'background read fixture' )
9499
@@ -109,17 +114,41 @@ test.describe('background executor', () => {
109114 const terminalRuns = [ 1 , 2 , 3 ] . map ( ( n ) =>
110115 sim . issue ( deviceId , CHAT_B , 'terminal' , {
111116 operation : 'run' ,
112- args : { command : `sleep 1; echo B-${ n } >> '${ marker } '` , waitSeconds : 30 } ,
117+ args : {
118+ command : `until [ -e '${ releaseCommands } ' ]; do sleep 0.1; done; echo B-${ n } >> '${ marker } '` ,
119+ waitSeconds : 30 ,
120+ } ,
113121 } )
114122 )
115123 const readConsent = launched . app . waitForEvent ( 'window' )
116124 const localRead = sim . issue ( deviceId , CHAT_B , 'read_local_file' , { path : readable } )
117- await ( await readConsent ) . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) . click ( )
125+ await answerShellDialog ( await readConsent , 'Allow folder' )
118126
119127 await window . goto ( `${ sim . origin } /workspace/ws-other/home` )
120128 await window . reload ( )
121129 await window . goto ( `${ sim . origin } /workspace/${ WORKSPACE } /chat/${ CHAT_C } ` )
122130
131+ // Chat B's first command holds its queue until released, so a claim that waited for the
132+ // calls ahead of it to run could never happen in time.
133+ await check ( "A: every call is claimed while chat B's first command still runs" , async ( ) => {
134+ await expect
135+ . poll (
136+ ( ) =>
137+ [ ...sim . calls . values ( ) ]
138+ . filter ( ( call ) => call . claimedAt === undefined )
139+ . map ( ( call ) => call . toolCallId ) ,
140+ { timeout : SIM_PICKUP_GRACE_MS }
141+ )
142+ . toEqual ( [ ] )
143+ } )
144+
145+ await check ( 'A: the lease is renewed while calls wait and run' , async ( ) => {
146+ await expect
147+ . poll ( ( ) => terminalRuns . filter ( ( id ) => sim . requireCall ( id ) . renewals === 0 ) )
148+ . toEqual ( [ ] )
149+ } )
150+ writeFileSync ( releaseCommands , '' )
151+
123152 await check ( 'A: every call completes exactly once with its own token' , async ( ) => {
124153 for ( const id of [ ...clicks , ...terminalRuns , localRead ] ) {
125154 const completion = await settled ( sim , id , 90_000 )
@@ -153,18 +182,6 @@ test.describe('background executor', () => {
153182 sim . requests . filter ( ( request ) => request . includes ( '/api/desktop/tool/authorize' ) )
154183 ) . toEqual ( [ ] )
155184 } )
156-
157- await check ( 'A: calls are picked up within 1.5 s at p95' , async ( ) => {
158- const latencies = [ ...sim . calls . values ( ) ]
159- . map ( ( call ) => ( call . claimedAt ?? Number . POSITIVE_INFINITY ) - call . issuedAt )
160- . sort ( ( a , b ) => a - b )
161- const p95 = latencies [ Math . ceil ( latencies . length * 0.95 ) - 1 ] ?? Number . POSITIVE_INFINITY
162- expect ( p95 ) . toBeLessThan ( 1_500 )
163- } )
164-
165- await check ( 'A: the lease is renewed while calls wait and run' , async ( ) => {
166- expect ( Math . max ( ...terminalRuns . map ( ( id ) => sim . requireCall ( id ) . renewals ) ) ) . toBeGreaterThan ( 0 )
167- } )
168185 } )
169186
170187 test ( 'background file reads require consent and Stop cancels pending permission' , async ( ) => {
@@ -181,7 +198,7 @@ test.describe('background executor', () => {
181198 const prompt = await shown
182199 await expect ( prompt . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) ) . toBeVisible ( )
183200 expect ( sim . requireCall ( call ) . completions ) . toHaveLength ( 0 )
184- await prompt . getByRole ( 'button' , { name : "Don't allow" , exact : true } ) . click ( )
201+ await answerShellDialog ( prompt , "Don't allow" )
185202 const completion = await settled ( sim , call )
186203 expect ( completion . status ) . toBe ( 'error' )
187204 expect ( JSON . stringify ( completion ) ) . not . toContain ( 'background consent fixture' )
@@ -202,7 +219,7 @@ test.describe('background executor', () => {
202219 const shown = launched . app . waitForEvent ( 'window' , { timeout : 10_000 } )
203220 const call = sim . issue ( deviceId , CHAT_B , 'read_local_file' , { path : readable } )
204221 const prompt = await shown
205- await prompt . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) . click ( )
222+ await answerShellDialog ( prompt , 'Allow folder' )
206223 expect ( ( await settled ( sim , call ) ) . status ) . toBe ( 'success' )
207224 const next = sim . issue ( deviceId , CHAT_A , 'read_local_file' , { path : readable } )
208225 expect ( JSON . stringify ( ( await settled ( sim , next ) ) . data ) ) . toContain (
@@ -225,7 +242,7 @@ test.describe('background executor', () => {
225242 const prompt = await shown
226243 await expect ( prompt . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) ) . toBeVisible ( )
227244 sim . disconnect ( )
228- await prompt . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) . click ( )
245+ await answerShellDialog ( prompt , 'Allow folder' )
229246 await expect
230247 . poll ( ( ) =>
231248 launched . app . evaluate ( ( { safeStorage } , toolCallId ) => {
@@ -245,7 +262,7 @@ test.describe('background executor', () => {
245262 expect ( JSON . stringify ( completion ) ) . not . toContain ( 'offline consent fixture' )
246263 const nextPrompt = launched . app . waitForEvent ( 'window' )
247264 const next = sim . issue ( deviceId , CHAT_B , 'read_local_file' , { path : readable } )
248- await ( await nextPrompt ) . getByRole ( 'button' , { name : "Don't allow" , exact : true } ) . click ( )
265+ await answerShellDialog ( await nextPrompt , "Don't allow" )
249266 expect ( ( await settled ( sim , next ) ) . status ) . toBe ( 'error' )
250267 } )
251268 } )
@@ -270,7 +287,7 @@ test.describe('background executor', () => {
270287 BrowserWindow . getAllWindows ( ) . map ( ( window ) => window . getParentWindow ( ) === null )
271288 )
272289 ) . toEqual ( [ true ] )
273- await prompt . getByRole ( 'button' , { name : "Don't allow" , exact : true } ) . click ( )
290+ await answerShellDialog ( prompt , "Don't allow" )
274291 expect ( ( await settled ( sim , call ) ) . status ) . toBe ( 'error' )
275292 } )
276293 } )
@@ -284,7 +301,7 @@ test.describe('background executor', () => {
284301 writeFileSync ( readable , 'cleanup consent fixture' )
285302 const shown = launched . app . waitForEvent ( 'window' )
286303 const call = sim . issue ( deviceId , CHAT_B , 'read_local_file' , { path : readable } )
287- await ( await shown ) . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) . click ( )
304+ await answerShellDialog ( await shown , 'Allow folder' )
288305 expect ( ( await settled ( sim , call ) ) . status ) . toBe ( 'success' )
289306 const grants = join ( userData , 'local-filesystem-grants.json' )
290307 expect ( existsSync ( grants ) ) . toBe ( true )
@@ -321,7 +338,7 @@ test.describe('background executor', () => {
321338 item . click ( )
322339 } )
323340 const failure = await failedSignOut
324- await failure . getByRole ( 'button' , { name : 'OK' , exact : true } ) . click ( )
341+ await answerShellDialog ( failure , 'OK' )
325342 expect ( existsSync ( join ( userData , 'account-data-teardown-required.json' ) ) ) . toBe ( true )
326343 await expect . poll ( ( ) => existsSync ( grants ) ) . toBe ( false )
327344 }
@@ -419,7 +436,7 @@ test.describe('background executor', () => {
419436 folderId : 'folder-e2e' ,
420437 } )
421438
422- await ( await importConsent ) . getByRole ( 'button' , { name : 'Allow folder' , exact : true } ) . click ( )
439+ await answerShellDialog ( await importConsent , 'Allow folder' )
423440
424441 await check ( 'D: the import completes with every entry it stored' , async ( ) => {
425442 const completion = await settled ( sim , call , 60_000 )
0 commit comments