feat(orchestrator): introduce new orchestrator#2829

merged50+
main
t3code/codex-turn-mapping
openedMay 27, 2026byJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 1d ago

Important

Revert before merging into main

V2-only stopgaps that must be undone or moved when this lands. Add to this list whenever a preview-only change goes in.

  • OpenCode 2 compatibility policy on preview builds. Preview builds keep their bundled OpenCode policy (OpenCode 2 supported, 1.x "limited support") instead of main's fetched manifest, which still marks OpenCode 2 broken (#14198). Before merging: remove the preview-only override in ModelManifest, and put the V2 OpenCode policy into main's apps/server/src/provider/model-manifest.json.

Summary

  • wire orchestration V2 provider adapter registry/factory flow for Codex and Claude provider instances
  • add Claude replay/query primitives, native fork/rollback fixtures, subagent fixture coverage, and provider replay harness updates
  • update debugger model/provider picker and improve user-facing orchestration errors

Validation

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test -- src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts -t claudeAgent
  • bun run test -- src/orchestration-v2/testkit/ClaudeReplayFixtures.integration.test.ts
  • bun run test -- src/orchestration-v2/testkit/ThreadFork.integration.test.ts -t Claude

Notes

  • Draft PR for review of current branch state. Codex all-provider replay still needs schema alignment with latest app-server behavior before it can be treated as a full-suite signal.

Closes

Verified against the branch with code/commit evidence. Issues listed under High confidence have a concrete V2 mechanism (named in the note). Medium confidence items belong to a V1 race or lifecycle class that V2 structurally removes; prune any you want to re-verify after merge.

High confidence

Closes #871 — V2 mints message identity itself in orchestration-v2/IdAllocator.ts (random id scoped by thread + ordinal) instead of keying projections on provider-supplied message… Closes #4673 — V2 owns queue state in the orchestrator with explicit queue controls and pending-question commands (fix(queue): preserve and hold queued messages after restart, fea… Closes #2778 — V2 tracks delegated children in projections and wakes the parent when they finish (fix(orchestrator): Stop treating a wait timeout as a dead child (#7427), fix(orch… Closes #4952 Closes #4873 Closes #4775 Closes #4795 Closes #4710 Closes #4668 Closes #4619 Closes #4584 Closes #4561 Closes #4713 Closes #4198 Closes #4452 Closes #3797 Closes #4232 Closes #3666 Closes #3580 Closes #2785 Closes #2789 Closes #3138 Closes #1404 Closes #231 Closes #216 Closes #12940 — CursorAdapterV2 passes enableAgentRetries: true to the Cursor SDK session (apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.ts:331) Closes #12928 — AcpAdapterV2 maps ACP tool kind search to file_search and only fetch to web_search, replacing main's canonicalItemTypeFromAcpToolKind which lumps search and… Closes #12915 — The buggy schedulePromptAdmissionRecovery path lives only in V1's OpenCodeAdapter.ts, which V2 removes in favour of OpenCodeAdapterV2 plus commits 'correlate OpenCode… Closes #12904 — V2 deletes the V1 provider adapter layer that raised ProviderAdapterSessionClosedError and replaces it with ProviderSessionManager plus ProviderRuntimeRecoveryService,… Closes #12679 — The branch carries 'fix(server): preserve provider history across repeated rollbacks (#12676)' and 'fix(pi): use native forks and preserve rollback session identity',… Closes #12285 — The settledDeliveryCount cohort cap no longer exists on the branch. Closes #12100 — V2 makes queuing server-owned with a queued_turn intent released as a separate turn after the active turn (fix(web): retain server-side queuing on v2, fix(orchestratio… Closes #11968 — V2's orchestrator MCP toolkit ships t3_thread_update with action='rename' that defaults to the calling thread (apps/server/src/mcp/ThreadMetadataMcpService.ts, toolkit… Closes #11889 — V2 deletes the reactor-based path (orchestration-v2/ThreadDeletion.ts runs through the serialized orchestrator and effect worker) and lands 'fix(server): cancel pendin… Closes #11799 — V2's ProviderSessionManager release path writes runtime-request.updated with a not_resumable capability for every pending approval_request and user_input_request bound… Closes #11730 — V2's server-owned settlement rejects threads with pendingBackgroundTasks/live activity (ThreadSettlementService.isAutoSettlementCandidate) and adds 'feat(orchestrator)… Closes #11711 — V2's isAutoSettlementCandidate in orchestration-v2/ThreadSettlementService.ts returns false when pinnedAt is set (covered by ThreadSettlementService.test.ts 'excludes… Closes #11428 — V2 commit "fix: stop retained background work after a turn settles" makes ProviderTurnControlService.interrupt accept a non-running run that still has pending backgrou… Closes #10928 — orchestration-v2/RestartContinuation.ts dispatches the automatic continuation with the source run's modelSelection, whose options carry reasoningEffort, so the restart… Closes #10786 — V2 records the reply on the user_input_request turn item itself as questionAnswer (answers plus questionTextById) in Orchestrator.ts rather than synthesizing a u… Closes #10545 — V2 adds a distinct Limited stop state with resume/snooze-at-reset ("feat(v2): show provider limit stops as Limited (#12677)", "#12686", "#12687"), documented in the V2… Closes #10480 — V2 runs Cursor through the official @cursor/sdk and explicitly does not use Cursor's ACP transport for V2 execution (user-cursor.md. Closes #10099 — V2 makes settlement server-owned in ThreadSettlementService. Closes #9107 — V2 models provider-owned background work as first-class turn items (background_task/background_command/monitor in orchestrationV2.ts) with normalized post-settlement W… Closes #9047 — apps/server/src/provider/Layers/CursorAdapter.ts does not exist on V2. Closes #9029 — ClaudeAdapterV2 projects TodoWrite todos into todo_list plan items rather than depending on Task tools, surfaced by "fix(web): surface v2 todo-list plans as task progr… Closes #8946 — V2's deriveTurnFolds pulls subagent items and background work entries into the run fold and drops main's agent-spawn never-fold exclusion. Closes #8594 — The V1 ClaudeAdapter is deleted on V2. Closes #8499 — V2 models native subagents and maps nested Codex subagent threads into thread lineage, rendered by "feat(web): show subagent models and running count in Lineage" after… Closes #8091 — Task steps are projected from the persisted event log, and "fix(orchestrator): preserve task-step elapsed time across restart (#10051)" restores the list after relaunch. Closes #7328 — V2 ports title regeneration to the orchestrator with tracked contract state: 'feat(contracts): track thread title regeneration', 'feat(orchestration): port thread titl… Closes #7281 — V2 carries per-subagent model through projections: 'fix(claude): retain requested subagent models', 'fix(server): preserve Claude subagent models', 'feat(web): show su… Closes #7244 — V2 runs Cursor on the official @cursor/sdk and treats CURSOR_API_KEY as the auth method (docs/user/cursor.md prerequisites. Closes #7155 — V2's provider session recovery plus '[orchestrator-v2] fix(orchestrator): Restore Claude session continuity for resume, wake, and idle release (#3860)' rebuilds the re… Closes #7075 — V2's CodexSessionRuntime sends thread/resume with excludeTurns: true on the main resume path (apps/server/src/provider/Layers/CodexSessionRuntime.ts:751 on the branch,… Closes #5953 — V2 models native Codex subagents as separate projected child threads (feat(orchestration-v2): model native subagents. Closes #5750 — ProviderRuntimeRecoveryService reconciles non-terminal runs against actual provider inventory at startup/shutdown and retires the outbox effects tied to the lost proce… Closes #5518 — V2 tracks delegated children in projections and settlement (fix(notifications): silence subagent threads. Closes #5476 — Server-owned ThreadSettlementService returns no settlement whenever any linked pull request snapshot is missing or still open, and the guarded thread.auto-settle comma… Closes #5454 — ProviderRuntimeRecoveryService reconciles on startup/shutdown and cancels every pending runtimeRequest with a user-facing 'server restarted before the provider work co… Closes #5436 — V2 makes the follow-up queue server-owned and durable (queued messages keep order and are held across a server restart. Closes #5110 — V2 adds ProviderTextDeltaCoalescer and ThreadLiveEventCoalescer, which buffer and flush provider text deltas before persistence/publication instead of writing one dura… Closes #4650 — ClaudeAdapterV2 handles the SDK compact_boundary message and publishes usedTokens: afterTokenCount from compact_metadata.post_tokens, replacing V1's monotonic… Closes #4495 — The failing call site (context.query.setPermissionMode wrapped as turn/setPermissionMode in apps/server/src/provider/Layers/ClaudeAdapter.ts) does not exist in V2. Closes #2477 — V2 models native subagents as distinct lineage nodes with their own projection rows rather than splicing their text into the parent stream — `feat(orchestration-v2): m…

Medium confidence (under review)

