@@ -295,6 +295,77 @@ describe('HostInteractionCoordinator', () => {
295295 } ) ;
296296 } ) ;
297297
298+ test ( 'does not hold Session admission while graph wake reconciliation waits' , async ( ) => {
299+ await withStore ( async ( { owner, store, stores } ) => {
300+ const workspace = join ( owner . capability . canonicalPath , 'wake-workspace' ) ;
301+ await mkdir ( workspace ) ;
302+ const session = await stores . sessionStore . create ( {
303+ cwd : workspace ,
304+ llmConnectionId : 'cccccccc-cccc-4ccc-8ccc-cccccccccccc' ,
305+ llmConnectionSlug : 'fake' ,
306+ model : 'fake-model' ,
307+ permissionMode : 'ask' ,
308+ } ) ;
309+ const identity = { ...RUN , sessionId : session . id } ;
310+ const wakeStarted = deferred ( ) ;
311+ const releaseWake = deferred ( ) ;
312+ const wakeFinished = deferred ( ) ;
313+ const coordinator = new HostInteractionCoordinator ( {
314+ store,
315+ sandboxBoundaries : stores . sessionStore ,
316+ sessionAdmission : new SessionAdmissionGate ( ) ,
317+ sessions : stores . sessionStore ,
318+ preflightSessionSnapshot : ( ) => true ,
319+ refreshCanonicalContinuity : async ( ) => { } ,
320+ onSandboxBoundarySettled : async ( ) => {
321+ wakeStarted . resolve ( ) ;
322+ await releaseWake . promise ;
323+ wakeFinished . resolve ( ) ;
324+ } ,
325+ onPoison : ( ) => { } ,
326+ } ) ;
327+ const binding = coordinator . bindRun ( identity ) ;
328+ const request = sandboxBoundaryEvent ( {
329+ sessionId : session . id ,
330+ requestId : 'boundary_wake_wait' ,
331+ status : 'pending' ,
332+ baseRevision : 0 ,
333+ turnId : identity . turnId ,
334+ runId : identity . runId ,
335+ expansion : { network : { enabled : true } } ,
336+ justification : 'Connect to the requested service.' ,
337+ createdAt : 1 ,
338+ } ) ;
339+ await binding . acceptSandboxBoundaryRequest ( {
340+ request,
341+ continuation : sandboxBoundaryContinuation ( identity , request . requestId ) ,
342+ } ) ;
343+
344+ const answer = coordinator . handlers [ 'interaction.answer' ] (
345+ {
346+ sessionId : session . id ,
347+ interactionId : request . requestId ,
348+ answer : { kind : 'sandbox_boundary' , decision : 'allow' } ,
349+ } ,
350+ connection ( ) ,
351+ ) ;
352+ await wakeStarted . promise ;
353+ const result = await Promise . race ( [
354+ answer ,
355+ new Promise < undefined > ( ( resolve ) => setTimeout ( ( ) => resolve ( undefined ) , 500 ) ) ,
356+ ] ) ;
357+ assert . notEqual ( result , undefined , 'interaction answer waited for graph wake reconciliation' ) ;
358+ assert . equal ( result ?. ok , true ) ;
359+ if ( result ?. ok ) assert . equal ( result . result . status , 'answered' ) ;
360+
361+ releaseWake . resolve ( ) ;
362+ await wakeFinished . promise ;
363+ await binding . close ( 'turn_terminal' ) ;
364+ binding . release ( ) ;
365+ await coordinator . close ( ) ;
366+ } ) ;
367+ } ) ;
368+
298369 test ( 'a queued stop waits for sandbox boundary publication before closing its Run' , async ( ) => {
299370 await withStore ( async ( { owner, store, stores } ) => {
300371 const workspace = join ( owner . capability . canonicalPath , 'publication-workspace' ) ;
0 commit comments