6b45b04f
docs: reconcile appearance review and scope wheel scrolling
a73x 2026-09-06 06:31
Commit message
CLAUDE.md
| Old | New | ||
|---|---|---|---|
| @@ -98,7 +98,7 @@ a symbol by its FILE stem (`wall_pump.askOn`) — a file, not a module. | |||
| 98 | | `src/engine/` | `term`(`term.zig`) — `protocol` `replica` `grid` · `engine`(`engine.zig`) — `delta` — the daemon's ghostty-vt; no client row imports it outside a test | | 98 | | `src/engine/` | `term`(`term.zig`) — `protocol` `replica` `grid` · `engine`(`engine.zig`) — `delta` — the daemon's ghostty-vt; no client row imports it outside a test | |
| 99 | | `src/server/` | `daemon`(`server.zig`) — `server_agent` `server_sessions` `cmd` `shellint` `quic_server` `upgrade` `server_test_*` · `pty` | | 99 | | `src/server/` | `daemon`(`server.zig`) — `server_agent` `server_sessions` `cmd` `shellint` `quic_server` `upgrade` `server_test_*` · `pty` | |
| 100 | | `src/client/` | `client` — `client_core` `hosts` `handoff` `layout` `keymap` `askpass` `session_pump` `buffered_wire` `open_wait` `resolver` `discovery` · `webhub` · `wasm_core` `client_core_wasm_check` (wasm roots the build wires outside the table) | | 100 | | `src/client/` | `client` — `client_core` `hosts` `handoff` `layout` `keymap` `askpass` `session_pump` `buffered_wire` `open_wait` `resolver` `discovery` · `webhub` · `wasm_core` `client_core_wasm_check` (wasm roots the build wires outside the table) | |
| 101 | | `src/gui/` | `native_core`(`native_core.zig`) — `workspace` `runtime` `picker` `persistence` `interaction` · `native`(`native.zig`) — `font` `atlas` `quads` `gl` `frame` `bench` | | 101 | | `src/gui/` | `native_core`(`native_core.zig`) — `workspace` `runtime` `picker` `persistence` `interaction` · `native`(`native.zig`) — `config` `theme` `font` `atlas` `quads` `gl` `frame` `bench` | |
| 102 | | `src/tui/` | `wall`(`wallview.zig`) — `interact` `paint` `select` `predict` `wall_host` `wall_picker` `wall_pump` `wall_layout` `wall_test_*` | | 102 | | `src/tui/` | `wall`(`wallview.zig`) — `interact` `paint` `select` `predict` `wall_host` `wall_picker` `wall_pump` `wall_layout` `wall_test_*` | |
| 103 | | `src/cli/` | `mux`(dispatch) — `main`(daemon) `mux_main`(client) `webhub_main`(hub) · `muxg`(native viewer) · `agent`(`muxa.zig`) · `cliflags`(`flags.zig`) | | 103 | | `src/cli/` | `mux`(dispatch) — `main`(daemon) `mux_main`(client) `webhub_main`(hub) · `muxg`(native viewer) · `agent`(`muxa.zig`) · `cliflags`(`flags.zig`) | |
| 104 | | `src/os/` | `server_os`(`server_os.zig`) — `server_os_linux` `server_os_macos` · `client_os`(`client_os.zig`) — `client_os_linux` `client_os_macos` · `spawn` — the platform layer, one row per side so the client never links a fork or a pty; imports nothing of ours (spec 2026-09-03) | | 104 | | `src/os/` | `server_os`(`server_os.zig`) — `server_os_linux` `server_os_macos` · `client_os`(`client_os.zig`) — `client_os_linux` `client_os_macos` · `spawn` — the platform layer, one row per side so the client never links a fork or a pty; imports nothing of ours (spec 2026-09-03) | |
RETRO.md
| Old | New | ||
|---|---|---|---|
| @@ -1021,3 +1021,25 @@ briefs. Shared wire/lifecycle review, NVIDIA validation and private webpage/vide | |||
| 1021 | handoffs remain standing practices, not separate unfinished features. Ligatures, | 1021 | handoffs remain standing practices, not separate unfinished features. Ligatures, |
| 1022 | font fallback, tabs and pane rearrangement remain outside the delivered scope; | 1022 | font fallback, tabs and pane rearrangement remain outside the delivered scope; |
| 1023 | hot reload is intentionally excluded. | 1023 | hot reload is intentionally excluded. |
| 1024 | |||
| 1025 | |||
| 1026 | ## Appearance review and merge handoff — 2026-09-06 | ||
| 1027 | |||
| 1028 | The user requested branch review against main, fixes, merge and a new worktree | ||
| 1029 | for GUI/TUI parity. Independent CLI/config/theme and font/render reviews found no | ||
| 1030 | actionable production regression; root reviewed the QUIC prerequisite and build/ | ||
| 1031 | test integration. Corrected two stale documentation claims: native config/theme | ||
| 1032 | module ownership and the QUIC accessor's use during teardown. No runtime behavior | ||
| 1033 | changed. Full CI, final check, ReleaseSafe native units/core and native integration | ||
| 1034 | passed; prior actual NVIDIA demo/scale/stress evidence applies to unchanged runtime | ||
| 1035 | behavior, with historical limits retained. The | ||
| 1036 | [review record](docs/superpowers/plans/2026-09-06-appearance-merge-review.md) | ||
| 1037 | records scope and evidence. | ||
| 1038 | |||
| 1039 | The next worktree is `gui-wheel-scrolling`; its | ||
| 1040 | [bounded sprint plan](docs/superpowers/plans/2026-09-06-native-wheel-scrolling.md) | ||
| 1041 | starts issue `8b16e26b` with wheel history and application wheel input. It carries | ||
| 1042 | forward stale-reply, independent-pane, high-DPI, passive-observation and private | ||
| 1043 | webpage/video requirements. Implementation has not started. Ligatures remain | ||
| 1044 | deferred. Retain the appearance worktree's live review pages and preserve main's | ||
| 1045 | staged user retro file when fast-forwarding. | ||
docs/superpowers/plans/2026-09-06-appearance-merge-review.md
| Old | New | ||
|---|---|---|---|
| @@ -0,0 +1,47 @@ | |||
| 1 | # Appearance branch review before merge | ||
| 2 | |||
| 3 | Scope: `main` at `bb91afde` through `ui-exploration` at `6c341990`, covering all | ||
| 4 | three appearance slices, the QUIC shutdown prerequisite, tests and delivery docs. | ||
| 5 | The user requested review, correction of findings, merge, then a fresh worktree | ||
| 6 | for GUI/TUI parity. Appearance demos are approved; ligatures remain deferred. | ||
| 7 | |||
| 8 | ## Review and fixes | ||
| 9 | |||
| 10 | Terra reviewed CLI/config/theme ownership, strict parsing, precedence, diagnostics, | ||
| 11 | defaults and render integration. Luna reviewed the combined font/render changes | ||
| 12 | against main, including scale rebuilds, selected-family lifetime, monospace | ||
| 13 | validation and framebuffer oracles. Root reviewed build/native gate wiring, | ||
| 14 | QUIC shutdown ordering, the full scope and integration evidence. Neither agent | ||
| 15 | found an actionable production regression. Root corrected two stale claims: | ||
| 16 | |||
| 17 | - `CLAUDE.md` now lists config/theme under the native rendering module. | ||
| 18 | - `Server.quicListener` now accurately documents teardown: notify peers through | ||
| 19 | the accessor, close client sinks, then free only the owned listener. Its old | ||
| 20 | comment said deinit did not call the accessor, contradicted by the shutdown fix. | ||
| 21 | |||
| 22 | No runtime behavior changed during this review. CONNECTION_CLOSE still occurs | ||
| 23 | before client sinks free their connection state; borrowed listener destruction | ||
| 24 | remains the caller's responsibility. Existing QUIC close tests and the real | ||
| 25 | session-stop integration exercise the underlying behavior. | ||
| 26 | |||
| 27 | ## Validation | ||
| 28 | |||
| 29 | Fresh review logs live in `dist/appearance-merge-review/` in the appearance | ||
| 30 | worktree. Full `make ci` passed (check, terminal integration, agent and | ||
| 31 | throughput), as did the final `make check` after the comment correction. Native | ||
| 32 | build/units/core and full native integration passed, including font/config/theme | ||
| 33 | cases. No gate or timeout was relaxed. The only source edit during these gates | ||
| 34 | was the documentation comment above; runtime code remained frozen. | ||
| 35 | The original appearance delivery record retains the actual NVIDIA demos, scale | ||
| 36 | checks and default/configured stress passes. Those apply to the unchanged runtime | ||
| 37 | behavior; this review does not claim a new GPU measurement or macOS validation. | ||
| 38 | Earlier intermittent NVIDIA misses and offscreen-growth captures remain open. | ||
| 39 | |||
| 40 | ## Handoff | ||
| 41 | |||
| 42 | Fast-forward main only after final checks, preserving its staged | ||
| 43 | `RETRO.pre-native-merge.md` byte-for-byte and in the index. Retain the appearance | ||
| 44 | worktree because it holds the private review pages and evidence. Create a new | ||
| 45 | `gui-wheel-scrolling` worktree from merged main, with a bounded plan for issue | ||
| 46 | `8b16e26b`: pane wheel history, app-mode wheel input and stale-reply handling. | ||
| 47 | Wheel implementation and its demo are a subsequent functional delivery. | ||
docs/superpowers/plans/2026-09-06-native-wheel-scrolling.md
| Old | New | ||
|---|---|---|---|
| @@ -0,0 +1,79 @@ | |||
| 1 | # Native parity — wheel scrolling | ||
| 2 | |||
| 3 | Status: scoped after the appearance branch review and merge; implementation has | ||
| 4 | not started. The user authorized a fresh worktree to begin closing GUI/TUI gaps. | ||
| 5 | This is the first functional slice of git-collab issue `8b16e26b`. | ||
| 6 | |||
| 7 | ## Sprint goal | ||
| 8 | |||
| 9 | Scroll the pane under the pointer with the wheel: shell history at a prompt, | ||
| 10 | arrow input in an alternate-screen application without mouse reporting, and | ||
| 11 | terminal mouse reports when an application requests them. Match existing TUI | ||
| 12 | behavior while keeping each pane independent. | ||
| 13 | |||
| 14 | ## Observable acceptance | ||
| 15 | |||
| 16 | - Three panes on two daemons, including off-origin and unfocused panes. Wheel | ||
| 17 | input affects only the pane under the pointer and does not move keyboard focus. | ||
| 18 | - At a shell prompt, each whole notch moves three history rows, with bounds at | ||
| 19 | the oldest retained history and live output. Return to live output restores | ||
| 20 | the cursor and ongoing updates. Typing returns the receiving pane to live view, | ||
| 21 | matching the TUI. Fractional wheel events accumulate per pane without leaking | ||
| 22 | into another pane; honor SDL's flipped direction flag. | ||
| 23 | - An alternate-screen app without mouse reporting receives the same arrow-key | ||
| 24 | behavior as the TUI, including application cursor-key mode. A mouse-reporting | ||
| 25 | app receives wheel reports with correct pane-relative terminal coordinates and | ||
| 26 | negotiated encoding. Verify the actual PTY bytes independently. | ||
| 27 | - Picker/recovery modals and active divider resizing do not leak wheel input to | ||
| 28 | underlying sessions. Headers, dividers and empty workspace do not scroll a | ||
| 29 | neighbouring pane accidentally. | ||
| 30 | - Delayed history replies cannot repaint live mode, a replacement attachment or | ||
| 31 | a resized viewport. Reconnect, detach and End retain bounded cleanup. The | ||
| 32 | authoritative live replica stays independent of the displayed history view. | ||
| 33 | - Demonstrate real NVIDIA Wayland wheel input at 200% and across the retained | ||
| 34 | scale transitions; verify other panes, focus, PTY sizes and shell identities. | ||
| 35 | |||
| 36 | Selection, clipboard copy/paste, general app click/drag forwarding, ligatures, | ||
| 37 | font fallback and terminal-wall retirement are later scope. Horizontal wheel | ||
| 38 | behavior is outside this initial vertical scrolling slice. | ||
| 39 | |||
| 40 | ## Opening architecture findings and ownership | ||
| 41 | |||
| 42 | `frame.zig` owns SDL events and logical-to-framebuffer conversion through | ||
| 43 | `physicalPoint`. `interaction.Controller` owns pane hit-testing and modal policy; | ||
| 44 | keep these decisions window-free so native-core tests can cover them. | ||
| 45 | |||
| 46 | `runtime.Live.capture` currently copies the pump's live grid only. The GUI | ||
| 47 | runtime owns the chosen pane view and transfers independent snapshots to the | ||
| 48 | painter under the existing pump lock. Keep observation hooks passive; assess | ||
| 49 | extracting touched hooks without turning that into an unrelated refactor. | ||
| 50 | |||
| 51 | `client.session_pump` currently has no scrollback mailbox request or chunk | ||
| 52 | handling. The wire already has `encodeScrollbackReq`, `scrollback_chunk` and | ||
| 53 | server extraction. `Replica.history_rows` and `scrollStart` supply history | ||
| 54 | positioning; `wasm_core` and the TUI provide existing reply-decoding examples. | ||
| 55 | Do not add a second wire protocol or let GUI code access the daemon engine. | ||
| 56 | Review asynchronous request correlation and live/history snapshot ownership | ||
| 57 | before implementing the smallest required shared-client extension. | ||
| 58 | |||
| 59 | `ClientCore.terminal_modes`, `TermModes.appMouse`, alternate-screen and cursor-key | ||
| 60 | flags supply app routing policy. SDL already supplies wheel deltas: the TUI's | ||
| 61 | private `MouseFilter.wheelNotches` parses encoded terminal input and is not a | ||
| 62 | ready-made SDL helper. Share semantic encoding where justified; keep the frozen | ||
| 63 | terminal wall behavior unchanged. | ||
| 64 | |||
| 65 | Assign Luna the bounded implementation and Terra adversarial review through the | ||
| 66 | repository sprint skill. The sprint lead owns shared-client integration, real | ||
| 67 | oracles, validation, recording, webpage, cleanup and commits. Coordinate any | ||
| 68 | shared wire/lifecycle meaning change across clients. | ||
| 69 | |||
| 70 | ## Validation and handoff | ||
| 71 | |||
| 72 | Follow `docs/native-sprint-workflow.md`: opening and closing cleanup, focused | ||
| 73 | client/core tests, real plural-pane wheel integration, full CI/native gates and | ||
| 74 | isolated NVIDIA stress. Build both binaries in ReleaseSafe. Preserve earlier | ||
| 75 | NVIDIA timing failures and the offscreen-growth limitation; neither is waived. | ||
| 76 | |||
| 77 | Finish with a private Tailscale webpage containing achievements, an actual GUI | ||
| 78 | video, controls, evidence and limits. Record user demo approval separately from | ||
| 79 | checks. Reuse the existing page workflow while preserving previous routes. | ||
src/server/server.zig
| Old | New | ||
|---|---|---|---|
| @@ -1535,8 +1535,8 @@ pub const Server = struct { | |||
| 1535 | }; | 1535 | }; |
| 1536 | } | 1536 | } |
| 1537 | 1537 | ||
| 1538 | /// Ownership is deinit's question alone, and it switches exhaustively | 1538 | /// Access does not transfer ownership. Deinit notifies peers through this |
| 1539 | /// rather than calling this. | 1539 | /// accessor, then frees only an owned listener after closing its clients. |
| 1540 | pub fn quicListener(self: *const Server) ?*quic_server.Listener { | 1540 | pub fn quicListener(self: *const Server) ?*quic_server.Listener { |
| 1541 | return switch (self.quic) { | 1541 | return switch (self.quic) { |
| 1542 | .none => null, | 1542 | .none => null, |