Closes #4568 Closes #4766 Closes #4456 Closes #4399 Closes #3744 Closes #2921 Closes #3624 Closes #3149 Closes #2336 Closes #538 Closes #2173 Closes #2065 Closes #12926 — The 'Provider session did not survive a server restart' path exists only on main (serverRuntimeStartup.ts:346) Closes #12885 — Cross-thread session eviction is a V1 session-lifecycle race. Closes #12762 — V2 never replays the V1 event log: LegacyV1ThreadImporter reads projection_thread_messages from a statev2.sqlite snapshot, so a legacy thread.message-sent row missing… Closes #12694 — V2 replaces ensureSessionForThread's restart branch with ProviderSessionTransitionPolicy plus recovery that checks providerThreadHasPendingBackgroundTasks before retir… Closes #12502 — Stuck-Working class that V2 addresses via run finalization separate from provider turn completion plus 'fix(grok): Prevent spurious wake run after in-turn monitors' an… Closes #12467 — The branch adds 'fix(server): recover Pi resumes without reusing native history (#12933)' and 'fix(pi): use native forks and preserve rollback session identity', which… Closes #12456 — The recovery path it skips (schedulePromptAdmissionRecovery in V1's OpenCodeAdapter) is deleted in V2, whose OpenCode admission and stream-EOF handling is rebuilt in O… Closes #12374 — Same Cursor ACP transport-drop class as #12940, which V2 addresses by enabling enableAgentRetries in CursorAdapterV2. Closes #12325 — Same never-terminating tool-row class. Closes #12206 — ProviderAdapterSessionClosedError is the ACP session-lifecycle class V2 rewrites ('feat(providers): standardize ACP providers', 'fix(antigravity): accept supported leg… Closes #12187 — V2's run interrupt explicitly handles runs in preparing/starting with no provider turn, emitting an interrupt result and marking attempt/node/run interrupted ('Handle… Closes #12155 — V2 carries reasoning as typed turn items across clients ('fix(providers): enable Codex and Claude reasoning summaries in V2', 'fix(timeline): align V2 reasoning disclo… Closes #12136 — Same OpenCode prompt-admission rework as #11889 ('guard OpenCode prompt admission races', 'abort external OpenCode sessions on release') plus V2's interrupt path that… Closes #12131 — V2 tracks subagents in server projections and replaces the ad-hoc agents panel with projection-backed lineage/workspace-card surfaces ('refactor(web): remove the agent… Closes #12094 — The V2 timeline rewrite re-lays out these exact rows ('fix(web): anchor turn duration below the initiating prompt', 'fix: keep working timers anchored to the active ru… Closes #12072 — V2's mobile timeline is rebuilt on paged V2 turn items with LegendList owning end-follow and anchoring ('fix(mobile): keep scroll bounds current after animations', 'pe… Closes #12037 — V2 keeps a failed turn as a settled transcript item instead of wedging the thread ('fix(v2): keep failed turns visible in the transcript', 'fix(server): preserve gener… Closes #11992 — V2 reworks the mobile running-turn UI so the pill is part of the composer hub and scroll bounds track animations ('feat(mobile): make the composer pill the hub for the… Closes #11907 — V2 commits intent, projection and command receipt in one transaction with idempotent receipts, and holds sends as server-side queued turns, removing the V1 admission r… Closes #11903 — Mobile timelines are rebuilt from V2 typed turn items ('Render mobile timelines from V2 turn items', 'Enrich mobile V2 execution items', 'fix(chat): present and summar… Closes #11796 — The V1 processTurnInterruptRequested path is gone. Closes #11777 — V2 projects native Codex subagents as durable child nodes with results ('Map nested Codex subagent threads correctly', 'feat(subagents): disclose projected results con… Closes #11670 — V2 standardizes ACP providers behind one adapter with session recovery and surfaces typed failures ('feat(providers): standardize ACP providers', 'fix(server): surface… Closes #11432 — V2 maps Codex background command completions to typed turn items (codexBackgroundCommandDetail, source kind background_command) and renders background completions as t… Closes #11353 — V2 persists each assistant text block as its own ordered assistant_message turn item with its own messageId, so a later item in the same turn cannot overwrite an earli… Closes #11182 — Branch-only "perf(server): stop decoding unrelated events during startup" (#12846) rewrites ProjectionPipeline bootstrap to read cursor metadata instead of full event… Closes #10973 — V2 commit "fix(server): recover OpenCode status reconciliation" ignores stale timers and duplicate evidence so an older prompt's idle event cannot finish newer steerin… Closes #10934 — The "Provider session did not survive a server restart" path exists only on main. Closes #10798 — V2 replaces the Codex adapter with scoped session runtimes plus a provider session recovery service, and run state is orchestrator-owned rather than derived from the a… Closes #10684 — Same mechanism as #10202: V2's durable thread.model-selection.set command and thread.model-selection-updated projection replace per-client sticky model state. Closes #10375 — ClaudeAdapterV2 classifies local_bash task types explicitly and never fabricates a subagent for them, and V2 rebuilt the worklog rows ("fix(timeline): unify worklog… Closes #10202 — V2 makes thread model selection durable server state via the thread.model-selection.set command and thread.model-selection-updated event, which every subscribed cl… Closes #10192 — V2 projects questions as turn items rendered identically across clients and makes settlement server-owned ("fix: align V2 question and checkpoint timelines across clie… Closes #10185 — V2 models native subagents in projections and surfaces their models in Lineage, replacing the Agents right panel ("feat(web): show subagent models and running count in… Closes #9892 — V2 tracks subagents in projections and maps Grok task envelopes to subagent lineage ("Map Grok task envelopes to subagent lineage", "feat(orchestration-v2): model nati… Closes #9772 — V2 orders the transcript from the append-only event log and pages history by keyset rather than by wall-clock timestamps ("perf(orchestration): bound history reads in… Closes #9698 — V2 separates run finalization from provider turn completion and retires background work after a turn settles ("fix: stop retained background work after a turn settles"… Closes #9672 — V2 models queued messages as first-class durable queued_turn intents promoted by the serialized orchestrator ("fix(queue): preserve and hold queued messages after re… Closes #9607 — V2's provider session recovery restarts live sessions after dead/stale records and reopens Claude queries on credential rotation ("fix(server): restart the live sessio… Closes #9586 — V2 makes liveness an orchestrator projection and the settlement service detaches idle provider sessions ("fix(orchestrator): Restore Claude session continuity for resu… Closes #9414 — V2 adds bounded per-thread history loading with true-end paging and bounded snapshots ("perf(orchestration): bound complete thread snapshots", "fix(orchestration): pag… Closes #9352 — V2 shows live context usage in the composer meter as a first-class V2 surface ("feat(orchestration-v2): show live context usage in the meter (#8144)", "fix(server): ke… Closes #9214 — Fold derivation now keys on server-owned runIds instead of provider turn ids, and "fix(server): recover OpenCode status reconciliation" makes OpenCode run state author… Closes #8945 — V2 folds group by server-owned runId and deliberately keep every provider turn since the initiating prompt in one visual response, so a mid-turn pause no longer starts… Closes #8896 — V2 isolates its migrations from the V1 database and flags divergent migration ids ("test(server): prove v1 to v2 cutover on a copied database and flag divergent migrat… Closes #8873 — V2 replaces the checkpoint reactor with effect-worker checkpointing that starts the provider turn when baseline capture fails (#12153) and finalizes runs when checkpoi… Closes #8648 — V2 bounds history reads in SQL, bounds complete thread snapshots and resume payloads, releases thread history after turn startup, and keeps tool payloads out of comple… Closes #8618 — Stop is a serialized V2 command whose intent commits with a durable receipt, and "fix(orchestrator): report terminal runs after wait timeout" ends the stuck Thinking s… Closes #8382 — V2 adds AcpRuntimeModel parsing of ACP usage_update/state_update usage into a per-session contextUsage snapshot that feeds "feat(orchestration-v2): show live context u… Closes #8320 — V2 records provider session lifecycle as persisted typed events with a session recovery service, plus "fix(server): surface actionable provider failure messages (#1256… Closes #8263 — ProviderTurnStartService prunes and recreates a missing worktree at the thread's branch before starting the provider turn ("fix(orchestration): recreate missing worktr… Closes #8259 — V2 shares Codex sessions across orchestration threads and maps turns to provider instances. Closes #8146 — V2 replaces the hand-written Codex wire with the generated effect-codex-app-server schemas and app-server integration, so initialize payload decoding is regenerated fr… Closes #8105 — V2 projects file-change and diff items per run and thread and narrows subscriptions to the viewed thread, so opening a second thread cannot capture another thread's li… Closes #8022 — V2 Cursor execution and provider checks no longer use the ACP transport or cursor/list_available_models — it goes through the official SDK ('Switch Cursor provider to… Closes #7781 — V2 replaces the inferred turn→checkpoint range with durable run identity and checkpoint coordination ('fix(orchestration): stabilize Codex turn mapping and settlement'… Closes #7722 — V2 models native Codex subagents as first-class threads with orchestrator-owned stop ('Map nested Codex subagent threads correctly', 'fix(server): wait for native Code… Closes #7589 — V2 records provider turn state independently from run finalization and settles threads server-side, and 'fix(server): restore Claude resume compaction' covers the comp… Closes #7314 — V2 models subagents in projections and re-derives status from events ('feat(orchestration-v2): model native subagents', 'refactor(mobile): share subagent status indica… Closes #6517 — V1's ProviderCommandReactor semaphore is replaced by the serialized orchestrator plus effect worker. Closes #6389 — The V2 Claude adapter emits into the orchestrator where events and projections commit in one transaction, removing the in-flight-tool map race at finalize. Closes #6368 — Thread settlement and snooze become server-owned in ThreadSettlementService ('fix(server): keep old failures from waking snoozed V2 threads (#9903)', 'fix: reconcile m… Closes #6358 — V2's server-owned settlement evaluates without a connected client and 'fix(orchestration): reanchor unsettled threads' removes the stuck-unsettled state that pins the… Closes #6128 — The V1 thread read model that caused the archived_at asymmetry is replaced by V2's projection store and ThreadLifecycleService, with archive handled as a domain comman… Closes #5958 — The reported 'Orchestration command invariant failed' comes from the V1 OrchestrationEngine command path, which V2 replaces with the serialized Orchestrator and EventS… Closes #5952 — V2 SubagentProjection plus OpenCodeAdapterV2 child-session mapping (fix(opencode): route child-session approvals through the v2 adapter) projects native child sessions… Closes #5754 — CodexAdapterV2 maps collab wait/spawn items and empty receiver sets explicitly (replay fixture subagent_v2 covers a wait with empty receiverThreadIds), and RunFinaliza… Closes #5685 — V2 CheckpointRollbackService coordinates workspace rollback with the provider conversation and the timeline (fix: align V2 question and checkpoint timelines across cli… Closes #5514 — V2 ThreadPullRequestService skips settled threads in ordinary discovery and only stamps a link. Closes #5447 — Commands are serialized through one orchestrator with idempotent receipts and sessions are owned by ProviderSessionManager, removing the duplicate-dispatch race that p… Closes #5395 — ClaudeAdapterV2 maps sidechain items onto V2's native subagent model (feat(orchestration-v2): model native subagents. Closes #5323 — Shutdown/startup runtime reconciliation records an explicit cancellation for work interrupted by the quit, replacing the stale 'stream failed' state a killed provider… Closes #5035 — V2 drops the V1 per-event runProjectorForEvent nesting: EventSink commits events, projections, receipt and outbox in a single sql.withTransaction, removing the nested-… Closes #4962 — V2 projects delegated-child progress server-side and shares it with mobile (refactor(mobile): share subagent status indicators. Closes #4944 — V2 owns provider switching through ProviderSwitchService/ProviderSessionTransitionPolicy/ProviderSessionManager (Allow provider switching via handoff in chat threads. Closes #4818 — V2 threads no longer write through the V1 receipt repository. Closes #4728 — V2 reprojects Claude assistant text blocks and buffers streaming output per block (fix(timeline): preview live reasoning and buffer complete paragraphs), so text emi… Closes #4723 — fix(orchestration): recreate missing worktrees before turns prunes stale registrations and recreates the saved branch/path in ProviderTurnStartService, and Provid… Closes #4560 — V2 binds each thread to its own provider session record (orchestration_v2_projection_provider_sessions, keyed by provider instance + thread) and serializes commands… Closes #4225 — V2 commits the user-message event before any provider work runs in the effect worker, so a provider auth failure leaves the prompt persisted and rendered instead of sw… Closes #4178 — V2 bounds the read model and subscription payloads: perf(orchestration): bound complete thread snapshots, feat(orchestration): bound thread history and resume paylo… Closes #2644 — V2 separates provider turn completion from run finalization and rewrites the OpenCode adapter's turn mapping, so a finished provider turn settles the thread rather tha… Closes #2519 — V2 projects proposed plans as first-class rows (fix(server): project Claude plans and todos, fix(server): preserve Claude planning lifecycle, inline-plans rework),… Closes #2343 — V2 provider session recovery plus budgeted context handoff rebuild a resumed thread's context from the persisted transcript when the native provider session is gone, r… Closes #881 — Run and turn state are derived from the committed event log and recovered at startup by the V2 recovery services, so a resumed thread shows real provider activity inst…

