Skip to content

Fix agent runtime queue races#52

Open
canvascoding wants to merge 2 commits into
mainfrom
codex/fix-agent-runtime-queue-pr
Open

Fix agent runtime queue races#52
canvascoding wants to merge 2 commits into
mainfrom
codex/fix-agent-runtime-queue-pr

Conversation

@canvascoding

@canvascoding canvascoding commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Serialize state-changing chat WebSocket actions per user/session so follow-ups cannot overtake runtime startup.
  • Keep follow-up queue ownership in the runtime and attach only one item to agent-core at a time.
  • Make Steer suspend all remaining follow-ups, so only the selected message enters the active runtime.
  • Add regression tests for WebSocket session ordering and runtime queue consumption.

Verification

  • npm run lint
  • npm run build
  • npm run test:websocket:session-queue
  • npm run test:pi:queue

Notes

  • No UI change; no Playwright run was started under the repository explicit-approval rule.

Greptile Summary

This PR changes how Pi runtime and WebSocket queues preserve chat action order. The main changes are:

  • Runtime-owned follow-up and steering queues in RuntimeMessageQueues.
  • One-at-a-time follow-up attachment to agent-core.
  • Per-user/session WebSocket action serialization.
  • Regression scripts for runtime queue and WebSocket ordering behavior.

Confidence Score: 4/5

The runtime queue promotion path can leave remaining follow-ups stuck.

  • Promoting one queued follow-up clears agent-core's follow-up queue.
  • Remaining runtime-owned follow-ups stay suspended after the steering message is consumed.
  • WebSocket session serialization and import changes look contained.

app/lib/pi/runtime-queue.ts

Important Files Changed

Filename Overview
app/lib/pi/runtime-queue.ts Adds runtime-owned queue management, with a stuck suspended-follow-up path after steering promotion.
app/lib/pi/live-runtime.ts Delegates follow-up, steering, remove, replace, and consume behavior to the new queue controller.
server/websocket-session-queue.ts Adds a per-user/session promise queue for ordered WebSocket action handling.
server/websocket-server.ts Wraps session-scoped chat actions in the new WebSocket session queue.
scripts/pi-runtime-queue-test.ts Adds coverage for one-at-a-time runtime queue attachment and steering promotion behavior.
scripts/websocket-session-queue-test.ts Adds coverage for FIFO session actions, cross-session parallelism, and recovery after failures.
package.json Adds npm scripts for the new queue tests.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Multiple follow-ups queued] --> B[One follow-up attached to agent-core]
  A --> C[User promotes a queued follow-up]
  C --> D[Agent follow-up queue is cleared]
  D --> E[Remaining follow-ups stay runtime-owned]
  E --> F[followUpsSuspended remains true]
  C --> G[Promoted message enters steering]
  G --> H[Steering message is consumed]
  H --> I[Remaining follow-ups are not re-attached]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
  A[Multiple follow-ups queued] --> B[One follow-up attached to agent-core]
  A --> C[User promotes a queued follow-up]
  C --> D[Agent follow-up queue is cleared]
  D --> E[Remaining follow-ups stay runtime-owned]
  E --> F[followUpsSuspended remains true]
  C --> G[Promoted message enters steering]
  G --> H[Steering message is consumed]
  H --> I[Remaining follow-ups are not re-attached]
Loading

Fix All in Codex

Reviews (1): Last reviewed commit: "Prevent Steer from draining queued follo..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used (3)

  • Context used - CLAUDE.md (source)
  • Context used - AGENTS.md (source)
  • Context used - seed_sys_prompts/AGENTS.md (source)

// the remaining entries runtime-owned so Steer injects only this entry.
agent.clearFollowUpQueue();
this.attachedFollowUpId = null;
this.followUpsSuspended = this.followUps.length > 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Suspended Follow-Ups Stay Stuck

When one follow-up is promoted while others remain queued, this clears agent-core's follow-up queue and leaves followUpsSuspended set to true. The promoted steering message is consumed from the steering queue, so the remaining follow-ups are never re-attached to agent-core; they stay visible in status but do not run unless the user manually removes or clears them.

Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant