Skip to content

fix(sessions): revert async prompt delivery β€” P0 regression (#3271)#3274

Merged
aegis-gh-agent[bot] merged 1 commit into
developfrom
fix/3271-prompt-delivery-regression
May 13, 2026
Merged

fix(sessions): revert async prompt delivery β€” P0 regression (#3271)#3274
aegis-gh-agent[bot] merged 1 commit into
developfrom
fix/3271-prompt-delivery-regression

Conversation

@OneStepAt4time

Copy link
Copy Markdown
Owner

Summary

Closes #3271 β€” P0 regression fix

Reverts the async prompt delivery from #3243 (#3253) to synchronous delivery. The async void deliverAsync() pattern caused prompt delivery tracking to hang indefinitely.

Root Cause

The fire-and-forget async delivery:

promptDelivery = { delivered: false, attempts: 0, status: "pending" };
session.promptDelivery = promptDelivery;
const deliverAsync = async () => { /* ... */ };
void deliverAsync();

Three problems:

  1. Tracking never updates β€” promptDelivery.status stays pending for 120s until JSON-RPC timeout, then failed
  2. Prompt IS delivered β€” Claude Code receives and processes the prompt (transcript confirms response), but the tracking layer never acknowledges it
  3. JSON-RPC response lost β€” the session/prompt request sends to CC, CC processes it, but the response never resolves the pending Promise (likely a transport/routing issue in the ACP JSON-RPC client)

Fix

Revert to synchronous await acpBackend.sendPrompt() β€” the proven pre-#3243 behavior. The POST blocks until CC acknowledges receipt.

const result = await acpBackend.sendPrompt(session.id, finalPrompt, scope);
promptDelivery = { delivered: result.delivered, attempts: result.attempts,
                   status: result.delivered ? "delivered" : "failed", error: result.error };

Verification

tsc --noEmit    βœ… Zero errors
npm run build   βœ… Success
npm test        βœ… 4125 passed / 1 pre-existing flaky (e2e-dogfood)

New/updated test: async-session-create-3243.test.ts β€” 8 tests covering:

  • βœ… Synchronous delivery returns delivered status
  • βœ… Failed delivery returns failed status with error
  • βœ… Throwing sendPrompt returns 500
  • βœ… Session without prompt skips sendPrompt
  • βœ… promptDelivery.status type variants (pending/delivered/failed/timeout)

Impact

  • promptDelivery.status is now delivered or failed immediately in the POST response
  • The pending β†’ polling pattern is no longer needed
  • Dashboard and ag run clients get immediate feedback
  • Requires server restart to take effect

Reproduction Evidence

Created 3 test sessions against running server (PID 107761, May 12 build):

  • All showed promptDelivery: { delivered: false, attempts: 0, status: "pending" } for 60+ seconds
  • All eventually transitioned to status: "failed" after JSON-RPC timeout (120s)
  • All transcripts showed Claude Code received and responded to the prompt

Post-merge

Server restart required to load the fix. The running instance (May 12 build) includes the broken async code.

@aegis-gh-agent aegis-gh-agent 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.

βœ… Approved. P0 fast-track.

Surgical revert of the async fire-and-forget delivery pattern to synchronous await acpBackend.sendPrompt().

Root cause is clear: void deliverAsync() allowed the JSON-RPC session/prompt response to be lost in the event loop β€” CC processed the prompt but the tracking layer never received confirmation. The pending β†’ polling pattern was broken by design.

Fix is correct:

  • Reverts to synchronous await β€” proven pre-#3243 behavior
  • Keeps promptDelivery.status field for backward compatibility (pending/delivered/failed/timeout)
  • Adds error field to promptDelivery type β€” useful for debugging
  • metrics.promptSent() called after delivery, not inside fire-and-forget

Tests: 8 tests rewritten from async→synchronous assertions. All green. Covers: delivered, failed, thrown error (500), no-prompt session, status type variants.

CI: All green. fix: title β€” no bump gate issue.

All 9 merge gates pass. Merging immediately β€” P0 does not wait for rebase.

The async prompt delivery from #3243 caused a P0 regression:
promptDelivery tracking hung indefinitely (status stuck at 'pending',
attempts: 0) even though Claude Code received and processed the prompt.

Root cause: the void deliverAsync() fire-and-forget pattern allowed
the JSON-RPC session/prompt response to be lost β€” the tracking layer
never received confirmation. The session/prompt request was sent, CC
processed it, but the response never resolved the pending Promise
(timeout after 120s β†’ status: 'failed').

Fix: revert to synchronous await acpBackend.sendPrompt() which blocks
until CC acknowledges receipt. This restores the proven pre-#3243
behavior.

Changes:
- src/routes/sessions.ts: revert async delivery to synchronous
  (keeps promptDelivery.status field for backward compat, adds error)
- src/__tests__/async-session-create-3243.test.ts: rewrite tests for
  synchronous behavior (8 tests, all passing)

Impact: promptDelivery.status will be 'delivered' or 'failed' immediately
in the POST response, no longer 'pending'. The polling pattern is no
longer needed.

Closes #3271
@OneStepAt4time OneStepAt4time force-pushed the fix/3271-prompt-delivery-regression branch from cccbf7f to 13cfcfe Compare May 13, 2026 06:22
@aegis-gh-agent aegis-gh-agent Bot merged commit a8ca1dd into develop May 13, 2026
36 of 39 checks passed
@aegis-gh-agent aegis-gh-agent Bot deleted the fix/3271-prompt-delivery-regression branch May 13, 2026 06:38
aegis-gh-agent Bot pushed a commit that referenced this pull request May 13, 2026
…#3277)

Fix docs drift caused by PR #3274 (revert of async prompt delivery).

Removed async polling documentation from promptDelivery note.
Updated status values: delivered or failed (removed pending, timeout).
Updated example response to show synchronous result.
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