Skip to content

Release CT: stage-batch4 — 4-PR low-risk batch (v0.51.122) — stale cache tail / inflight UI / segment flush / reasoning accumulator#2815

Merged
nesquena-hermes merged 5 commits into
masterfrom
release/stage-batch4
May 24, 2026
Merged

Release CT: stage-batch4 — 4-PR low-risk batch (v0.51.122) — stale cache tail / inflight UI / segment flush / reasoning accumulator#2815
nesquena-hermes merged 5 commits into
masterfrom
release/stage-batch4

Conversation

@nesquena-hermes
Copy link
Copy Markdown
Collaborator

Release CT — v0.51.122 — stage-batch4 — 4-PR low-risk batch

Fourth batch from the May 24 sweep. Four contributor PRs, all bug fixes targeting state/cache/streaming lifecycle issues, all well-tested, all pre-cleared by Opus advisor:

PR Author LOC Surface Risk
#2802 @ai-ag2026 +141/-0 api/models.py cache reconciliation low — supersedes held #2733, tighter guard
#2796 @ai-ag2026 +226/-41 static/messages.js + sessions.js low — 5-commit squash, clears stale inflight UI state
#2777 @b3nw +154/-0 static/messages.js segment render low — flush before reset, narrow scope
#2778 @b3nw +179/-10 static/messages.js + ui.js reasoning low — turn-boundary reset + read preference

Cherry-picks

225ea786 fix: drop stale cached user tail after saved assistant            (#2802 — supersedes #2733)
39242c58 fix: clear stale inflight UI state                                (#2796 — squashed from 5 commits)
1f56fad7 fix(chat): flush pending render before segment reset              (#2777)
160cd03c fix(chat): reset reasoning accumulator per turn                   (#2778)
6bfded9e Stamp CHANGELOG for v0.51.122

Special handling

Pre-Opus gate

Check Result
Python ast.parse + node -c on all touched PASS
Merge-marker grep clean
Cross-stage surface overlap check #2777 + #2778 both touch messages.js tool/interim_assistant handlers; verified non-overlapping line ranges
New regression tests (53 across 5 files) pass in isolation
Full pytest 6296 passed, 7 skipped, 0 failed

Opus advisor verdict

PR Verdict Notes
#2802 SHIP Guard stack is sound; content-equality check prevents false positives on genuine concurrent edits.
#2796 SHIP One narrow cross-tab localStorage race during the sub-second /api/chat/start round-trip window; degraded recovery UX, not data loss.
#2777 SHIP Cancel-then-write order is correct; _smdWrite is delta-based so no duplication risk.
#2778 SHIP Clean line-distance coexistence with #2777 in both touched handlers; only CHANGELOG conflict to resolve.

All four ship together for v0.51.122.

What's NOT in this batch

ai-ag2026 and others added 5 commits May 24, 2026 04:06
…mits)

Cherry-pick of PR #2796 by @ai-ag2026, squashed from 5 author commits onto current master:
- dcee056 fix: drop stale optimistic sidebar rows
- 3a73400 fix: clear stale busy state before send
- 46c3b90 fix: preserve server idle rows during optimistic merge
- de51d27 fix: let chat start survive pre-start UI errors
- d2f5c90 fix: hide nonfatal pre-start send warnings

Authorship preserved via --author. Code-only squash (no CHANGELOG).
…boundaries

Fixes #2713 — live assistant text can truncate at tool-call segment
boundaries during streaming.

Before _resetAssistantSegment() in the tool and interim_assistant SSE
handlers, synchronously flush any pending rAF render work so tokens that
arrived during the 66ms throttle window are written to the DOM before
assistantBody is cleared. Without this flush, the pending _doRender
callback fires after assistantBody is null and skips the write silently,
causing the tail of the pre-tool segment to disappear from the live view.

Implementation:
- Extract _flushPendingSegmentRender() helper (guarded by assistantBody
  && _renderPending) that cancels the pending rAF and synchronously
  writes via smd/renderMd/esc — same cascade as _doRender.
- Call the helper from both the tool and interim_assistant handlers
  before their respective _resetAssistantSegment() calls.
- Normal cases where the rAF has already fired are unaffected (guard
  skips immediately).

Completed transcripts were never affected (renderMessages rebuilds from
the full assistantText accumulator on done).

Adds tests/test_issue2713_streaming_segment_flush.py with 11 static
analysis regression tests pinning the helper shape and call-site
ordering.
…content (closes #2565)

Two confirmed bugs in the thinking/reasoning display:

1. reasoningText was initialized once when the SSE stream opened and never
   reset between turns. On the done event, the last assistant message
   received the union of every turn's reasoning. Now reset at both turn
   boundaries: tool (alongside existing liveReasoningText reset) and
   interim_assistant (the other turn boundary where prior reasoning closes).

2. ui.js renderMessages preferred m.reasoning (which could be corrupted by
   bug 1) over m.reasoning_content (the clean per-turn value from the
   backend). The fallback now reads m.reasoning_content || m.reasoning.

Both fixes are needed: bug 2 alone cannot cover providers that stream
reasoning events without populating reasoning_content on the final API
message.

Updated test_streaming_race_fix.py to scope its reconnect-accumulator
guard to the _wireSSE preamble only, since turn-boundary resets inside
event listeners are intentional and correct.

9 new regression tests in test_issue2565_reasoning_accumulation.py.
…isk batch)

Cherry-picked PRs:
- #2802 (ai-ag2026) — drop stale cached user tail (supersedes held #2733)
- #2796 (ai-ag2026) — clear stale inflight UI state (5-commit squash)
- #2777 (b3nw) — flush pending render at segment boundaries
- #2778 (b3nw) — reset reasoning accumulator per turn + prefer reasoning_content
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.

3 participants