Files
orca/src/main/runtime/orca-runtime-structured-tui-tab-binding.test.ts
T
Brennan Benson ca409f0634 fix(native-chat): let the reservation holder win an overlapping adoption
Two adoptions of the same Codex pane destroyed each other. The pane binding
was released by pty id alone, gated on a `priorBoundSessionId` sampled before
the reservation, and both attempts carry the same sessionId — so the attempt
whose reservation had been superseded unbound the pane the winner was proving
on, `admitProof` refused the winner's `/status` keystroke, and both failed.

The write gate now records which attempt holds a pane, keyed on the spawn
token the reservation already mints: a claim supersedes another attempt's but
never a settled owner's, the release is a compare-and-clear, and a proven
owner settles the binding so no later attempt can take it. No lock is needed;
the reservation release beside it was already fence-scoped and unchanged.

A failed `releaseAdoptedTuiReservation` stays swallowed — the proof error is
the one the user must act on — but is now logged with session, fence and spawn
token, because a release that never persisted leaves the lease latched and
refuses every later attempt with no record of why.

Adoption's no-record branch is deleted. The only caller reserves the lease
first and nothing deletes a record, so it minted an owner for a session the
store had never heard of in unit tests only; its test now drives the real
reserve-then-adopt sequence, and a new one pins the refusal.

Launch-at-chat discarded `waitForAgentReady`'s result, so a readiness timeout
still flipped the tab to chat and adoption then probed a shell. It stays in
terminal view instead: the terminal is usable and the view toggle re-runs
adoption whenever the user wants it.

Each fix was reverted against its new test to confirm the test reddens; all
four defects had been living under green suites.
2026-08-19 20:43:00 -07:00