Supersedes

These pull requests target the V1 orchestration/provider layers this PR replaces, and V2 already delivers the same fix or feature by another route. They are linked here (not auto-closed) so their authors can find the replacement; most were closed pending V2, the rest stay open for maintainer review.

High confidence

  • Supersedes #12478 — V2 decides commands without provider I/O and runs effects in the leased EffectWorker, serializing only per-identity via KeyedSerialExecutor rather than a process-wide…
  • Supersedes #12458 — V2 ships UsageLimitRecoveryWorker and the 'Resume at reset' / 'Auto-resume limited threads' feature (commits 'resume limited threads when usage resets (#12686)', 'snoo…
  • Supersedes #12114 — V2's thread metadata MCP tool supports action='rename' and 'regenerate_title' through the server-owned metadata workflow.
  • Supersedes #12018 — V2 has ThreadMetadataMcpService and the t3_thread_metadata update tool (commit 'feat(mcp): update thread metadata (#8690)').
  • Supersedes #11864 — V2's orchestrator MCP toolkit already exposes create_threads and t3_thread_list scoped to the calling project.
  • Supersedes #11795 — V2 ships OrchestratorMcpService with create_threads and t3_thread_launch (commits 'Add orchestration MCP toolkit', 'feat(mcp): expose project thread launch service').
  • Supersedes #11628 — V2 owns queueing in orchestration — follow-up messages become queued runs delivered in order (QueuedRunOrder/queued-run edit, reorder, promote-to-steer) instead of an…
  • Supersedes #11613 — OpenCodeAdapterV2 has a dedicated admission reconciliation generation and reconcile-idle action for delayed prompt admission (commits `correlate OpenCode prompt admi…
  • Supersedes #11560 — V2 ships t3_worktree_handoff, t3_worktree_status, and t3_worktree_list in the MCP worktree toolkit, including the queued continuation prompt.
  • Supersedes #11452 — OpenCodeAdapterV2 maps child sessions to subagent contexts and projects them as child threads via SubagentProjection.
  • Supersedes #11360 — V2's MCP toolkit provides t3_thread_launch (plus create_threads) for handing work to a new workspace-aware thread.
  • Supersedes #11356 — V2 ships Devin ACP support in the generic registry adapter (Adapters/DevinAcp.ts plus fix(acp): support Devin terminals, questions, and native subagents).
  • Supersedes #11303 — V2's MCP orchestrator toolkit already exposes persistent peer-thread coordination (t3_thread_launch, t3_thread_send, t3_thread_wait, t3_thread_read) with durab…
  • Supersedes #11262 — OpenCodeAdapterV2 models native subagents with lifecycle events and child-session mapping into projected subagent threads.
  • Supersedes #11225 — Cursor V2 no longer uses the ACP transport at all — execution goes through @cursor/sdk, and V2 additionally rejects partial output from failed Cursor runs.
  • Supersedes #11215 — V2 adds Limited run state plus snooze-until-reset and auto-resume-at-reset scheduling (commits #12677/#12686/#12687 and the Limited section of the user docs).
  • Supersedes #11214 — CursorAdapterV2 projects Cursor task subagents as read-only child app threads with their tool activity and final result (docs/user/cursor.md, SubagentProjection).
  • Supersedes #11202 — V2 thread settlement is server-owned: the guarded thread.auto-settle command rejects newer activity and live/blocked work and detaches idle provider sessions (`provi…
  • Supersedes #11170 — Cursor V2 runs on the official @cursor/sdk (CursorAcpExtension deleted) and CursorAdapterV2 maps updateTodos tool calls into task steps with emitsTodoList: true.
  • Supersedes #11096 — V2 delivers cross-provider forks and handoffs natively (t3_thread_fork, ContextHandoffServiceV2, commits fix(orchestration-v2): resolve cross-provider forks and `f…
  • Supersedes #10858 — OpenCodeAdapterV2 declares supportsSubagents/exposesSubagentThreadIds and maps child sessions through SubagentProjection into real child threads.
  • Supersedes #10793 — V2 persists Codex async questions as user_input_request items and runtime-request.respond commits the resolution plus the user message in one transaction against t…
  • Supersedes #10726 — OpenCodeAdapterV2 derives the real providerID/modelID from the native payload per assistant message and records it on the V2 turn (model field on the turn projecti…
  • Supersedes #10611 — V2 persists queued messages in the event log and restart recovery holds them with identity intact (queueHeld in orchestrationV2 contracts.
  • Supersedes #10608 — V2 serializes all commands for a thread through ThreadCommandExecutor and re-validates restore in CheckpointRestoreSafety "at command admission and again before pr…
  • Supersedes #10586 — V2 adds a first-class thread.user-input.dismiss command and ProviderEventIngestor.dismissNativeUserInputs, which clears native user inputs when the turn ends or th…
  • Supersedes #10550 — V2 commit "feat(v2): show provider limit stops as Limited (#12677)" plus usageLimitResetAt in orchestrationV2.ts.
  • Supersedes #10510 — V2 deletes CursorAcpSupport.ts and maps runtime modes onto the Cursor SDK directly: "full access disables its sandbox, while restricted modes and explicit non-full-a…
  • Supersedes #9852 — V2's ProviderTurnStartService recreates a missing worktree before starting a provider turn ("provider turn start recreating missing worktree"), matching commit "fix(…
  • Supersedes #9823 — V2's ThreadCommandExecutor is a KeyedSerialExecutor<ThreadId>, serializing per-thread work "without coupling unrelated identities to a process-wide mutex".
  • Supersedes #9437 — Same V2 fork model (ThreadForkService, thread.fork command, mobile fork/merge-back surfaces in commits "fix(mobile): wait for fork shell before navigation" and "pr…
  • Supersedes #9436 — V2 ships ThreadForkService with fork lineage, lazy context transfer and merge-back handoffs (commits "Add thread fork lineage and lazy context transfer", "feat(mcp):…
  • Supersedes #9247 — V2's CheckpointRestoreSafety resolves fileSystem.realPath on both the checkpoint scope cwd and the thread worktree before comparing, so symlinked paths compare equal.
  • Supersedes #9206 — V2 delivers this generically via commit "feat(orchestration-v2): show live context usage in the meter (#8144)" with usage normalized in GrokAdapterV2.
  • Supersedes #9124 — V2 persists read state server-side as thread.visit/thread.visited events with lastVisitedAt on the thread projection plus a thread.mark-unread command, so ever…
  • Supersedes #9051 — V2 deletes CursorAdapter.ts and runs Cursor through CursorAdapterV2/CursorAgentSdk on the official @cursor/sdk (docs/user/cursor.md: "does not use Cursor's ACP…
  • Supersedes #8453 — V2's normalizeClaudeTurnTokenUsage returns usageScope main_agent on every path, so subagent tokens cannot reach the parent context meter.
  • Supersedes #8412 — GrokAdapterV2 wires extractXAiAcpSubagentUpdate/extractXAiAcpSubagentEndNotice into V2 subagent lineage (Map Grok task envelopes to subagent lineage).
  • Supersedes #7393 — OpenCodeAdapterV2 declares supportsSubagents/exposesSubagentThreadIds/emitsSubagentLifecycle and maps child sessions through SubagentProjection into V2 lineage.
  • Supersedes #7308 — V2 delivers server-owned limit handling: show provider limit stops as Limited (#12677), resume limited threads when usage resets (#12686), snooze limited threads (#126…
  • Supersedes #7287 — V2 projects subagent identity through SubagentProjection and carries the requested model (fix(claude): retain requested subagent models.
  • Supersedes #7240 — V2 persists queued runs in the event log with queued-run.reorder/cancel/edit and queued-message.promote-to-steer commands (fix(queue): preserve and hold queued message…
  • Supersedes #7179 — Settlement and snooze are server-owned in V2 (ThreadSettlementService, thread.snoozed/unsnoozed projections) and the branch already carries fix(server): keep old failu…
  • Supersedes #7143 — ClaudeAdapterV2 derives every message and turn-item id from the native provider item id via IdAllocator.derive.messageFromProviderItem, so stream position is never the…
  • Supersedes #6148 — V2 routes every provider session by providerInstanceId and the orchestrator emits provider-session.detached plus a provider-session.detach effect for providerSwitchPla…

