Skip to content

fix(bridge): subscribe before respond on ask resume; edit answered ask to ✅; separate resumed text - #8

Merged
bigduu merged 1 commit into
mainfrom
fix/ask-resume-race-and-ask-card-edit
Jul 15, 2026
Merged

fix(bridge): subscribe before respond on ask resume; edit answered ask to ✅; separate resumed text#8
bigduu merged 1 commit into
mainfrom
fix/ask-resume-race-and-ask-card-edit

Conversation

@bigduu

@bigduu bigduu commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Fixes #6 — final reply never renders after an ask is answered.

Root cause

render_until_settled resolved an answered ask as respond → subscribe. A server-side resubscribe (bamboo ws_v2::subscribe) REPLACES the channel's forwarder and takes a fresh broadcast-bus cut — nothing is replayed. So every event the resumed run emitted between POST /respond and the subscribe frame was lost; and when the WS was mid-reconnect (Subscribe commands queue unprocessed during backoff), the WHOLE resumed run through Complete could land in the gap. The new receiver then never yields, the render task waits forever, the status card stays '⏸ Waiting for your input…', and the final reply never renders — silently, exactly the #6 symptom. The button-callback e2e (2026-07-15) won this race by milliseconds, which is why it rendered while the earlier text-path run didn't.

Fixes

  1. Subscribe BEFORE respond — the same subscribe-before-execute invariant the initial run already relies on (module doc's mapping table / ARCHITECTURE.md). A failed subscribe still records the answer (old degradation path preserved: dropping the user's decision is strictly worse than rendering nothing).
  2. Answered-ask edit — the ask message is edited to {ask text}\n\n✅ {answer} (best-effort, edit_message-gated). Closes the follow-up gap noted on bridge: final reply never renders after an ask is answered — run resumes and completes at bamboo, chat shows nothing #6: the chat shows what was chosen, and the now-stale buttons can't be pressed again. render_ask returns the sent MessageRef instead of discarding it.
  3. Resume paragraph breakStreamingRenderer::resume inserts \n\n between pre-pause text and the resumed run's tokens; previously the final reply glued onto the question (Pick one:OASIS), reading as missing even when the race was won. finalize_success trims trailing whitespace for the no-more-tokens case.

Tests

  • paused_run_renders_buttons_with_nonce_and_resolves_via_callback now asserts cross-method call order [subscribe, subscribe, respond] via a new ordered op log on FakeBambooApi (the per-method vecs can't see interleaving), and that the ask message got the ✅ Approve edit.
  • streaming_mode_resume_keeps_editing_the_same_status_message now pins the separator.
  • Fake buttons_and_edit_capabilities() actually sets edit_message: true as its name always claimed, so the callback-resolution test exercises the streaming renderer.

Not fixed here (separate issue to file): resynced asks (resync_pending_asks) are parked without an ask_resolution sender, so an answer after a magpie restart falls through try_resolve_pending_ask into the normal message path and starts a new run instead of resolving the parked question.

https://claude.ai/code/session_014iw5PBsSzDFHus1GfkAK4y

…k to ✅; separate resumed text (#6)

Three fixes for issue #6 (final reply never renders after an ask is answered):

1. render_until_settled now re-subscribes to the session's WS channel
   BEFORE POST /respond — the same subscribe-before-execute invariant the
   initial run relies on. A server-side resubscribe REPLACES the channel's
   forwarder with a fresh broadcast cut, so subscribing after respond left
   a window where the resumed run's events (or, with the WS mid-reconnect,
   the entire run through Complete) were emitted into no subscription at
   all — the render task then waited forever on an idle channel and the
   final reply never rendered. A failed subscribe still records the answer
   (the old degradation path).

2. The answered ask message is now edited to '{ask text}\n\n✅ {answer}'
   (best-effort, gated on edit_message) — the chat shows what was chosen
   and the stale buttons can't be pressed again.

3. StreamingRenderer::resume inserts a paragraph break between pre-pause
   text and the resumed run's tokens — previously the final reply glued
   straight onto the question ('Pick one:OASIS'), reading as missing.
   finalize_success trims trailing whitespace for the no-tokens case.

Test hooks: FakeBambooApi grows an ordered subscribe/respond op log (the
per-method vecs can't express cross-method ordering); the fake
buttons_and_edit_capabilities now actually sets edit_message like its name
claims, putting the callback-resolution test on the streaming renderer.

Closes #6

Claude-Session: https://claude.ai/code/session_014iw5PBsSzDFHus1GfkAK4y
@bigduu
bigduu merged commit 19fe88b into main Jul 15, 2026
3 checks passed
@bigduu
bigduu deleted the fix/ask-resume-race-and-ask-card-edit branch July 15, 2026 16:37
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.

bridge: final reply never renders after an ask is answered — run resumes and completes at bamboo, chat shows nothing

1 participant