fix(agent-hooks): a WSL host's Codex account-home launch with hooks off skips too; mark the R42 guard to drop with the bridge

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Neil
2026-10-22 05:33:23 -07:00
co-authored by Claude
parent f57817e216
commit 0146ba170b
4 changed files with 39 additions and 8 deletions
@@ -12,6 +12,8 @@ const { prepareHooks, resolveHome, listHomes } = vi.hoisted(() => ({
listHomes: vi.fn(() => ['/home/u/.local/share/orca/codex-accounts/a1/home'])
}))
const wslHost = vi.hoisted(() => vi.fn(() => false))
vi.mock('../ipc/wsl-guest-windows-drive-path', () => ({ isWslHostOrcadProcess: wslHost }))
vi.mock('../codex/codex-account-home-hook', () => ({
reconcileCodexAccountHomeHook: prepareHooks
}))
@@ -41,6 +43,19 @@ describe('orcadCodexAccountHomes', () => {
prepareHooks.mockClear()
})
it('on a WSL host with hooks off, leaves the bridge-shared entry alone (R42)', async () => {
wslHost.mockReturnValue(true)
const homes = orcadCodexAccountHomes(
() => settings({ agentStatusHooksEnabled: false }),
noCleanup
)
await expect(homes.selectLaunchHome(undefined, { CODEX_HOME: ACCOUNT_HOME })).resolves.toBe(
ACCOUNT_HOME
)
expect(prepareHooks).not.toHaveBeenCalled()
wslHost.mockReturnValue(false)
})
it('puts the hook into a client-sent account home and launches on it', async () => {
const homes = orcadCodexAccountHomes(() => settings({}), noCleanup)
await expect(
+6 -5
View File
@@ -7,6 +7,7 @@ import {
import { reconcileCodexAccountHomeHook } from '../codex/codex-account-home-hook'
import { stopCodexStateDbBackfillRecoveries } from '../codex/codex-state-db-backfill-recovery'
import type { GetSelectedCodexHomePath } from '../ipc/pty/host-env/types'
import { isWslHostOrcadProcess } from '../ipc/wsl-guest-windows-drive-path'
import type { OrcadRuntimeCleanup } from './orcad-runtime-lifetime'
/**
@@ -26,11 +27,11 @@ export function orcadCodexAccountHomes(
if (!home) {
return null
}
await reconcileCodexAccountHomeHook(
home,
() => isAgentStatusHooksEnabledForAgent(getSettings(), 'codex'),
context?.launchesCodex === true
)
const isEnabled = () => isAgentStatusHooksEnabledForAgent(getSettings(), 'codex')
// R42, COMPAT(wsl-bridge): the bridge's panes share these homes; off skips until D4 drops it.
if (isEnabled() || !isWslHostOrcadProcess()) {
await reconcileCodexAccountHomeHook(home, isEnabled, context?.launchesCodex === true)
}
return home
}
return {
@@ -19,10 +19,13 @@ vi.mock('../ipc/wsl-guest-windows-drive-path', () => ({
}))
function controller(): RuntimeClientSettingsController {
const settings = createGlobalSettingsFixture({ agentStatusHooksEnabled: true })
let settings = createGlobalSettingsFixture({ agentStatusHooksEnabled: true })
return new RuntimeClientSettingsController({
getSettings: () => settings,
updateSettings: (updates: Partial<GlobalSettings>) => Object.assign(settings, updates),
updateSettings: (updates: Partial<GlobalSettings>) => {
settings = { ...settings, ...updates }
return settings
},
runDurableMutation: async (mutate) => mutate().value
})
}
@@ -46,4 +49,16 @@ describe('turning status hooks off through a paired client', () => {
expect.objectContaining({ keepSharedEntries: keep })
)
})
it('keeps them too when one agent is disabled on a WSL host', async () => {
mocks.wslHost.mockReturnValue(true)
await controller().update({ disabledTuiAgents: ['claude'] })
expect(mocks.apply).toHaveBeenCalledWith(
true,
expect.anything(),
expect.objectContaining({ keepSharedEntries: true })
)
})
})
+1 -1
View File
@@ -246,7 +246,7 @@ export class RuntimeClientSettingsController {
return
}
await applyAgentStatusHooksEnabled(settings.agentStatusHooksEnabled !== false, settings, {
// R42: in a distro the WSL bridge still runs panes on these entries, as startup knows.
// R42, COMPAT(wsl-bridge): the bridge's panes in this distro share these entries; drop at D4.
keepSharedEntries: isWslHostOrcadProcess(),
shouldHydrateShellPath: getAppEnvironment().isPackaged(),
onInstallError: recordManagedHookInstallFailure,