a73x

scroll viewport: anchored history, selection, and wheel behavior

open   by a73x

# Scroll viewport: anchored history, selection, and wheel behavior

This supersedes the implementation slices described in the earlier GUI-only issue body: the viewport is not limited to the client replica. Track the work here as separately delegated slices; this administrative setup authorizes no source changes, tests, builds, or commits.

## Setup and delivery checklist

- [x] Verified backup: `/home/xanderle/code/rad/mux-backups/scroll-bug-20260909T055012Z` (restore-validation sibling: `/home/xanderle/code/rad/mux-backups/scroll-bug-restore-validation-20260909T055012Z`).
- [x] Behavioral baseline: portable, user-facing tests.
- [ ] Engine-owned single-coordinate namespace and bounded scrollback fetch.
- [ ] Client: one follow/anchored viewport, one cache, and one pending correlated fetch.
- [ ] GUI integration while preserving existing selection/copy behavior.
- [ ] Focused/native checks, then `make check` and `make ci`.

## Behavioral-baseline evidence (SLICE1)

- Base/worktree: `eef028e2cae68a72e941f778fcab8d3efc5e251b`, `/home/xanderle/code/rad/mux/.worktrees/scroll-viewport` on `scroll-viewport`; the only changed tracked files are `test/native_wheel.py` (new `anchored_output` real-PTY scenario) and `test/native_journey.py` (journey wiring). No production fix is included.
- Baseline author run passed: `ZIG=/home/xanderle/.local/share/mise/installs/zig/0.15.2/bin/zig make native-e2e`, log `/tmp/mux-scroll-viewport-logs/baseline-native-e2e.log`.
- Independent validation, worker `openai-codex/gpt-5.6-terra:medium`, Linux only: Zig `0.15.2`; `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile test/native_wheel.py test/native_journey.py` and `git diff --check` both exited 0. `ZIG=/home/xanderle/.local/share/mise/installs/zig/0.15.2/bin/zig make native-e2e` exited 2 through Make; full log `/tmp/mux-scroll-viewport-logs/independent-native-e2e.log`.
- The red result is the intended behavioral failure, not setup or timing: the first 17 established journey checkpoints passed, then `anchored_output` timed out waiting for a newer `painted_seq` with unchanged retained text. Failure artifact `/tmp/muxg-tiling-z_xqepx0`; its state changes from `ANCHOR-0287..0298` at seq 63 before producer output to `ANCHOR-0290..` at seq 66 after it. This reproduces the author's modified run (`/tmp/mux-scroll-viewport-logs/modified-native-e2e.log`) and its same assertion, proving output moves an anchored viewport.
- Independent review approved the test slice. Review and validation are Linux evidence only; no macOS run/evidence exists. Future engine, client/access-viewport, and GUI validation slices remain TODO; this does not make later checks, implementation, or all gates green.

## Workspace and ownership

- The old dirty worktree remains untouched: `/home/xanderle/code/rad/mux/.worktrees/scroll-bug` at `03661841b1ef0853f43317067d4894ebe355a937`; it retains its 19 tracked modifications plus the untracked plan.
- Fresh worktree: `/home/xanderle/code/rad/mux/.worktrees/scroll-viewport`, branch `scroll-viewport`, created from local `main` at `eef028e2cae68a72e941f778fcab8d3efc5e251b`. No fetch, rebase, or main update was performed.
- Setup worker model: `openai-codex/gpt-5.6-terra:medium`. Behavioral-test worker, validator, and independent reviewer will be separately delegated by the coordinator; their models are not yet configured.

## Excluded scope

- Legacy old-release compatibility.
- Independent QUIC or mutex fixes.

Existing selection/copy user behavior remains preserved; this is not a terminal-wall redesign or a general history-subscription feature.

## Engine substep (completed; pending commit)

- Completed engine work: `RowAnchor` reuses tracked selection; a real page-eviction test uses `max_scrollback` bytes; and the bounded engine encoder reports the correct count for `count == 0`.
- Independent reviewer approved this engine substep. An independent `make check` passed; log: `/tmp/mux-scroll-viewport-logs/engine-substep-independent-check.log`.
- This work is pending commit. The only dirty files in this worktree are `src/engine/engine.zig` and the mechanical new server argument in `src/server/server.zig`.

## Remaining scrollback-access/fetch and client/GUI work

