Skip to content

fix(server): queued delegated completions keep a newer model choice - #22579

Open
f4llenz wants to merge 2 commits into
pingdotgg:mainfrom
f4llenz:fix/queued-run-keeps-thread-model-selection
Open

f4llenz wants to merge 2 commits into
pingdotgg:mainfrom
f4llenz:fix/queued-run-keeps-thread-model-selection

Conversation

@f4llenz

@f4llenz f4llenz commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A delegated-task completion notice that waits in the queue reverts the thread's model when it starts. If the model changes while the notice waits, with the picker or t3_thread_configure, the notice's turn and the turns after it run on the old model. The expected behavior is that the notice starts on the thread's current model and leaves it unchanged.

Change

ProviderContinuationService queues the notice with no modelSelection, so message.dispatch stores a copy of the thread's selection on the run. At start, queuedRunModelSelection returned that copy, and the start wrote it back to the thread. A queued delegated completion now starts on the thread's current selection and conversation. #21314 gave queued PR-watch updates the same rule. The change adds one condition to followsCurrentConversation and drops a comment that named only monitor updates.

Queued messages that a user sends carry the composer's selection and keep it, as #19376 intends.

The late-steer follow-up in EffectWorker passes its run's selection when it dispatches. If that follow-up waits in the queue, it now also starts on the thread's current selection. If it starts at once, it uses its run's selection as before. The two selections differ only when the model changed while the steered run was active.

Scope and approval

Fixes #22577, which has the diagnosis and the reproduction steps and is awaiting triage. The change also qualifies as a small, focused fix for an obvious bug. A notice that the app created reverted a model that a user or an agent had chosen. The fix applies #21314's rule to one more kind of app-owned queued update. It changes no contract, client, provider adapter or user-message behavior.

Verification

  • On a 0.0.46 nightly, two queued completion runs on one thread each started in the same millisecond as a thread.model-selection-updated event with no command. Each event restored the enqueue-time selection over a t3_thread_configure change from about a minute earlier. A queued delegated-task completion reverts a model change made while it waited #22577 has the event log.
  • The new test in runtimeLayer.test.ts, "starts a queued delegated completion on a selection set while it waited", queues a notice shaped like ProviderContinuationService's delivery. It then changes the thread's model, completes the active run and starts the queue. It has two cases, a model change on the same provider instance and a switch to another instance.
    • Against main (4f651cb), both cases fail. The run starts on gpt-5.4 instead of gpt-5.5, and thread.modelSelection reverts to gpt-5.4.
    • With the fix, both cases pass.
  • To check the user-message boundary, I made every queued run follow the thread. 11 existing tests failed, including "keeps queued user selections and pauses only the limited provider".
  • vp test run passes 177 of 177 tests in the 8 related files: runtimeLayer, DelegatedCompletionDelivery, SteeringCompletion.integration, ProviderContinuationService, QueuedRunOrder, testkit/ProviderSwitch.integration, ClaudeAutomaticDelivery.integration and EffectWorker.
  • The server typecheck passes. vp fmt --check and vp lint pass on the changed files, apart from one existing warning on an untouched line.
  • I did not check a full app run with a live provider and a real delegate_task child.

Created with Claude Opus 5.5 in Claude Code (T3 Code).

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 21, 2026
The test fails on main. The completion run starts on the selection copied when it was queued, and the start writes that copy back to the thread.
A delegated-task completion is queued with no selection of its own, so its run stores a copy of the thread's selection. Starting on that copy reverted a model change made while the notice waited. Queued delegated completions now follow the thread's current selection and conversation, as queued PR-watch updates do since pingdotgg#21314.
@f4llenz
f4llenz force-pushed the fix/queued-run-keeps-thread-model-selection branch from 6febf86 to 282206f Compare October 21, 2026 06:36
@f4llenz
f4llenz marked this pull request as ready for review October 21, 2026 06:37
@coderabbitai

coderabbitai Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 566583c1-3e0b-4dd3-86e9-421f08e80ac4
📥 Commits

Reviewing files that changed from the base of the PR and between 6a6c84f and 282206f.

📒 Files selected for processing: 2
  • apps/server/src/orchestration-v2/Orchestrator.ts
  • apps/server/src/orchestration-v2/runtimeLayer.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The orchestrator now treats delegated-completion messages as following the current conversation. A regression test verifies that a queued completion uses the model selection and provider instance configured while it waited.

Changes: Queued delegated-completion model selection

Layer / File(s) Summary
Current selection and regression test
apps/server/src/orchestration-v2/Orchestrator.ts, apps/server/src/orchestration-v2/runtimeLayer.test.ts
The orchestrator now treats delegated-completion messages as following the current conversation. The test changes the thread’s model selection while a completion waits, then verifies the resumed run and active attempt use the newer model selection and provider instance. A comment was removed; the model-selection logic it described is unchanged.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: voltcrash

Merge Risk: ⚪ Minimal · up to 28220

The queued-completion selection change appears ready to merge after normal checks; no merge-blocking issue was identified.

Architecture risk: 🔵 Low · up to 28220

The change affects 1 system.

Changed systems: apps/server

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — apps/server (service) was modified; 2 changed files map to changed impact.

Before / after behavior

  • observed — Modified behavior in apps/server/src/orchestration-v2/Orchestrator.ts: followsCurrentConversation now returns true for messages with a delegated completion, as well as non-buffered monitor notifications.
  • observed — Modified behavior in apps/server/src/orchestration-v2/Orchestrator.ts: Removed the comment describing app-owned monitor updates in queuedRunModelSelection; executable model-selection behavior was unchanged.
  • observed — Modified behavior in apps/server/src/orchestration-v2/runtimeLayer.test.ts: Adds coverage for queued delegated completions: after queuing completion delivery, changing the thread’s model selection, and completing the active run, the queued run starts with the newer model selection and provider instance.
Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main fix: queued delegated completions preserve a newer model choice.
Description check Passed The description covers the problem, change, scope and approval rationale, focused verification, test results, known failures from boundary checking, and the unperformed live-provider check.
Linked Issues check Passed The PR satisfies the active coding requirements in [#22577]. followsCurrentConversation now includes delegated-completion messages, so a queued completion uses the thread's current selection and con…
Out of Scope Changes check Passed The reported changes are limited to the delegated-completion queue-selection condition, its related comment removal, and a focused regression test. These changes directly implement [#22577]. The evide…
Full details: Linked Issues check

Explanation

The PR satisfies the active coding requirements in [#22577]. followsCurrentConversation now includes delegated-completion messages, so a queued completion uses the thread's current selection and conversation instead of its enqueue-time copy. The added runtimeLayer.test.ts regression test covers model changes within the same provider instance and across provider instances. The described behavior preserves queued user-message selections from contextual [#19376] and preserves immediate late-steer behavior.

Full details: Out of Scope Changes check

Explanation

The reported changes are limited to the delegated-completion queue-selection condition, its related comment removal, and a focused regression test. These changes directly implement [#22577]. The evidence shows no unrelated contract, client, provider-adapter, or user-message changes.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

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

size:XS 0-9 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A queued delegated-task completion reverts a model change made while it waited

1 participant