Partially / likely superseded

  • Supersedes #12221 — V2 queues additional runs instead of superseding a live one, and ProviderRuntimeRecoveryService/RunFinalizationService terminalize any nonterminal run whose provider w…
  • Supersedes #12189 — planThreadDeletion emits deletion events and cleanup effects in one EventSink transaction, with the effect worker performing the durable cleanup afterwards.
  • Supersedes #12135 — V2 keeps subagents in the thread projection (SubagentProjection) independent of the bounded message history window ('feat(orchestration): bound thread history and resu…
  • Supersedes #12073 — V2's generic ACP provider registry (AcpRegistryAdapterV2, 'feat(providers): standardize ACP providers') lets a DeepSeek ACP agent be registered without a bespoke drive…
  • Supersedes #12003 — OpenCodeAdapterV2's prompt-admission state machine plus 'cancel pending OpenCode prompts safely' cover the interrupt-before-submission window.
  • Supersedes #11908 — The transcript is the server-owned v2 event log, and ProviderSwitchServiceV2 plus ContextHandoffServiceV2 plan an instance change without the provider session owning t…
  • Supersedes #11839 — ProviderRuntimeRecoveryService cancels nonterminal runtime requests and background turn items whose provider process is gone before admitting new work.
  • Supersedes #11838 — V2 deletes ProviderSessionReaper entirely.
  • Supersedes #11640 — OpenCodeAdapterV2 reconciles prompt admission against the live session status (reconcileOpenCodePromptAdmissionStatus, commit 'recover OpenCode status reconciliation').
  • Supersedes #11471 — V1 CodexAdapter is deleted.
  • Supersedes #11423 — V2's ACP Registry lets any registry agent be added without a bespoke Copilot driver, so only the Copilot-specific quota/driver bits would remain.
  • Supersedes #11284 — GrokAdapterV2 is built on makeAcpAdapterV2, whose shared contextUsage tracking drives the V2 live context meter (commit `feat(orchestration-v2): show live context us…
  • Supersedes #11139 — V2 supports Devin through its ACP Registry path (Adapters/DevinAcp.ts, commit fix(acp): support Devin terminals, questions, and native subagents) rather than a bespo…
  • Supersedes #11090 — OpenCodeAdapterV2's admission state machine tracks idleDuringAdmission and emits reconcile-idle, replacing the V1 idle/turn-boundary handling.
  • Supersedes #10939 — V1 ProviderService is deleted.
  • Supersedes #10893 — V2 ships a generic ACP Registry adapter (AcpRegistryAdapterV2) that can register any registry agent, so a bespoke omp driver is at most partially needed.
  • Supersedes #10805 — OpenCodeAdapterV2 has an explicit prompt-admission state machine (admissionPending/idleDuringAdmission/reconcile-idle) so an idle signal during admission no long…
  • Supersedes #10799 — V1 CodexAdapter is deleted.
  • Supersedes #10607 — V2's ProviderRuntimeRecoveryService plus "harden Grok v2 runtime lifecycle" and "dedupe Grok continuation dispatch" handle crashed sessions centrally.
  • Supersedes #10575 — V2 projects native subagents as separate read-only child threads with their own tool activity (SubagentProjection), so per-subagent stream isolation is structural.
  • Supersedes #10295 — V2 replaces ActivityPayloadProjection.ts with ShellStream and the v2 activity log ("fold completed trailing background activity", "keep shell snapshots bounded and…
  • Supersedes #10132 — V2 ships UsageLimitRecoveryWorker with usageLimitContinuationOfRunId ("feat(v2): resume limited threads when usage resets (#12686)", "share scheduling for tasks an…
  • Supersedes #10087 — V2's diagnostics budget already keeps bounded detail: 64 KiB encoded payload budget with structural summaries that "retain routing identifiers, methods, status, and er…
  • Supersedes #9922 — Cursor V2 gets its model list from CursorSdkCatalog via @cursor/sdk instead of the CLI (CursorProvider.ts loses ~1060 lines of CLI probing), so CLI-version model f…
  • Supersedes #9612 — V2 deletes ProviderSessionReaper.ts.
  • Supersedes #9408 — V2's SubagentProjection plus "Codex background command completion and subagent resume" track subagent lifecycle in projections rather than in the deleted `ClaudeAdap…
  • Supersedes #9391 — V2 separates RunFinalizationService from provider turn completion and makes settlement server-owned in ThreadSettlementService ("stop retained background work afte…
  • Supersedes #9344 — V2 owns session lifecycle in ProviderSessionManager + ProviderRuntimeRecoveryService, which retires effects tied to lost provider processes before admitting new wo…
  • Supersedes #9319 — V2's RuntimeRequestService/runtime-request.respond reads the persisted request, validates required answers, and commits the resolution and user message in one tran…
  • Supersedes #9227 — CodexAdapterV2 persists Codex async notifications as user_input_request turn items and runtime requests that survive turn end, provider exit, and restart.
  • Supersedes #9158 — V2's generic ACP Registry (AcpRegistryAdapterV2, "feat(providers): standardize ACP providers") lets registry agents be added without a first-party driver, so the bes…
  • Supersedes #9130 — V2 replaces ProviderSessionDirectory/ProviderService with ProviderSessionManager and ProviderSessionTransitionPolicy, which decide resume versus fresh session from persisted session state.
  • Supersedes #8952 — V2 models native subagents in SubagentProjection ("feat(orchestration-v2): model native subagents", "show subagent details and history in workspace card")
  • Supersedes #8939 — V2 records run/turn state as committed events and handles OpenCode cancellation in OpenCodeAdapterV2 ("cancel pending OpenCode prompts safely", "abort external OpenC…
  • Supersedes #8857 — V2 replaces the usage-limit handover draft with ContextHandoffServiceV2 portable handoffs plus Limited status and resume-at-reset (feat(server): preserve budgeted hist…
  • Supersedes #8842 — ClaudeAdapterV2 derives deterministic ids from native item ids and V2 restores resume continuity explicitly (fix(server): restore Claude resume compaction.
  • Supersedes #8796 — ThreadDeletionReactor and ProviderSessionDirectory are deleted on V2.
  • Supersedes #8737 — V2 requires the MCP registry for provider sessions and rebuilds credentials per session (fix(claude): reopen queries after MCP credential rotation.
  • Supersedes #8659 — V2's live context meter (#8144) plus OpenCodeAdapterV2's own turn token accumulator already deliver OpenCode context and cost on the meter.
  • Supersedes #8619 — V2 commits stop intent plus its receipt in one transaction and acknowledges before provider work settles (fix(server): wait for native Codex start before Stop #10024.
  • Supersedes #8617 — V2 separates the thread-level contextUsage snapshot from per-turn TurnTokenUsage with explicit partial/complete status (fix(server): keep current provider context usage).
  • Supersedes #8425 — V2 rollback goes through CheckpointRollbackService with provider coordination and the orchestrator resolves runtime requests transactionally (fix(orchestration): exclu…
  • Supersedes #8097 — V2 persists queued/task state in the event log and restores it across restart (fix(queue): preserve and hold queued messages after restart.
  • Supersedes #7993 — Same ACP Registry path covers running Droid as a registry agent.
  • Supersedes #7865 — V2's generic ACP Registry (AcpRegistryAdapterV2 plus feat(providers): standardize ACP providers #6461) lets an ACP agent be registered without a bespoke first-party pr…
  • Supersedes #7854 — ProviderRuntimeIngestion.ts is deleted on V2.
  • Supersedes #7591 — V2 run state is server-owned and background work is modeled explicitly (fix: stop retained background work after a turn settles.
  • Supersedes #7520 — V2's normalizeClaudeTurnTokenUsage stamps usageScope main_agent with an explicit hasSubagents flag instead of folding subagent tokens into the parent turn.
  • Supersedes #7246 — ClaudeAdapterV2 derives the SDK permission mode from the runtime policy in permissionModeForClaudeRuntimePolicy (fix(claude): preserve approvals with full-access sandbox.
  • Supersedes #7238 — V2 adds a from-scratch CodexTurnTokenUsage.ts normalizer and maps nested Codex subagent threads to their own nodes, so parent turns no longer inherit child totals.
  • Supersedes #7192 — V2 separates provider turn end from run finalization (RunFinalizationService) and ClaudeAdapterV2 buffers late/idle notifications behind replay tombstones so post-fina…
  • Supersedes #7184 — ActivityPayloadProjection.ts is deleted on V2.
  • Supersedes #7072 — V2 ships a live context meter (feat(orchestration-v2): show live context usage in the meter #8144) fed by OpenCodeAdapterV2's own token accumulator (fix(server): retai…
  • Supersedes #6584 — V2 models native subagents as separate execution nodes whose completion does not block the root run (feat(orchestration-v2): model native subagents.
  • Supersedes #6162 — V2 adds a first-class provider-session.detach command with attached/updated/detached projections, so a thread's session can be released and rebuilt on the next turn wi…
  • Supersedes #6004 — CodexProgressCoalescer.ts is deleted on V2 and replaced by Adapters/ProviderTextDeltaCoalescer.ts feeding ProviderEventIngestor, with transport payloads bounded (perf(…
  • Supersedes #5711 — ProviderSessionReaper is deleted on V2.
  • Supersedes #5524 — V2 deletes ProviderSessionDirectory/ProviderService entirely and tracks session liveness as persisted provider-session.attached/updated/detached events plus ProviderRu…
  • Supersedes #5142 — ClaudeAdapter.ts is deleted on V2.