- [ ] Full scrollback-access/fetch slice remains TODO/in progress. A finite server budget is deferred: the browser has a 256 KiB/exact-count expectation and the agent assumes one complete reply, so no limit/partial-wire behavior shipped; the server currently passes `maxInt`.
- [ ] Client viewport GUI native regression remains TODO and is expected red. No CI or macOS claim is made.
- Behavioral baseline was previously committed as `cdf7e30e` and passed `make check`.

## Old worktree backup comparison (read-only)

- Compared `/home/xanderle/code/rad/mux/.worktrees/scroll-bug` with verified backup `/home/xanderle/code/rad/mux-backups/scroll-bug-20260909T055012Z`: HEAD is still `03661841b1ef0853f43317067d4894ebe355a937`; `git diff HEAD --binary` is identical; all 20 captured file hashes match; and the recorded status is identical (19 tracked modifications and 1 untracked plan). Nothing was reset or reverted.

Comments

a73x   2026-09-09 09:28

## Native integration milestone (current; pending final active fixes)

- Native integration worker: `openai-codex/gpt-5.6-terra:medium` (explicit configuration).
- All 34 native checkpoints PASSED in the native integration milestone; Linux-only evidence: `/tmp/mux-scroll-viewport-logs/native-new-selection-fix.log`. Checkpoint 18 records anchored output stable while held copy has a NEW nonzero-row selection, and repeated wheel return to live.
- Current baseline HEAD is `cdf7e30e` (`test: capture anchored viewport movement during output`); the implementation remains uncommitted.
- Architecture now uses one Ghostty row store; `RowAnchor` reuses existing selection pins; one per-client server anchor; canonical protocol request `0x13` / reply `0x99` with no legacy two-history path; native has one cache/pending/intent; and the consumer span retains old one-shot semantics (error if it cannot fit). Existing queue/frame-bound behavior remains: no pagination or new 1 MiB cap; browser stays fixed at 256 KiB.
- Passing own checks include engine actual page eviction, server independence/live boundary/drop cleanup, and native async-selection/lifecycle matrices. TUI, server, and protocol final review are approved.
- Still OPEN/TODO: explicit final native queued-wheel-after-LIVE / expiry-preservation / bad-LIVE-retry-cycle fixes are active; browser-agent final bounded-allocation / canonical-count / correlation fixes are active. Both require re-review. Integrated `make check`, `make ci`, and final native e2e rerun remain pending.
- Linux only; macOS remains untested. Do not make delivery claims. The original scroll-bug worktree remains unchanged and its backup was verified previously; no rehash is needed now. No capture/archive edits.

a73x   2026-09-09 11:06

## Final implementation and Linux validation status (pending commit delivery)

- [x] Engine-owned single-coordinate namespace and bounded scrollback fetch.
- [x] Client follow/anchored viewport, cache, and correlated fetch.
- [x] GUI/native integration preserving selection/copy behavior.
- [x] Linux validation: focused/native checks, `make check`, and `make ci`.
- [ ] Commit delivery.
- [ ] macOS validation.

Implementation and integration are complete and approved, but remain uncommitted and unstaged: baseline `cdf7e30e` (`test: capture anchored viewport movement during output`), 16 intended files. No source commit or push was requested or made. This issue stays OPEN pending commit delivery, macOS validation, and any pre-existing unresolved tasks.

All component independent reviews approved, including native workflow `wf_37f4fa2d`. Latest stable-tree independent gates PASS: `check`, `ci`, `native-e2e`, and `diffcheck`; logs: `/tmp/mux-scroll-viewport-logs/approved-final-{check,ci,native-e2e}.log`. CI convergence `117e2e38`: agent 10/0, native 34, including anchored output stable while held copy has a new nonzero-row selection and wheel return to live; lint: 105 files, 0 errors, 0 warnings. Native ordered intent, OOM lock/release correlation, and timeout behavior are covered.

Source pre/post diff SHA `6a16118e…eac4c034` is identical; index is empty. Prior CI port collision was diagnosed as an existing harness issue and remains separate: no test-harness edits, no failing gate waived, and latest gates are clean without retry. No macOS claim and no old-release compatibility claim are made.

Preserved backup evidence: `../scroll-bug` remains read-only and verified MATCH; combined patch `048dbf68…37d6b5`, all 20 hashes; expected untouched state is 19 tracked changes plus 1 untracked file. Prior backup records remain authoritative.