Skip to content

fix(server): Claude steers no longer fail when only next-turn options differ - #14615

Merged
juliusmarminge merged 1 commit into
t3code/codex-turn-mappingfrom
t3code/claude-steer-turn-scoped-selection
Oct 1, 2026
Merged

juliusmarminge merged 1 commit into
t3code/codex-turn-mappingfrom
t3code/claude-steer-turn-scoped-selection

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Problem

Steering a running Claude turn from web failed every time with "Claude cannot redirect an active run. Stop it first, then send the message." (seen on a thread started from mobile).

dispatchSteerIntoRun forced interrupt-and-restart whenever the steer's model selection differed from the running run's, however small the difference. The web composer adds an explicit fastMode: false that mobile-started runs don't carry, so the selections never matched. Claude supports live steering (supportsActiveSteering) but not supportsSteeringByInterruptRestart, so the forced restart was always rejected:

CommandPolicyCapabilityUnsupportedError: claudeAgent cannot satisfy interrupt_restart_steering:
providerInstanceId cannot satisfy a required interrupt-and-restart

Fix

A changed selection now forces a restart only when it has to apply immediately:

  • Must apply now (provider switch, or a transition plan other than apply_on_next_turn): restart as before, or reject if the provider can't restart.
  • Turn-scoped change, provider can restart (Codex, OpenCode, ACP): restart as before.
  • Turn-scoped change, provider can't restart (Claude, Pi): the steer joins the running turn, and the thread records the new selection (thread.model-selection-updated) so it applies from the next turn. Previously these providers rejected the steer.

Verification

  • New SteeringCompletion.integration.test.ts case: a provider that can steer but not restart, receiving a steer whose options differ (fastMode: false). It steers once, starts no second attempt, keeps the run's selection and stores the new one on the thread.
    • Before (base Orchestrator.ts): × steers a changed turn-scoped selection into a provider that cannot restart, failing with codex cannot satisfy interrupt_restart_steering … cannot satisfy a required interrupt-and-restart
    • After: passes.
  • SteeringCompletion, SelectionRestart, CommandPolicy: 38/38 pass. Server typecheck clean.

This is a server-only change, so there are no screenshots; the before/after test above shows the behaviour.

Part of the fix for the hung "Add Find in Diff View" thread. The related client fixes are separate PRs (paused-queue status, Resume queue action).

🤖 Generated with Claude Code


Devin Review

… differ

A steer whose model selection differed from the running run's was always
forced into interrupt-and-restart. Claude steers live but cannot restart a
turn, so any options-only difference (the web composer sends an explicit
fastMode: false) rejected every steer with "cannot redirect an active run".

A selection the provider applies on its next turn now only forces a restart
when the provider supports one. Otherwise the steer joins the running turn and
the thread keeps the new selection for the next turn. Model or provider
switches that need a new session still restart or are rejected as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Oct 1, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 1, 2026
@github-actions github-actions Bot added the size:M 30-99 changed lines (additions + deletions). label Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 4.9 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.4 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 4.9 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.7 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 20.8 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: ac085d7 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 106.1 KiB
  • Claude decoded thread snapshot: 106.4 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge
juliusmarminge marked this pull request as ready for review October 1, 2026 16:00
@macroscopeapp

macroscopeapp Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at ac085d7

Macroscope's review found this PR approvable — This is a localized server bug fix that avoids rejecting active Claude steering when only next-turn options differ, while preserving restart behavior when it is required and recording the selection for the next turn. A focused integration test covers the changed path, with no schema, deployment, security, billing, authentication, or default-setting changes.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge merged commit 0613071 into t3code/codex-turn-mapping Oct 1, 2026
40 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/claude-steer-turn-scoped-selection branch October 1, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant