a73x

2dd9158f

docs: copy/paste discovery — measured, and it reorders the work

a73x   2026-08-15 13:07

Commit message
docs: copy/paste discovery — measured, and it reorders the work

Three escapes and an OSC 52 emitted by a session, none of them reaching
the host tty; the same capture proving itself live on ?1049 and ?2026.
Then the inbound half, which turned out to already work: paste brackets
typed at the client arrive at the session's pty byte for byte.

So bracketed paste is not a paste feature, it is one direction of a
missing mode mirror — and that mirror is also the whole of mouse support.
Filed as ee062dd9 (mirror), 7c777ec6 (OSC 52, with the query direction
refused on purpose), 063cec67 (scrollback copy, which the mirror's mouse
half will make necessary by taking the host's own selection away).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

docs/decisions.md
Old New
@@ -3564,3 +3564,59 @@ so they still pin the fallbacks they were written for.
3564 answers from `pgid`/`settle` and carries no exit code. That is legible 3564 answers from `pgid`/`settle` and carries no exit code. That is legible
3565 rather than silent — every reply already names its `mechanism`, and 3565 rather than silent — every reply already names its `mechanism`, and
3566 `marks` simply stops being the one you get by default. 3566 `marks` simply stops being the one you get by default.
3567
3568 ## 2026-08-15 (copy/paste discovery — what the instrument showed)
3569
3570 Discovery only: no product code changed, three issues filed (`ee062dd9`
3571 mode mirror, `7c777ec6` OSC 52, `063cec67` scrollback copy). The point was
3572 to stop reasoning about copy/paste from the source and measure it.
3573
3574 **The rig.** `muxd --shell /bin/sh`, a real `mux` client on a pty via
3575 `test/ptyclient --out`, and the capture file read as "what the host
3576 terminal would have received". `--out` already existed for convergence;
3577 pointed at this question it is a passthrough oscilloscope.
3578
3579 **Outbound: nothing gets through.** The session emitted `ESC[?2004h`,
3580 `ESC[?1000h`, `ESC[?1006h` and an OSC 52 clipboard set, then a visible
3581 marker. In the host capture: marker present (1), `ESC[?1049h` present (1),
3582 `ESC[?2026h` present (1) — so the capture was live and the session really
3583 ran — and `?2004h`, `?1000h`, `?1006h`, `]52;` all **zero**. The marker was
3584 also in `muxd dump`, so the daemon's engine had every one of them and the
3585 client simply never forwards any.
3586
3587 **Inbound: already transparent, and this was the surprise.** Same rig,
3588 session running `cat -v`, client sent a literal `ESC[200~pasted line
3589 oneESC[201~`. `cat -v` echoed `^[[200~pasted line one^[[201~`. Paste
3590 brackets reach the session's pty byte for byte. **The inbound half needs no
3591 work at all** — the defect is entirely that the host terminal is never told
3592 to *produce* them.
3593
3594 That is the finding that reorders the work. "Bracketed paste is broken"
3595 sounded like a paste-path feature; it is one direction of one missing
3596 mirror, and the same mirror is the whole of mouse support. Two symptoms,
3597 one mechanism, and the daemon already holds the state (ghostty-vt tracks
3598 `bracketed_paste`, `mouse_event_*`, `mouse_format_*`; `term.modes.get`
3599 reads them).
3600
3601 **Three rules extracted.**
3602
3603 **Measure the direction, not the feature.** Reading the code would have
3604 said "no bracketed paste" and a fix would have been designed for both
3605 halves. One `cat -v` said half of it already works.
3606
3607 **A repainting client is not a passthrough client, and the difference is
3608 exactly the side channels.** Modes and OSC escapes are what a two-engine
3609 design silently drops, because neither is grid state and neither survives
3610 "paint what the daemon has". That class — not this instance — is what to
3611 audit next: title (already carried), bell, hyperlinks, colour queries.
3612
3613 **The mode mirror trades a working path for an unbuilt one.** No mouse
3614 reporting is why your terminal's own selection works over a mux screen
3615 today. Mirroring the session's mouse modes takes that away the moment an
3616 app asks for the mouse — correct, and what every terminal does under tmux,
3617 but it means mux needs a copy mechanism of its own landing with, or before,
3618 the mouse half. Bracketed paste carries no such coupling and can ship
3619 alone. The claim that native selection works is reasoned plus confirmed in
3620 the negative (the escapes are absent); nobody has dragged a mouse across a
3621 real mux screen to check wide chars and trailing spaces, and that is named
3622 as unverified in `063cec67` rather than assumed.