fix(clients): disable steering for queued standalone commands#25035

open3
main
maria/takeover-pr-22802
opened3d agobyMmaria
View on GitHubTwo-way sync enabledPR last imported 13h ago

Problem

Queued /goal, /compact, and /logout commands should run as separate turns. Their Steer controls and shortcut selection need to reflect that restriction.

Change

Reuse the server's existing rejection rule in shared contracts. Web and mobile disable rejected steering with a reason; the web shortcut skips rejected rows. Stopped-thread Send now still starts the first queued command. Guest attribution and editing behavior stay unchanged.

Scope and approval

Maria requested this focused replacement for #22802 and the queued-command steering bug in #22397. This aligns existing controls with existing server rejection rules and preserves Send now.

Verification

  • Regression tests failed on main before the fix. Blacksmith: 120 tests across eight existing files, affected typechecks across 30 packages, lint, format, and GraphQL checks pass.
  • Linux web, system Chrome, real Codex through T3's OAuth proxy: matching queued goal/plain messages before and after; goal steering disabled, ordinary steering enabled; Ctrl+Shift+Enter delivers the plain message and leaves the goal queued.
  • Two independent GPT-6.1-Sol reviews approve merge head 42f0b3c630569e0a2d81e05791291854219ecd53.
  • Merged github/main (44df336016) with a merge commit. Post-merge vp run check:changed passes on Blacksmith: format, lint, both knip passes, GraphQL generation, 30 affected package typechecks, and 121 tests in eight files. All 31 GitHub checks pass on 42f0b3c630569e0a2d81e05791291854219ecd53, including Lint, Check, CodeRabbit, and native fingerprint. Live Send now delivered the queued goal and returned GOAL_COMPLETE; a fresh shortcut pass delivered PLAIN_FINAL before the goal ran as a separate turn.
  • Unverified: native mobile, Electron shell, relay/tunnel, other providers. Send now is covered by browser and mobile presentation tests. Known coverage limits: no dedicated all-ineligible shortcut case or guest-attributed slash-command case.

Before, on main:

main offers steer for the queued goal

After, with the same queued messages:

goal steering disabled while the plain message remains steerable

Shortcut skips the goal and delivers the plain message:

shortcut steers the plain message and leaves the goal queued

Takeover

Replaces #22802, with thanks to @lnieuwenhuis for the original implementation.

Built with GPT-6.1-Sol in the Codex harness on T3 Code.

current main merge verification

Merged github/main (becf853defb6) into this branch without rebasing. Resolved three conflicts while preserving main's queue redesign and server goal stop/requeue paths. The focused change remains 12 files, +190/-43 against main.

On bbeca01a811638f442af335161f4f3c4add0b935, Blacksmith vp run check:changed passes: 121 tests in eight existing files, 31 affected package typechecks, lint, format, both knip passes, and GraphQL generation. Main's existing queued-goal promotion integration test also passes. Two independent GPT-6.1-Sol reviews found no in-scope blockers.

Live system Chrome with real Codex: goal Steer disabled, plain Steer enabled; Ctrl+Shift+Enter delivers the plain message and receives PLAIN_VERIFIED while leaving the goal queued. The goal subsequently runs as its own turn and returns GOAL_VERIFIED. After stopping a fresh run, Send now stays enabled for a queued goal and returns SEND_NOW_VERIFIED. Native mobile, Electron shell, relay/tunnel, and other providers remain unverified. All 31 GitHub checks passed on this head, with no conflicts and no actionable bot findings.

merged queue preserves main layout and disables goal steering

merged shortcut delivers the plain message while the goal stays queued

Checks

23 successful · 8 skipped
All checks passed
bbeca01

Added 1 commit

  • fix(clients): disable steering for queued standalone commands1b269f1
Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 42f0b3c630569e0a2d81e05791291854219ecd53 and bbeca01a811638f442af335161f4f3c4add0b935.

