From 2fb26b6624af11e024fc4c50fc3752000b998d0f Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Sun, 23 Aug 2026 12:52:49 -0700 Subject: [PATCH] test(codex): strengthen resume home snapshot contract --- .../codex/codex-resume-home-snapshot.test.ts | 34 +++++++++++++++++++ src/main/index.ts | 8 +---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/codex/codex-resume-home-snapshot.test.ts b/src/main/codex/codex-resume-home-snapshot.test.ts index 9a601cf2f5a..dd2ad2e2cad 100644 --- a/src/main/codex/codex-resume-home-snapshot.test.ts +++ b/src/main/codex/codex-resume-home-snapshot.test.ts @@ -196,6 +196,40 @@ describe('STA-4919 Codex resume home snapshot', () => { }) }) + it('propagates a still-indeterminate selected home instead of admitting or skipping it', async () => { + const { service, homeA } = await createTwoAccountService() + const markerA = join(realpathSync(homeA), '.orca-managed-home') + lstatFaults.failNext(markerA, 2) + const { ManagedCodexHomeTemporarilyUnavailableError } = + await import('../codex-accounts/host-codex-managed-home-ownership') + + expect(() => + snapshotCodexResumeHomes({ + systemHomePath: getSystemCodexHomePath(), + runtimeHome: service + }) + ).toThrow(ManagedCodexHomeTemporarilyUnavailableError) + expect(lstatFaults.readsFor(markerA)).toBe(2) + }) + + it('deduplicates equivalent Windows home spellings while preserving the first path', () => { + const selectedHome = 'c:/users/brennan/.codex/' + const discoveredHome = String.raw`C:\Users\Brennan\.codex` + + expect( + snapshotCodexResumeHomes({ + systemHomePath: String.raw`C:\Users\System\.codex`, + runtimeHome: { + getHostCodexHomePathsForSessionDiscovery: () => [discoveredHome], + resolveSelectedHostAccountCodexHomePathForResume: () => selectedHome + } + }) + ).toEqual({ + trustedCodexHomes: [String.raw`C:\Users\System\.codex`, discoveredHome], + selectedAccountCodexHome: selectedHome + }) + }) + it('still excludes a genuinely untrusted home that holds a competing alias', async () => { const { service, homeA, store } = await createTwoAccountService() const untrustedHome = join(testState.userDataDir, 'outside', 'account-c', 'home') diff --git a/src/main/index.ts b/src/main/index.ts index 2b10d205772..654e6c53421 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1165,13 +1165,7 @@ async function prepareCodexSessionResumeForLaunch(args: { const systemHomePath = getSystemCodexHomePath() // Why: codexSessionSourceHome is import-only; treating it as CODEX_HOME would mutate history sources and bypass account auth. const settingsStore = store - // Why: discovery omits a home whose ownership read is `indeterminate` - // (antivirus EBUSY); selection microseconds later may verify that same home. - // Snapshot both from this one call and union the verified selected home into - // the scan list, or a competing alias in another account wins (STA-4919). - // An unreadable selected home still throws rather than collapsing to "no - // selection" (STA-4422). The selected home is included only because this - // read verified it — never because verification was skipped. + // Why: include a newly verified selection when transient discovery omitted it (STA-4919). const { trustedCodexHomes: trustedHomes, selectedAccountCodexHome } = snapshotCodexResumeHomes({ systemHomePath, runtimeHome: codexRuntimeHome