@@ -761,15 +761,28 @@ export async function createAdeRuntime(args: {
761761 const ptyBackend = process . env . ADE_DISABLE_SUPERVISED_PTY_HOST === "1"
762762 ? null
763763 : createSupervisedPtyLoader ( { logger } ) ;
764+ // The sync runtime is created after ptyService (it takes ptyService as a
765+ // dependency), so live PTY forwarding binds late through this ref — same
766+ // pattern as desktop main. Without this bridge, paired phones only ever
767+ // receive terminal snapshots, never live terminal_data push.
768+ let syncServiceForPtyEvents : ReturnType < typeof createSyncService > | null = null ;
764769 const ptyService = createPtyService ( {
765770 projectRoot,
766771 transcriptsDir : paths . transcriptsDir ,
767772 laneService,
768773 sessionService,
769774 processRegistry,
770775 logger,
771- broadcastData : ( event ) => pushEvent ( "pty" , { type : "pty_data" , event } ) ,
772- broadcastExit : ( event ) => pushEvent ( "pty" , { type : "pty_exit" , event } ) ,
776+ broadcastData : ( event ) => {
777+ pushEvent ( "pty" , { type : "pty_data" , event } ) ;
778+ const { projectRoot : _projectRoot , ...syncEvent } = event ;
779+ syncServiceForPtyEvents ?. handlePtyData ( syncEvent ) ;
780+ } ,
781+ broadcastExit : ( event ) => {
782+ pushEvent ( "pty" , { type : "pty_exit" , event } ) ;
783+ const { projectRoot : _projectRoot , ...syncEvent } = event ;
784+ syncServiceForPtyEvents ?. handlePtyExit ( syncEvent ) ;
785+ } ,
773786 onSessionEnded : ( event ) => {
774787 void sessionDeltaService . computeSessionDelta ( event . sessionId ) . catch ( ( error ) => {
775788 logger . warn ( "runtime.session_delta_compute_failed" , {
@@ -1301,6 +1314,7 @@ export async function createAdeRuntime(args: {
13011314 getModelPickerStore : ( ) => getSharedModelPickerStore ( db ) ,
13021315 onStatusChanged : ( snapshot ) => pushEvent ( "runtime" , { type : "sync-status" , snapshot } ) ,
13031316 } ) ;
1317+ syncServiceForPtyEvents = syncService ;
13041318 }
13051319
13061320 if ( syncService ) {
0 commit comments