Compare commits

...

1 Commits

Author SHA1 Message Date
Josh McKinney
a40bb0af20 docs(tui2): document viewport/history architecture
- Add architecture/roadmap doc + running notes for the TUI2 transcript-owned
  viewport/history work (PR index, module map, gaps, roadmap).
- Add tester-facing guide for validation and triage (scroll, selection/copy,
  streaming reflow, overlays, exit printing, perf).
- Keep earlier design docs intact but add links to the new docs; align tables.

Docs in this change were automatically created by codex (gpt-5.2 xhigh).
2026-01-05 13:33:39 -08:00
6 changed files with 1746 additions and 41 deletions

View File

@@ -1,5 +1,8 @@
# TUI2 Scroll Input: Model and Implementation
Note: This doc is historical. For the current architecture/status/roadmap, see
`tui2/docs/tui2_viewport_history_architecture.md`.
This is the single "scrolling doc of record" for TUI2.
It describes what we implemented, why it works, and what we tried before this approach.
@@ -307,51 +310,51 @@ Analysis of 16 scroll-probe logs (13,734 events) across 8 terminals shows large
| Terminal | Scenario | Median Dt (ms) | P95 Dt (ms) | Typical burst | Notes |
| --------------------------------------- | --------------- | -------------: | ----------: | ------------: | ----------- |
| Apple_Terminal 455.1 | wheel_single | 0.14 | 97.68 | 3 |
| Apple_Terminal 455.1 | wheel_small | 0.12 | 23.81 | 19 |
| Apple_Terminal 455.1 | wheel_long | 0.03 | 15.93 | 48 |
| Apple_Terminal 455.1 | trackpad_single | 92.35 | 213.15 | 2 |
| Apple_Terminal 455.1 | trackpad_slow | 11.30 | 75.46 | 14 |
| Apple_Terminal 455.1 | trackpad_fast | 0.13 | 8.92 | 96 |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_single | 0.07 | 0.34 | 9 |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_small | 0.05 | 5.04 | 65 |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_long | 0.01 | 0.42 | 166 |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_single | 9.77 | 32.64 | 10 |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_slow | 7.93 | 16.44 | 74 |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_fast | 5.40 | 10.04 | 74 |
| WezTerm 20240203-110809-5046fc22 | wheel_single | 416.07 | 719.64 | 1 |
| WezTerm 20240203-110809-5046fc22 | wheel_small | 19.41 | 50.19 | 6 |
| WezTerm 20240203-110809-5046fc22 | wheel_long | 13.19 | 29.96 | 10 |
| WezTerm 20240203-110809-5046fc22 | trackpad_single | 237.56 | 237.56 | 1 |
| Apple_Terminal 455.1 | wheel_single | 0.14 | 97.68 | 3 | |
| Apple_Terminal 455.1 | wheel_small | 0.12 | 23.81 | 19 | |
| Apple_Terminal 455.1 | wheel_long | 0.03 | 15.93 | 48 | |
| Apple_Terminal 455.1 | trackpad_single | 92.35 | 213.15 | 2 | |
| Apple_Terminal 455.1 | trackpad_slow | 11.30 | 75.46 | 14 | |
| Apple_Terminal 455.1 | trackpad_fast | 0.13 | 8.92 | 96 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_single | 0.07 | 0.34 | 9 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_small | 0.05 | 5.04 | 65 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | wheel_long | 0.01 | 0.42 | 166 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_single | 9.77 | 32.64 | 10 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_slow | 7.93 | 16.44 | 74 | |
| WarpTerminal v0.2025.12.17.17.stable_02 | trackpad_fast | 5.40 | 10.04 | 74 | |
| WezTerm 20240203-110809-5046fc22 | wheel_single | 416.07 | 719.64 | 1 | |
| WezTerm 20240203-110809-5046fc22 | wheel_small | 19.41 | 50.19 | 6 | |
| WezTerm 20240203-110809-5046fc22 | wheel_long | 13.19 | 29.96 | 10 | |
| WezTerm 20240203-110809-5046fc22 | trackpad_single | 237.56 | 237.56 | 1 | |
| WezTerm 20240203-110809-5046fc22 | trackpad_slow | 23.54 | 76.10 | 10 | 12.5% horiz |
| WezTerm 20240203-110809-5046fc22 | trackpad_fast | 7.10 | 24.86 | 32 | 12.6% horiz |
| alacritty | wheel_single | 0.09 | 0.33 | 3 |
| alacritty | wheel_small | 0.11 | 37.24 | 24 |
| alacritty | wheel_long | 0.01 | 15.96 | 56 |
| alacritty | trackpad_single | n/a | n/a | 1 |
| alacritty | trackpad_slow | 41.90 | 97.36 | 11 |
| alacritty | trackpad_fast | 3.07 | 25.13 | 62 |
| ghostty 1.2.3 | wheel_single | 0.05 | 0.20 | 9 |
| ghostty 1.2.3 | wheel_small | 0.05 | 7.18 | 52 |
| ghostty 1.2.3 | wheel_long | 0.02 | 1.16 | 146 |
| alacritty | wheel_single | 0.09 | 0.33 | 3 | |
| alacritty | wheel_small | 0.11 | 37.24 | 24 | |
| alacritty | wheel_long | 0.01 | 15.96 | 56 | |
| alacritty | trackpad_single | n/a | n/a | 1 | |
| alacritty | trackpad_slow | 41.90 | 97.36 | 11 | |
| alacritty | trackpad_fast | 3.07 | 25.13 | 62 | |
| ghostty 1.2.3 | wheel_single | 0.05 | 0.20 | 9 | |
| ghostty 1.2.3 | wheel_small | 0.05 | 7.18 | 52 | |
| ghostty 1.2.3 | wheel_long | 0.02 | 1.16 | 146 | |
| ghostty 1.2.3 | trackpad_single | 61.28 | 124.28 | 3 | 23.5% horiz |
| ghostty 1.2.3 | trackpad_slow | 23.10 | 76.30 | 14 | 34.7% horiz |
| ghostty 1.2.3 | trackpad_fast | 3.84 | 37.72 | 47 | 23.4% horiz |
| iTerm.app 3.6.6 | wheel_single | 74.96 | 80.61 | 1 |
| iTerm.app 3.6.6 | wheel_small | 20.79 | 84.83 | 6 |
| iTerm.app 3.6.6 | wheel_long | 16.70 | 50.91 | 9 |
| iTerm.app 3.6.6 | trackpad_single | n/a | n/a | 1 |
| iTerm.app 3.6.6 | trackpad_slow | 17.25 | 94.05 | 9 |
| iTerm.app 3.6.6 | trackpad_fast | 7.12 | 24.54 | 33 |
| vscode 1.107.1 | wheel_single | 58.01 | 58.01 | 1 |
| vscode 1.107.1 | wheel_small | 16.76 | 66.79 | 5 |
| vscode 1.107.1 | wheel_long | 9.86 | 32.12 | 8 |
| vscode 1.107.1 | trackpad_single | n/a | n/a | 1 |
| vscode 1.107.1 | trackpad_slow | 164.19 | 266.90 | 3 |
| vscode 1.107.1 | trackpad_fast | 16.78 | 61.05 | 11 |
| xterm-kitty | wheel_single | 0.16 | 51.74 | 3 |
| xterm-kitty | wheel_small | 0.10 | 24.12 | 26 |
| xterm-kitty | wheel_long | 0.01 | 16.10 | 56 |
| iTerm.app 3.6.6 | wheel_single | 74.96 | 80.61 | 1 | |
| iTerm.app 3.6.6 | wheel_small | 20.79 | 84.83 | 6 | |
| iTerm.app 3.6.6 | wheel_long | 16.70 | 50.91 | 9 | |
| iTerm.app 3.6.6 | trackpad_single | n/a | n/a | 1 | |
| iTerm.app 3.6.6 | trackpad_slow | 17.25 | 94.05 | 9 | |
| iTerm.app 3.6.6 | trackpad_fast | 7.12 | 24.54 | 33 | |
| vscode 1.107.1 | wheel_single | 58.01 | 58.01 | 1 | |
| vscode 1.107.1 | wheel_small | 16.76 | 66.79 | 5 | |
| vscode 1.107.1 | wheel_long | 9.86 | 32.12 | 8 | |
| vscode 1.107.1 | trackpad_single | n/a | n/a | 1 | |
| vscode 1.107.1 | trackpad_slow | 164.19 | 266.90 | 3 | |
| vscode 1.107.1 | trackpad_fast | 16.78 | 61.05 | 11 | |
| xterm-kitty | wheel_single | 0.16 | 51.74 | 3 | |
| xterm-kitty | wheel_small | 0.10 | 24.12 | 26 | |
| xterm-kitty | wheel_long | 0.01 | 16.10 | 56 | |
| xterm-kitty | trackpad_single | 155.65 | 289.87 | 1 | 12.5% horiz |
| xterm-kitty | trackpad_slow | 16.89 | 67.04 | 16 | 30.4% horiz |
| xterm-kitty | trackpad_fast | 0.23 | 16.37 | 78 | 20.6% horiz |

