fix(channel): roll back history on PromptCancelled to prevent poisoned turns#114
Merged
jamiepine merged 3 commits intospacedriveapp:mainfrom Feb 22, 2026
Merged
Conversation
…d turns When Rig raises PromptCancelled (e.g. reply tool fires and hook terminates the turn), the carried history snapshot was captured *before* the tool batch executed. It contains the assistant's tool-call message but not the tool results, leaving a dangling tool-call that causes every subsequent turn to fail with 'tool call result does not follow tool call (2013)'. Also roll back on hard errors — Rig mutates history in-place but does not carry it back in error variants, which can leave dangling tool-call messages. MaxTurnsError is safe to write back — Rig pushes all tool results into a User message before raising it, so history remains consistent.
Tests cover all four cases of apply_history_after_turn: - Ok: writes full post-turn history back - MaxTurnsError: writes back (Rig includes tool results) - PromptCancelled: rolls back to pre-turn snapshot - Hard error (CompletionError): rolls back to pre-turn snapshot Also includes an end-to-end scenario test verifying the next turn is clean after a PromptCancelled rollback (no dangling tool-calls).
- ToolError (ToolNotFoundError) rolls back via catch-all arm - Rollback on empty history is a no-op and doesn't panic - Rollback when nothing was appended leaves history unchanged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The previous rollback fix (PR #104) correctly handles hard errors but misses
PromptCancelled. This causes channels to permanently break after any cancelled turn (e.g. thereplytool fires and the hook terminates the turn).Root cause: When Rig raises
PromptCancelled, the history it carries was snapshotted before the tool batch executed. It contains the assistant's tool-call message but not the tool results. Writing that back leaves a dangling tool-call that poisons every subsequent turn with:Concrete trace:
replytool fires → hook returnsTerminate { "reply delivered" }→PromptCancelledraised → carried history hasassistant(tool_call: reply)but no tool result → written toself.state.history→ next turn fails permanently.Fix: extract the history write-back into
apply_history_after_turnand treatPromptCancelledlike hard errors — truncate tohistory_len_before. The side-effects (reply sent, worker spawned, etc.) have already happened; we don't need the history to reflect them.MaxTurnsErrorcontinues to write back — Rig pushes all tool results into aUsermessage before raising it, so history is consistent.Tests: five unit tests covering all four match arms plus an end-to-end scenario verifying the next turn is clean after a
PromptCancelledrollback.