External image Files selected for processing: 7
  • apps/mobile/src/features/threads/ThreadQueueControl.tsx
  • apps/mobile/src/features/threads/threadQueueControlPresentation.ts
  • apps/server/src/orchestration-v2/CommandPolicy.ts
  • apps/server/src/orchestration-v2/Orchestrator.ts
  • apps/web/src/components/chat/QueuedRunsControl.browser.test.tsx
  • apps/web/src/components/chat/QueuedRunsControl.tsx
  • packages/contracts/src/orchestrationV2.ts
External image Files with no reviewable changes: 1
  • apps/server/src/orchestration-v2/CommandPolicy.ts
External image Files skipped from review as they are similar to previous changes: 1
  • apps/mobile/src/features/threads/ThreadQueueControl.tsx

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

Walkthrough

Shared contracts define when queued commands cannot be steered. Client queue state derives these rejection reasons, and web and mobile controls use them to select eligible runs and present rejection details. Server steer validation uses the shared rules.

Changes: Queued-run steering

Layer / File(s)Summary
Shared rejection rules and server validation
packages/contracts/src/orchestrationV2.ts, packages/contracts/src/orchestrationV2.test.ts, apps/server/src/orchestration-v2/CommandPolicy.ts, apps/server/src/orchestration-v2/Orchestrator.ts, apps/server/src/orchestration-v2/RestartContinuation.ts
Contracts add rejection checks for standalone /goal, /compact, and /logout commands. Server steer dispatch uses the shared rejection helper, and server imports use the shared maintenance-command classifier.
Queue state and web steering controls
packages/client-runtime/src/state/threadWorkflows.ts, packages/client-runtime/src/state/threadWorkflows.test.ts, apps/web/src/components/chat/QueuedRunsControl.tsx, apps/web/src/components/chat/QueuedRunsControl.browser.test.tsx
Queue state derives and stores each run’s rejection reason. Web controls select an eligible run, disable rejected steer actions, and display the rejection reason. Tests cover selection and command dispatch.
Mobile queue controls
apps/mobile/src/features/threads/ThreadQueueControl.tsx, apps/mobile/src/features/threads/threadQueueControlPresentation.ts, apps/mobile/src/features/threads/threadQueueControlPresentation.test.ts
Mobile controls pass rejection reasons into row-control resolution, prevent rejected runs from being sent when steering is required, and display the reason in menu and accessibility text. Tests cover sendability and row states.

Priority: External image Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Possibly related issues

  • pingdotgg/t3code#24137 — The change applies a shared rejection rule to standalone /compact commands in client steering controls.

Suggested labels: bugfix

Suggested reviewers: t3dotgg

Merge Risk: External image Minimal · up to bbeca

No blocking issue was identified; the change is ready to merge after normal checks.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title "fix(clients): disable steering for queued standalone commands" follows conventional commit style and names the main change. The changeset disables Steer for queued /goal, /compact, and /log…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Description checkPassedThe pull request description includes all required sections: Problem, Change, Scope and approval, and Verification. It provides expected behavior, implementation details, approval references, focused …
Full details: Title check

Explanation

The title "fix(clients): disable steering for queued standalone commands" follows conventional commit style and names the main change. The changeset disables Steer for queued /goal, /compact, and /logout commands in web and mobile, and makes the web shortcut skip rejected rows. The title is specific and matches the objectives and file changes. "Standalone commands" is slightly less precise than naming the command types, but it does not mislead.

Full details: Description check

Explanation

The pull request description includes all required sections: Problem, Change, Scope and approval, and Verification. It provides expected behavior, implementation details, approval references, focused test results, manual UI verification, screenshots, known coverage limits, and the agent model and harness.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • 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.

Synced from GitHub

Approvability

Verdict: Approved at bbeca01

