test: retire a dormant worker through host-owned status (#23686)

* test(e2e): await renderer recovery after worker exit

* test(e2e): publish worker recovery through authenticated hooks

* test: keep retired background worker dormant before activation
This commit is contained in:
Neil
2026-09-28 14:34:49 -07:00
committed by GitHub
parent 8c61a5df1f
commit e87772b3a4
2 changed files with 57 additions and 89 deletions
@@ -160,21 +160,13 @@ for (const closeMode of ['terminal-close-cli', 'worker-release'] as const) {
const workerBefore = terminalIdentity(worker)
const workerPaneKey = `${worker.tabId}:${worker.leafId}`
expect(worker.worktreeId).toBe(targetWorktreeId)
await orcaPage.evaluate(
({ tabId, worktreeId }) => {
window.dispatchEvent(
new CustomEvent('orca-background-mount-terminal-worktree', {
detail: { worktreeId, tabIds: [tabId] }
})
)
},
{ tabId: worker.tabId, worktreeId: targetWorktreeId }
)
await expect
.poll(() =>
orcaPage.evaluate((tabId) => Boolean(window.__paneManagers?.get(tabId)), workerBefore.tabId)
// Keep the never-opened worker dormant so foreground-shell cleanup cannot retire it first.
expect(
await orcaPage.evaluate(
(tabId) => Boolean(window.__paneManagers?.get(tabId)),
workerBefore.tabId
)
.toBe(true)
).toBe(false)
expect(
await orcaPage.evaluate(
(worktreeId) => window.__store?.getState().everActivatedWorktreeIds.has(worktreeId),
@@ -202,70 +194,13 @@ for (const closeMode of ['terminal-close-cli', 'worker-release'] as const) {
throw new Error('Background worker did not receive its dispatch capability')
}
const transcriptPath = seedCurrentCodexTranscript(
isolatedHome,
PROVIDER_SESSION_ID,
targetWorktreePath
)
seedCurrentCodexTranscript(isolatedHome, PROVIDER_SESSION_ID, targetWorktreePath)
await orcaPage.evaluate(
({
agentCommand,
paneKey,
providerSessionId,
tabId,
terminalHandle,
transcriptPath,
worktreeId
}) => {
const state = window.__store?.getState()
if (!state) {
throw new Error('Renderer store unavailable')
}
const providerSession = {
key: 'session_id' as const,
id: providerSessionId,
transcriptPath
}
const metadata = { tabId, worktreeId, terminalHandle }
const recovery = {
providerSession,
launchConfig: {
// Why not bare 'codex': resume prefers the captured command over
// agentCmdOverrides, so a bare name would resolve the machine's real
// Codex off PATH and unpin the adoption leg this spec exercises.
agentCommand,
agentArgs: '--dangerously-bypass-approvals-and-sandbox',
agentEnv: {}
}
}
state.setAgentStatus(
paneKey,
{ state: 'working', prompt: 'Report completion, then exit normally', agentType: 'codex' },
'Completed background worker',
undefined,
metadata,
recovery
)
state.setAgentStatus(
paneKey,
{ state: 'done', prompt: 'Report completion, then exit normally', agentType: 'codex' },
'Completed background worker',
undefined,
metadata,
recovery
)
},
{
agentCommand: completedWorkerFakeCodexCommand,
paneKey: workerPaneKey,
providerSessionId: PROVIDER_SESSION_ID,
tabId: worker.tabId,
terminalHandle: workerHandle,
transcriptPath,
worktreeId: targetWorktreeId
}
)
await client.call('terminal.send', {
terminal: workerHandle,
text: 'ORCA_E2E_PUBLISH_DONE',
enter: true
})
const expectedRecovery = {
origin: 'live',
@@ -348,18 +283,23 @@ for (const closeMode of ['terminal-close-cli', 'worker-release'] as const) {
await expect
.poll(() => readCompletedWorkerLedger().filter((event) => event.event === 'normal-exit'))
.toHaveLength(1)
expect(
await orcaPage.evaluate(
({ paneKey, tabId, worktreeId }) => {
const state = window.__store?.getState()
return {
tabPresent: Boolean(state?.tabsByWorktree[worktreeId]?.some((tab) => tab.id === tabId)),
recoveryPresent: Boolean(state?.sleepingAgentSessionsByPaneKey[paneKey])
}
},
{ paneKey: workerPaneKey, tabId: workerBefore.tabId, worktreeId: targetWorktreeId }
// The exit marker precedes the asynchronous renderer recovery update.
await expect
.poll(() =>
orcaPage.evaluate(
({ paneKey, tabId, worktreeId }) => {
const state = window.__store?.getState()
return {
tabPresent: Boolean(
state?.tabsByWorktree[worktreeId]?.some((tab) => tab.id === tabId)
),
recoveryPresent: Boolean(state?.sleepingAgentSessionsByPaneKey[paneKey])
}
},
{ paneKey: workerPaneKey, tabId: workerBefore.tabId, worktreeId: targetWorktreeId }
)
)
).toEqual({ tabPresent: true, recoveryPresent: true })
.toEqual({ tabPresent: true, recoveryPresent: true })
await orcaPage.evaluate(
({ paneKey, tabId, worktreeId }) => {
@@ -20,14 +20,34 @@ import { buildFakeAgentCommandOverride } from './fake-agent-command-override'
import { FAKE_AGENT_PASTE_END_SCANNER_SOURCE } from './fake-agent-paste-end-scanner'
const fakeCliDir = mkdtempSync(path.join(os.tmpdir(), 'orca-e2e-retired-worker-'))
const recoveryConfigPath = path.join(fakeCliDir, 'recovery-config.json')
const lifecycleLedgerPath = path.join(fakeCliDir, 'codex-lifecycle.jsonl')
export const completedWorkerFakeCodexCommand = buildFakeAgentCommandOverride(
path.join(fakeCliDir, process.platform === 'win32' ? 'codex.cmd' : 'codex')
)
const fakeCodexSource = `
const { appendFileSync } = require('node:fs')
const { appendFileSync, readFileSync } = require('node:fs')
const ledger = process.env.ORCA_E2E_CODEX_LIFECYCLE_LEDGER
const append = (event) => appendFileSync(ledger, JSON.stringify({ pid: process.pid, ...event }) + '\\n')
async function publishRecovery() {
const config = JSON.parse(readFileSync(${JSON.stringify(recoveryConfigPath)}, 'utf8'))
for (const hook_event_name of ['UserPromptSubmit', 'Stop']) {
const response = await fetch('http://127.0.0.1:' + process.env.ORCA_AGENT_HOOK_PORT + '/hook/codex', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Orca-Agent-Hook-Token': process.env.ORCA_AGENT_HOOK_TOKEN },
body: JSON.stringify({
paneKey: process.env.ORCA_PANE_KEY,
tabId: process.env.ORCA_TAB_ID,
worktreeId: process.env.ORCA_WORKTREE_ID,
launchToken: process.env.ORCA_AGENT_LAUNCH_TOKEN,
env: process.env.ORCA_AGENT_HOOK_ENV,
version: process.env.ORCA_AGENT_HOOK_VERSION,
payload: { hook_event_name, prompt: 'Report completion, then exit normally', ...config }
})
})
if (response.status !== 204) throw new Error('Recovery hook rejected: ' + response.status)
}
}
const args = process.argv.slice(2)
if (args.includes('app-server')) {
process.stderr.write("error: unrecognized subcommand 'app-server'\\n")
@@ -44,6 +64,10 @@ process.stdin.on('data', (chunk) => {
process.stdout.write('\\x1b[?25h')
}
append({ event: 'input', input })
if (input.includes('ORCA_E2E_PUBLISH_DONE')) {
void publishRecovery().catch((error) => process.stderr.write(String(error)))
return
}
if (input.includes('ORCA_E2E_EXIT_AFTER_DONE')) {
append({ event: 'normal-exit' })
process.exit(0)
@@ -179,6 +203,10 @@ export function seedCurrentCodexTranscript(
payload: { id: providerSessionId, cwd }
})}\n`
)
writeFileSync(
recoveryConfigPath,
JSON.stringify({ session_id: providerSessionId, transcript_path: transcriptPath })
)
return transcriptPath
}