@@ -3759,6 +3759,75 @@ describe("codex manager cli commands", () => {
37593759 expect ( promptLoginModeMock ) . toHaveBeenCalledTimes ( 1 ) ;
37603760 } ) ;
37613761
3762+ it ( "realigns restored family routing when a backup carries a stale active index" , async ( ) => {
3763+ const now = Date . now ( ) ;
3764+ setInteractiveTTY ( true ) ;
3765+ const restoredStorage = {
3766+ version : 3 as const ,
3767+ activeIndex : 99 ,
3768+ activeIndexByFamily : { codex : 99 } ,
3769+ accounts : [
3770+ {
3771+ email : "stale@example.com" ,
3772+ accountId : "acc_stale" ,
3773+ refreshToken : "refresh-stale" ,
3774+ accessToken : "access-stale" ,
3775+ expiresAt : now + 3_600_000 ,
3776+ addedAt : now - 2_000 ,
3777+ lastUsed : now - 2_000 ,
3778+ enabled : true ,
3779+ } ,
3780+ {
3781+ email : "selected@example.com" ,
3782+ accountId : "acc_selected" ,
3783+ refreshToken : "refresh-selected" ,
3784+ accessToken : "access-selected" ,
3785+ expiresAt : now + 7_200_000 ,
3786+ addedAt : now - 1_000 ,
3787+ lastUsed : now - 1_000 ,
3788+ enabled : true ,
3789+ } ,
3790+ ] ,
3791+ } ;
3792+ let storageState : typeof restoredStorage | null = null ;
3793+ loadAccountsMock . mockImplementation ( async ( ) =>
3794+ storageState == null ? null : structuredClone ( storageState ) ,
3795+ ) ;
3796+ saveAccountsMock . mockImplementation ( async ( nextStorage ) => {
3797+ storageState = structuredClone ( nextStorage ) ;
3798+ } ) ;
3799+ getNamedBackupsMock . mockResolvedValue ( [
3800+ {
3801+ path : "/mock/backups/stale-index.json" ,
3802+ fileName : "stale-index.json" ,
3803+ accountCount : 2 ,
3804+ mtimeMs : now ,
3805+ } ,
3806+ ] ) ;
3807+ restoreAccountsFromBackupMock . mockResolvedValue ( structuredClone ( restoredStorage ) ) ;
3808+ setCodexCliActiveSelectionMock . mockResolvedValueOnce ( true ) ;
3809+ selectMock
3810+ . mockResolvedValueOnce ( "restore-backup" )
3811+ . mockResolvedValueOnce ( "latest" ) ;
3812+ promptLoginModeMock . mockResolvedValueOnce ( { mode : "cancel" } ) ;
3813+ const { runCodexMultiAuthCli } = await import ( "../lib/codex-manager.js" ) ;
3814+
3815+ const exitCode = await runCodexMultiAuthCli ( [ "auth" , "login" ] ) ;
3816+
3817+ expect ( exitCode ) . toBe ( 0 ) ;
3818+ expect ( saveAccountsMock ) . toHaveBeenCalledTimes ( 1 ) ;
3819+ expect ( storageState ) . toMatchObject ( {
3820+ activeIndex : 1 ,
3821+ activeIndexByFamily : { codex : 1 } ,
3822+ } ) ;
3823+ expect ( setCodexCliActiveSelectionMock ) . toHaveBeenCalledWith (
3824+ expect . objectContaining ( {
3825+ accountId : "acc_selected" ,
3826+ email : "selected@example.com" ,
3827+ } ) ,
3828+ ) ;
3829+ } ) ;
3830+
37623831 it ( "clears the empty onboarding snapshot after adding the first account" , async ( ) => {
37633832 const now = Date . now ( ) ;
37643833 let storageState : {
0 commit comments