test(codex): cover the runtime controller's resume-pinned account recording

The runtime controller's spawn path repeats the same
recordCodexPaneAccountForSpawn call the ipc handler makes, but nothing
exercised it: reverting either pinnedByResume or launchCodexHomePath at
that site left all 392 tests green. That site is the CLI/relay resume
path (terminal.ts accepts resumeProviderSession, orca-runtime threads it
into ptyController.spawn), so an unnoticed revert there would silently
restore the bug for those clients.

Also corrects the guard's rationale. The shared runtime mirror only
hot-swaps to the current selection on the legacy flag-OFF lane; with the
real-home routing that ships unconditionally, syncForCurrentSelection
early-returns through syncSelfContainedManagedSelection and never
rewrites the mirror's auth.json. Declining to attribute is still right —
an unowned home cannot be named — but not for the stated reason, and a
pane resumed into the mirror after the per-account rollout is genuinely
stale and stays unreported.
This commit is contained in:
Brennan Benson
2026-07-26 18:28:26 -07:00
parent d2885b6207
commit 6ba25c67f4
2 changed files with 126 additions and 3 deletions
+6 -3
View File
@@ -66,8 +66,11 @@ function resolveCodexHomeOwnerAccountId(args: {
getCodexSelectionLaneKey(getCodexSelectionTargetForAccount(account)) === laneKey &&
normalizeRuntimePathForComparison(account.managedHomePath) === launchHome
)
// Why: the shared runtime mirror hot-swaps to whichever account is selected, so
// an unattributable home is no evidence the pane is on a different one. A
// wrong restart notice silently drops every keystroke in that terminal.
// Why: an unowned home cannot be named, and naming the account a pane is stuck
// on is the prompt's whole job — so decline rather than guess. A wrong notice
// silently drops every keystroke in that terminal. Note the shared runtime
// mirror only hot-swaps to the current selection on the legacy flag-OFF lane;
// a pane resumed into it after the per-account rollout is genuinely stale but
// still unnameable, so that cohort stays unreported.
return owner ? owner.id : undefined
}
+120
View File
@@ -13638,6 +13638,126 @@ describe('registerPtyHandlers', () => {
expect(forgetCodexPaneAccountMock).toHaveBeenCalledWith('pty-resumed')
})
// Why: the runtime controller is the CLI/relay resume path, and it repeats the
// same recording call the ipc handler makes. Without its own coverage a revert
// there is invisible.
it('records the origin account for a resumed Codex pane spawned by the runtime controller', async () => {
type RuntimeSpawnController = {
spawn(args: Record<string, unknown>): Promise<{ id: string }>
}
setLocalPtyProvider({
spawn: vi.fn(async () => ({ id: 'pty-runtime-resumed' })),
write: vi.fn(),
resize: vi.fn(),
kill: vi.fn(),
shutdown: vi.fn(),
onData: vi.fn(() => vi.fn()),
onExit: vi.fn(() => vi.fn()),
listProcesses: vi.fn(async () => []),
getForegroundProcess: vi.fn(async () => null)
} as never)
const runtime = {
setPtyController: vi.fn(),
registerPty: vi.fn(),
noteTerminalSpawnCommand: vi.fn(),
onPtySpawned: vi.fn(),
onPtyExit: vi.fn(),
onPtyData: vi.fn()
}
const getSettings = vi.fn().mockReturnValue({
activeCodexManagedAccountId: 'account-b',
codexManagedAccounts: [
{ id: 'account-a', managedHomePath: '/managed/origin/home' },
{ id: 'account-b', managedHomePath: '/managed/current/home' }
]
})
handlers.clear()
registerPtyHandlers(
mainWindow as never,
runtime as never,
vi.fn(() => '/managed/current/home'),
getSettings as never,
undefined,
undefined,
{ prepareCodexSessionResume: async () => ({ codexHomePath: '/managed/origin/home' }) }
)
const controller = runtime.setPtyController.mock.calls[0]?.[0] as RuntimeSpawnController
await controller.spawn({
cols: 80,
rows: 24,
worktreeId: 'wt-runtime',
command: 'codex resume session-a',
launchAgent: 'codex',
resumeProviderSession: {
key: 'session_id',
id: 'session-a',
transcriptPath: '/managed/origin/home/sessions/2026/07/20/rollout-a.jsonl'
}
})
expect(recordCodexPaneAccountMock.mock.calls).toEqual([
['pty-runtime-resumed', { selectionKey: 'host', accountId: 'account-a' }]
])
expect(forgetCodexPaneAccountMock).not.toHaveBeenCalled()
})
it('leaves a runtime-controller resumed Codex pane unattributed when no account owns its home', async () => {
type RuntimeSpawnController = {
spawn(args: Record<string, unknown>): Promise<{ id: string }>
}
setLocalPtyProvider({
spawn: vi.fn(async () => ({ id: 'pty-runtime-resumed' })),
write: vi.fn(),
resize: vi.fn(),
kill: vi.fn(),
shutdown: vi.fn(),
onData: vi.fn(() => vi.fn()),
onExit: vi.fn(() => vi.fn()),
listProcesses: vi.fn(async () => []),
getForegroundProcess: vi.fn(async () => null)
} as never)
const runtime = {
setPtyController: vi.fn(),
registerPty: vi.fn(),
noteTerminalSpawnCommand: vi.fn(),
onPtySpawned: vi.fn(),
onPtyExit: vi.fn(),
onPtyData: vi.fn()
}
const getSettings = vi.fn().mockReturnValue({
activeCodexManagedAccountId: 'account-b',
codexManagedAccounts: [{ id: 'account-b', managedHomePath: '/managed/current/home' }]
})
handlers.clear()
registerPtyHandlers(
mainWindow as never,
runtime as never,
vi.fn(() => '/managed/current/home'),
getSettings as never,
undefined,
undefined,
{ prepareCodexSessionResume: async () => ({ codexHomePath: '/managed/shared-mirror/home' }) }
)
const controller = runtime.setPtyController.mock.calls[0]?.[0] as RuntimeSpawnController
await controller.spawn({
cols: 80,
rows: 24,
worktreeId: 'wt-runtime',
command: 'codex resume session-a',
launchAgent: 'codex',
resumeProviderSession: {
key: 'session_id',
id: 'session-a',
transcriptPath: '/managed/shared-mirror/home/sessions/2026/07/20/rollout-a.jsonl'
}
})
expect(recordCodexPaneAccountMock).not.toHaveBeenCalled()
expect(forgetCodexPaneAccountMock).toHaveBeenCalledWith('pty-runtime-resumed')
})
it('seeds cold restore at recovered dimensions with a legacy dimensionless fallback', async () => {
const oscLinks = [{ row: 0, startCol: 0, endCol: 8, uri: 'https://example.com/restored' }]
const coldRestore = {