@@ -1274,11 +1274,6 @@ export class DevMockHost {
12741274 case 'shell-command' : {
12751275 const content = [ textBlock ( `$ ${ input . command } ` ) ] ;
12761276 const turn = this . beginTurn ( session , content , input ) ;
1277- this . emit ( sessionId , {
1278- type : 'user-message' ,
1279- messageId : userRowMessageId ( turn . graph . turnId ) ,
1280- content,
1281- } ) ;
12821277 settleTurn ( session , turn , 'completed' ) ;
12831278 this . sendSuccess ( replyTo ) ;
12841279 break ;
@@ -1317,11 +1312,6 @@ export class DevMockHost {
13171312 name,
13181313 ...( args !== undefined && { arguments : args } ) ,
13191314 } ) ;
1320- this . emit ( session . sessionId , {
1321- type : 'user-message' ,
1322- messageId : userRowMessageId ( turn . graph . turnId ) ,
1323- content,
1324- } ) ;
13251315 session . status = 'running' ;
13261316 this . emit ( session . sessionId , { type : 'status' , status : 'running' } ) ;
13271317 if ( fixture . reply === undefined ) {
@@ -1365,16 +1355,11 @@ export class DevMockHost {
13651355 const turn = this . beginTurn ( session , content , p . input . type === 'prompt' ? undefined : p . input ) ;
13661356 this . send ( { kind : 'turn.submitted' , replyTo : p . clientReqId , turnId : turn . graph . turnId } ) ;
13671357 if ( p . input . type === 'prompt' ) {
1368- const result = await this . streamMockReply ( session , turn , content ) ;
1358+ const result = await this . streamMockReply ( session , content ) ;
13691359 settleTurn ( session , turn , result . ok ? 'completed' : 'failed' ) ;
13701360 return ;
13711361 }
13721362 // Command/shell turns just echo — the mock has no directive execution behind turn.submit.
1373- this . emit ( p . sessionId , {
1374- type : 'user-message' ,
1375- messageId : userRowMessageId ( turn . graph . turnId ) ,
1376- content,
1377- } ) ;
13781363 settleTurn ( session , turn , 'completed' ) ;
13791364 }
13801365
@@ -1405,6 +1390,13 @@ export class DevMockHost {
14051390 } ;
14061391 session . graphTurns . push ( turn ) ;
14071392 session . runningTurnId = turnId ;
1393+ // Echo before graph.changed so a subscribed projection store sees the new leaf row and
1394+ // treats a plain send as continuation, matching the engine dispatcher.
1395+ this . emit ( session . sessionId , {
1396+ type : 'user-message' ,
1397+ messageId : userRowMessageId ( turnId ) ,
1398+ content,
1399+ } ) ;
14081400 this . send ( {
14091401 kind : 'conversation.graph.changed' ,
14101402 sessionId : session . sessionId ,
@@ -1420,25 +1412,19 @@ export class DevMockHost {
14201412 content : ContentBlock [ ] ,
14211413 ) : Promise < void > {
14221414 const turn = this . beginTurn ( session , content ) ;
1423- const result = await this . streamMockReply ( session , turn , content ) ;
1415+ const result = await this . streamMockReply ( session , content ) ;
14241416 settleTurn ( session , turn , result . ok ? 'completed' : 'failed' ) ;
14251417 if ( result . ok ) this . sendSuccess ( replyTo ) ;
14261418 else this . sendFailure ( replyTo , result . message , { reportedInConversation : true } ) ;
14271419 }
14281420
14291421 private async streamMockReply (
14301422 session : MockSession ,
1431- turn : MockTurn ,
14321423 content : ContentBlock [ ] ,
14331424 ) : Promise < { ok : true } | { ok : false ; message : string } > {
14341425 const text = promptText ( content ) ;
14351426 if ( text && ! session . title ) session . title = text . slice ( 0 , 80 ) ;
14361427 session . status = 'running' ;
1437- this . emit ( session . sessionId , {
1438- type : 'user-message' ,
1439- messageId : userRowMessageId ( turn . graph . turnId ) ,
1440- content,
1441- } ) ;
14421428 this . emit ( session . sessionId , { type : 'status' , status : 'running' } ) ;
14431429
14441430 // Cancel/stop bump the session epoch; a stale epoch means this turn was cancelled and the
0 commit comments