Skip to content

tui: pasting into the Playbook never reaches the daemon, and silently unhooks all later typing #1103

Description

@edwin-zvs

Paste is routed through on_paste, which inserts into the Playbook buffer and returns:

self.insert_playbook_text(&text);return;

(crates/cli/src/app.rs ~line 6786 @ ad47152, reached from CtEvent::Paste(text) => self.on_paste(text).await ~line 10454)

Unlike handle_playbook_key, which snapshots the buffer and calls flush_playbook_live_edit afterwards (crates/cli/src/app/editor.rs ~lines 652 / 822), this path never publishes. The pasted text exists only in the client.

It then poisons everything after it: the next keystroke's anchored diff is computed against a before the daemon never saw, playbook.edit fails with old_string not found, and that failure is swallowed (#1089). So after a paste, nothing the user types reaches the document either — silently.

Repro

  1. Open a Playbook in the TUI on a session whose document is seed\n (daemon v27).
  2. Put the caret at the end and paste - one\n- two\n - nested\n.

Observed:

=== TUI ===            === daemon ===
seed- one              v 27
  • two                'seed\n'
    • nested
  1. Keep typing — the daemon stays at v27.

C-x C-s does publish, so the text is recoverable if the user knows to press it. But when the daemon has meanwhile changed, that save is a 3-way merge, and an unreconcilable one writes git conflict markers into the shared document:

'<<<<<<< ours\nse*ed- one\n- two\n  - nested\n\n||||||| original\nseed\n=======\n\tTABbed\n>>>>>>> theirs\n'

The status line does say playbook merged with conflicts to resolve, but the markers now live in a document the owning agent will read and Run.

The web UI has no equivalent problem — its paste handler goes through document.execCommand("insertText", …), which fires input and syncs normally (crates/daemon/assets/index.html ~line 9284).

Expected

Paste is an edit; it publishes like every other edit.

Acceptance criteria

  • Pasting into the Playbook publishes to the daemon without an explicit save.
  • Typing after a paste continues to sync.
  • Regression test: paste into an open Playbook, then assert client and daemon documents are equal.

Related: #1088 (the same missing-flush shape on undo), #1089 (why the failure is invisible).

Found during a hands-on UX audit of the Playbook in the TUI and web UI.

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