Skip to content

Agent session has no turn-concurrency guard: concurrent message_send spawn two subprocesses in one worktree #57

Description

@loraldx

agentMessageSend (agent.go:95-188) reads the session (line 104) but never checks session.State; updateAgentSession(state="running") (agent.go:164-168) is an unconditional overwrite, not a compare-and-reject. async defaults to true, so even a sequential second agent.message_send before the first job finishes launches a second agent subprocess in the same session.Cwd (the task worktree). Under HTTP each POST is its own goroutine with no global lock, so two concurrent sends also both appendAgentMessage(user) (line 116), both readAgentMessages a different partial history (line 119), and both RunCommand — two subprocesses mutating the same worktree while the messages NDJSON degrades to USER/USER/ASSISTANT/ASSISTANT.

Fix: reject agent.message_send when session.State == "running" (compare-and-set), i.e. one in-flight turn per session. Pairs with the R0 write-serialization work. Distinct from #24/#25.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions