Skip to content

Fix repeated steering and reliable stop#3903

Open
Quicksaver wants to merge 4 commits into
pingdotgg:mainfrom
Quicksaver:fix/repeated-steering-and-stop
Open

Fix repeated steering and reliable stop#3903
Quicksaver wants to merge 4 commits into
pingdotgg:mainfrom
Quicksaver:fix/repeated-steering-and-stop

Conversation

@Quicksaver

@Quicksaver Quicksaver commented Jul 12, 2026

Copy link
Copy Markdown

Summary

Allow users to send consecutive steering prompts while a conversation is running and reliably stop the active Codex turn after any number of steers. Steering dispatches now clear as soon as the server projects the exact submitted user message, while interruption resolves the provider's live active turn instead of relying on potentially stale projected state.

What Changed

  • Track the expected user-message id for each local dispatch and acknowledge only that exact projected message.
  • Re-enable the composer after an in-turn steering message is projected without waiting for a new turn or session transition.
  • Preserve the projected active turn id in root interruption inputs while keeping explicit child-turn targeting isolated from root fallback behavior.
  • Resolve root Codex interruptions from a live thread/read request with turns included, selecting the newest in-progress turn by timestamp and falling back to provider response order when timestamps are absent.
  • Bound active-turn lookup time, log lookup failures, and fall back to the cached session turn only when the lookup fails.
  • Suppress stale interrupts when a successful live lookup reports no active turn.
  • Add regression coverage for repeated steering, exact-message acknowledgement, interruption targeting, live-turn selection, timeout and failure fallback, and empty live reads.

Why

Running conversations could leave the composer busy after steering because acknowledgement depended on turn or session transitions that do not occur for an in-turn steer. After steering, stop could also target a stale cached turn rather than the provider's actual active turn. Together, these behaviors prevented repeated steering and made interruption unreliable precisely when users needed it most.

Validation

  • pnpm exec vp check (passes with existing lint warnings)
  • pnpm exec vp run typecheck
  • pnpm exec vp test apps/web/src/components/ChatView.logic.test.ts apps/server/src/provider/Layers/CodexSessionRuntime.test.ts (40 tests passed)
  • pnpm exec vp test apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts (32 tests passed)

Proof

  • Automated regression coverage in the changed web and server test suites.

Note

Medium Risk
Changes stop/interrupt targeting and composer in-flight semantics during active turns; behavior is constrained by timeouts, explicit fallbacks, and new regression tests.

Overview
Fixes in-turn steering leaving the composer stuck “busy” and stop targeting a stale Codex turn after multiple steers.

On the web side, each send records an expected user message id in the local dispatch snapshot. hasServerAcknowledgedLocalDispatch now treats a running session steer as acknowledged when that exact message appears on the thread, without waiting for turn or session field changes. ChatView passes the outgoing message id into beginLocalDispatch and feeds getLatestUserMessageId into the ack check.

On the server, Codex interruptTurn no longer defaults to the cached session.activeTurnId alone. resolveCodexInterruptTurnId issues a bounded thread/read (with turns), picks the active turn via findActiveCodexTurnId, falls back to the cached id only when the read fails, and skips interrupt when the read succeeds but reports no in-progress turn.

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

Note

Fix repeated steering acknowledgment and reliable turn interrupt stop

  • Steer (send while running) is now acknowledged when the expected user message appears on the thread, tracked via a new expectedUserMessageId field in LocalDispatchSnapshot (ChatView.logic.ts).
  • interruptTurn now fetches the current thread state via thread/read (2-second timeout) to resolve the active turn, rather than relying on a potentially stale projected activeTurnId (CodexSessionRuntime.ts).
  • If the server read succeeds but no turn is active, the interrupt is skipped entirely instead of falling back to the stale id.
  • Behavioral Change: hasServerAcknowledgedLocalDispatch now requires a latestUserMessageId argument at all call sites.

Macroscope summarized 3414977.

- Resolve the provider runtime’s authoritative active Codex turn
- Treat projected steer messages as server dispatch acknowledgement
- Avoid stale root turn IDs when interrupting for steering
- Cover active-turn lookup and running-thread steer behavior
- Resolve active Codex turns from timed, observable thread reads
- Match projected steer acknowledgements to the dispatched message
- Add realistic regression coverage for interrupt and steer paths
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9f987aa6-9741-4c2a-b7be-9e3c135ce145

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 12, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cf6b0c8. Configure here.

Comment thread apps/server/src/provider/Layers/CodexSessionRuntime.ts
@macroscopeapp

macroscopeapp Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR modifies core session runtime logic - turn interruption now makes an RPC call to the provider rather than using local state, and adds new steer acknowledgement tracking. Changes to session management behavior warrant human review.

You can customize Macroscope's approvability policy. Learn more.

- Fall back to provider response order when start times are absent
- Cover both mixed timestamp ordering cases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 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.

1 participant