@@ -29,6 +29,47 @@ function createTurn(id: string, status: v2.TurnStatus = "inProgress"): v2.Turn {
2929}
3030
3131describe ( 'native custody metadata' , ( ) => {
32+ test ( 'enumerates loaded and persisted native queues without input, then verifies stable IDs' , async ( ) => {
33+ const id = '01a0d435-bb2b-7047-afe7-0a639be8e5d4' ;
34+ const client = createFakeClient ( { } ) . client ;
35+ client . threadLoadedList = async ( ) => ( { data : [ id ] , nextCursor : null } ) ;
36+ client . threadList = async ( ) => ( { data : [ { id } as v2 . Thread ] , nextCursor : null , backwardsCursor : null } ) ;
37+ let calls = 0 ;
38+ client . threadQueueList = async ( ) => {
39+ calls ++ ;
40+ return { data : [ { id : 'queue_1' , clientUserMessageId : 'opaque_1' , input : [ { text : 'PRIVATE' } ] } ] , nextCursor : null } ;
41+ } ;
42+ const result = await new CodexService ( client ) . readGlobalNativeCustody ( ) ;
43+ assert . equal ( result . scope , 'all-enumerated-unarchived-native-threads' ) ;
44+ assert . equal ( result . atomic , false ) ;
45+ assert . equal ( result . queuedSubmissionCount , 1 ) ;
46+ assert . deepEqual ( result . loadedThreadIds , [ id ] ) ;
47+ assert . equal ( calls , 2 ) ;
48+ assert . doesNotMatch ( JSON . stringify ( result ) , / P R I V A T E / ) ;
49+ } ) ;
50+
51+ test ( 'rejects a changing native queue rather than claiming safe custody' , async ( ) => {
52+ const id = '01a0d435-bb2b-7047-afe7-0a639be8e5d4' ;
53+ const client = createFakeClient ( { } ) . client ;
54+ client . threadLoadedList = async ( ) => ( { data : [ id ] , nextCursor : null } ) ;
55+ client . threadList = async ( ) => ( { data : [ { id } as v2 . Thread ] , nextCursor : null , backwardsCursor : null } ) ;
56+ let calls = 0 ;
57+ client . threadQueueList = async ( ) => ( { data : calls ++ === 0
58+ ? [ ] : [ { id : 'queue_2' , clientUserMessageId : 'opaque_2' , input : [ ] } ] , nextCursor : null } ) ;
59+ await assert . rejects ( new CodexService ( client ) . readGlobalNativeCustody ( ) , / c h a n g e d / ) ;
60+ } ) ;
61+
62+ test ( 'rejects a loaded native thread omitted by persisted inventory' , async ( ) => {
63+ const client = createFakeClient ( { } ) . client ;
64+ client . threadLoadedList = async ( ) => ( { data : [ '01a0d435-bb2b-7047-afe7-0a639be8e5d4' ] , nextCursor : null } ) ;
65+ await assert . rejects ( new CodexService ( client ) . readGlobalNativeCustody ( ) , / m i s s i n g / ) ;
66+ } ) ;
67+
68+ test ( 'does not report an empty global queue when native listing is unsupported' , async ( ) => {
69+ const client = createFakeClient ( { } ) . client ;
70+ client . threadLoadedList = async ( ) => { throw new Error ( 'native method unavailable' ) ; } ;
71+ await assert . rejects ( new CodexService ( client ) . readGlobalNativeCustody ( ) , / u n a v a i l a b l e / ) ;
72+ } ) ;
3273 test ( 'pages native queue through the existing client without returning input' , async ( ) => {
3374 const fake = createFakeClient ( { } ) ;
3475 const client = fake . client ;
@@ -286,6 +327,9 @@ function createFakeClient(overrides: {
286327 calls . threadListParams . push ( params ?? { } ) ;
287328 return { data : [ ] , nextCursor : null } ;
288329 } ,
330+ async threadLoadedList ( ) {
331+ return { data : [ ] , nextCursor : null } ;
332+ } ,
289333 async threadRead ( params ) {
290334 calls . threadReadParams . push ( params ) ;
291335 if ( overrides . threadRead ) {
0 commit comments