Closes discussions

Discussions cannot be auto-closed; these are linked so they can be resolved by hand after merge.

Note

Introduce orchestration V2 runtime, services, provider adapters, and MCP toolkits

  • Adds a complete orchestration V2 server runtime: projection store, event store, effect outbox, command receipts, checkpoint capture/rollback, thread management, run execution, provider session management, context handoff, runtime policy, and legacy V1 thread importer, composed through runtimeLayer.ts
  • Adds V2 provider adapters for Codex, Claude, Cursor, Grok, OpenCode, and ACP Registry with a shared adapter contract, driver registry, and selection-transition policy
  • Adds MCP toolkit services and HTTP registration for orchestrator delegation, thread operations, worktree handoff, project lifecycle, attachments, environment preferences, and preview controls
  • Adds scheduled-task persistence, scheduling logic, server service, client runtime atoms, and a settings UI surface
  • Migrates client-runtime and web/mobile UI from legacy session/turn fields to V2 projection-based runtime/run state, including thread details panel, queue controls, relationship graph, history loading, and item inspector
  • Registers database migrations 050–061 for V2 foundation tables, subagents, provider-session bindings, launch workflows, application event sourcing, effect cancellation, scheduled tasks, legacy import state, and recovery/shell indexes
  • Risk: replaces the legacy EnvironmentApi orchestration interface with orchestrationV2; removes serverUpdateThreadContinuation capability; CursorSettings no longer exposes binaryPath or apiEndpoint; ProviderUsageLimitsIngestionLive no longer subscribes to runtime events; thread routing resolves existing non-deleted threads directly to ready instead of loading

Macroscope summarized 6102d00.


Note

Medium Risk Mobile thread persistence and list/archive/stop behavior change with V2 runtime semantics; removing the thread-transfer report workflow reduces PR visibility into transfer budget regressions.

Overview This slice of the orchestration V2 rollout retires the thread-transfer PR comment pipeline (trusted publisher script, tests, and workflow_run workflow) while CI can still emit transfer artifacts; it also installs build-essential in CI so ACP process-tree fixtures compile instead of soft-skipping.

Mobile moves onto shared V2 client-runtime pieces: SQLite cache uses ORCHESTRATION_CACHE_SCHEMA_VERSION and stored V2 shell/thread snapshots, runtime wiring swaps in bounded thread snapshot loading and history control, and thread detail/review/archive flows read projections (runtime, RuntimeRequestId, checkpoint summaries from runId) instead of V1 session/turn shapes. UX additions include activity inspector, queue control, relationships banner, progressive history controls, server visit watermarking, stricter archive rules via threadCanArchive, and approval/user-input cards that honor live vs dead provider responseCapability.

Smaller touches: shared brand mark module, new uniwind adaptive color tokens, desktop env test for user-data dir names, README link to appearance docs, and marketing copy for Cursor harness.

Reviewed by Cursor Bugbot for commit 9eeed8c17109be3752d2f8e1643583d1f579ea2d. Bugbot is set up for automated code reviews on this repo. Configure here.


Devin Review

Checks

46 successful · 17 skipped
All checks passed
b37fcea
Synced from GitHub

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

Provider-initiated turns are invisible: post-turn SDK activity is dropped entirely

Two reproductions today (threads 47763f5e, 71e29ba5), one root cause. Filing here since the fix is squarely in turn-mapping territory; relates to the t3code/scheduled-tasks follow-up "thread-bound fires steer active turns".

Symptom

A thread shows finished in the UI while the Claude SDK session is actively running a turn — making tool calls, pushing to PRs. The work is invisible: no run, no turn items, no activity log entries, nothing in orchestration_events after the last user-requested turn completed.

Repro timelines

Thread 47763f5e (background-task wakeup):

  • 22:10:01 — turn completes (result, end_turn: "…polling every minute, up to 25 min"). Run ordinal 9 → completed, session → ready. Last orchestration event for the thread.
  • 22:12:56 — SDK wakes the session: system/task_updated + system/task_notification (watcher task bdknlk0tp completed) → system/init → full new streaming turn with tool calls (visible in the provider protocol log only).
  • Several minutes of real work (incl. git push) with zero orchestration events.

Thread 71e29ba5 (ScheduleWakeup self-pacing loop):

  • 22:36:13 — run 58 completes with stop_reason: "tool_use" (agent called ScheduleWakeup and went to sleep). Last orchestration event.
  • 22:36:49 — task_updated (status failed!) + task_notification for blrc0l01r → system/init → new turn.
  • 22:37:55 — invisible turn completes (~66s, 8 SDK turns), calls ScheduleWakeup again. Loop repeats: one invisible turn per wakeup. No run 59 exists.

Root cause chain

  1. Adapter (ClaudeAdapter.ts): context.turnState is created only by sendTurn (orchestrator-requested prompt) and cleared in handleResultMessage. When the SDK starts a turn on its own (task-notification wakeup), there is no turnState, so handleStreamEvent early-returns and drops everything streamed. The synthetic-turn fallback in handleAssistantMessage (~L2468) triggers too late (first complete assistant message) and demonstrably did not rescue either repro.
  2. Ingestion (ProviderRuntimeIngestion.ts): a turn.started with no active turn would be accepted (session → running), but no run exists — ordinals/userMessageId/provider-turn binding all come from thread.turn-start-requested, so turn-scoped events have nowhere to project.
  3. Bonus bug: the adapter has no system/task_updated case — it falls through to the unknown-message default. 7 occurrences in one thread, including failed and killed status patches, all dropped as "unknown SDK message" warnings.