Macroscope's review found this PR approvable — This is a focused fix that synchronizes web and mobile queue controls with existing server restrictions for standalone maintenance and goal commands. Normal queued-message sending remains unchanged, with shared classification and targeted tests covering the new behavior.

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

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB−7 B (−0.1%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.2 KiB1.2 KiB−7 B (−0.6%)2.0 KiB✅
CodexLive turn WebSocket decoded20.9 KiB20.9 KiB0 B (0.0%)29.3 KiB✅
CodexLive turn messages220 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.2 KiB21.2 KiB0 B (0.0%)29.3 KiB✅
ClaudeLive turn messages220 (0.0%)8✅

Baseline: becf853 · PR result: bbeca01 · 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: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

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

Added 2 commits

  • chore: merge main into queued command steering fix42f0b3c
  • chore: merge main into queued command steering fixbbeca01

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified unchanged head bbeca01a811638f442af335161f4f3c4add0b935 on this task-owned linux boat vm. git.cafe and github both identify this as pr #25035. the pr is open; none of its three commits are authored by juliusmarminge or t3dotgg.

used a separate ../main worktree at github/main (1abf368532), ran vp i, and started the real dev server in the background. stopped it before starting the exact pr head after its own vp i. each server used an empty, isolated .t3 home. used repo Playwright with /usr/bin/google-chrome; created a project pointing at a real git repository, threads, and messages through the web app. all agent turns used real Codex gpt-6.1-sol through the local proxy. no mocks, fixtures, replay provider, or seeded data.

  • reproduced on main: while a real Codex turn ran, queued /compact had an enabled "send now" action. clicking it failed with Context compaction must run as a separate turn. Queue it or wait for the active turn to finish. and left it queued. current main has newer queue styling; its queued goal action already stops the active turn and runs the goal separately, so that path was not the failing baseline.
  • on the pr, queued /goal, /compact, and /logout each had a disabled "steer" control and the corresponding explanation. the ordinary message remained enabled. the matching before/after data is shown below.
  • Ctrl+Shift+Enter skipped all three standalone commands and delivered the ordinary message as a steer. Codex acknowledged the message and returned PLAIN_VERIFIED. after removing the queued maintenance commands through the UI, the goal ran separately and returned GOAL_VERIFIED.
  • with only ineligible rows queued, Ctrl+Shift+Enter preserved the queue.
  • on a fresh thread, queued a goal during an active turn, stopped the turn, and verified "send now" became enabled. clicking it started the goal and Codex returned SEND_NOW_VERIFIED.

short runtime transcript:

text
1main: enabled /compact queue action -> OrchestrationV2DispatchCommandError
2 Context compaction must run as a separate turn.
3pr: steer disabled [goal, compact, logout, plain] = [true, true, true, false]
4pr: Ctrl+Shift+Enter -> ordinary message becomes Steer; 3 standalone rows remain
5pr: all-ineligible shortcut preserves queue = true
6Codex: PLAIN_VERIFIED
7Codex: GOAL_VERIFIED
8pr: stopped goal Send now enabled = true
9Codex: SEND_NOW_VERIFIED

ran existing checks through blacksmith-check: 61 tests passed across contracts, queue workflow, mobile queue presentation, and server command policy; the focused existing queued-goal promotion integration test also passed (62 total). all 31 published CI checks on this head are green. no source changes, commits, or pushes were necessary; check:changed was not rerun.

before, current main with the same four queued messages:

main exposes enabled actions for the standalone commands

after, exact pr head:

pr disables standalone steering and preserves ordinary steering

recording of the three rejection explanations and the shortcut delivering the ordinary message:

shortcut skips the three standalone commands

provider results through the real client:

Codex returns the steered response and then completes the separate goal

stopped-thread send now reaches Codex and returns SEND_NOW_VERIFIED

Not verified

native iOS/Android and Electron shell behavior were not exercised on this linux web run. relay/tunnel, other providers, guest attribution, and attachment-specific command classification were not exercised. /compact and /logout were verified as disabled queue controls, including their explanations; their actual compaction/sign-out operations were not run on the pr. the screenshots and trimmed recording were inspected; uploaded video playback and seeking worked in T3's browser player.