Skip to content

A message sent just before a foreground bash wait starts never detaches it #465

Open

Description

@null-axiom

AFT: 0.59.0 · Host: OpenCode V2 (2.0.28)

What happens

detach_on_user_message only checks for a waiting bash at the moment the message is submitted. If the model is still generating the tool call when the message arrives, there is nothing to detach yet. The wait: true command then starts and runs in the foreground until it finishes, while the user's message sits pending.

Sending the same message a few seconds later, after the command has started, works as documented: the wait moves to the background and the message is handled at once.

Timeline (from aft-plugin.log and the session's messages, UTC)

Time Event
17:28:57.9 Assistant step starts (model generating a bash call)
17:28:58.0 User sends a message (V2 steer)
17:28:59.0 bash_wait_detach: … detached=false active_wait_sessions=0 → no active wait found
17:29:08.6 bash spawned for deploy.sh with wait: true, timeout 20 min
17:30:33.1 Deploy finishes; the step ends and the message is delivered

The message was pending for about 95 s. The same log shows the detach succeeding when the message arrives during the wait (detached=true … detached wait for session …, 2026-10-15 13:21:13 and 19:58:13).

Why

The detach is triggered from the V2 session prompt hook (V1: chat.message). Both fire once, when the message is admitted (interruptBashWaitsForChatMessage → signalBashWaitDetachForProject). Nothing re-checks when a foreground wait begins afterwards. So this applies on V1 too, not only V2.

Expected

A message that arrived after the current step started, and is still pending when a foreground wait begins, should detach that wait as if it had arrived during it. In other words, the wait starts already detached (or detaches immediately).

Possible approach

When a sync wait starts, check for a pending message for that session. Two ways to know:

  • AFT records "message arrived, nothing to detach" per session and clears it at the next step boundary or user turn. This needs no host API.
  • The host exposes pending-input state or an event. V2 holds this in its session inbox, but I'm not aware of a plugin-facing API for it.

The first seems enough, as long as the flag is cleared once the message is delivered, so a later wait in a new turn isn't detached by mistake.

Impact

It's a delay, not data loss: the message waits for that one command. It is long when the command is long (a build or deploy with a 20-minute timeout). The window is narrow, the few seconds while the model writes the call, so it's intermittent and hard to notice.

Activity

  1. aft-alfonso commented on Oct 16, 2026

    @aft-alfonso

    Thanks for the detailed timeline; your diagnosis is right. AFT only checks for a waiting command when the message arrives, so a message sent while the call is still being written is missed. We're fixing it as you suggest: AFT will remember a message that arrived with nothing to detach, and a foreground wait that starts in the same step will detach at once. The record clears when the message is delivered, so later turns aren't affected. It will ship in the release after 0.60.0, and we'll close this once it's out.

  2. added a commit that references this issue on Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions