docs/superpowers/plans/2026-09-05-native-interaction-debt.md
Ref: Size: 6.9 KiB History
# Native interaction ownership — debt sprint The user authorized this sprint after the completed SSH follow-up. Sprint 5 remains accepted; the SSH recording's acceptance remains pending. Advancing to this sprint does not imply acceptance of that recording. Status: implementation, review and all required validation complete. Recorded-demo acceptance is pending. The user authorized the [component-separation sprint](2026-09-05-component-separation.md) before this recording was accepted; that authorization is not demo approval. ## Scope and acceptance Give native command modes, menu transitions, held input and captured pending End actions a clear owner outside SDL window handling and painting. Preserve current controls, labels, attachment identity rules, persistence and test-observation schema. `Ctrl+\\`, then `p` remains Pane actions; Enter opens insertion, while Choose session replaces the captured pane through the same picker. Luna began the extraction but returned an unwired state-only seam. Root completed the controller migration and focused regressions; Terra independently reviewed the final controller, SDL adapter, shared navigation and tests. Root owns the validation, delivery record and promoted `test/native_scale.py` fixture. Workspace geometry, attachment runtime, persistence and SSH retry policy retain their existing boundaries. A generic menu framework and terminal CLI redesign are outside this sprint. Opening assessment: no preparatory cleanup is needed. The substantial interaction refactor is the deliverable itself. Luna and Terra were reused; their recorded session `turn_context.model` values were checked immediately on resuming and confirm `gpt-5.6-luna` and `gpt-5.6-terra` respectively. Acceptance uses real multi-pane/host fixtures: insertion and replacement; held keys and modal text; delayed End through command, focus, picker, resize, drag, replacement and detach transitions; recovery and explicit Retry; resize and DPI changes with independent PTY and framebuffer checks. Run the real SSH gate to exercise recovery through the new controller. Preserve the terminal layout sentinel. Record the actual GUI and keep demo approval distinct from automation. ## Delivery evidence The final change moves command/resize modes, held-key and text suppression, picker/recovery lifetimes, captured pending End actions, pointer resizing and intent saves into `src/gui/interaction.zig`. `frame.zig` translates SDL events, measures geometry, synchronizes mouse capture and paints snapshots. A small shared menu-key mapping preserves navigation aliases while leaving j/k as editor text. The existing observation JSON and SDL regression scenarios remain intact. Closing review found no remaining correctness issue. The preliminary unused Effect API was removed. Two direct controller tests pin exact key release, post-dismissal repeats, text suppression reset, command-to-resize, focus loss, and modal precedence over the prefix. Existing SDL tests retain adapter coverage. No workspace, runtime, transport or terminal-client behavior changed. Final source was frozen before these commands, using the pinned compiler and `ZIG_GLOBAL_CACHE_DIR=/tmp/muxg-zig-cache`; local socket/PTY checks ran with the required authorized permissions: | Gate | Result | | --- | --- | | `deps/zig/zig build install native native-test -Doptimize=ReleaseSafe -p dist/native-interaction-release` | Passed; both release binaries from one build, 46 native test blocks | | `make native-e2e` | Passed; 62 real-boundary scenarios | | `native_picker.old_daemon` with `/tmp/muxg-sprint2-old-mux` | Passed separately; 63 total native integration scenarios | | `test/native_ssh.py` with both release binaries, Wayland at 200% | All five real OpenSSH groups passed | | `test/native_scale.py` with both release binaries and `--output HEADLESS-1` | Passed 200%/100%/150%/200%, drag cancellation, nested resize, PTYs and pixels | | `make native-stress`, Wayland on isolated GPU compositor | Passed unchanged budgets | | `make check` | Passed before commit | | `make ci` | Full retry passed, including all e2e, agent and throughput gates | The initial CI failure was `test/e2e_09_hosts.sh` waiting 15 seconds for the born session's selected row (`2> 1`). The unchanged terminal host group passed all 15 scenarios when rerun with `E2E_ONLY=09_hosts make e2e`. The precise cause of that first timeout is not established; its failure log is retained. The subsequent full CI run passed without source or test changes. Stress used a headless Sway output backed by NVIDIA GeForce RTX 3080, GLES2, with no concurrent GUI fixture or recording. In 30.3 seconds the flooded daemon read 105.7 MB. Sampled input-to-painted maxima were 55.4 ms on the shared daemon and 55.5 ms on the separate daemon (94 samples each); final frame p99 was 18.1 ms. The 5 ms polling interval and snapshot observation overhead make those input numbers upper bounds, not exact input latency. These are Linux results; no new macOS performance or compatibility claim is made. The 57-second actual GUI recording uses the final release at 200%, H.264 1100×700 with no audio. It shows insertion cancellation, keyboard resize, delayed shared-session End, Pane actions, close/reopen, unavailable-host return, missing-session replacement, Detach and End. Three continuous clips have two restart cuts. Input is injected through ordinary SDL events; this recording does not claim a new compositor mouse-path trial. The owned compositor and fixtures were stopped. Recording acceptance remains pending. Retained local recording: `/home/xanderle/.codex/visualizations/2026/09/05/01a071c2-5767-7790-a335-1a84536c9ca5/native-interaction-trial.mp4`. Evidence is in the sibling `interaction-evidence/` directory: final logs, the initial CI failure and targeted rerun, release/source hashes, stress JSON, recording driver and model metadata. This recording has not been published to Tailscale; prior demo routes retain their existing approved payloads. ## Retained debt and next actions - `frame.zig` still contains painting and test-observation hooks. They stay together for this bounded ownership change; the next painter/test-protocol change should assess extracting those hooks without changing passive observation semantics. - The general screen recorder remains an artifact helper rather than a repository tool. The scale gate is now durable. A future recording-tooling package owns parameterizing capture, process cleanup and clip composition; no further production refactor depends on it. - Use a fresh task-specific agent context for the next substantial extraction. Reused Luna stopped before wiring, and root completed implementation. Terra provided useful concrete review. Recorded models and cumulative counters are retained, with cached input separate; this sprint establishes no cost saving. - Record this demo's approval separately from the earlier SSH demo and any hands-on feedback. Start further production work only when authorized.