Skip to content

fix(daemon): recover interrupt seq from the live watermark - #257

Merged
lzvxck merged 2 commits into
devfrom
cursor/daemon-interrupt-seq-10cc
Oct 7, 2026
Merged

lzvxck merged 2 commits into
devfrom
cursor/daemon-interrupt-seq-10cc

Conversation

@lzvxck

@lzvxck lzvxck commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

What and why

Follow-up to #255 / #254. Crash recovery assigned turn-interrupted from MAX(persisted seq). Live text-delta / reasoning-delta rows are not stored, so that sequence sits behind envelopes a client already received. Reconnect after=N then missed the terminal event.

A second hole: if turn-complete was persisted and finishTurn did not run, recovery appended turn-interrupted after an existing terminal.

How

  • Persist turns.last_seq (schema 7) on every emit, including deltas that skip daemon_events.
  • Recovery continues from max(last_seq, persisted max) + 1.
  • If the last persisted event is already terminal, finish the turn to match it and do not append another.

Graceful stop() still drains via cancelAll + waitForIdle and ends with turn-complete. Planned SIGTERM already has a terminal event. This PR is crash recovery, not drain-before-update.

Verification

  • bun run typecheck
  • bun test (running)
  • bun run build, and ran the resulting binary
  • Negative control: the three new turns tests failed on current dev (after=4 returned no events; leftover turn-complete became interrupted; live deltas left last_seq at 0). After the fix they pass.

Cross-platform impact

Notes for the reviewer

  • Does not change graceful update restart. That path already terminalizes as turn-complete.
  • last_seq is an integer update per live delta, not a JSON daemon_events row. Deltas stay omitted from history.
Open in Web Open in Cursor 

cursoragent and others added 2 commits October 6, 2026 13:57
Crash recovery used MAX(persisted seq), which sits behind live
text-deltas that are not stored. A reconnect after that watermark
then missed turn-interrupted. Persist last_seq on the turn and
continue from it. If the last persisted event is already terminal,
finish the turn to match it instead of appending a second one.

Co-authored-by: Lionel <[email protected]>
A crash mid-tool leaves an assistant tool-call with no tool-result.
The next attended turn then dies with AI_MissingToolResultsError.
Insert the same execution-denied rows the in-process abort path
writes, before streamText, so daemon restart and TUI continue both
resume.

Co-authored-by: Lionel <[email protected]>
@lzvxck
lzvxck marked this pull request as ready for review October 7, 2026 12:11
@lzvxck
lzvxck merged commit cfa214e into dev Oct 7, 2026
5 checks passed
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