docs/superpowers/plans/2026-09-06-native-selection-follow.md
Ref: Size: 8.1 KiB History
# Native selection follows output Status: implemented, functionally validated and architecturally reviewed. Product accepted on 2026-09-06; existing NVIDIA frame-time debt remains open. Goal: a completed local selection follows the same terminal text as output scrolls. This includes Shift+drag in an application using mouse reporting. The existing desktop clipboard stays unchanged until another copy; copying again resolves the tracked text, rather than its former screen position. ## Scope and ownership | Behavior | Reuse | Owner | | --- | --- | --- | | Terminal identity | Pinned Ghostty Selection.track and PageList pins | Engine wrapper, one owned selection per attached server client | | Text extraction | Engine.extractSelection and existing formatter | Engine | | Correlation and compatibility | Framed protocol, server client slots | Shared protocol and server | | Position and clipboard delivery | Session pump mutex, request tickets and attachment lifetime | Shared client | | Drag and highlight | Existing selection.Drag and pane-relative hit testing | Native interaction | No second terminal parser, text matching, or global Ghostty Screen.selection. Opening inspection found no independent cleanup needed; the engine adapter belongs to the feature. Source stays frozen throughout validation before commit. The existing selection request/reply now carries a gesture ID, copy request ID, terminal sequence and authoritative source token. Registering against a stale source is refused. Source tokens must advance even when identical rows produce no visual delta. Positions are delivered after the matching terminal frame; the renderer hides an unmatched position until its corresponding state arrives. Copy uses the daemon's tracked endpoints. The user explicitly excluded backward compatibility: clients require the updated daemon. One action field selects extract/start/copy/clear; TUI and browser extraction use the same exchange. There is no parallel legacy request or capability fallback. The released range becomes the durable selection. Ctrl+Shift+C during a held drag still copies the current range; later copies and release register their current endpoints. Output moving during a held drag retains conservative cancellation; tracking an unfinished gesture is a later slice. Resize/reflow, screen replacement, disconnection and discarded endpoints invalidate selection and preserve the clipboard. GUI paste and ligatures remain outside this slice. A remote daemon needs rebuilding alongside the client. Character insertion/deletion and rectangular margins retire local selection; a linear range crossing a partially scrolled region also retires rather than claiming to represent unchanged text. ## Acceptance - Select a line in a pane with nonzero origin; append output until it moves up. Its highlight follows it, and copying again returns the intended text. - Exercise primary history and alternate-screen vertical scrolling, including repeated identical rows and a scroll region. Position follows engine identity. - Shift-local selection sends no application mouse gesture and follows output. - Two client selections remain independent; another pane's output has no effect. - Discarded endpoints, resize, screen switch and reconnect clear the highlight without replacing the clipboard. Late requests cannot select unrelated text. - Retain existing viewport-wheel selection, soft-wrap extraction and app mouse behavior. Verify real GUI pixels and clipboard, plus engine/wire boundaries. ## Delivery Use the repository sprint gates and a localhost review page with an actual GUI recording. Publishing is optional when requested. Product acceptance remains separate from tests and architectural review. Carry forward the existing NVIDIA frame-time budget miss; retain evidence rather than rerunning until green. ## Integrated architecture and review The engine adapter owns one pair of Ghostty tracked pins per attached client. Ghostty owns page growth, history eviction, Unicode width and wrapping. Partial vertical operations that copy/rotate row contents need explicit endpoint moves; the adapter uses parsed actions and rebinds the existing pins after those moves. REP delegates each repeated character to the existing print hook using Ghostty's previous character. No client parses VT and no duplicate terminal state exists. The server owns tracker teardown, source validation and copy extraction. The pump owns queued/sent correlation, attachment cancellation and matching position metadata to the displayed snapshot or history chunk. The renderer receives grid, origin and position together. During a sequence gap it hides unmatched geometry without destroying the gesture. Clipboard delivery remains separate from unsolicited position updates. Closing cleanup consolidated selection into one action-based wire exchange and removed unused follow-state bookkeeping. Direct TUI/browser extraction reuses the same codecs and formatter. Review resolved extraction lifetime, tracked-pin allocation cleanup, alternate-screen allocator reuse, discarded-row tracking, partial-region movement and held-copy regressions. The independent Terra review has no remaining architectural blocker; final gate results remain separate. ## Final evidence and handoff - `dist/selection-follow/ci-final.log`: full CI passed, including check, 117 e2e scenarios / 38 convergence points, 10 agent checks and throughput. - `native-final-rerun.log`: ReleaseSafe native-core/native tests and the full native integration chain passed. Its offscreen tmux skip is supplemented by the separate actual Wayland fixture below. - `wayland-final.log`: selection, follow-selection, wheel and real 200%/100%/150%/200% scale checks passed with the matched release binaries. - `wayland-tmux-final.log`: three shared foot/tmux mouse checkpoints passed. A later counter assertion exposed ordering between real Wayland motion and the FIFO key hook; the fixture now observes the extended highlight first. `wayland-tmux-counter-final.log` passes held/released copying through tmux in both windowed and fullscreen modes with that independent pixel observation. - `stress-final.log` and retained `stress-result.json`: raw output continued for 30.1 seconds (120.5 MB read), reopen succeeded, and 186 sampled input-to- painted observations stayed at or below 60.4 ms including 5 ms polling. The frame gate remains **red**: p99 20.576/20.716 ms against 20 ms. This is the previously recorded NVIDIA presentation debt, not a performance pass. - Earlier failing logs remain. They include an existing PTY exit timing flake, actual implementation failures fixed before delivery, fixture mistakes, and a CI agent compile caught during a source change. Final CI is a separate, successful frozen-source run. No red result was overwritten as a pass. Matched demo binaries were built with `make install INSTDIR=dist/native-follow-release BINDIR=dist/native-follow-bin`; daemon and GUI both use ReleaseSafe. The maintained page is [the selection-follow review page](../../demos/native-selection-follow.html). Its 25-second, 960×600 H.264 recording is continuous at 5 fps, no audio, on NVIDIA Wayland at 200% scale. It shows a real pointer drag, three appended rows, neighbour output and independently read clipboard replacement/recopy. Video decoding, page loading and HTTP byte ranges were verified. Product sign-off — 2026-09-06: the user approved after confirming that wheel scrolling the viewport preserves the highlight. The held-drag limitation concerns terminal output moving the underlying coordinate source, not merely looking at other existing rows. This records the reported hands-on wheel behavior and explicit approval, not hands-on verification of every automated scenario. The former localhost review URL on port 18778 is retired. No publication was created. Verified server PID 257482 named this worktree's `dist/selection-follow/serve-page.py`, stopped it, and verified port 18778 closed. `dist/selection-follow/accepted-demo-teardown.json` records the cleanup. Recording and test rigs had already closed; owned compositor PID 141229 had already been stopped. Page, recording and validation evidence remain; unrelated services were preserved. No next sprint was started by this approval.