Proposed fix

  1. Orchestrator: mint runs for turns nobody requested. In processRuntimeEvent, when an accepted turn.started has no pending turn-start (getPendingTurnStartByThreadId → None), dispatch a run.provider-initiated command: next ordinal from the same counter, no userMessageId, trigger payload from the event, provider-turn→run binding as if a pending turn-start had been claimed. Key on turnId for replay idempotency. Everything downstream (turn items, messages, checkpoints, turn.completed → run completed) reuses existing projection code.
  2. Adapter: open the turn at the wakeup signal, not the first assistant message. On stream_event/message_start (or system/status: requesting) with turnState === undefined, create a synthetic turnState and emit turn.started with trigger metadata. Keep the assistant-message fallback as a safety net.
  3. Schedule fires (t3code/scheduled-tasks): front door when idle. A thread-bound fire hitting a thread with no active turn should go through the normal turn-start pipeline (synthetic user message), not silently steer the idle session. Keep steer for genuinely-active turns. (Doesn't cover SDK-internal wakeups — hence 1+2.)
  4. Adapter: handle system/task_updated — apply the patch to claudeTasks state / emit a task-updated runtime event instead of dropping failed/killed statuses.
  5. Observability: loud warning when a decoded SDK message arrives while session status is ready with no turnState. This was only diagnosable by diffing the provider protocol log against the event store.

Gift from the SDK

The post-wakeup result already carries "origin": {"kind": "task-notification"} — the SDK explicitly labels provider-initiated turns. The adapter can carry origin straight into the synthetic turn.started payload and the run record; no correlation heuristics needed.

UI implication: a run with trigger: "provider" renders with a trigger header ("resumed: background task completed / schedule fired") instead of a user bubble, and the thread correctly shows running during autonomous work.

🤖 Generated with Claude Code

Follow-up: post-turn wakeup handling implemented (design revised)

Implemented on this branch (t3code/codex-turn-mapping), with one significant revision to the plan in my earlier comment after re-reading the raw provider chunks: not every wakeup should become a new run. The SDK distinguishes two cases, and they now get different treatment:

1. ScheduleWakeup sleep loops — adapter-only, no orchestrator involvement

The recorded chunks are explicit: the yield result carries stop_reason: "tool_use" (not end_turn), and the ScheduleWakeup tool result carries structured {scheduledFor, clampedDelaySeconds} plus prose ("Nothing more to do this turn — the harness re-invokes you…"). ClaudeAdapterV2 now tracks the observed ScheduleWakeup result on the turn context and does not finalize such turns: the run stays active, run-scoped ingestion stays subscribed, and the wakeup continuation streams into the same run. A 25-minute poll loop is one run, not a run per wakeup.

2. True end_turn re-invocations — provider-initiated runs

When Claude genuinely ends the turn and the SDK later re-invokes it (background task notification), holding the run open is wrong (dev servers run forever), so:

  • ClaudeAdapterV2 buffers the post-turn activity (skipping stream-event noise) and emits a new turn.wakeup adapter event once real activity starts, with origin extracted from the task_notification.
  • ProviderWakeupService (new): relay queue + daemon (breaks the session-manager ↔ orchestrator layer cycle). The daemon waits for thread quiescence (the wakeup announce races the previous run's terminal commit by milliseconds), then dispatches message.dispatch with new mode attach_wakeup.
  • The orchestrator mints a run through the existing dispatch machinery — synthetic message (createdBy: "system", creationSource: "provider", turn item inputIntent: "provider_wakeup") — and RunExecutionService delivers via the new optional adapter method attachTurn (adopt in-flight turn + replay buffer; nothing sent to the provider).
  • Guards: superseded by any blocking run; no provider switch; no pending context transfers. A user turn that races the wakeup wins; the adapter drops its buffer (task bookkeeping is still applied).

3. Backgrounded commands (Bash + run_in_background)

Previously these projected as completed command_execution items the instant the tool returned, while the command kept running. Now: a tool result carrying tool_use_result.backgroundTaskId keeps the item running, registered session-level; the matching task_updated flips it terminal (killed/failed no longer dropped — there was no task_updated handling at all), and task_notification enriches the output with the summary. This works cross-run: routeProviderEvent accepts item/node updates for owned provider threads, so a wakeup run can complete an earlier run's item.

Tests

New replay fixture claude_provider_wakeup built frame-by-frame from the recorded thread 47763f5e chunks (watcher task, second init, message_start announce, origin: task-notification result). It drives the full loop end-to-end: replay stream → adapter buffer/announce → session-manager pump → wakeup relay → attach_wakeup dispatch → run minting → attachTurn replay → cross-run background-command completion → follow-up user turn. New fixture step await_provider_wakeup_run awaits daemon-minted runs. Full orchestration-v2 suite green (273 tests; all 69 pre-existing replay fixtures unchanged).

Known follow-ups

  • Session idle reaper (30 min) vs long scheduled sleeps (ScheduleWakeup clamps to 60 min) — a session could be reaped mid-sleep.
  • Superseded wakeup buffers replay only task bookkeeping; the dropped wakeup turn's content is lost for that round (logged).
  • OrchestrationV2ProviderTurn has no waiting status literal — held-open turns read as running; consider adding waiting for honest UI during sleeps.
  • UI: render inputIntent: "provider_wakeup" turn items as a resume marker instead of a user bubble.

🤖 Generated with Claude Code

Synced from GitHub

I really want this feature, so I thought I’d help out by testing it. So far in testing it for an hour I haven’t had any major issues.

I found several small things that I noticed. Feel free to use/ignore at your own discretion:

What I noticed A queued message is both shown above the input box but also in the chat history. This confused me briefly at first. Because I thought the message was already sent directly.

Really like the interrupt UI. Maybe a bit harsh of a harsh red color. Feels like “Interrupt requested -> Run interrupted” is doubled up.

“Running” is not distinct and different copy than the sidebar “Working”. Would it make sense to harmonize those UIs? Currently it is hard to see at a glance which ones are running. Also it kept in "Running" even though the agents were done. CleanShot 2026-07-10 at 19 26 43@2x

I didn’t see a way to see which model is being used for the subagents. This is also annoying in Cursor, so would be nice plus if you get it right. This is relevant because Fable is expensive and I don’t really want the subagents to be Fable either. It is nice to easily see if my CLAUDE.md is working correctly.

The lineage UI is confusing to me. When going back the ‘action’ icon is on the left. But when going into a child it is on the right. Also took me a while to notice the muted ‘this is a fork’ icon:  CleanShot 2026-07-10 at 19 31 51@2x CleanShot 2026-07-10 at 19 32 04@2x CleanShot 2026-07-10 at 19 32 12@2x CleanShot 2026-07-10 at 19 33 14@2x

Synced from GitHub

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This is a large production orchestration replacement, not a bounded additive change: it introduces new persistence, provider execution, MCP workflows, checkpoint/rollback behavior, and web/mobile/native integration across 2,027 files. The unresolved review set also identifies material security, lifecycle, data-consistency, and runtime risks, while the PR changes Macroscope configuration and product defaults.

Not approved because:

  • 452 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Scheduled task reports success while its new-thread launch fails in background

Tested on aec85c546e597dbcf78db81b134e7438d9a5ada3 with a scheduled task configured to create a new worktree. Reproduced twice with fresh threads.

Observed

The scheduled-task record ends with lastRunStatus: succeeded, but the generated thread has ordinal 1 failed before provider start:

text
1Workspace preparation failed during generate metadata:
2Text generation failed in generateBranchName: Failed to write temp file
3
4ENOENT: no such file or directory, open
5/tmp/t3code-codex-schema-208069-6MZJpS/919af017300b

The first reproduction used a custom TMPDIR; I restarted the desktop/server with TMPDIR=/tmp and confirmed the active server process inherited it. The second reproduction failed identically, so this is not caused by that local temp configuration, permissions, or available space.

Status propagation

ScheduledTaskService.runTask treats threadLaunch.launch(...) returning as completion and immediately derives lastRunStatus from that Exit. ThreadLaunchService.launch returns successfully after schedulePreparation(...) forks prepareInBackground into preparationScope. When generateBranchName later fails, the prepared run/thread is marked failed, but that failure cannot update the already-completed scheduled-task run.

This creates two user-visible problems:

  1. A recoverable branch-name metadata failure prevents the scheduled task from starting at all.
  2. The scheduled task still reports success because it tracks dispatch rather than background preparation outcome.

Local workaround confirmed from the launch conditions: choose Use the project checkout or Use a specific checkout; both bypass the implicit worktree branch-name generation path. New-worktree scheduled tasks remain broken in this environment.

Suggested direction: await a preparation receipt/outcome before completing the scheduled-task run, and either fall back to fallbackBranchName(threadId) when branch-name generation fails or otherwise make metadata failure non-fatal.

Synced from GitHub

@juliusmarminge Based on communications I've seen on twitter and elsewhere, it seems that this branch is, in some sense "the future" of t3code. I'm wondering why, then, it is kept in a constant state of conflict with main. Presumably, the two will have to be reconciled, at some point, right?

As someone who maintains a somewhat substantial set of patches on top of upstream t3code, its a bit difficult to know how to proceed with maintaining these. I don't mind not getting any of my stuff merged ever, but it would be nice to understand roughly where things are headed with this branch, because a lot of the patches that I have touch the surface of what is going on here, and its difficult to know what exactly I should be tracking...

Synced from GitHub

Hey, just came across an issue with scheduled tasks for remote projects. The UI lets me select a project from another environment, but the task is created and executed in the local environment. Since it only stores the projectId, the local server tries to find the remote project in its own database, and the run fails with Project not found. I think the task should be routed to the selected project’s environment, or the project picker should only show projects from the environment where the task will run.

Synced from GitHub

Is this pr actually just a stress test of github's pull request page? love to see +181,657 -85,511. There's really no way any of this could have been done more incrementally?

Synced from GitHub

Is this pr actually just a stress test of github's pull request page? love to see +181,657 -85,511. There's really no way any of this could have been done more incrementally?

Julius contributed :) Знімок екрана 2026-08-21 о 13 38 11

Synced from GitHub

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $34.58, which exceeds your per-review limit of $15.00.

The top 3 files driving up this estimate:

FileDiff SizeEstimate
packages/contracts/src/orchestrationV2.ts127.64KB$5.06
apps/server/src/mcp/OrchestratorMcpService.ts75.98KB$3.01
apps/server/src/orchestration-v2/EventSink.ts34.00KB$1.35

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

Synced from GitHub

A key use case for provider switching is quota exhaustion. When a user reaches the usage limit of the active model or provider during a long-running session, T3 Code should allow switching to another authenticated provider without losing the thread context, current worktree, pending plan, or file-change state.

Ideally, the limit error should offer a direct Continue with another provider action. If full context replay is unavailable, T3 Code could generate and transfer a structured handoff automatically.

Fixed in 84ef39dce4d. Stash is a separate tab again. The queue and activity share a column that stops 4px before Stash. Opening Stash shows its own drawer and preserves the queue's expanded or collapsed state when closed. Waiting threads keep the Stash tab too.

Stash open:

Stash drawer with four entries

Checked the queue, waiting state, expanded tasks, and Stash at desktop and narrow widths. Targeted lint, web typecheck, and all six existing queue/stash tests passed. No new tests or stylesheets.

Queued-message editing is fixed in a794ced3160. These screenshots replace the earlier edit-row examples.

  • Editing highlights the original queue row instead of hiding it or adding a row. The count and header remain visible, including with one queued message.
  • Row numbers are removed. There is one Cancel action, and the save button uses a checkmark.
  • Edit, Steer, and Remove use the app tooltip component instead of native title tooltips.
  • The narrow-screen toolbar keeps the same height when switching between Stop and Save.

Verified in the shared preview: typing and Cancel leave the saved text unchanged; Save updates the message in place. Queue and composer dimensions stay unchanged when entering and leaving edit mode at desktop and narrow widths. Targeted lint, web typecheck, and 21 existing focused tests pass. No new tests were added.

This covers the shared web/desktop composer and narrow web layouts. Provider adapters, wire contracts, connection modes, and the native mobile client are unchanged. The composer documentation now describes saving with the checkmark.

Before:

Before: editing lowers the count and adds a separate row with duplicate cancel controls

After:

After: original queued message stays visible while its draft is edited, with one Cancel and a checkmark to save

Short edit and cancel demo

Single-message, narrow-screen, and tooltip examples

Editing the only queued message retains its header and count

Single-message editing at a narrow viewport

App-styled edit tooltip

Updated the composer actions in a41ba601149.

  • A running turn shows Interrupt only when the composer is empty.
  • With text or attachments, the button shows a steer arrow. Click or Enter steers.
  • Holding Cmd/Ctrl changes it to a queue icon. Modifier-click and Cmd/Ctrl+Enter queue.
  • Editing a queued message keeps the checkmark, even while holding a modifier.
  • Each state uses an app-styled tooltip, including disabled Submit and busy states.

Verified click and keyboard dispatch, edit save/cancel, modifier release, and the narrow web layout in the mock preview. Targeted lint, the web typecheck, and 30 existing tests passed. No new tests or CSS files.

Interrupt, queued update, idle, and narrow layout

Disabled idle Submit button still shows its tooltip

Narrow web composer shows only Steer when it has content

Fixed the tooltip wrapping on Mod in 330c44fd4d7.

Changing the order of the shortcut text triggered the tooltip's content resize. The text now stays Enter to steer, Mod+Enter to queue while the icon and action still switch to Queue.

Verified repeated Mod press/release cycles at desktop and narrow widths. The tooltip stayed 26px high throughout, compared with 42px when the old text wrapped. Targeted lint and the web typecheck passed.

Before fix, Mod heldAfter fix, Mod held
Wrapped tooltipStable single-line tooltip

Watch two Mod press/release cycles.

Synced from GitHub

Bug: delegated-task completion wakes are silently starved after two deliveries per cohort — parent waits forever on the third wave

TL;DR. delegate_task (async) promises the parent a wake on every child terminal, and its tool description tells the agent to "end the turn instead of polling." But finalizeDelegatedCompletionDelivery refuses to reserve a follow-up delivery once a cohort has settled two deliveries (settledDeliveryCount < 2). Any child whose completion lands in a third wave stays completionDelivery: "pending" forever: no wake, no queued message, nothing on restart. The orchestrating agent — following the tool contract — sits idle waiting for a completion that already happened. With 4–5+ parallel children whose completions straddle wake turns, this is close to guaranteed.

Observed on the #7211 stack (V2 snapshot of 2026-08-28); everything cited below is apps/server/src/orchestration-v2/ code from this PR's branch (none of it exists on main), and none of it is provider-specific.

The two contracts that collide

OrchestratorMcpService.ts, delegate-task creation:

ts
1// Async delegations wake the parent on every child terminal; wait
2// delegations deliver through the blocking tool call, so a wake is
3// only needed if the parent settled first (timeout, disconnect).
4completionWake: input.mode === "wait" ? "settled_only" : "always",

Orchestrator.ts, planDelegatedCompletionDelivery:

ts
1const settledDeliveryCount = cohort?.settledDeliveryCount ?? 0;
2if (settledDeliveryCount >= 2) {
3 // A cohort permits one initial delivery and one successor. Keep the
4 // result pending and inspectable instead of recursively re-arming the
5 // parent for every child that finishes after that bounded handoff.
6 ...state: "pending"..., offer: false

…and the same settledDeliveryCount < 2 guard in finalizeDelegatedCompletionDelivery's canReserveFollowUp, which is the sweep that runs when a wake turn settles. settledDeliveryCount never resets, so this isn't a throttle — it's lifetime starvation per cohort. Nothing ever revisits a "pending" task after the cap engages: handleTerminalRun only sweeps delivery runs, the startup recovery path re-runs the same capped sweep, and finalizeAppOwnedSubagent early-returns on existingResultTransfer. The tool description ("An async child's completion wakes this thread… end the turn instead of polling") makes the failure mode maximally quiet: the agent does exactly what it was told and hangs.

Forensic timeline (real thread, from orchestration_v2_projection_*)

Parent thread delegated 5 async children in one turn (run 7), so all 5 share run 7's cohort. Timestamps from the projections DB:

time (UTC)eventcohort state
01:01:52run 7 delegates t10, t11, t13, t15, t17—
01:05:49t10 completes → delivery 1, wake run 8 startssettled=0, delivery gen 1
01:05:56–01:07:01t17, t13, t15 complete during run 8 → "pending"
01:07:11run 8 settles → sweep reserves delivery 2 = {t15, t17, t13} → wake run 9 starts 01:07:12settled=1, delivery gen 2
01:07:20t11 completes, 8s into run 9 → "pending"
01:09:12run 9 settles → sweep: settledDeliveryCount → 2, pendingTaskIds = [t11], but canReserveFollowUp requires < 2 → refusedsettled=2, delivery null, t11 pending
01:09–01:29parent idle; t11's result queryable but no wake exists or ever will
01:29:48human notices the stall and nudges; that run reads task_status → t11 finally acknowledged

Final cohort row on run 7: settledDeliveryCount=2, nextGeneration=3, disposition=open, delivery=null — with a terminal, never-delivered task. Children delegated during later wake turns (t12 on run 8, t14 on run 9, t16 on run 10…) each started fresh cohorts with reset counters, so their wakes worked — which is exactly why moderate parallelism masks the bug until one dispatch wave is large enough to stagger across ≥3 waves.

(The queued-delivery merging worked beautifully, for the record — t13/t15/t17 amending the queued wake into one bundled message is the right behavior. The problem is only the lifetime cap.)

Suggested fixes (any of these)

  1. Make the cap a concurrency bound, not a lifetime bound. The recursion the comment fears is "one delivery in flight + one reserved successor" — that's already bounded without a lifetime counter. Reset settledDeliveryCount (or simply drop it) whenever a sweep finds pendingTaskIds.length > 0 after the delivery drains; the wake-per-terminal contract then holds and the parent still never sees more than one queued wake at a time.
  2. Sweep pendings on any parent-run settle. Extend handleTerminalRun to arm a delivery for terminal app-owned tasks left "pending"/unarmed whenever the parent thread goes non-live. The existing generation + alreadyDispatched dedupe in ProviderContinuationService.currentDelegatedCompletionDelivery already guards against the duplicate-wake concern.
  3. At minimum, don't be silent. If the cap stays, surface refused deliveries (system line in the thread: "N delegated results pending — read with task_status") and soften the tool description's "end the turn instead of polling," which is currently a trap.

Related smaller hole in the same family: for mode="wait" children (settled_only), planDelegatedCompletionDelivery returns with the task untouched (not even "pending") when the parent has a live run — that branch precedes the pending-marking branches — and the post-timeout wake-policy upgrade knowingly skips re-planning when the parent settled in between ("a missed wake is cheaper than a duplicate one"). Same silent-starvation class, just harder to hit because the blocking wait usually owns delivery.

Happy to provide the raw projection rows or test this against a patched build — we run this stack daily.

Synced from GitHub

@juliusmarminge one addition I'd really like here: scheduled messages.

I think this should be separate from normal queued messages. Queued messages mean “send after the current run finishes”; a scheduled message means “send this message at a specific date/time.”

The important architectural requirement is that the schedule must be persisted and executed by the T3 server/environment that actually runs the agent, not by whichever web/mobile/desktop client created it. If I schedule a message from my laptop or phone against an agent running on another machine, I should be able to close/disconnect that client and the message should still fire at the selected time.

In other words, the client should only create/edit/cancel the schedule. The host environment owns the durable record and dispatch timer.

A simple UX could be a “Send later” action from the composer that creates a one-shot scheduled message for the current thread. It should be visible/cancellable/editable before it fires.

I noticed this PR already adds server-persisted scheduled tasks, but those schedules appear recurring (interval / fixed_time). This feels like the same server-side scheduling infrastructure could support a one-shot send_at/timestamp schedule without conflating it with the existing queued-message semantics.

@juliusmarminge one addition I'd really like here: scheduled messages.

I think this should be separate from normal queued messages. Queued messages mean “send after the current run finishes”; a scheduled message means “send this message at a specific date/time.”

The important architectural requirement is that the schedule must be persisted and executed by the T3 server/environment that actually runs the agent, not by whichever web/mobile/desktop client created it. If I schedule a message from my laptop or phone against an agent running on another machine, I should be able to close/disconnect that client and the message should still fire at the selected time.

In other words, the client should only create/edit/cancel the schedule. The host environment owns the durable record and dispatch timer.

A simple UX could be a “Send later” action from the composer that creates a one-shot scheduled message for the current thread. It should be visible/cancellable/editable before it fires.

I noticed this PR already adds server-persisted scheduled tasks, but those schedules appear recurring (interval / fixed_time). This feels like the same server-side scheduling infrastructure could support a one-shot send_at/timestamp schedule without conflating it with the existing queued-message semantics.

CleanShot 2026-08-29 at 19 21 01@2x

Implemented T3 action summaries in c01ff20757e. The same groups now describe orchestration work instead of reducing it to “used tools”:

  • Ran 2 commands and sent messages to 3 threads
  • Sent 5 messages to 2 threads, with repeated message IDs deduplicated
  • Created 4 threads and delegated 2 tasks, including batch creation

Mixed groups show two specific categories and a count of the remaining actions. Commands, file changes, and orchestration changes take priority over reads and status checks. Failed calls do not inflate successful sends or creations; failure counts appear first so narrow layouts cannot truncate them away. A reported child failure is separate from failure of the status-check tool itself.

Grouping boundaries, expansion, individual call details, and icons are unchanged. Native mobile layout is unchanged. Preview/worktree tools and unknown tools retain the generic fallback.

Verified 53 focused tests across the timeline, T3 counting, and tool presentation, plus scoped lint and web/shared/client-runtime typechecks. Checked the scripted preview at desktop and narrow widths, including expanding back to the original calls and their input/output.

Narrow layout — failure count stays visible

Narrow T3 activity summaries

Removed the added failure/unfinished-count prefixes in d7d29629493 from web/desktop and the shared mobile summary path. The requested T3 action summaries and individual tool failure details are unchanged.

The existing web timeline, mobile activity, and T3 counting tests pass, along with scoped lint and typechecks. Confirmed the prefix is gone in the running web preview.

Synced from GitHub

apps/server/src/cli/app.ts:232-239

(Posted at PR level: an inline comment could not be anchored on this file in the current diff.)

The Effect.tryPromise catch in runAppCommand collapses six semantically distinct failures into one error whose distinction survives only as an English sentence inside cause: Schema.Defect() — response timeout, oversized response, non-JSON response, schema-invalid response, request-id mismatch, and "connection closed" all become DesktopAppUnreachableError, whose message asserts the desktop app could not be reached and tells the user to start it. In the four response-shaped cases the app did answer, so that caller-visible message is wrong, and cli/app.test.ts asserts on the prose (cause: { message: "The desktop app response is invalid." }), which makes it behavior rather than diagnostics.

The conventions ask that failures be distinguished by stable structural attributes with the message derived only from them, and that a translation boundary wrap only genuinely lower-level failures rather than flatten known ones. Consider having sendDesktopAppActivationRequest reject with tagged errors (or return a tagged result) so the CLI can keep DesktopAppUnreachableError for the connect-level ENOENT/ECONNREFUSED case its message describes, and add e.g. DesktopAppResponseInvalidError { requestId, workspaceRoot, byteLength } and DesktopAppResponseTimeoutError { requestId, timeoutMs } for the rest, each keeping the real socket error as cause where one exists.

Posted via Macroscope — Effect Service Conventions

Posted via Macroscope — Effect Service Conventions

Synced from GitHub

This PR is too large for Bugbot to review. It changes 99,401 lines and 4,022,800 characters. Split the change into smaller pull requests to get a review.

Synced from GitHub

@juliusmarminge do you have an ETA for when this feature comes to nightly? :D

I think it is fair to say that it is not just a feature, it is pretty big T3 Code overhaul :). I personally couldn't wait longer, so I fired these few lines in my term, and use it already :)

1git clone --branch t3code/codex-turn-mapping https://github.com/pingdotgg/t3code.git ~/Git/github.com/pingdotgg/t3code
2cd ~/Git/github.com/pingdotgg/t3code
3brew install vite-plus
4vp i
5vp run dev:desktop --home-dir /tmp/t3code-pr-2829
Synced from GitHub

Only way i use t3code anymore, can't wait to see it completed! Good luck :)

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

With the amount of changes happening here, might as well throw in a Rust port as well.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Synced from GitHub

Does this cover normalizing conversation history across provider boundaries, serializing an in-progress thread's turns into a provider-agnostic format and re-hydrating them into a different driver's native session or prompt format? Or does provider-session binding here stay scoped to same-driver instance switching, as in #11908, for now?

If cross-provider hydration isn't in scope yet, worth spinning out a follow-up issue to track it, since #3797 is already closed.

Synced from GitHub

Supporting this as the vehicle for conversation branching (issue #1404 / discussion #6707). I verified current main still has no user-facing thread fork/duplicate — only New thread on branch (empty history) and in-place rewind — while provider-native fork exists for Codex/Claude/OpenCode. The ThreadFork replay coverage here looks like the right foundation. Happy to test fork/side-chat behavior on V2 when ready.

Synced from GitHub

just out of curiosity, is there an ETA for this (massive, I know) PR to be merged?

Synced from GitHub

It has become part of my daily routine to check this PR couple of times a day to see if it has been merged yet, only to be a little sad to see it's not.

Synced from GitHub

I went looking for a separate provider-conformance framework, but V2 already has most of the right primitive in ProviderReplayHarness + ORCHESTRATOR_REPLAY_FIXTURES.

A small follow-up that seems useful is a coverage contract, not another test system: derive a provider × invariant manifest from the replay fixtures and capability declarations, then fail when a provider advertises a capability without either (a) a replay scenario covering the invariant or (b) an explicit unsupported/exemption reason.

Useful rows from the existing adapter boundary would be roughly:

start / multi-turn / resume / steer / interrupt / rollback / compact / model+option switch / permissions / questions / attachments / subagents / usage / transport death / reconnect

That would have caught the same class of drift the review has already found around advertised vs actual capabilities, and it gives new integrations (Pi, generic ACP agents, eventually Hermes) a concrete “done” target: add transcripts/output assertions instead of inventing bespoke provider test harnesses.

I would keep this generated/test-only; no runtime abstraction required.

Added 50 commits

  • fix(web): thread panel lists the project's saved scripts (#14350)8ca8bd7
  • fix(clients): a thread left running a dev server alerts as completed (#14213)82f884d
  • fix(server): V2 Codex sessions identify as T3 Code, like main (#14377)f71c079
  • fix(server): managed Codex refreshes after sign-out even when a check was interrupted (#14376)8297ccf
  • fix(web): Stop works while a run is still starting (#14201)0a42dd3
  • fix(web): show accurate, steady thread relationship status (#14412)89f4f81
  • fix(server): process-group kills never reach every process the user owns (#14461)6562235
  • fix(server): reject overlapping v2 checkpoint restore workspaces (#14370)1716694
  • refactor(server): import Effect services as namespaces (#14385)16d72f4
  • refactor(clients): import Effect services as namespaces (#14389)4e51609
  • refactor(orchestration-v2): import Effect services as namespaces (#14387)2dfd313
  • fix(server): preview builds keep their bundled OpenCode 2 compatibility policy (#14368)0fb3731
  • fix(server): Grok API errors fail the run instead of completing it empty (#14487)f82eb0f
  • fix(server): Grok's reply to a finished background command opens its own run (#14488)9449473
  • feat(server): detect OpenCode 1.x or 2.x per instance and route by it (#14239)14f74e1
  • build(server): add the OpenCode 2 Effect client (#14221)79e3d0a
  • feat(server): run OpenCode 2 servers from the driver (#14241)1f657e8
  • feat(server): run turns, text, reasoning and tools on OpenCode 2 (#14269)f3eb99e
  • chore(v2): merge main into the V2 branch (12 commits)f1e6515
  • fix(server): checkpoint restore ignores the cwd of a provider session shared across threads (#14502)f48d257
  • chore(v2): merge t3code/codex-turn-mapping into the main sync6b1d22f
  • refactor(server): threads without a project run through a ScratchWorkspace service18e38d3
  • fix(server): two Scratch threads never share a folder1f0a1ad
  • fix(server): keep ScratchWorkspace.make privated17305f
  • feat(server): report OpenCode 2 usage, context windows, models and history (#14270)253ef68
  • feat(server): OpenCode 2 approvals, questions and every runtime mode (#14407)5eae8ff
  • fix(build): desktop and CLI builds resolve catalog overrides on selectors (#14529)4ee6c32
  • feat(server): OpenCode 2 subagents and background wake-ups (#14474)2330919
  • chore(v2): merge main into the V2 branch (11 commits)bb607b0
  • refactor(server): projects T3 creates for you run through one servicea5d108e
  • fix(server): a named project never deletes a folder another project owns3b6d791
  • fix(clients): stop stranded thinking after a steer (#14546)981cd69
  • chore(v2): merge t3code/codex-turn-mapping into the project-folders refactorfa65ee6
  • feat(server): OpenCode 2 native steering, fork and rollback (#14468)40920d9
  • fix(server): Claude steers no longer fail when only next-turn options differ (#14615)0613071
  • fix(clients): a paused queue no longer shows the thread as working (#14616)7b616a3
  • feat(server): OpenCode 2 compaction, plan mode and workspace inventory (#14374)6fa450f
  • fix(server): a Claude subagent's own subagents run on their requested model (#14583)4d72e2c
  • fix(server): a Claude-initiated turn no longer ends a queued /compact early (#14547)0fbd755
  • fix(server): a Claude subagent's own subagents no longer wake the root agent (#14641)b08e051
  • feat(server): OpenCode 2 text generation, MCP injection and restart reconciliation (#14386)a2ca40a
  • fix(server): a subagent's events are no longer stored twice across runs (#14665)f438d65
  • chore(v2): merge main into the V2 branch (#14668)6f042ef
  • fix(server): OpenCode 2 keeps a reused subagent's background work and forks before continuations (#14679)b729550
  • feat(server): Pi 1.0 support, with replay fixtures recorded on 1.0 (#14688)de95adc
  • fix(server): Stop always ends the background work a thread shows (#14636)66a9107
  • fix(server): long T3 tool calls from Claude no longer time out at 60 seconds (#14835)3eaae44
  • chore(v2): merge main into the V2 branch (15 commits)3d45bd9
  • test(web): import the drop helpers the Working shelf tests useaf7de21
  • chore(v2): merge main into the V2 branch (3 commits)b37fcea
Synced from GitHub

huge, now please fix mobile for android, its so unrepsonsive