fix(agent): a racing cancel can no longer wedge the session's turn slot

Port of upstream grok-build 0.2.103. session/prompt runs an async intake
preamble before enqueueing SessionCommand::Prompt on the actor mailbox; a
concurrent cancel could enqueue Cancel first, land on an idle actor as a
no-op, and the prompt then started a turn nothing would ever cancel.

The per-session prompt-intake lock becomes the dispatch lock: prompt()
holds it across intake as before, and cancel() now holds it around its
Cancel send, so a cancel orders behind the prompt it targets. Regression
test ported verbatim (unix-only harness, like its siblings).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSy9S31pZNWXtRZNVJ1sDf
This commit is contained in:
ZacharyZhang-NYandClaude Fable 5 committed 2026-08-27 09:53:09 -04:00
1 parent 6e0464fa74
commit 6a4bff0d45
5 files changed
+77 -25

No files matched your search

@@ -978,7 +978,7 @@ impl MvpAgent {
sessions: RefCell::new(HashMap::new()),
activity,
loading_sessions: RefCell::new(HashMap::new()),
prompt_intake_locks: RefCell::new(HashMap::new()),
dispatch_locks: RefCell::new(HashMap::new()),
session_threads: RefCell::new(HashMap::new()),
resident_roster_titles: RefCell::new(HashMap::new()),
initialize_request: OnceLock::new(),