View File

@@ -1,5 +1,8 @@
# Streaming Markdown Wrapping & Animation TUI2 Notes
Note: This doc is historical. For the current architecture/status/roadmap, see
`tui2/docs/tui2_viewport_history_architecture.md`.
This document mirrors the original `tui/streaming_wrapping_design.md` and
captures how the same concerns apply to the new `tui2` crate. It exists so that
future viewport and streaming work in TUI2 can rely on the same context without
@@ -82,4 +85,3 @@ the legacy behavior while the viewport work (scrolling, selection, exit
transcripts) is being ported. This document exists to make that tradeoff
explicit for TUI2 and to provide a natural home for any TUI2specific streaming
wrapping notes as the design evolves.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,362 @@
# TUI2 viewport + history: running notes (DRAFT)
This file is intentionally a scratchpad. It exists so we can iterate, capture raw findings,
and survive compaction without losing breadcrumbs.
If youre new, start with `tui2/docs/tui2_viewport_history_architecture.md`.
---
## Work log (what changed in these docs)
- 2026-01-05: Created `tui2_viewport_history_architecture.md` + this notes doc, and added
“historical” pointers to the older viewport/scroll/streaming design docs, and indexed
Josh-authored PRs that
touch `tui2/` (with links + a first-pass architecture/gaps/roadmap).
- 2026-01-05: Added commit links to the PR table, added a doc completeness checklist +
justification section, clarified the “critical path” modules, and verified there are no
extra Josh “tui2” PRs outside `tui2/` (revset search).
- 2026-01-05: Expanded the embedded TODO/checklist sections (doc + implementation), and added an
at-a-glance completeness checklist under “Whats missing / gaps”.
- 2026-01-05: Filled the optional deep dives in the main doc (bottom pane integration, streaming
markdown pipeline, frame scheduling/redraw control, overlays/backtrack, and legacy scrollback
insertion).
---
## Working agreement for this doc
- Prefer short bullets over essays.
- Keep command lines and key outputs (trimmed) so later readers can reproduce.
- When a finding seems “important”, migrate it into the main doc and leave a link here.
- Keep TODOs grouped and checked off as theyre resolved.
---
## Scope (decisions so far)
- Repo: `https://github.com/openai/codex`
- Baseline (“before”): legacy TUI
- Priority: `tui2/**` changes (repo-root: `codex-rs/tui2/**`)
- Secondary: supporting changes outside `tui2/` required for the work
- Focus: PRs authored by joshka-oai / joshka
- Keep older docs as-is, but link them to the new doc
Note on paths:
- `jj show --name-only` prints repo-root-relative paths (often `codex-rs/...`).
- When navigating from within `codex-rs/`, drop the `codex-rs/` prefix (e.g. `tui2/src/app.rs`).
Open questions:
- Are there specific “must-include” PRs you want to seed the table with?
- Should we treat “stacked PRs” specially in the PR index?
---
## TODO (high level)
- [x] Confirm scope boundaries (what counts as viewport/history work)
- Repo: `https://github.com/openai/codex`
- Baseline: legacy TUI
- [x] Build PR index table from `jj log` (paths + PR numbers + dates)
- Captured Josh-authored PRs touching `tui2/` on `main`
- Added PR + merge-commit links in the main doc
- [x] Draft “before vs after” framing (high level)
- Captured the “why app-owned transcript” story and major behavior changes
- [x] Deep legacy TUI compare (optional)
- Added a “legacy scrollback insertion” deep dive in the main doc.
- [x] Map architecture and data flow with a diagram
- Added diagram + data-shape glossary in the main doc
- [x] Identify missing pieces / gaps (correctness, UX, perf, tests)
- Recorded confirmed gaps (suspend printing, drag auto-scroll, streaming reflow/tests, cleanup)
- [x] Draft roadmap with phases and owners (if applicable)
- Grouped into P0/P1/P2 for completeness work
- [x] Add “historical” pointers to earlier design docs
- [x] Optional deep dives (streaming, frames, overlays)
- Added a dedicated “Deep dives” section in the main doc.
---
## Investigation checklist (where to look)
### Entry points / startup
- [x] `tui2/src/main.rs` (binary entry)
- [x] `tui2/src/lib.rs` (bootstrap/config)
- [x] `tui2/src/tui.rs` (terminal modes, alt screen, suspend/exit)
### App render loop + viewport
- [x] `tui2/src/app.rs` (render loop and layout)
- [x] `tui2/src/frames.rs` (frame timing/render helpers)
- [x] `tui2/src/tui/scrolling/**` (scroll state, mouse model, anchors)
### Transcript pipeline
- [x] `tui2/src/history_cell.rs` (cell types and transcript lines)
- [x] `tui2/src/transcript_render.rs` (flatten/wrap/meta)
- [x] `tui2/src/transcript_view_cache.rs` (wrapped + raster cache)
- [x] `tui2/src/transcript_selection.rs` (selection model)
- [x] `tui2/src/transcript_copy.rs` / `tui2/src/transcript_copy_ui.rs` (copy behavior)
### Bottom pane and widgets
- [x] Identify composer/footer integration points + key PRs
- [ ] Deep dive: composer, popups, approvals, footer (optional)
### Streaming and wrapping
- [x] `tui2/docs/streaming_wrapping_design.md` (design constraints)
- [x] `tui2/src/markdown_stream.rs` / `tui2/src/markdown_render.rs`
---
## Commands and outputs (fill as we go)
### PR discovery
Planned commands (examples; adapt as needed):
```bash
jj --no-pager log tui2 -r '::main'
jj --no-pager log tui2 -r '::main & (author(joshka) | committer(joshka))'
jj --no-pager log -r '::main & (author(joshka) | committer(joshka))' -n 200
```
Notes:
- Prefer `jj log <paths...>` to restrict to viewport/history work.
- Capture PR numbers from subjects like `(... #1234)` and convert to links once the base URL is
known.
### Secondary PR search (Josh; outside `tui2/`)
This checks whether there are Josh-authored commits that mention “tui2” but do not touch
`tui2/`.
```bash
jj --no-pager log -n 20 \
-r '((::main) & (author(substring:"joshka") | committer(substring:"joshka")) & \
description(substring:"tui2")) ~ files(tui2)' \
-T 'committer.timestamp().local().format("%Y-%m-%d") ++ " " ++ commit_id.short() ++ " " ++ \
description.first_line() ++ "\n"'
```
Result: no matches.
---
## Findings (raw; to migrate into main doc)
## Broad commit inventory (Joshka; touches `tui2/**`)
Command:
```bash
jj --no-pager log -G -n 60 tui2 \
-r '::main & (author(substring:"joshka") | committer(substring:"joshka"))' \
-T 'committer.timestamp().local().format("%Y-%m-%d") ++ " " ++ commit_id.short() ++ " " ++ \
description.first_line() ++ "\n"'
```
Raw list (to refine into the PR index and architecture narrative):
- 2026-01-04 `181ff89cbd33` [#8718] copy selection dismisses highlight
- 2026-01-04 `567821305831` [#8716] render copy pill at viewport bottom
- 2026-01-03 `279283fe02bf` [#8695] avoid scroll stickiness at cell boundaries
- 2026-01-03 `19525efb22ca` [#8697] brighten transcript copy affordance
- 2026-01-03 `90f37e854992` [#8693] cache transcript view rendering
- 2026-01-02 `3cfa4bc8be78` [#8681] reduce unnecessary redraws
- 2025-12-23 `96a65ff0ed91` [#8499] cap redraw scheduling to 60fps
- 2025-12-23 `0130a2fa405a` [#8471] add multi-click transcript selection
- 2025-12-22 `282854932328` [#8466] start transcript selection on drag
- 2025-12-22 `310f2114ae8f` [#8463] fix screen corruption
- 2025-12-22 `414fbe0da95a` [#8462] add copy shortcut + UI affordance
- 2025-12-22 `f6275a51429c` [#8418] include tracing targets in file logs
- 2025-12-22 `7d0c5c7bd5da` [#8449] copy transcript selection outside viewport
- 2025-12-22 `4e6d6cd7982d` [#8419] constrain transcript mouse selection bounds
- 2025-12-22 `3c353a3acab9` [#8423] re-enable ANSI for VT100 tests
- 2025-12-20 `63942b883c49` [#8357] tune scrolling input (commit subject truncated)
- 2025-12-19 `1d4463ba8137` [#8295] coalesce transcript scroll redraws
- 2025-12-18 `df46ea48a230` [#8252] terminal detection metadata for scroll scaling
- 2025-12-16 `3fbf379e02e0` [#8122] docs: refine tui2 viewport roadmap
- 2025-12-15 `f074e5706b1c` [#8089] make transcript line metadata explicit
- 2025-12-15 `b093565bfb5b` [#7601] WIP: rework viewport, history printing, selection/copy
- 2025-12-12 `6ec2831b91a3` [#7965] sync tui2 with tui and keep dual-run glue
- 2025-12-10 `90f262e9a46e` [#7833] copy tui crate and normalize snapshots (massive sync)
- 2025-12-09 `0c8828c5e298` [#7793] add feature-flagged tui2 frontend
Baseline note:
- [#7833] is the “massive sync” baseline:
- `jj --no-pager diff --stat -r 90f262e9a46e` reports `742 files changed` and ~`53k` insertions.
## PR notes (broad; key files touched)
These are quick “what changed where” notes, based on `jj show --name-only`.
- [#7793] bring-up (feature-flagged tui2 frontend)
- Touches: `codex-rs/tui2/src/lib.rs`, `codex-rs/tui2/src/main.rs`,
`codex-rs/core/src/features.rs`, `codex-rs/cli/src/main.rs`, `docs/config.md`.
- [#7965] sync tui2 with tui + dual-run glue
- Touches many files under `codex-rs/tui2/src/**` plus `codex-rs/tui2/tests/**`.
- Appears to keep some `codex-tui` interop conversions in `codex-rs/tui2/src/lib.rs`.
- [#7601] WIP: rework viewport/history printing/selection-copy
- Touches: `codex-rs/tui2/src/app.rs`, `codex-rs/tui2/src/tui.rs`,
`codex-rs/tui2/src/tui/job_control.rs`, `codex-rs/tui2/src/insert_history.rs`,
`codex-rs/tui2/src/clipboard_copy.rs`, `codex-rs/tui2/src/bottom_pane/footer.rs`,
`codex-rs/tui2/src/chatwidget.rs`, `codex-rs/tui2/src/pager_overlay.rs`.
- Adds/updates docs: `tui2/docs/tui_viewport_and_history.md`,
`tui2/docs/streaming_wrapping_design.md`.
- [#8089] transcript line metadata refactor
- Touches: `codex-rs/tui2/src/tui/scrolling.rs`, `codex-rs/tui2/src/app.rs`,
`codex-rs/tui2/src/tui.rs`.
- [#8693] transcript view caching (wrapped transcript + row raster cache)
- Touches: `codex-rs/tui2/src/transcript_view_cache.rs`,
`codex-rs/tui2/src/transcript_render.rs`, `codex-rs/tui2/src/app.rs`.
- Also touches `codex-rs/tui2/src/terminal_palette.rs` and `codex-rs/tui/src/terminal_palette.rs`.
- Adds: `docs/tui2/performance-testing.md`.
- [#8122] docs: refine tui2 viewport roadmap
- Touches: `codex-rs/tui2/docs/tui_viewport_and_history.md`.
- [#8252] terminal detection metadata (per-terminal scroll scaling)
- Touches: `codex-rs/core/src/terminal.rs`, `codex-rs/tui2/src/lib.rs`.
- [#8295] coalesce transcript scroll redraws
- Touches: `codex-rs/tui2/src/app.rs`.
- [#8357] scroll input model: stream-based wheel/trackpad normalization
- Touches: `codex-rs/tui2/src/tui/scrolling/mouse.rs`,
`codex-rs/tui2/src/tui/scrolling.rs`, `codex-rs/tui2/src/app.rs`,
`codex-rs/tui2/docs/scroll_input_model.md`.
- Also touches config/docs: `codex-rs/core/src/config/types.rs`, `docs/config.md`.
- [#8423] VT100 tests: force ANSI on under NO_COLOR
- Touches: `codex-rs/tui2/src/test_backend.rs`.
- [#8419] selection bounds: ignore mouse outside transcript region
- Touches: `codex-rs/tui2/src/app.rs`.
- [#8449] copy selection outside viewport (full logical selection range)
- Touches: `codex-rs/tui2/src/transcript_selection.rs`,
`codex-rs/tui2/src/app.rs`, `codex-rs/tui2/src/lib.rs`.
- [#8418] include tracing targets in file logs
- Touches: `codex-rs/tui/src/lib.rs`, `codex-rs/tui2/src/lib.rs`.
- [#8462] copy shortcut + “copy pill” UI affordance
- Touches: `codex-rs/tui2/src/transcript_copy.rs`, `codex-rs/tui2/src/app.rs`,
`codex-rs/tui2/src/bottom_pane/footer.rs`, `codex-rs/tui2/src/key_hint.rs`.
- [#8463] fix screen corruption (alt-screen nesting + first-draw clear)
- Touches: `codex-rs/tui2/src/tui/alt_screen_nesting.rs`, `codex-rs/tui2/src/tui.rs`.
- [#8466] start transcript selection on drag
- Touches: `codex-rs/tui2/src/transcript_selection.rs`, `codex-rs/tui2/src/app.rs`.
- [#8471] multi-click transcript selection (word/line/paragraph/cell)
- Touches: `codex-rs/tui2/src/transcript_multi_click.rs`,
`codex-rs/tui2/src/transcript_selection.rs`, `codex-rs/tui2/src/transcript_render.rs`.
- [#8499] cap redraw scheduling to 60fps
- Touches: `codex-rs/tui2/src/tui/frame_requester.rs`,
`codex-rs/tui2/src/tui/frame_rate_limiter.rs`, `codex-rs/tui2/src/tui.rs`.
- [#8681] reduce unnecessary redraws
- Touches: `codex-rs/tui2/src/chatwidget.rs`, `codex-rs/tui2/src/bottom_pane/chat_composer.rs`.
- [#8697] brighten transcript copy affordance
- Touches: `codex-rs/tui2/src/transcript_copy_ui.rs`.
- [#8695] scroll anchoring: make spacer rows first-class
- Touches: `codex-rs/tui2/src/tui/scrolling.rs`, `codex-rs/tui2/src/app.rs`.
- [#8716] render copy pill at viewport bottom (edge case)
- Touches: `codex-rs/tui2/src/transcript_copy_ui.rs`.
- [#8718] copy action clears highlight + shows footer feedback
- Touches: `codex-rs/tui2/src/transcript_copy_action.rs`, `codex-rs/tui2/src/app.rs`,
`codex-rs/tui2/src/bottom_pane/footer.rs`.
TODO:
- [x] Verify the list above includes all relevant PRs authored by joshka-oai/joshka.
- [x] Treat [#7833] as the pre-work baseline in the narrative and PR index.
- [ ] Add any “secondary” Josh PRs outside `tui2/` if needed for coherence.
## Legacy TUI precursor PRs (Josh; may be relevant background)
Found via:
```bash
jj --no-pager log -G -n 200 \
-r '::main & (author(substring:"joshka") | committer(substring:"joshka")) & \
(description(substring:"tui2") | description(substring:"tui"))' \
-T 'committer.timestamp().local().format("%Y-%m-%d") ++ " " ++ commit_id.short() ++ " " ++ \
description.first_line() ++ "\n"'
```
- 2025-12-08 `a9f566af7bfb` [#7660] restore status header after stream recovery
- 2025-12-02 `58e1e570faf0` [#7461] tui.rs extract several pieces
- 2025-11-21 `3ea33a061650` [#6382] fail when stdin is not a terminal
- 2025-11-10 `60deb6773a35` [#6477] job-control for Ctrl-Z handling
- 2025-11-07 `9fba811764c7` [#6373] cleanup deprecated flush logic
- 2025-10-27 `66a4b8982268` [#5568] clarify Windows auto mode requirements
- 2025-10-23 `e258f0f0441c` [#5582] use Option symbol for mac key hints
- 2025-10-15 `18d00e36b9b8` [#5035] warn high effort rate use
[#5035]: https://github.com/openai/codex/pull/5035
[#5568]: https://github.com/openai/codex/pull/5568
[#5582]: https://github.com/openai/codex/pull/5582
[#6373]: https://github.com/openai/codex/pull/6373
[#6382]: https://github.com/openai/codex/pull/6382
[#6477]: https://github.com/openai/codex/pull/6477
[#7461]: https://github.com/openai/codex/pull/7461
[#7660]: https://github.com/openai/codex/pull/7660
---
## Gaps / follow-ups (confirmed so far)
- Suspend printing:
- `tui2/src/app.rs` prints an ANSI transcript on exit via `AppExitInfo.session_lines`.
- `tui2/src/tui/job_control.rs` handles Ctrl-Z by leaving alt screen and restoring modes, but
does not print transcript/history to scrollback.
- Drag selection auto-scroll (near viewport edges) does not appear to be implemented yet; it is
still listed as P1 in `tui2/docs/tui_viewport_and_history.md`.
- `tui2/src/tui.rs` has `pending_history_lines` and `Tui::insert_history_lines`, but they appear
unused in the current alt-screen-default flow (no drain/flush path found).
- Streaming wrapping/reflow remains conservative per `tui2/docs/streaming_wrapping_design.md`.
- Some UX actions (copy and multi-click expansion) rebuild the wrapped transcript view; treat as a
known `O(total transcript text)` tradeoff unless optimized later.
[#7601]: https://github.com/openai/codex/pull/7601
[#7793]: https://github.com/openai/codex/pull/7793
[#7833]: https://github.com/openai/codex/pull/7833
[#7965]: https://github.com/openai/codex/pull/7965
[#8089]: https://github.com/openai/codex/pull/8089
[#8122]: https://github.com/openai/codex/pull/8122
[#8252]: https://github.com/openai/codex/pull/8252
[#8295]: https://github.com/openai/codex/pull/8295
[#8357]: https://github.com/openai/codex/pull/8357
[#8418]: https://github.com/openai/codex/pull/8418
[#8419]: https://github.com/openai/codex/pull/8419
[#8423]: https://github.com/openai/codex/pull/8423
[#8449]: https://github.com/openai/codex/pull/8449
[#8462]: https://github.com/openai/codex/pull/8462
[#8463]: https://github.com/openai/codex/pull/8463
[#8466]: https://github.com/openai/codex/pull/8466
[#8471]: https://github.com/openai/codex/pull/8471
[#8499]: https://github.com/openai/codex/pull/8499
[#8681]: https://github.com/openai/codex/pull/8681
[#8693]: https://github.com/openai/codex/pull/8693
[#8695]: https://github.com/openai/codex/pull/8695
[#8697]: https://github.com/openai/codex/pull/8697
[#8716]: https://github.com/openai/codex/pull/8716
[#8718]: https://github.com/openai/codex/pull/8718

View File

@@ -0,0 +1,250 @@
# TUI2 viewport/history: tester-facing overview (DRAFT)
Status: **draft**
This is a short, team-facing guide for testing and triaging the recent TUI2
viewport/history changes.
For the full architecture and PR index, start with:
- `tui2/docs/tui2_viewport_history_architecture.md`
---
## What changed (high level)
TUI2 now treats “scrollback” as an app-owned transcript, not the terminals native
scrollback buffer. The transcript is wrapped, cached, and rendered into an on-screen
viewport each frame.
That shift enables deterministic scrolling, selection, and copy across terminal
implementations and mode changes, at the cost of moving more complexity into the app
(wrapping/caching/scroll anchors/selection mapping).
---
## Why it matters (what to look for as a tester)
The main promise of the work is that the transcript behaves consistently:
- Scrolling should feel “native” (wheel and trackpad) and should not jump, duplicate,
or lose lines across resizes or mode changes.
- Selection/copy should match logical content (not pixels), should ignore non-content
UI regions (like the gutter), and should allow copying beyond whats currently
visible.
When bugs show up, they often look like correctness failures (“the transcript view is
out of sync”) or UX failures (“it feels wrong compared to my terminal”).
---
## How to enable TUI2 (and confirm youre in it)
Codex selects the TUI implementation at runtime based on the `tui2` feature flag.
### Enable via config
In `config.toml`:
```toml
[features]
tui2 = true
```
### Enable via one-off CLI override
When launching `codex`:
```bash
codex -c features.tui2=true
```
### Quick confirmation cues
These are not “official”, but they tend to be fast signals youre in the new flow:
- The footer advertises a “copy selection” shortcut (usually `Ctrl+Shift+C`, but
`Ctrl+Y` in VS Codes integrated terminal).
- A small on-screen “⧉ copy …” pill appears near an active transcript selection.
- Scrolling behavior feels normalized across wheel densities (1 vs 3 vs 9+ events per
notch).
---
## Test focus areas (prioritized)
These sections are written to be runnable as manual test checklists. Each starts with
the “why” and then lists concrete things to try.
### Scroll + viewport stability (P0)
This is the core correctness bar: transcript content should render exactly once, in
order, and scrolling should be stable at history cell boundaries.
Try:
- Produce enough output to require scrolling (a few screens).
- Scroll with a wheel and with a trackpad (if available).
- Repeatedly scroll across “cell boundaries” (where a history entry changes from one
cell to the next) and look for “stickiness”, jumps, or repeated lines.
- Use keyboard scrolling if you rely on it (PageUp/PageDown/Home/End).
- Resize the terminal while scrolled up:
- Verify the same content remains visible (no sudden jumps to bottom).
- Verify wrapping reflows without duplicating or dropping lines.
If you can, repeat the same checks in multiple terminals (especially one with dense
wheel events, and one with sparse wheel events). See `tui2/docs/scroll_input_model.md`
for the motivation and the knobs that can help diagnose “scroll feels wrong”.
### Selection + copy (P0)
Selection is transcript-relative, not terminal-row-relative. That means the selection
can extend beyond the visible viewport and can be reconstructed for copy.
Try:
- Click-drag to select transcript text; verify selection does not start outside the
transcript region (e.g. the left gutter).
- Multi-click selection expansion (word → line → larger scopes) and confirm it does
not accidentally include UI chrome.
- Extend selection beyond the viewport (drag, then scroll) and copy it:
- Use the shortcut shown in the footer (`Ctrl+Shift+C` or `Ctrl+Y`).
- Click the on-screen “⧉ copy …” pill.
- Verify copied text matches logical content:
- Soft-wrapped prose should copy as a paragraph, not with hard line breaks.
- Preformatted blocks should preserve indentation.
Notes:
- VS Codes integrated terminal often intercepts `Ctrl+Shift+C`, so TUI2 falls back to
advertising/accepting `Ctrl+Y` there.
### Streaming output + wrapping (P1)
Streaming is intentionally “partially solved”: we favor conservative behavior to avoid
regressions, but resize/reflow mid-stream is still a risk area.
Try:
- Stream long markdown content (lists, headings, code blocks).
- Resize the terminal while streaming is still producing output.
- Watch for:
- Duplicate lines during reflow.
- Dropped lines (missing chunks).
- Over-aggressive rewrapping that makes the transcript feel unstable while output is
still arriving.
For deeper context, see `tui2/docs/streaming_wrapping_design.md`.
### Overlays / backtrack / pager interactions (P1)
TUI2 uses overlays (pager/backtrack-style modes) that interact with alt-screen and
render state. Bugs here often present as “screen corruption” when entering/exiting an
overlay.
Try:
- Enter/exit overlays repeatedly (whatever your workflow uses: pager, backtrack, etc.).
- Resize while an overlay is active, then exit it.
- Verify you return to a correct transcript viewport with no persistent corruption.
### Exit + suspend semantics (P2)
Exit printing is the “must-have” contract: leaving TUI2 should print the sessions
transcript to the normal terminal scrollback.
Try:
- Exit normally and confirm the transcript appears in your terminal scrollback.
- Suspend/resume (if you use it) and note current behavior:
- “Print transcript on suspend” is not implemented yet (known gap).
### Performance + redraw behavior (P2)
Recent work adds redraw coalescing, a 60fps cap, and transcript view caching. The goal
is “no jank” during scroll/selection and no event-loop backlog under high input rate.
Try:
- Rapid scrolling (wheel bursts and fast trackpad swipes).
- Rapid resize (dragging the window size back and forth).
- Long sessions (lots of transcript content) and then repeated selection/copy.
- Watch for:
- Input lag (scroll events applying late).
- Excessive CPU usage when idle.
- Flicker or repeated redraw of unchanged content.
---
## Diagnostics (what to capture in a bug report)
The fastest bug reports for this area include both “what happened” and the context
that impacts terminal behavior.
Capture:
- Terminal + OS (e.g. WezTerm on macOS, iTerm2, VS Code integrated terminal).
- Whether the footer shows `Ctrl+Shift+C` or `Ctrl+Y` for copy selection.
- Whether the issue involves wheel vs trackpad scrolling (or `scroll_mode` overrides).
- A short description of the content type involved (prose vs code block vs mixed markdown).
- Whether a resize or overlay transition occurred right before the issue.
Optional: record a JSONL session log for replay/analysis:
```bash
CODEX_TUI_RECORD_SESSION=1 \
CODEX_TUI_SESSION_LOG_PATH=/tmp/codex-session.jsonl \
codex -c features.tui2=true
```
---
## Key PRs to skim (by testing area)
This is a small, tester-oriented subset. For the full PR map, see the “PR index”
section in `tui2/docs/tui2_viewport_history_architecture.md`.
| Area | PRs | Notes |
| ---------------------------- | ----------------------------- | ----------------------------- |
| Enable/dispatch | [#7793] | Flag-gated TUI2 from `codex` |
| Scroll normalization | [#8252], [#8357], [#8695] | Stream model + stickiness fix |
| Selection gestures | [#8419], [#8466], [#8471] | Bounds + drag + multi-click |
| Copy UX | [#8449], [#8462], [#8716] | Off-screen copy + pill hint |
| Perf/redraw | [#8295], [#8499], [#8693] | Coalesce + 60fps + caching |
| Overlay stability | [#8463] | Nested alt-screen corruption |
[#7793]: https://github.com/openai/codex/pull/7793
[#8252]: https://github.com/openai/codex/pull/8252
[#8295]: https://github.com/openai/codex/pull/8295
[#8357]: https://github.com/openai/codex/pull/8357
[#8419]: https://github.com/openai/codex/pull/8419
[#8449]: https://github.com/openai/codex/pull/8449
[#8462]: https://github.com/openai/codex/pull/8462
[#8463]: https://github.com/openai/codex/pull/8463
[#8466]: https://github.com/openai/codex/pull/8466
[#8471]: https://github.com/openai/codex/pull/8471
[#8499]: https://github.com/openai/codex/pull/8499
[#8693]: https://github.com/openai/codex/pull/8693
[#8695]: https://github.com/openai/codex/pull/8695
[#8716]: https://github.com/openai/codex/pull/8716
---
## Known gaps / current limitations
These are called out in more detail (with context and references) in the architecture
docs “Whats missing / gaps” section. Theyre repeated here because they affect what
“complete” testing looks like.
- “Print transcript on suspend” is not implemented yet.
- Auto-scroll while dragging selection near viewport edges is not implemented yet.
- Streaming resize/reflow behavior is conservative and still needs broader test coverage.
---
## Further reading
- `tui2/docs/tui2_viewport_history_architecture.md` (architecture + PR index + roadmap)
- `tui2/docs/tui2_viewport_history_notes.md` (running notes + archaeology commands)
- `tui2/docs/scroll_input_model.md` (wheel/trackpad model and per-terminal defaults)
- `tui2/docs/streaming_wrapping_design.md` (streaming wrapping constraints)

View File

@@ -1,5 +1,8 @@
# TUI2 Viewport, Transcript, and History Design Notes
Note: This doc is historical. For the current architecture/status/roadmap, see
`tui2/docs/tui2_viewport_history_architecture.md`.
This document describes the viewport and history model we are implementing in the new
`codex-rs/tui2` crate. It builds on lessons from the legacy TUI and explains why we moved away
from directly writing history into terminal scrollback.