2dd9158f
docs: copy/paste discovery — measured, and it reorders the work
a73x 2026-08-15 13:07
Commit message
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. | ||