831 lines
29 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { getDefaultWorkspaceSession } from '../../shared/constants'
import type { StructuredAgentSessionHandoffTransport } from '../native-chat/agent-session-wire/structured-agent-session-handoff-types'
import { setStructuredAgentSessionHost } from '../native-chat/agent-session-wire/structured-agent-session-registry'
import { createEphemeralAgentSessionClaimSigner } from './agent-session-claim-identity'
import { agentSessionPtyWriteGate } from './agent-session-pty-write-gate'
import { OrcaRuntimeService } from './orca-runtime'
const {
probeAgentSessionProcessIdentity,
proveCodexTuiRollout,
readStructuredTuiProcessIdentity,
resolveLiveCodexTuiRollout,
resolvePinnedCodexRolloutProof
} = vi.hoisted(() => ({
probeAgentSessionProcessIdentity: vi.fn(),
proveCodexTuiRollout: vi.fn(),
readStructuredTuiProcessIdentity: vi.fn(),
resolveLiveCodexTuiRollout: vi.fn(),
resolvePinnedCodexRolloutProof: vi.fn()
}))
vi.mock('./structured-tui-process-identity', () => ({ readStructuredTuiProcessIdentity }))
vi.mock('../codex/codex-tui-rollout-proof', () => ({
proveCodexTuiRollout,
resolveLiveCodexTuiRollout,
resolvePinnedCodexRolloutProof
}))
vi.mock('./agent-session-process-identity-probe', async (importOriginal) => ({
...(await importOriginal()),
probeAgentSessionProcessIdentity
}))
const WORKTREE_ID = 'repo-1::/tmp/structured-handoff'
function terminalAdoptionHarness() {
const runtime = new OrcaRuntimeService({ getSettings: () => ({ agentDefaultEnv: {} }) } as never)
runtime.setPtyController({
listProcesses: async () => [
{ id: 'pty-adopt', incarnationId: 'inc-adopt', rootProcessId: 31337 }
]
} as never)
const internal = runtime as unknown as {
ptysById: Map<string, unknown>
resolveRuntimeFileTarget(): Promise<unknown>
resolveStructuredAgentSessionCreateIntent(input: { envelope: unknown }): Promise<unknown>
issueStructuredTuiPtyHandle(): string
}
internal.ptysById.set('pty-adopt', {
ptyId: 'pty-adopt',
connected: true,
connectionId: null,
wslDistro: null,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
worktreeId: WORKTREE_ID,
incarnationId: 'inc-adopt'
})
internal.resolveRuntimeFileTarget = vi.fn(async () => ({
connectionId: null,
worktree: { id: WORKTREE_ID }
}))
internal.resolveStructuredAgentSessionCreateIntent = vi.fn(async ({ envelope }) => ({
envelope,
location: {
executionHostId: 'local',
wslDistro: null,
workspaceId: WORKTREE_ID,
workspaceKind: 'git-worktree'
},
provider: 'codex',
agent: 'codex',
accountHome: { variable: 'CODEX_HOME', path: '/tmp/codex-home' },
runtimeKind: 'native'
}))
internal.issueStructuredTuiPtyHandle = vi.fn(() => 'term-adopt')
return runtime
}
/** The host half adoption now needs: the lease is reserved before the provider probe runs. */
function structuredHostDouble(overrides: Record<string, unknown> = {}) {
return {
reserveAdoptedTuiOwner: vi.fn(async (input: { spawnToken: string }) => ({
ok: true,
fence: 1,
spawnToken: input.spawnToken
})),
releaseAdoptedTuiReservation: vi.fn(async () => undefined),
adoptTuiOwner: vi.fn(async () => ({ ok: true, replayed: false, fence: 1 })),
...overrides
}
}
function notifier(revealTerminalSession: ReturnType<typeof vi.fn>) {
return {
worktreesChanged: vi.fn(),
reposChanged: vi.fn(),
activateWorktree: vi.fn(),
createTerminal: vi.fn(),
revealTerminalSession,
splitTerminal: vi.fn(),
renameTerminal: vi.fn(),
focusTerminal: vi.fn(),
closeTerminal: vi.fn(),
sleepWorktree: vi.fn(),
terminalFitOverrideChanged: vi.fn(),
terminalDriverChanged: vi.fn()
}
}
function structuredTabNotifier() {
return {
...notifier(vi.fn()),
focusEditorTab: vi.fn()
}
}
describe('structured TUI launch tab binding', () => {
it('adopts the proven local Codex pane as a durable TUI owner', async () => {
const runtime = terminalAdoptionHarness()
const adoptTuiOwner = vi.fn(async () => ({ ok: true, replayed: false, fence: 1 }))
setStructuredAgentSessionHost(structuredHostDouble({ adoptTuiOwner }) as never)
proveCodexTuiRollout.mockResolvedValueOnce({
transcriptPath: '/tmp/codex-home/rollout.jsonl'
})
const process = {
hostId: 'local',
pid: 4242,
processStartTimeMs: 1_700_000_000_000,
spawnToken: 'spawn-adopt'
}
readStructuredTuiProcessIdentity.mockResolvedValueOnce(process).mockResolvedValueOnce(process)
try {
await expect(
runtime.adoptStructuredAgentSessionTerminal(
{
envelope: {
sessionId: 'session-adopt',
clientOperationId: 'operation-adopt',
expectedRuntimeFence: null,
payloadFingerprint: 'f'.repeat(64)
},
worktree: `id:${WORKTREE_ID}`,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
ptyId: 'pty-adopt',
threadId: 'thread-adopt'
},
{ callerKey: 'renderer-1' }
)
).resolves.toMatchObject({ ok: true })
expect(adoptTuiOwner).toHaveBeenCalledWith(
expect.objectContaining({
owner: expect.objectContaining({
adoptedTerminal: true,
historySource: 'provider-resume',
transcriptPath: '/tmp/codex-home/rollout.jsonl',
link: expect.objectContaining({
origin: 'adopted',
handle: { provider: 'codex', threadId: 'thread-adopt' }
})
})
})
)
expect(agentSessionPtyWriteGate.boundSessionId('pty-adopt')).toBe('session-adopt')
expect(proveCodexTuiRollout).toHaveBeenCalledWith(
expect.objectContaining({ threadId: 'thread-adopt' })
)
expect(resolvePinnedCodexRolloutProof).not.toHaveBeenCalled()
} finally {
agentSessionPtyWriteGate.unbindPty('pty-adopt')
setStructuredAgentSessionHost(null)
}
})
it('refuses adoption when the provider rollout cannot be proved', async () => {
const runtime = terminalAdoptionHarness()
const host = structuredHostDouble()
setStructuredAgentSessionHost(host as never)
proveCodexTuiRollout.mockRejectedValueOnce(
new Error('The agent terminal did not prove the expected Codex rollout.')
)
readStructuredTuiProcessIdentity.mockResolvedValueOnce({
hostId: 'local',
pid: 4242,
processStartTimeMs: 1_700_000_000_000,
spawnToken: 'spawn-adopt'
})
try {
await expect(
runtime.adoptStructuredAgentSessionTerminal(
{
envelope: {
sessionId: 'session-adopt',
clientOperationId: 'operation-adopt',
expectedRuntimeFence: null,
payloadFingerprint: 'f'.repeat(64)
},
worktree: `id:${WORKTREE_ID}`,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
ptyId: 'pty-adopt',
threadId: 'thread-adopt'
},
{ callerKey: 'renderer-1' }
)
).rejects.toThrow('did not prove the expected Codex rollout')
expect(agentSessionPtyWriteGate.boundSessionId('pty-adopt')).toBeNull()
// A proof that never lands hands the reservation back; nothing latches the next attempt.
expect(host.releaseAdoptedTuiReservation).toHaveBeenCalledTimes(1)
} finally {
setStructuredAgentSessionHost(null)
}
})
it('reports a reservation release that fails, without masking the proof error', async () => {
const runtime = terminalAdoptionHarness()
const host = structuredHostDouble({
releaseAdoptedTuiReservation: vi.fn(async () => {
throw new Error('store write failed')
})
})
setStructuredAgentSessionHost(host as never)
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
proveCodexTuiRollout.mockRejectedValueOnce(
new Error('The agent terminal did not prove the expected Codex rollout.')
)
readStructuredTuiProcessIdentity.mockResolvedValueOnce({
hostId: 'local',
pid: 4242,
processStartTimeMs: 1_700_000_000_000,
spawnToken: 'spawn-adopt'
})
try {
await expect(
runtime.adoptStructuredAgentSessionTerminal(
{
envelope: {
sessionId: 'session-release-failure',
clientOperationId: 'operation-release-failure',
expectedRuntimeFence: null,
payloadFingerprint: 'f'.repeat(64)
},
worktree: `id:${WORKTREE_ID}`,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
ptyId: 'pty-adopt',
threadId: 'thread-adopt'
},
{ callerKey: 'renderer-1' }
)
).rejects.toThrow('did not prove the expected Codex rollout')
const reserved = host.reserveAdoptedTuiOwner.mock.calls[0]?.[0] as { spawnToken: string }
const logged = warn.mock.calls.find(
([message]) => message === '[native-chat] adopted TUI reservation release failed'
)?.[1] as { error: Error } | undefined
// A latched lease refuses every later attempt, so the cause cannot vanish with the throw.
expect(logged).toMatchObject({
sessionId: 'session-release-failure',
fence: 1,
spawnToken: reserved.spawnToken
})
expect(logged?.error.message).toBe('store write failed')
} finally {
warn.mockRestore()
setStructuredAgentSessionHost(null)
agentSessionPtyWriteGate.unbindPty('pty-adopt')
}
})
it('refuses a thread proof when the Codex process changes during it', async () => {
const runtime = terminalAdoptionHarness()
const host = structuredHostDouble()
setStructuredAgentSessionHost(host as never)
proveCodexTuiRollout.mockResolvedValueOnce({
transcriptPath: '/tmp/codex-home/rollout.jsonl'
})
readStructuredTuiProcessIdentity
.mockResolvedValueOnce({
hostId: 'local',
pid: 4242,
processStartTimeMs: 1_700_000_000_000,
spawnToken: 'spawn-adopt'
})
.mockResolvedValueOnce({
hostId: 'local',
pid: 5252,
processStartTimeMs: 1_700_000_010_000,
spawnToken: 'spawn-adopt'
})
await expect(
runtime.adoptStructuredAgentSessionTerminal(
{
envelope: {
sessionId: 'session-process-swap',
clientOperationId: 'operation-process-swap',
expectedRuntimeFence: null,
payloadFingerprint: 'f'.repeat(64)
},
worktree: `id:${WORKTREE_ID}`,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
ptyId: 'pty-adopt',
threadId: 'thread-adopt'
},
{ callerKey: 'renderer-1' }
)
).rejects.toThrow('process changed during conversation proof')
expect(agentSessionPtyWriteGate.boundSessionId('pty-adopt')).toBeNull()
expect(host.releaseAdoptedTuiReservation).toHaveBeenCalledTimes(1)
setStructuredAgentSessionHost(null)
})
it('discovers the provider thread when hook status has not published it yet', async () => {
const runtime = terminalAdoptionHarness()
const adoptTuiOwner = vi.fn(async () => ({ ok: true, replayed: false, fence: 1 }))
setStructuredAgentSessionHost(structuredHostDouble({ adoptTuiOwner }) as never)
resolveLiveCodexTuiRollout.mockResolvedValueOnce({
threadId: 'thread-discovered',
transcriptPath: '/tmp/codex-home/discovered.jsonl'
})
const process = {
hostId: 'local',
pid: 4242,
processStartTimeMs: 1_700_000_000_000,
spawnToken: 'spawn-adopt'
}
readStructuredTuiProcessIdentity.mockResolvedValueOnce(process).mockResolvedValueOnce(process)
try {
await expect(
runtime.adoptStructuredAgentSessionTerminal(
{
envelope: {
sessionId: 'session-discovered',
clientOperationId: 'operation-discovered',
expectedRuntimeFence: null,
payloadFingerprint: 'f'.repeat(64)
},
worktree: `id:${WORKTREE_ID}`,
tabId: 'tab-adopt',
paneKey: 'tab-adopt:leaf-adopt',
ptyId: 'pty-adopt'
},
{ callerKey: 'renderer-1' }
)
).resolves.toMatchObject({ ok: true })
expect(adoptTuiOwner).toHaveBeenCalledWith(
expect.objectContaining({
owner: expect.objectContaining({
transcriptPath: '/tmp/codex-home/discovered.jsonl',
link: expect.objectContaining({
handle: { provider: 'codex', threadId: 'thread-discovered' }
})
})
})
)
} finally {
agentSessionPtyWriteGate.unbindPty('pty-adopt')
setStructuredAgentSessionHost(null)
}
})
it('reveals the structured chat tab when reverse handoff completes', () => {
const runtime = new OrcaRuntimeService()
const targetNotifier = structuredTabNotifier()
runtime.setNotifier(targetNotifier as never)
const transport = (
runtime as unknown as {
createStructuredAgentSessionHandoffTransport(): StructuredAgentSessionHandoffTransport
}
).createStructuredAgentSessionHandoffTransport()
transport.revealNativeSession?.({ workspaceId: WORKTREE_ID, sessionId: 'session-1' })
expect(targetNotifier.focusEditorTab).toHaveBeenCalledWith(
'structured-agent-session-session-1',
WORKTREE_ID
)
})
it.each([
{
restoreMode: 'development reload',
durableTerminalHandle: 'term_current_runtime',
persistedIncarnationId: 'incarnation-1'
},
{
restoreMode: 'packaged restart',
durableTerminalHandle: 'term_previous_runtime',
persistedIncarnationId: 'incarnation-1'
},
{
restoreMode: 'packaged restart before incarnation hydration',
durableTerminalHandle: 'term_previous_runtime',
persistedIncarnationId: null
}
])(
'recovers a live TUI after a $restoreMode with current runtime routing',
async ({ durableTerminalHandle, persistedIncarnationId }) => {
const namespace = {
machine: 'native:test',
principal: 'uid:1',
container: 'native',
providerRoot: '/tmp/codex-home'
}
const signer = createEphemeralAgentSessionClaimSigner('profile-test')
const claim = signer.createClaim({
namespace,
identity: { agent: 'codex', providerSession: { key: 'session_id', id: 'thread-1' } },
canonicalWorktreeId: WORKTREE_ID
})
const terminalHandle = 'term_current_runtime'
const leafId = '23013912-13f8-44e5-818f-d40a1ff4e8c5'
const conflictingLeafId = '33013912-13f8-44e5-818f-d40a1ff4e8c5'
resolvePinnedCodexRolloutProof.mockResolvedValue('/tmp/codex-home/sessions/thread-1.jsonl')
const writeAgentSessionProof = vi.fn(() => false)
const persistedSession = {
...getDefaultWorkspaceSession(),
tabsByWorktree: {
[WORKTREE_ID]: [
{
id: 'tab-cold-owner',
ptyId: 'pty-cold-owner',
worktreeId: WORKTREE_ID,
title: 'Codex',
customTitle: null,
color: null,
sortOrder: 0,
createdAt: 1
}
]
},
terminalLayoutsByTabId: {
'tab-cold-owner': {
root: { type: 'leaf' as const, leafId },
activeLeafId: leafId,
expandedLeafId: null,
ptyIdsByLeafId: { [leafId]: 'pty-cold-owner' }
}
},
terminalPtyIncarnationsByPaneKey: persistedIncarnationId
? { [`tab-cold-owner:${leafId}`]: persistedIncarnationId }
: {}
}
const runtime = new OrcaRuntimeService(
{ getWorkspaceSession: () => persistedSession } as never,
undefined,
{
agentSessionClaimSigner: signer
}
)
runtime.setPtyController({
listProcesses: vi.fn(async () => [
{
id: 'pty-cold-owner',
incarnationId: 'incarnation-1',
rootProcessId: 31337,
cwd: '/tmp/structured-handoff',
title: 'codex',
worktreeId: WORKTREE_ID,
terminalHandle: durableTerminalHandle,
agentSessionOwners: [
{
claim,
generation: 'generation-1',
phase: 'live' as const,
ptyId: 'pty-cold-owner',
surface: {
worktreeId: WORKTREE_ID,
tabId: 'tab-cold-owner',
leafId,
terminalHandle: durableTerminalHandle
}
}
]
},
{
id: 'pty-conflicting-owner',
incarnationId: 'incarnation-2',
rootProcessId: 41337,
cwd: '/tmp/structured-handoff',
title: 'codex',
worktreeId: WORKTREE_ID,
terminalHandle: 'term_conflicting_runtime',
agentSessionOwners: [
{
claim,
generation: 'generation-2',
phase: 'live' as const,
ptyId: 'pty-conflicting-owner',
surface: {
worktreeId: WORKTREE_ID,
tabId: 'tab-conflicting-owner',
leafId: conflictingLeafId,
terminalHandle: 'term_conflicting_runtime'
}
}
]
}
]),
write: () => true,
kill: () => true,
writeAgentSessionProof,
getForegroundProcess: async () => null
})
const internal = runtime as unknown as {
createStructuredAgentSessionHandoffTransport(): StructuredAgentSessionHandoffTransport
refreshMobileSessionPtyRecords(): Promise<Set<string> | null>
listResolvedWorktrees(): Promise<unknown[]>
resolveTerminalWorkspaceLaunchScope(): Promise<{
id: string
path: string
connectionId: null
repo: null
folderWorkspace: null
}>
getAgentSessionExecutionNamespace(): typeof namespace
ptysById: Map<
string,
{ launchToken: string | null; launchAgent: string | null; agentSessionOwners: unknown[] }
>
}
internal.listResolvedWorktrees = vi.fn(async () => [
{ id: WORKTREE_ID, repoId: 'repo-1', path: '/tmp/structured-handoff' }
])
internal.resolveTerminalWorkspaceLaunchScope = vi.fn(async () => ({
id: WORKTREE_ID,
path: '/tmp/structured-handoff',
connectionId: null,
repo: null,
folderWorkspace: null
}))
internal.getAgentSessionExecutionNamespace = () => namespace
runtime.registerPreAllocatedHandleForPty('pty-cold-owner', terminalHandle)
probeAgentSessionProcessIdentity.mockResolvedValue({
outcome: 'identity-matched',
matchedOn: ['process-start-time']
})
readStructuredTuiProcessIdentity.mockResolvedValue({
hostId: 'local',
pid: 4243,
processStartTimeMs: 10,
spawnToken: 'spawn-token'
})
await internal.refreshMobileSessionPtyRecords()
const coldPty = internal.ptysById.get('pty-cold-owner')!
expect(coldPty).toMatchObject({ launchToken: null, launchAgent: null })
expect(coldPty.agentSessionOwners).toHaveLength(1)
const owner = await internal.createStructuredAgentSessionHandoffTransport().recoverTuiOwner({
sessionId: 'session-1',
location: { workspaceId: WORKTREE_ID, executionHostId: 'local' },
accountHome: { variable: 'CODEX_HOME', path: namespace.providerRoot },
providerHandleChain: [
{ handle: { provider: 'codex', threadId: 'thread-1' }, observedAt: 1 }
],
lease: {
ownerProcess: {
hostId: 'local',
pid: 4243,
processStartTimeMs: 10,
spawnToken: 'spawn-token'
},
runtimeFence: 3
}
} as never)
expect(owner.terminal).toEqual({
handle: terminalHandle,
tabId: 'tab-cold-owner',
paneKey: `tab-cold-owner:${leafId}`,
ptyId: 'pty-cold-owner'
})
if (durableTerminalHandle !== terminalHandle) {
expect(owner.terminal.handle).not.toBe(durableTerminalHandle)
}
expect(resolvePinnedCodexRolloutProof).toHaveBeenCalledWith(
namespace.providerRoot,
'thread-1'
)
expect(writeAgentSessionProof).not.toHaveBeenCalled()
expect(readStructuredTuiProcessIdentity).toHaveBeenCalledWith(
expect.objectContaining({ rootPid: 31337, spawnToken: 'spawn-token' })
)
expect(agentSessionPtyWriteGate.boundSessionId('pty-cold-owner')).toBe('session-1')
expect(agentSessionPtyWriteGate.boundSessionId('pty-conflicting-owner')).toBeNull()
agentSessionPtyWriteGate.unbindPty('pty-cold-owner')
}
)
it('proves the published launch tab before returning its revealed renderer binding', async () => {
let explicitStatus: {
state: 'working' | 'done'
prompt: string
receivedAt: number
stateStartedAt: number
paneKey: string
terminalHandle: string
} | null = null
const revealTerminalSession = vi.fn(
(_worktreeId: string, _options: { tabId?: string; leafId?: string; ptyId?: string }) =>
Promise.resolve({ tabId: 'tab-renderer' })
)
const runtime = new OrcaRuntimeService(
{
getSettings: () => ({
disabledTuiAgents: [],
agentCmdOverrides: {},
agentDefaultArgs: {
codex: '-m gpt-5.6-sol -c model_reasoning_effort=high'
},
agentDefaultEnv: {}
})
} as never,
undefined,
{
getAgentStatusSnapshot: () => (explicitStatus ? [explicitStatus as never] : [])
}
)
runtime.setNotifier(notifier(revealTerminalSession) as never)
const spawn = vi.fn().mockResolvedValue({ id: 'pty-structured', pid: 4242 })
runtime.setPtyController({
spawn,
write: () => true,
kill: () => true,
getForegroundProcess: async () => null
})
const internal = runtime as unknown as {
createStructuredAgentSessionHandoffTransport(): StructuredAgentSessionHandoffTransport
resolveTerminalWorkspaceLaunchScope(): Promise<{
id: string
path: string
connectionId: null
repo: null
folderWorkspace: null
}>
markLocalWorkspaceTrustedForAgent(): void
waitForTerminal(): Promise<unknown>
waitForStructuredTuiProof(): Promise<{ transcriptPath?: string }>
waitForStructuredTuiPtyExit(): Promise<void>
closeTerminal(handle: string): Promise<unknown>
handles: Map<
string,
{
rendererGraphEpoch: number
tabId: string
leafId: string
}
>
graphStatus: 'ready'
}
internal.resolveTerminalWorkspaceLaunchScope = vi.fn(async () => ({
id: WORKTREE_ID,
path: '/tmp/structured-handoff',
connectionId: null,
repo: null,
folderWorkspace: null
}))
internal.markLocalWorkspaceTrustedForAgent = vi.fn()
const waitForTerminal = vi.fn(async () => ({}))
internal.waitForTerminal = waitForTerminal
const waitForStructuredTuiProof = vi.fn(async () => {
const snapshot = await runtime.listMobileSessionTabs(`id:${WORKTREE_ID}`)
expect(snapshot.tabs).toContainEqual(
expect.objectContaining({
type: 'terminal',
parentTabId: expect.any(String),
leafId: expect.any(String),
ptyId: 'pty-structured',
terminal: expect.any(String)
})
)
expect(revealTerminalSession).not.toHaveBeenCalled()
return { transcriptPath: '/tmp/rollout.jsonl' }
})
internal.waitForStructuredTuiProof = waitForStructuredTuiProof
const waitForStructuredTuiPtyExit = vi.fn(async () => {})
internal.waitForStructuredTuiPtyExit = waitForStructuredTuiPtyExit
const closeTerminal = vi.fn(async () => undefined)
internal.closeTerminal = closeTerminal
readStructuredTuiProcessIdentity.mockResolvedValue({
hostId: 'local',
pid: 4243,
processStartTimeMs: 10,
spawnToken: 'spawn-token'
})
probeAgentSessionProcessIdentity.mockResolvedValue({
outcome: 'identity-matched',
matchedOn: ['process-start-time']
})
const transport = internal.createStructuredAgentSessionHandoffTransport()
const owner = await transport.launchTui({
record: {
sessionId: 'session-1',
location: { workspaceId: WORKTREE_ID, executionHostId: 'local' },
accountHome: { variable: 'CODEX_HOME', path: '/tmp/codex-home' },
options: { model: 'gpt-5.6-terra', effort: 'medium' },
providerHandleChain: [
{ handle: { provider: 'codex', threadId: 'thread-1' }, observedAt: 1 }
]
} as never,
fence: 3,
spawnToken: 'spawn-token'
})
const reveal = revealTerminalSession.mock.calls[0]?.[1] as {
tabId: string
leafId: string
}
expect(owner.terminal).toMatchObject({
tabId: 'tab-renderer',
paneKey: `${reveal.tabId}:${reveal.leafId}`,
ptyId: 'pty-structured'
})
expect(waitForTerminal).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({ condition: 'tui-idle' })
)
expect(waitForStructuredTuiProof).toHaveBeenCalledOnce()
expect(waitForStructuredTuiProof.mock.invocationCallOrder[0]).toBeLessThan(
revealTerminalSession.mock.invocationCallOrder[0]!
)
const launchCommand = spawn.mock.calls[0]?.[0]?.command
expect(launchCommand).toContain("'-m' 'gpt-5.6-terra'")
expect(launchCommand).toContain("'-c' 'model_reasoning_effort=medium'")
expect(launchCommand).not.toContain('gpt-5.6-sol')
expect(launchCommand).not.toContain('model_reasoning_effort=high')
Object.assign(internal.handles.get(owner.terminal.handle)!, {
rendererGraphEpoch: -1,
tabId: 'tab-retired',
leafId: 'leaf-retired'
})
internal.graphStatus = 'ready'
explicitStatus = {
state: 'working',
prompt: '',
receivedAt: Date.now(),
stateStartedAt: Date.now(),
paneKey: owner.terminal.paneKey,
terminalHandle: owner.terminal.handle
}
expect(transport.tuiStatus(owner)).toBe('busy')
await expect(
transport.waitForTuiIdleOrExit(owner, new AbortController().signal)
).resolves.toBeNull()
explicitStatus = { ...explicitStatus, state: 'done', receivedAt: Date.now() }
expect(transport.tuiStatus(owner)).toBe('idle')
await expect(transport.waitForTuiIdleOrExit(owner, new AbortController().signal)).resolves.toBe(
'idle'
)
explicitStatus = null
const livePty = (
runtime as unknown as {
ptysById: Map<
string,
{
tailBuffer: string[]
tailPartialLine: string
preview: string
lastAgentStatus: null
lastAgentStatusObservedLive: boolean
}
>
}
).ptysById.get('pty-structured')!
Object.assign(livePty, {
tailBuffer: [
'OpenAI Codex (v0.147.0)',
'model: gpt-5.6-terra',
'directory: /tmp/structured-handoff'
],
tailPartialLine: '',
preview: '',
lastAgentStatus: null,
lastAgentStatusObservedLive: false
})
expect(transport.tuiStatus(owner)).toBe('idle')
await expect(transport.waitForTuiIdleOrExit(owner, new AbortController().signal)).resolves.toBe(
'idle'
)
const pty = (
runtime as unknown as {
ptysById: Map<string, { connected: boolean; launchToken: string | null }>
}
).ptysById.get('pty-structured')!
pty.launchToken = null
const persistedRecord = {
sessionId: 'session-1',
providerHandleChain: [{ handle: { provider: 'codex', threadId: 'thread-1' }, observedAt: 1 }],
lease: { ownerProcess: owner.process, provenHandleLinkId: owner.link.linkId }
} as never
const rebound = await transport.reproveTuiOwner({ record: persistedRecord, owner })
expect(rebound.terminal).toMatchObject({
ptyId: 'pty-structured',
tabId: owner.terminal.tabId,
paneKey: owner.terminal.paneKey
})
expect(rebound.terminal.handle).not.toBe(owner.terminal.handle)
await transport.waitForTuiExit(rebound)
expect(waitForStructuredTuiPtyExit).toHaveBeenCalledWith('pty-structured')
expect(waitForStructuredTuiProof).toHaveBeenCalledOnce()
await expect(transport.closeTuiOwner?.(rebound)).resolves.toEqual({
transcriptPath: '/tmp/rollout.jsonl'
})
expect(closeTerminal).toHaveBeenCalledWith(rebound.terminal.handle)
explicitStatus = null
pty.connected = false
await expect(
transport.waitForTuiIdleOrExit(rebound, new AbortController().signal)
).resolves.toBe('exited')
await expect(transport.stopFailedTuiLaunch?.(rebound)).resolves.toBeUndefined()
})
})