fix(codex): strip the daemon-inherited Orca CODEX_HOME override for real-home routing

The daemon spawns PTYs from its own inherited environment and honors only
spawnOptions.envToDelete, so mutating the sparse env object was not enough to
strip an Orca-owned CODEX_HOME the daemon already carries. Add the strip to
envToDelete for both daemon host-spawn paths, preserving a user-set CODEX_HOME.

Verified live via CDP against a sandboxed dev instance (flag ON): an
Orca-spawned pane reports empty CODEX_HOME/ORCA_CODEX_HOME, so Codex resolves
its own ~/.codex. Adds daemon-path unit coverage (strip Orca-owned, preserve
user-owned, no-op when flag OFF).
This commit is contained in:
Brennan Benson
2026-07-14 22:33:22 -07:00
parent 07afc8fbb7
commit 6d980bb97c
2 changed files with 79 additions and 21 deletions
+33
View File
@@ -1750,6 +1750,39 @@ describe('registerPtyHandlers', () => {
}
})
it('strips the daemon-inherited Orca-owned CODEX_HOME for real-home routing', async () => {
const spawnOptions = await daemonSpawnAndGetOptions(
{},
() => null,
() => ({ codexSystemDefaultRealHomeEnabled: true }) as never,
{ CODEX_HOME: '/managed/home', ORCA_CODEX_HOME: '/managed/home' }
)
expect(spawnOptions.env.CODEX_HOME).toBeUndefined()
expect(spawnOptions.env.ORCA_CODEX_HOME).toBeUndefined()
expect(spawnOptions.envToDelete).toEqual(
expect.arrayContaining(['CODEX_HOME', 'ORCA_CODEX_HOME'])
)
})
it('preserves a daemon-inherited user CODEX_HOME for real-home routing', async () => {
const spawnOptions = await daemonSpawnAndGetOptions(
{},
() => null,
() => ({ codexSystemDefaultRealHomeEnabled: true }) as never,
{ CODEX_HOME: '/home/me/.config/codex', ORCA_CODEX_HOME: undefined }
)
expect(spawnOptions.envToDelete).toEqual(expect.arrayContaining(['ORCA_CODEX_HOME']))
expect(spawnOptions.envToDelete).not.toEqual(expect.arrayContaining(['CODEX_HOME']))
})
it('does not strip the daemon-inherited CODEX_HOME when the flag is OFF', async () => {
const spawnOptions = await daemonSpawnAndGetOptions({}, () => null, undefined, {
CODEX_HOME: '/managed/home',
ORCA_CODEX_HOME: '/managed/home'
})
expect(spawnOptions.envToDelete ?? []).not.toEqual(expect.arrayContaining(['CODEX_HOME']))
})
it('prepends the bare-orca CLI shim dir to PATH for packaged Linux spawns', async () => {
const originalPlatform = process.platform
Object.defineProperty(process, 'platform', {
+46 -21
View File
@@ -647,12 +647,23 @@ const CODEX_HOME_ENV_KEYS = ['CODEX_HOME', 'ORCA_CODEX_HOME'] as const
// the marker so a shell-ready wrapper cannot restore the managed home. A
// user-set CODEX_HOME with no Orca marker is preserved untouched (see #8606).
function stripInheritedOrcaCodexHomeOverride(baseEnv: Record<string, string>): void {
const inheritedOrcaOverride = baseEnv.ORCA_CODEX_HOME ?? process.env.ORCA_CODEX_HOME
const inheritedCodexHome = baseEnv.CODEX_HOME ?? process.env.CODEX_HOME
if (inheritedOrcaOverride && inheritedCodexHome === inheritedOrcaOverride) {
delete baseEnv.CODEX_HOME
for (const key of getInheritedOrcaCodexHomeEnvKeysToDelete(baseEnv)) {
delete baseEnv[key]
}
delete baseEnv.ORCA_CODEX_HOME
}
// Why: the daemon spawns the PTY from its own inherited environment and honors
// only spawnOptions.envToDelete, so mutating the sparse env object is not enough
// to strip an Orca-owned CODEX_HOME the daemon already carries. Return the exact
// keys to delete, preserving a user-owned CODEX_HOME.
function getInheritedOrcaCodexHomeEnvKeysToDelete(env: Record<string, string>): string[] {
const inheritedOrcaOverride = env.ORCA_CODEX_HOME ?? process.env.ORCA_CODEX_HOME
const inheritedCodexHome = env.CODEX_HOME ?? process.env.CODEX_HOME
const keysToDelete = ['ORCA_CODEX_HOME']
if (inheritedOrcaOverride && inheritedCodexHome === inheritedOrcaOverride) {
keysToDelete.push('CODEX_HOME')
}
return keysToDelete
}
type GetSelectedCodexHomePath = (target?: CodexAccountSelectionTarget) => string | null
@@ -3082,6 +3093,12 @@ export function registerPtyHandlers(
isDaemonHostSpawn &&
shouldSkipCodexHomeEnvForWindowsShell(daemonShellOverride, cwd) &&
!selectedCodexHomePath
const stripInheritedOrcaCodexHome = shouldStripInheritedOrcaCodexHome({
target: codexSelectionTarget,
selectedCodexHomePath,
skipCodexHomeEnv,
settings: getSettings?.()
})
if (isDaemonHostSpawn && sessionId) {
if (!isSafePtySessionId(sessionId, app.getPath('userData'))) {
throw new Error('Invalid PTY session id')
@@ -3091,12 +3108,7 @@ export function registerPtyHandlers(
userDataPath: app.getPath('userData'),
selectedCodexHomePath,
skipCodexHomeEnv,
stripInheritedOrcaCodexHome: shouldStripInheritedOrcaCodexHome({
target: codexSelectionTarget,
selectedCodexHomePath,
skipCodexHomeEnv,
settings: getSettings?.()
}),
stripInheritedOrcaCodexHome,
githubAttributionEnabled: getSettings?.()?.enableGitHubAttribution ?? false,
launchCommand: args.command,
launchAgent: isTuiAgent(args.launchAgent) ? args.launchAgent : undefined,
@@ -3129,6 +3141,13 @@ export function registerPtyHandlers(
spawnOptions.envToDelete,
CODEX_HOME_ENV_KEYS
)
} else if (stripInheritedOrcaCodexHome) {
// Why: the daemon inherits its own CODEX_HOME; strip the Orca-owned
// override there too, preserving a user-set CODEX_HOME.
spawnOptions.envToDelete = mergePtyEnvDeletions(
spawnOptions.envToDelete,
getInheritedOrcaCodexHomeEnvKeysToDelete(env ?? {})
)
}
deleteRequestedEnvKeys(env, spawnOptions.envToDelete)
promoteAgentTeamsShimPath(env, requestedAgentTeamsPath)
@@ -3955,6 +3974,12 @@ export function registerPtyHandlers(
isDaemonHostSpawn &&
shouldSkipCodexHomeEnvForWindowsShell(effectiveShellOverride, cwd) &&
!selectedCodexHomePath
const stripInheritedOrcaCodexHome = shouldStripInheritedOrcaCodexHome({
target: codexSelectionTarget,
selectedCodexHomePath,
skipCodexHomeEnv,
settings: getSettings?.()
})
if (isDaemonHostSpawn) {
if (effectiveSessionId === undefined) {
// Should be unreachable: the expression above returns a string when
@@ -3979,12 +4004,7 @@ export function registerPtyHandlers(
userDataPath: app.getPath('userData'),
selectedCodexHomePath,
skipCodexHomeEnv,
stripInheritedOrcaCodexHome: shouldStripInheritedOrcaCodexHome({
target: codexSelectionTarget,
selectedCodexHomePath,
skipCodexHomeEnv,
settings: getSettings?.()
}),
stripInheritedOrcaCodexHome,
githubAttributionEnabled: getSettings?.()?.enableGitHubAttribution ?? false,
launchCommand: args.command,
launchAgent: isTuiAgent(args.launchAgent) ? args.launchAgent : undefined,
@@ -4023,12 +4043,17 @@ export function registerPtyHandlers(
const combinedEnvToDelete = mergePtyEnvDeletions(
mergePtyEnvDeletions(
mergePtyEnvDeletions(
mergePtyEnvDeletions(envToDelete, args.envToDelete ?? []),
agentTeamsEnvToDelete ?? []
mergePtyEnvDeletions(
mergePtyEnvDeletions(envToDelete, args.envToDelete ?? []),
agentTeamsEnvToDelete ?? []
),
isDaemonHostSpawn ? getInheritedAgentHookEnvKeysToDelete(spawnEnv) : []
),
isDaemonHostSpawn ? getInheritedAgentHookEnvKeysToDelete(spawnEnv) : []
skipCodexHomeEnv ? CODEX_HOME_ENV_KEYS : []
),
skipCodexHomeEnv ? CODEX_HOME_ENV_KEYS : []
// Why: real-home routing strips the Orca-owned override the daemon
// inherits, while preserving a user-set CODEX_HOME.
stripInheritedOrcaCodexHome ? getInheritedOrcaCodexHomeEnvKeysToDelete(spawnEnv ?? {}) : []
)
deleteRequestedEnvKeys(spawnEnv, combinedEnvToDelete)
promoteAgentTeamsShimPath(spawnEnv, requestedAgentTeamsPath)