Skip to content

fix(orchestrator): Safely admit execution after uncertain selection - #11

Draft
mwolson wants to merge 1 commit into
contrib/ctm/compatible-active-steeringfrom
contrib/ctm/execution-selection-admission
Draft

mwolson wants to merge 1 commit into
contrib/ctm/compatible-active-steeringfrom
contrib/ctm/execution-selection-admission

Conversation

@mwolson

@mwolson mwolson commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

What Changed

When a provider start or a model change fails partway, T3 Code stops assuming the provider is running the selection it asked for. The thread's next message is admitted through a fresh session for that thread, following the existing steering policy for pooled providers, instead of reusing a binding whose model may be wrong. The failed prompt is not resubmitted, and other threads sharing the same provider process keep running.

Output a provider buffered for a thread is delivered before that thread's session changes and keeps its original selection. If it cannot be delivered safely, the change is refused with "Earlier background output from this conversation has not been delivered yet. Try again after it arrives."

A change that would replace a provider process while the affected thread's binding still has running background work is refused with "This change would replace a provider process with running background work. Wait for it to finish or explicitly Stop it before trying again." Claude keeps its existing check for its own background agents and commands. Non-destructive changes still go through, including Codex option changes while its own background commands run, and a CLI the user has stopped can be replaced while it exits.

OpenCode 2 reports the background wake-ups it holds for a thread as undelivered output, so those continuation turns are admitted and deliver the reply instead of being refused. When a Claude background command finishes after the turn ended, the wake-up turn Claude starts is admitted as soon as it begins, so its reply lands in a T3 continuation run instead of being refused.

A thread that a rollback reopened after an idle release, with nothing run on it yet, is admitted as a fresh attachment instead of forcing a provider restart, so a message sent during or after the rollback no longer interrupts it. Output a provider holds for a thread is still protected at admission even when T3 has not recorded which selection produced it.

Why

A start or selection change that partially applied left T3 trusting a selection the native session might not have, so later turns could run on the wrong model, restarts could kill a process that still owned background work, and buffered completions could be dropped or attributed to the new selection. A stale detach with an equal timestamp could also close a binding that had just been admitted. Execution evidence is now scoped to the actual runtime and binding, a failure invalidates it, and only a trustworthy start acknowledgment restores it.

Known Limitations

Switching a Claude thread's model or permission policy while a finished background command's notice is still waiting to be delivered drops that notice with the old process; output Claude produces after the switch is still delivered. If Claude's process dies after a background wake-up is offered but before T3 admits it, that wake-up's buffered output is kept until Stop instead of being dropped right away. Claude initialization has no timeout, so a hung CLI start waits until Stop cancels it. Output buffered while an ACP agent such as Grok has not reported its model can be cleared only with Stop. A Codex start with a different selection and no explicit service tier may still restart its session after a failed start. Switching a Claude thread's model before any intervening turn can drop an earlier opaque shell-completion notification.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

@mwolson
mwolson added this pull request to stack #36 September 27, 2026 21:48
@mwolson
mwolson force-pushed the contrib/ctm/execution-selection-admission branch from 189b969 to 32c37ae Compare October 1, 2026 12:38
@mwolson
mwolson removed this pull request from stack #36 October 1, 2026 12:39
@mwolson
mwolson added this pull request to stack #53 October 1, 2026 12:41
@mwolson
mwolson force-pushed the contrib/ctm/execution-selection-admission branch from 32c37ae to a2bd3cf Compare October 1, 2026 14:13
@mwolson
mwolson removed this pull request from stack #53 October 1, 2026 14:13
@mwolson
mwolson added this pull request to stack #55 October 1, 2026 14:13
@mwolson
mwolson force-pushed the contrib/ctm/execution-selection-admission branch from a2bd3cf to 77bc6cf Compare October 3, 2026 20:27
@mwolson
mwolson removed this pull request from stack #55 October 3, 2026 20:28
@mwolson
mwolson added this pull request to stack #57 October 3, 2026 20:28
@mwolson
mwolson force-pushed the contrib/ctm/execution-selection-admission branch from 77bc6cf to aa97afa Compare October 4, 2026 03:12
@mwolson
mwolson removed this pull request from stack #57 October 4, 2026 03:12
@mwolson
mwolson added this pull request to stack #60 October 4, 2026 03:13

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant