@@ -1622,6 +1622,44 @@ describe("session.message-v2.latest", () => {
16221622 ] as SessionV1 . Part [ ] ,
16231623 }
16241624
1625+ test ( "selects latest messages by creation time when IDs are nonmonotonic" , ( ) => {
1626+ const oldUser = { ...userInfo ( "msg_z_user" ) , time : { created : 100 } }
1627+ const newUser = { ...userInfo ( "msg_a_user" ) , time : { created : 200 } }
1628+ const oldAssistant = {
1629+ ...assistantInfo ( "msg_z_assistant" , oldUser . id ) ,
1630+ time : { created : 300 } ,
1631+ finish : "stop" ,
1632+ } as SessionV1 . Assistant
1633+ const newAssistant = {
1634+ ...assistantInfo ( "msg_a_assistant" , newUser . id ) ,
1635+ time : { created : 400 } ,
1636+ finish : "stop" ,
1637+ } as SessionV1 . Assistant
1638+
1639+ const state = MessageV2 . latest ( [
1640+ { info : newAssistant , parts : [ ] } ,
1641+ { info : oldUser , parts : [ ] } ,
1642+ { info : oldAssistant , parts : [ ] } ,
1643+ { info : newUser , parts : [ ] } ,
1644+ ] )
1645+
1646+ expect ( state . user ?. id ) . toBe ( newUser . id )
1647+ expect ( state . assistant ?. id ) . toBe ( newAssistant . id )
1648+ expect ( state . finished ?. id ) . toBe ( newAssistant . id )
1649+ } )
1650+
1651+ test ( "uses ID as a deterministic tie-breaker for equal creation times" , ( ) => {
1652+ const lower = { ...userInfo ( "msg_a_user" ) , time : { created : 100 } }
1653+ const higher = { ...userInfo ( "msg_z_user" ) , time : { created : 100 } }
1654+
1655+ const state = MessageV2 . latest ( [
1656+ { info : higher , parts : [ ] } ,
1657+ { info : lower , parts : [ ] } ,
1658+ ] )
1659+
1660+ expect ( state . user ?. id ) . toBe ( higher . id )
1661+ } )
1662+
16251663 // Regression for double auto-compaction. The reorder in filterCompacted
16261664 // (#27145) returns [compaction-user, summary, ...tail..., continue-user],
16271665 // so picking lastFinished by array position landed on the pre-compaction
@@ -1670,4 +1708,33 @@ describe("session.message-v2.latest", () => {
16701708 expect ( state . tasks ) . toHaveLength ( 1 )
16711709 expect ( state . tasks [ 0 ] ) . toMatchObject ( { type : "compaction" , auto : true } )
16721710 } )
1711+
1712+ test ( "selects compaction and subtask work after the finished boundary by creation time" , ( ) => {
1713+ const finished = {
1714+ ...assistantInfo ( "msg_z_finished" , "msg_parent" ) ,
1715+ time : { created : 200 } ,
1716+ finish : "stop" ,
1717+ } as SessionV1 . Assistant
1718+ const oldTask : SessionV1 . WithParts = {
1719+ info : { ...userInfo ( "msg_z_old" ) , time : { created : 100 } } ,
1720+ parts : [ { ...basePart ( "msg_z_old" , "old" ) , type : "compaction" , auto : true } ] as SessionV1 . Part [ ] ,
1721+ }
1722+ const newTask : SessionV1 . WithParts = {
1723+ info : { ...userInfo ( "msg_a_new" ) , time : { created : 300 } } ,
1724+ parts : [
1725+ {
1726+ ...basePart ( "msg_a_new" , "new" ) ,
1727+ type : "subtask" ,
1728+ prompt : "inspect" ,
1729+ description : "inspect ordering" ,
1730+ agent : "general" ,
1731+ } ,
1732+ ] as SessionV1 . Part [ ] ,
1733+ }
1734+
1735+ const state = MessageV2 . latest ( [ newTask , { info : finished , parts : [ ] } , oldTask ] )
1736+
1737+ expect ( state . tasks ) . toHaveLength ( 1 )
1738+ expect ( state . tasks [ 0 ] ) . toMatchObject ( { type : "subtask" , prompt : "inspect" } )
1739+ } )
16731740} )
0 commit comments