@@ -436,6 +436,107 @@ describe("turn router", () => {
436436 expect ( mockInterpretWriteTurn ) . not . toHaveBeenCalled ( ) ;
437437 } ) ;
438438
439+ it ( "prefers the interpreter targetRef entity over discourse focus for write turns" , async ( ) => {
440+ mockClassification ( {
441+ turnType : "edit_request" ,
442+ confidence : 0.96 ,
443+ } ) ;
444+ mockInterpretWriteTurn . mockResolvedValueOnce ( {
445+ operationKind : "edit" ,
446+ actionDomain : "task" ,
447+ targetRef : { entityId : "task-2" } ,
448+ taskName : null ,
449+ fields : { scheduleFields : { time : t ( 11 , 0 ) } } ,
450+ sourceText : "Move weekly review to 11" ,
451+ confidence : {
452+ "scheduleFields.time" : 0.95 ,
453+ } ,
454+ unresolvedFields : [ ] ,
455+ } ) ;
456+
457+ const result = await routeMessageTurn ( {
458+ rawText : "Move weekly review to 11" ,
459+ normalizedText : "Move weekly review to 11" ,
460+ recentTurns : [ ] ,
461+ tasks : [
462+ {
463+ id : "task-2" ,
464+ userId : "user-1" ,
465+ sourceInboxItemId : "inbox-1" ,
466+ lastInboxItemId : "inbox-1" ,
467+ title : "Weekly review" ,
468+ lifecycleState : "pending_schedule" ,
469+ externalCalendarEventId : null ,
470+ externalCalendarId : null ,
471+ scheduledStartAt : null ,
472+ scheduledEndAt : null ,
473+ calendarSyncStatus : "in_sync" ,
474+ calendarSyncUpdatedAt : null ,
475+ rescheduleCount : 0 ,
476+ lastFollowupAt : null ,
477+ followupReminderSentAt : null ,
478+ completedAt : null ,
479+ archivedAt : null ,
480+ priority : "medium" ,
481+ urgency : "medium" ,
482+ } ,
483+ ] ,
484+ discourseState : {
485+ focus_entity_id : "task-1" ,
486+ currently_editable_entity_id : "task-1" ,
487+ last_user_mentioned_entity_ids : [ ] ,
488+ last_presented_items : [ ] ,
489+ pending_clarifications : [ ] ,
490+ mode : "editing" ,
491+ } ,
492+ } ) ;
493+
494+ expect ( result . interpretation . resolvedEntityIds ) . toEqual ( [ "task-2" ] ) ;
495+ expect ( result . policy . targetEntityId ) . toBe ( "task-2" ) ;
496+ expect ( result . policy . resolvedOperation ?. targetRef ) . toEqual ( {
497+ entityId : "task-2" ,
498+ } ) ;
499+ } ) ;
500+
501+ it ( "falls back to resolveWriteTarget when the interpreter does not resolve an entity" , async ( ) => {
502+ mockClassification ( {
503+ turnType : "edit_request" ,
504+ confidence : 0.96 ,
505+ } ) ;
506+ mockInterpretWriteTurn . mockResolvedValueOnce ( {
507+ operationKind : "edit" ,
508+ actionDomain : "task" ,
509+ targetRef : null ,
510+ taskName : null ,
511+ fields : { scheduleFields : { time : t ( 11 , 0 ) } } ,
512+ sourceText : "Move it to 11" ,
513+ confidence : {
514+ "scheduleFields.time" : 0.95 ,
515+ } ,
516+ unresolvedFields : [ ] ,
517+ } ) ;
518+
519+ const result = await routeMessageTurn ( {
520+ rawText : "Move it to 11" ,
521+ normalizedText : "Move it to 11" ,
522+ recentTurns : [ ] ,
523+ discourseState : {
524+ focus_entity_id : "task-1" ,
525+ currently_editable_entity_id : null ,
526+ last_user_mentioned_entity_ids : [ ] ,
527+ last_presented_items : [ ] ,
528+ pending_clarifications : [ ] ,
529+ mode : "editing" ,
530+ } ,
531+ } ) ;
532+
533+ expect ( result . interpretation . resolvedEntityIds ) . toEqual ( [ "task-1" ] ) ;
534+ expect ( result . policy . targetEntityId ) . toBe ( "task-1" ) ;
535+ expect ( result . policy . resolvedOperation ?. targetRef ) . toEqual ( {
536+ entityId : "task-1" ,
537+ } ) ;
538+ } ) ;
539+
439540 it ( "clears prior committed fields when the interpreted workflow changes" , async ( ) => {
440541 mockClassification ( {
441542 turnType : "planning_request" ,
0 commit comments