@@ -1611,6 +1611,44 @@ describe("session.message-v2.latest", () => {
16111611 ] as SessionV1 . Part [ ] ,
16121612 }
16131613
1614+ test ( "selects latest messages by creation time when IDs are nonmonotonic" , ( ) => {
1615+ const oldUser = { ...userInfo ( "msg_z_user" ) , time : { created : 100 } }
1616+ const newUser = { ...userInfo ( "msg_a_user" ) , time : { created : 200 } }
1617+ const oldAssistant = {
1618+ ...assistantInfo ( "msg_z_assistant" , oldUser . id ) ,
1619+ time : { created : 300 } ,
1620+ finish : "stop" ,
1621+ } as SessionV1 . Assistant
1622+ const newAssistant = {
1623+ ...assistantInfo ( "msg_a_assistant" , newUser . id ) ,
1624+ time : { created : 400 } ,
1625+ finish : "stop" ,
1626+ } as SessionV1 . Assistant
1627+
1628+ const state = MessageV2 . latest ( [
1629+ { info : newAssistant , parts : [ ] } ,
1630+ { info : oldUser , parts : [ ] } ,
1631+ { info : oldAssistant , parts : [ ] } ,
1632+ { info : newUser , parts : [ ] } ,
1633+ ] )
1634+
1635+ expect ( state . user ?. id ) . toBe ( newUser . id )
1636+ expect ( state . assistant ?. id ) . toBe ( newAssistant . id )
1637+ expect ( state . finished ?. id ) . toBe ( newAssistant . id )
1638+ } )
1639+
1640+ test ( "uses ID as a deterministic tie-breaker for equal creation times" , ( ) => {
1641+ const lower = { ...userInfo ( "msg_a_user" ) , time : { created : 100 } }
1642+ const higher = { ...userInfo ( "msg_z_user" ) , time : { created : 100 } }
1643+
1644+ const state = MessageV2 . latest ( [
1645+ { info : higher , parts : [ ] } ,
1646+ { info : lower , parts : [ ] } ,
1647+ ] )
1648+
1649+ expect ( state . user ?. id ) . toBe ( higher . id )
1650+ } )
1651+
16141652 // Regression for double auto-compaction. The reorder in filterCompacted
16151653 // (#27145) returns [compaction-user, summary, ...tail..., continue-user],
16161654 // so picking lastFinished by array position landed on the pre-compaction
@@ -1659,4 +1697,33 @@ describe("session.message-v2.latest", () => {
16591697 expect ( state . tasks ) . toHaveLength ( 1 )
16601698 expect ( state . tasks [ 0 ] ) . toMatchObject ( { type : "compaction" , auto : true } )
16611699 } )
1700+
1701+ test ( "selects compaction and subtask work after the finished boundary by creation time" , ( ) => {
1702+ const finished = {
1703+ ...assistantInfo ( "msg_z_finished" , "msg_parent" ) ,
1704+ time : { created : 200 } ,
1705+ finish : "stop" ,
1706+ } as SessionV1 . Assistant
1707+ const oldTask : SessionV1 . WithParts = {
1708+ info : { ...userInfo ( "msg_z_old" ) , time : { created : 100 } } ,
1709+ parts : [ { ...basePart ( "msg_z_old" , "old" ) , type : "compaction" , auto : true } ] as SessionV1 . Part [ ] ,
1710+ }
1711+ const newTask : SessionV1 . WithParts = {
1712+ info : { ...userInfo ( "msg_a_new" ) , time : { created : 300 } } ,
1713+ parts : [
1714+ {
1715+ ...basePart ( "msg_a_new" , "new" ) ,
1716+ type : "subtask" ,
1717+ prompt : "inspect" ,
1718+ description : "inspect ordering" ,
1719+ agent : "general" ,
1720+ } ,
1721+ ] as SessionV1 . Part [ ] ,
1722+ }
1723+
1724+ const state = MessageV2 . latest ( [ newTask , { info : finished , parts : [ ] } , oldTask ] )
1725+
1726+ expect ( state . tasks ) . toHaveLength ( 1 )
1727+ expect ( state . tasks [ 0 ] ) . toMatchObject ( { type : "subtask" , prompt : "inspect" } )
1728+ } )
16621729} )
0 commit comments