I run a personal fork on top of the orchestrator v2 PR (#2829) and hit five bugs. Four are in #2829's code; one (3) is on main. I checked each against #2829's current head (3e4ca4c532) and main (effaab94e3), and they're still there. I have small, tested fixes for each and am happy to open focused PRs (against #2829's branch for 1, 2, 4, 5 and against main for 3) if you'd like them. Just say which, so you don't have to re-fix them yourselves.
1. Interrupted threads never resume after a restart (v2)
With "Continue threads after restarts" on, a thread that was mid-turn when the server restarted is cancelled and waits for a manual "continue".
restartContinuationRun() in apps/server/src/orchestration-v2/RestartContinuation.ts skips any run whose provider session status isn't "running". But only the OpenCode adapter ever writes "running"; the shared ProviderSessionManager writes ready/stopped. Everywhere else v2 treats a session as live when it's not stopped/error (Orchestrator.ts, ProjectionStore.ts). Fix: check session.status === "stopped" || session.status === "error" instead (3 lines plus a test).
2. A steered subagent shows as finished in Lineage while it runs again (v2)
After a subagent finishes and is sent new work, Lineage still shows it as completed and leaves it out of the "N running" count.
The parent's subagent record settles when the spawning run ends, and a new run on the child thread doesn't reopen it. deriveThreadRelationshipGraph() in packages/client-runtime/src/state/threadRelationships.ts uses subagent.status for the edge, and ThreadRelationshipsControl.tsx counts running agents from the records, while thread nodes already use thread.activityRunStatus. Fix: prefer the child thread's live activityRunStatus for subagent edges and the count, falling back to the record.
Related but different trigger: #7314.
3. A hung page makes preview_navigate outlive its deadline and disconnects the browser host (main)
When a page never finishes loading, preview_navigate (or preview_open reusing a tab) times out. The broker then disconnects the whole client's automation connection, and the agent's current tab is forgotten, so agents fall back to opening new tabs.
In apps/web/src/components/preview/PreviewAutomationHosts.tsx, the open (reuse) and navigate cases await bridge.navigate(...) with no limit (on desktop it settles only when webContents.loadURL does), then give waitForNavigationReadiness the full request timeout instead of what's left before hostDeadlineMs. Every other operation respects the host budget from #4685. PreviewAutomationBroker.ts treats the unanswered request as a dead connection. Fix: race the navigate call against the host deadline and pass the remaining budget to the readiness wait.
Related: #12407 (same eviction mechanism, preview_wait_for).
4. Disconnecting a Codex session leaves the thread loaded, with its MCP servers running (v2)
All Codex threads share one codex app-server. Disconnecting a thread detaches it in T3, but the native thread stays loaded in the app-server along with its MCP servers (e.g. one language server per thread or subagent). Over a day I measured about 80 idle processes and 9 GB.
ProviderSessionManager.ts's detach path for multi-thread runtimes never tells the runtime to unload the native thread; the adapter interface has no unload operation, and CodexAdapterV2.ts never sends thread/unsubscribe, although the generated client supports it. Fix: an optional unloadThread on the session runtime, implemented for Codex with thread/unsubscribe and called after detaching from a shared runtime. Verified live: 11 MCP processes went to 0.
5. A failed turn shows as "waiting" while background work is still pending (v2)
If a turn fails while subagents or background tasks are still pending, the sidebar and the notification coordinator show the thread as waiting, not failed, until the background work drains.
resolveSidebarThreadStatus in apps/web/src/components/Sidebar.logic.ts returns "waiting" for runtime.status === "idle" before checking for failure, and the runtime parks at idle while background work is pending. Fix: treat idle with a failed latest run as failed, checked before the idle branch.
I run a personal fork on top of the orchestrator v2 PR (#2829) and hit five bugs. Four are in #2829's code; one (3) is on
main. I checked each against #2829's current head (3e4ca4c532) andmain(effaab94e3), and they're still there. I have small, tested fixes for each and am happy to open focused PRs (against #2829's branch for 1, 2, 4, 5 and againstmainfor 3) if you'd like them. Just say which, so you don't have to re-fix them yourselves.1. Interrupted threads never resume after a restart (v2)
With "Continue threads after restarts" on, a thread that was mid-turn when the server restarted is cancelled and waits for a manual "continue".
restartContinuationRun()inapps/server/src/orchestration-v2/RestartContinuation.tsskips any run whose provider session status isn't"running". But only the OpenCode adapter ever writes"running"; the sharedProviderSessionManagerwritesready/stopped. Everywhere else v2 treats a session as live when it's notstopped/error(Orchestrator.ts,ProjectionStore.ts). Fix: checksession.status === "stopped" || session.status === "error"instead (3 lines plus a test).2. A steered subagent shows as finished in Lineage while it runs again (v2)
After a subagent finishes and is sent new work, Lineage still shows it as completed and leaves it out of the "N running" count.
The parent's subagent record settles when the spawning run ends, and a new run on the child thread doesn't reopen it.
deriveThreadRelationshipGraph()inpackages/client-runtime/src/state/threadRelationships.tsusessubagent.statusfor the edge, andThreadRelationshipsControl.tsxcounts running agents from the records, while thread nodes already usethread.activityRunStatus. Fix: prefer the child thread's liveactivityRunStatusfor subagent edges and the count, falling back to the record.Related but different trigger: #7314.
3. A hung page makes
preview_navigateoutlive its deadline and disconnects the browser host (main)When a page never finishes loading,
preview_navigate(orpreview_openreusing a tab) times out. The broker then disconnects the whole client's automation connection, and the agent's current tab is forgotten, so agents fall back to opening new tabs.In
apps/web/src/components/preview/PreviewAutomationHosts.tsx, theopen(reuse) andnavigatecases awaitbridge.navigate(...)with no limit (on desktop it settles only whenwebContents.loadURLdoes), then givewaitForNavigationReadinessthe full request timeout instead of what's left beforehostDeadlineMs. Every other operation respects the host budget from #4685.PreviewAutomationBroker.tstreats the unanswered request as a dead connection. Fix: race the navigate call against the host deadline and pass the remaining budget to the readiness wait.Related: #12407 (same eviction mechanism,
preview_wait_for).4. Disconnecting a Codex session leaves the thread loaded, with its MCP servers running (v2)
All Codex threads share one
codex app-server. Disconnecting a thread detaches it in T3, but the native thread stays loaded in the app-server along with its MCP servers (e.g. one language server per thread or subagent). Over a day I measured about 80 idle processes and 9 GB.ProviderSessionManager.ts's detach path for multi-thread runtimes never tells the runtime to unload the native thread; the adapter interface has no unload operation, andCodexAdapterV2.tsnever sendsthread/unsubscribe, although the generated client supports it. Fix: an optionalunloadThreadon the session runtime, implemented for Codex withthread/unsubscribeand called after detaching from a shared runtime. Verified live: 11 MCP processes went to 0.5. A failed turn shows as "waiting" while background work is still pending (v2)
If a turn fails while subagents or background tasks are still pending, the sidebar and the notification coordinator show the thread as waiting, not failed, until the background work drains.
resolveSidebarThreadStatusinapps/web/src/components/Sidebar.logic.tsreturns"waiting"forruntime.status === "idle"before checking for failure, and the runtime parks atidlewhile background work is pending. Fix: treatidlewith a failed latest run as failed, checked before the idle branch.