Skip to content

fix(chat): stop completed turn timers and preserve terminal state across races - #169

Merged
akemmanuel merged 1 commit into
masterfrom
fix/chat-completion-timer-races
Oct 22, 2026
Merged

akemmanuel merged 1 commit into
masterfrom
fix/chat-completion-timer-races

Conversation

@touch2be

Copy link
Copy Markdown
Collaborator

Summary

Fix a completed assistant turn continuing to show an increasing thinking/response duration until the user sends another message or reloads the chat.

This is a frontend state-reconciliation issue, not evidence that the model is still working. In the investigated incident, the persisted Run had finished after approximately five minutes; a later user message made the old duration snap back to that recorded value.

Reproduced causes

The regression tests render the real HostProvider with the real event dispatcher and transcript store; only Host network responses are controlled.

  1. A delayed Session list can overwrite a delivered terminal event's idle state with an older running status. Older lists can also overtake newer ones, or incorrectly clear a newly started Run.
  2. An in-flight readSession can return an older snapshot after run_completed was delivered, replacing the live transcript and losing its terminal entry.
  3. Initial SSE readiness previously skipped rehydration, leaving the initial read/subscription gap unrepaired. Hydration requests arriving during another read were silently dropped, including repairs needed when events arrive before the first stream exists.
  4. The footer trusted the general Session busy flag even when the specific turn already had a persisted completion timestamp.

These races are deterministically reproduced. Without a historical browser/network trace, we cannot establish which race triggered the original incident.

Changes

  • Guard Session lists with request generations and per-Session observation revisions, including optimistic Run starts and hydration writes.
  • Merge full reads with concurrently delivered durable entries and live buffers instead of rolling the transcript back; derive status from newer lifecycle entries.
  • Repair the read/subscription gap on initial readiness as well as reconnect, coalescing pending hydration requests and repairing events seen before the first stream exists.
  • Give the turn's completion timestamp priority over a stale busy flag. In-progress tool turns keep running.
  • Preserve current upstream behavior for Send now/new-Run live text, model retry state, and concurrent model/reasoning changes.

Validation

Rebased onto current upstream master (aa8548e).

  • Focused HostProvider/transcript/footer/duration tests: 85 passed across 13 files.
  • pnpm run test:frontend: 759 passed across 146 files.
  • pnpm exec vp check: formatting, lint and types passed without warnings.
  • pnpm run slop-check: passed.
  • pnpm run build: passed (bundle-size advisory only).
  • git diff --check.

Additional regressions cover completion, failure, abort/interruption, a new Run after completion, live deltas during reads, ongoing tool turns, initial-read gaps, queued repair reads, retry state, and model/reasoning metadata changes. Before the fix, integration regressions failed on the actual state-overwrite paths. A local replay using only redacted lifecycle metadata confirms that a completed turn stays stopped at its recorded duration even with a stale busy flag.

Deployment / review

No production deployment, server restart, account change, or chat mutation was performed. This PR is for maintainer review and normal release integration. No private chat contents, account identifiers, server credentials, or raw production artifacts are included.

Delayed session lists and snapshot reads could overwrite delivered run completion, while initial stream readiness skipped gap repair. Reconcile concurrent entries, guard list writes with request and session revisions, queue hydration repairs, and let terminal turn timestamps stop duration labels. Cover the real HostProvider races with integration regressions.
@touch2be
touch2be requested a review from akemmanuel October 22, 2026 12:29
@akemmanuel
akemmanuel merged commit b30671c into master Oct 22, 2026
2 checks passed
@akemmanuel akemmanuel mentioned this pull request Oct 22, 2026
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.

2 participants