Skip to content

Fix repeated steering and reliable stop#3903

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

Fix repeated steering and reliable stop#3903
Quicksaver wants to merge 6 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.
  • Keep the Quicksaver Expo owner, EAS project id, and OTA update endpoint aligned so fork builds receive updates from their own project.
  • 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.

The upstream merge also introduced an Expo OTA endpoint that still targeted the upstream EAS project after this branch restored the fork's owner and project id. Aligning all three values prevents installed Quicksaver builds from querying the wrong update project.

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 (45 tests passed)
  • pnpm exec vp test apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts (32 tests passed)
  • APP_VARIANT=production pnpm exec expo config --json (owner, project id, and OTA endpoint match)
  • pnpm exec vp run lint:mobile

Proof

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

Note

Medium Risk
Changes user-visible send/stop behavior and Codex interrupt targeting; logic is well-tested but affects running-turn orchestration. The bundled mobile EAS project/owner switch affects OTA/update routing if unintended.

Overview
Fixes repeated steering while a turn is running and makes Codex stop target the live active turn.

The web chat now records the expected user message id on each local send and treats a steer as server-acknowledged when that exact message appears on the thread—without waiting for a new turn or session transition. beginLocalDispatch is wired to pass the outgoing message id through send/retry paths.

On the server, Codex interruptTurn no longer defaults straight to cached session.activeTurnId. It resolves the turn via a bounded thread/read (with turns), picks the newest in-progress turn (timestamp order, with provider order when timestamps are missing), uses the cached id only when the lookup fails or times out, and does not revive a stale cached id when a successful read shows no active turn.

Also updates mobile Expo/EAS config (updates.url, eas.projectId, owner) to a different project id and owner—orthogonal to the chat/Codex behavior.

Regression tests cover steer acknowledgement, active-turn selection, interrupt resolution edge cases, and related helpers.

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

Note

Fix repeated steering and add reliable stop by resolving active turn via live thread read

  • interruptTurn in CodexSessionRuntime.ts now performs a live provider thread read (with a 2s timeout) to resolve the correct active turn before sending an interrupt; if no active turn is found, the interrupt is skipped entirely.
  • Steer acknowledgement in ChatView.logic.ts now tracks an expectedUserMessageId on the local dispatch snapshot, treating projection of that message onto a running thread as server acknowledgement even when turn/session fields are unchanged.
  • Send flows in ChatView.tsx generate and pass expectedUserMessageId into beginLocalDispatch, wiring the new acknowledgement logic end-to-end.
  • Behavioral Change: interruptTurn may now skip sending the interrupt if the live thread read returns no active turn, rather than always sending to the session-projected turn id.

Macroscope summarized 06e38dc.

- 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: 7d3c61f3-2228-4061-bd7e-1037d7f00844

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
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

High severity unresolved comment identifies accidentally committed personal Expo project configuration that could break production OTA updates. Additionally, the PR modifies runtime behavior for interrupt resolution and steering acknowledgment, warranting human verification.

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
- Merge upstream/main through Android mobile support
- Keep Quicksaver Expo ownership in the mobile config
- Preserve repeated steering and live Codex interruption behavior
- Extract and test active turn ordering and interrupt fallbacks
Comment thread apps/mobile/app.config.ts
- Use the Quicksaver EAS project id for the OTA endpoint

@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.

Reviewed by Cursor Bugbot for commit 06e38dc. Configure here.

Comment thread apps/mobile/app.config.ts
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