Skip to content

Reply guard stalls on busy panes — text accumulates unsubmitted, no recovery path #54

Description

@djbclark

Summary

The reply guard introduced in v0.17.0 (PR #39) correctly protects against answering dialogs, but has a UX gap when the target pane is busy streaming output: text arrives in the terminal but the submit key is never sent, the draft stays in the compose box, and retry accumulates duplicate text in the pane with no way to submit or clear it from the PWA.

Scenario

  1. Agent pane (Claude Code) is actively streaming output (working on a response).
  2. User types a message in Collie's composer and taps Send.
  3. Guard step 1 — pane.send_text(text, submit: false) — succeeds: the text lands on the pane's input line.
  4. Guard step 2 — polling the pane to verify the text appeared on the > prompt input line — fails, because the > prompt is scrolled off/obscured by streaming output.
  5. Guard step 3 — Enter is withheld. The Collie compose box keeps the draft.
  6. User taps Send again — steps 3–5 repeat — text accumulates multiple times on the pane's input line with no way to submit it.

Observed behavior

  • The terminal mirror confirms the text IS in the pane's input buffer (it appears on the > line).
  • The Collie compose box still shows the draft, implying the send "failed."
  • Repeated sends type additional copies of the text in the pane but never add a trailing Enter.
  • No PWA affordance to: send a bare Enter, clear the pane's input line, or retry the submit without retyping.

Related

What makes this different from related issues

The guard was designed around a dialog-active scenario, where stalling is correct (you don't want to send Enter into a dialog). But the more common trigger (pane busy streaming) has the opposite UX: the text WAS delivered to the pane's input buffer, it just needs Enter to submit it. The guard treats both scenarios identically when it should distinguish them.

Suggested improvements

1. Clear the compose box on verified type regardless of submit outcome

Once send_text returns ok, the text is in the pane. The compose box should clear immediately — the draft was successfully transmitted even if Enter hasn't been sent yet. Keeping the draft is misleading because the user sees it and assumes "it didn't go through," then retries and accumulates.

2. Retry submit standalone

When the guard stalls (text verified, Enter withheld), offer a "Resend Enter" action. The user can tap it later once they visually confirm in the mirror that the prompt is ready. The original text is already in the pane — only the submit key is missing.

3. Pre-check pane state before typing

Before the guard types anything, check if the pane is in a readable state (output settled, > prompt visible). If the pane is streaming, wait for it to settle rather than typing blind.

Workaround (for documentation)

On the Mac/TUI: tap Cmd+K then Enter in the target pane to clear the accumulated text and start fresh.

From the PWA: tap Keys -> send Ctrl+C to cancel a stuck state, then try sending again when the pane is idle.

Environment

  • Collie v0.20.2 (bridge herdr.collie)
  • Herdr 0.7.4
  • Bridge host: macOS (Apple Silicon), behind tailscale serve
  • Harness: Claude Code panes
  • Client: Android PWA (installed to home screen)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions