You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Pending messages: a session replaced inside the same pane is not noticed when the agent reports no native session #540
Found by a Codex adversarial pass during the review of #520 (bridge-owned pending messages). Not fixed there; reported here so it is not lost. It does not block #520.
What happens
A pending message is bound to the pane's agent by pendingIdentity() in server/index.ts: the agent name, the terminal_id, and herdr's native agent_session (kind:source:value), or null when herdr reports none. Before the paste and before Enter, pendingContext() compares that identity with the pane's current one and refuses with pending_target_changed when they differ.
For an agent without a native session reference both sides are agent / same terminal / null, so a session change inside the same pane is not seen:
An OmO pane. OmoStatus (server/omo-status.ts) does discover the session (sessionOf()), but apply() projects only the agent name and status into the snapshot, so the discovered session never reaches the comparison.
A hookless Claude Code pane (server/claude-session.contract.test.ts, "reads each hookless Claude pane's own conversation in a shared cwd": agent_session is undefined).
Sequence: a connection queues a message while the agent works. The session in that pane is replaced (a new session started from the terminal or another client, a resume) while the pane and the attachment stay. When the new session becomes ready, the bridge delivers the old session's message into it.
Impact
The message goes to the same pane, the same agent process and the same user, but into a different conversation. No other connection gains anything.
Pinning OmO's discovered session can hold a message wrongly when the session is discovered only after the message was queued (null at enqueue, known at delivery).
A hookless Claude pane has no stable identity to pin at all, so "refuse when no identity can be established" would turn the feature off for it.
Possible fix
Carry the discovered session identity into pendingIdentity() where one exists (OmO), and compare only when both sides know it.
Decide what a pane with no identity at all should do: deliver as today, or hold for an explicit Send now once anything suggests the session changed (for example a transcript file that is not the one read at enqueue).
A contract test that changes the session without replacing the attachment.
Partly fixed by #1069 (38d6863): a process replaced in the same pane (pid/birth) and a different OmO session are now held. Remaining: a /clear or resume inside the same process, by an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process.
Partly fixed again by #1310: a queued message is now held when Claude Code switches session inside the same process (/clear, resume). Still open: the same in-process switch for an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process.
Closing as not planned. #1069 holds a queued message when the pane's process is replaced or the OmO session changes, and #1310 when Claude Code switches session inside the same process. What remains is an in-process session switch by an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process. For a queued message this is a sub-second race in practice: agents generally refuse a new session while working, and the message is delivered as soon as the agent goes idle. A held message is sent only on an explicit Send now. Closing the gap needs session identity from herdr or the agent. Reopen if that becomes available or a real case is reported.
Activity
feat(chat): simplify send controls and queued follow-ups (#520)
fix(chat): hold pending input after process replacement (#1069)
devswha commentedon Oct 16, 2026
Partly fixed by #1069 (38d6863): a process replaced in the same pane (pid/birth) and a different OmO session are now held. Remaining: a
/clearor resume inside the same process, by an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process.fix(chat): hold a queued message when Claude switches session in its …
devswha commentedon Oct 19, 2026
Partly fixed again by #1310: a queued message is now held when Claude Code switches session inside the same process (
/clear, resume). Still open: the same in-process switch for an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process.devswha commentedon Oct 19, 2026
Closing as not planned. #1069 holds a queued message when the pane's process is replaced or the OmO session changes, and #1310 when Claude Code switches session inside the same process. What remains is an in-process session switch by an agent that reports neither a native nor an OmO session, and Windows panes where herdr reports no foreground process. For a queued message this is a sub-second race in practice: agents generally refuse a new session while working, and the message is delivered as soon as the agent goes idle. A held message is sent only on an explicit Send now. Closing the gap needs session identity from herdr or the agent. Reopen if that becomes available or a real case is reported.
fix(pending): bind a queued message to the agent process as command o…