docs(vterm): record Stage 1 review round 2

Record the control-free cell and SGR mouse hardening, accepted cleanup changes,
remaining DECSTBM/allocation/limit deferrals, behavioral bite, and final gate
counts in framing Revision 5 and project continuity docs.
This commit is contained in:
Levi Neuwirth 2026-07-21 16:31:10 -04:00
parent 9797adaa0b
commit fc4e0ce77d
3 changed files with 85 additions and 46 deletions

View File

@ -1,8 +1,8 @@
# Agent handoff — cross-machine continuity # Agent handoff — cross-machine continuity
**Last updated: 2026-07-21, after Vterm Stage 1 review round 1 was addressed **Last updated: 2026-07-21, after Vterm Stage 1 review round 2 was addressed
and fully gated on `vterm-core` (awaiting follow-up; not merged). Vterm Stages and fully gated on `vterm-core` (awaiting merge authorization; not merged).
2 and 3 are not implemented.** This file is the bridge between development Vterm Stages 2 and 3 are not implemented.** This file is the bridge between development
machines. If you are an agent reading on a fresh clone: this document machines. If you are an agent reading on a fresh clone: this document
plus the `docs/*-framing.md` files ARE your memory. Read this fully plus the `docs/*-framing.md` files ARE your memory. Read this fully
before taking on work, seed persistent memory from it, and **update this before taking on work, seed persistent memory from it, and **update this
@ -121,11 +121,12 @@ next machine reads it the way you just did.
`basedpyright` filtered); `git diff --check` clean. Stage 3 landed `basedpyright` filtered); `git diff --check` clean. Stage 3 landed
as #125 and completed Arc 4 on `main`. as #125 and completed Arc 4 on `main`.
- **Vterm Stage 1 terminal core IMPLEMENTED ON `vterm-core`, FULLY GATED, - **Vterm Stage 1 terminal core IMPLEMENTED ON `vterm-core`, FULLY GATED,
AWAITING REVIEW FOLLOW-UP, NOT MERGED** (`docs/vterm-framing.md` rev 4). AWAITING MERGE AUTHORIZATION, NOT MERGED** (`docs/vterm-framing.md` rev 5).
- Implementation commits: `bbc1f33` (Stage 1), `962944b` (Darwin signal - Implementation commits: `bbc1f33` (Stage 1), `962944b` (Darwin signal
normalization), and review fixes `f0a235f`, `28f2e6c`, `bf972a7`; pull normalization), first-review fixes `f0a235f`, `28f2e6c`, `bf972a7`, and
request: #126, <https://github.com/levineuwirth/pmacs/pull/126> (open, second-review hardening `9797ada`; pull request: #126,
non-draft, targeting `main`). <https://github.com/levineuwirth/pmacs/pull/126> (open, non-draft,
targeting `main`).
- `AnsiParserProfile::{LineOriented, FullScreen}` preserves compile/REPL - `AnsiParserProfile::{LineOriented, FullScreen}` preserves compile/REPL
behavior while terminal PTYs emit the full cursor/mode/device operation behavior while terminal PTYs emit the full cursor/mode/device operation
set. `src/terminal/{screen,input,session}.rs` owns the state machine, set. `src/terminal/{screen,input,session}.rs` owns the state machine,
@ -150,20 +151,23 @@ next machine reads it the way you just did.
- Review round 1 added typed IND/NEL/RI with margin-correct screen behavior, - Review round 1 added typed IND/NEL/RI with margin-correct screen behavior,
defaults absent `TERM` to `xterm-256color`, makes shutdown liveness defaults absent `TERM` to `xterm-256color`, makes shutdown liveness
acceptance portable with `kill(pid, 0)`, and preserves custom tab stops on acceptance portable with `kill(pid, 0)`, and preserves custom tab stops on
resize. Stage 2 must uniquify default terminal buffer names. Exact CUU/CUD resize. Review round 2 rejects C0/C1 controls before they enter screen
margin clamping, combining across controls, xterm alternate-screen details, cells, preserves the released button code in SGR mouse reports, removes
legacy non-SGR mouse, and the printable ASCII allocation fast path are dead screen paths, and clears stale round-trip state during prune. Stage 2
explicit post-arc deferrals in the framing. must uniquify default terminal buffer names.
- Final from-start rerun after review round 1: Clippy clean; 1,660 default + - Exact CUU/CUD and out-of-range DECSTBM clamping, combining across controls,
1,836 CRDT library tests (3 ignored each); 8 default + 9 CRDT vterm xterm alternate-screen details, legacy non-SGR mouse, printable ASCII and
CSI-dispatch allocation fast paths, and scrollback-cap naming are explicit
post-arc deferrals in the framing.
- Final from-start rerun after review round 2: Clippy clean; 1,661 default +
1,837 CRDT library tests (3 ignored each); 9 default + 10 CRDT vterm
acceptance; M4 114 passed (3 ignored, 1 filtered); required GPU 109; acceptance; M4 114 passed (3 ignored, 1 filtered); required GPU 109;
workspace 2,767 passed across 79 suites (19 ignored, 1 filtered); diff workspace 2,769 passed across 79 suites (19 ignored, 1 filtered); diff
check clean. The first review Clippy pass found only identical LF/IND match check clean. `scripts/bite HEAD^ src/terminal/screen.rs --test
arms; after consolidation the complete sequence restarted at gate 1. vterm_stage1_acceptance terminal_cells_reject_child_control_characters`
`scripts/bite HEAD^ src/ansi.rs --lib is a clean behavioral bite. The parser dispatch has its independent clean
parser_split_points_produce_identical_screen` is a clean behavioral bite; behavioral bite; the original `main`/crate-root bite remains explicitly
the original `main`/crate-root bite remains explicitly weaker compile-time weaker compile-time API evidence.
API evidence.
- Stage 2 reviews require a durable focus/input resize owner, owning - Stage 2 reviews require a durable focus/input resize owner, owning
`FrontendId` for the global `C-c` continuation, and local clipboard/BEL `FrontendId` for the global `C-c` continuation, and local clipboard/BEL
signal drainage. Stage 3 additionally owns `pmacs-gpu/src/attach.rs`, signal drainage. Stage 3 additionally owns `pmacs-gpu/src/attach.rs`,

View File

@ -92,13 +92,14 @@ faces, and semantic/GPU transport through protocol v18.
- **Compile-mode landed** in #113: line-oriented PTY/ANSI output, - **Compile-mode landed** in #113: line-oriented PTY/ANSI output,
error-regex navigation, and `M-x compile`. error-regex navigation, and `M-x compile`.
- **Vterm Stage 1 terminal core** is implemented, review round 1 is addressed, - **Vterm Stage 1 terminal core** is implemented, two review rounds are
and the branch is fully gated on `vterm-core`; PR #126 awaits review addressed, and the branch is fully gated on `vterm-core`; PR #126 awaits
follow-up and is **not merged**. It adds compatibility parser profiles, merge authorization and is **not merged**. It adds compatibility parser
bounded VT screen/scrollback/reflow state, IND/NEL/RI, input encoders, profiles, bounded VT screen/scrollback/reflow state, IND/NEL/RI, input
internal `TerminalManager`, read-only identity buffers, process lifecycle, encoders, internal `TerminalManager`, read-only identity buffers, process
and headless real-PTY acceptance. It intentionally adds no interactive Lua lifecycle, renderer-safe control-free cells, and headless real-PTY
command or frontend rendering. acceptance. It intentionally adds no interactive Lua command or frontend
rendering.
- **Vterm Stage 2 TUI** starts only after Stage 1 merges: terminal-window - **Vterm Stage 2 TUI** starts only after Stage 1 merges: terminal-window
composition, input/resize, per-context scroll/selection/copy, and the Lua composition, input/resize, per-context scroll/selection/copy, and the Lua
surface. surface.

View File

@ -1,15 +1,15 @@
# Vterm — framing (Arc 5 stage 2, three-PR delivery) # Vterm — framing (Arc 5 stage 2, three-PR delivery)
**Revision 4 — 2026-07-21. Status: Stage 1 review round 1 fixes implemented **Revision 5 — 2026-07-21. Status: Stage 1 review round 2 fixes implemented
and fully gated on `vterm-core`; awaiting review follow-up, not merged. Stages and fully gated on `vterm-core`; awaiting merge authorization, not merged.
2 and 3 are not implemented.** Stages 2 and 3 are not implemented.**
Revision 4 closes the first Stage 1 review: full-screen parsing now implements Revision 5 establishes the renderer-facing cell invariant before Stage 2:
IND/NEL/RI and terminal children default to `TERM=xterm-256color`; shutdown terminal text discards C0/C1 controls rather than storing host-terminal control
acceptance probes process liveness portably; resize preserves application tab bytes in grapheme cells. SGR mouse release preserves the released button code;
stops; the line-oriented EOF flush is explicit; and remaining VT-fidelity, review cleanups remove dead screen paths and stale round-trip state; and the
performance, and lifecycle nits are recorded below. The architecture remains remaining VT-fidelity and allocation nits are explicit deferrals. Architecture
unchanged: `C-c` is the terminal editor escape (`C-c C-c` sends interrupt); is unchanged: `C-c` is the terminal editor escape (`C-c C-c` sends interrupt);
main-screen resize reflows while alternate screen clips/pads; exited buffers main-screen resize reflows while alternate screen clips/pads; exited buffers
remain with an Emacs-style process message; protocol v19 is additive with remain with an Emacs-style process message; protocol v19 is additive with
complete frames; shared `Style` stays unchanged; and one `BufferId` owns one complete frames; shared `Style` stays unchanged; and one `BufferId` owns one
@ -35,11 +35,12 @@ Arc 5 stage 2 ships as three separately reviewed PRs:
There is no single mega-PR. Each stage is useful and testable by itself, and a There is no single mega-PR. Each stage is useful and testable by itself, and a
later stage starts only after the preceding stage lands on `main`. later stage starts only after the preceding stage lands on `main`.
## 0. Revision 4 — Stage 1 implementation and review record ## 0. Revision 5 — Stage 1 implementation and review record
The first of the three vterm PRs is implemented and fully gated on The first of the three vterm PRs is implemented, reviewed, and fully gated on
`vterm-core`, awaiting review follow-up. Initial feature commit `bbc1f33` and `vterm-core`, awaiting merge authorization. Initial feature commit `bbc1f33`,
review fixes through `bf972a7` are published as open, non-draft PR #126, first-review fixes through `bf972a7`, and second-review hardening `9797ada` are
published as open, non-draft PR #126,
<https://github.com/levineuwirth/pmacs/pull/126>, targeting `main`. <https://github.com/levineuwirth/pmacs/pull/126>, targeting `main`.
It is deliberately headless: there is no `pmacs.terminal` Lua module, It is deliberately headless: there is no `pmacs.terminal` Lua module,
interactive terminal command, TUI paint branch, or GPU/protocol surface yet. interactive terminal command, TUI paint branch, or GPU/protocol surface yet.
@ -117,16 +118,17 @@ All fourteen Stage 1 criteria are implemented:
The initial delivery gate run fixed missing acceptance-crate documentation; The initial delivery gate run fixed missing acceptance-crate documentation;
PR CI then exposed Darwin's numeric `strsignal` suffix, fixed in `962944b`. PR CI then exposed Darwin's numeric `strsignal` suffix, fixed in `962944b`.
Review round 1's first Clippy pass found only identical LF/IND match arms, Review round 1's first Clippy pass found only identical LF/IND match arms,
consolidated in `bf972a7`; the complete sequence restarted from gate 1: consolidated in `bf972a7`. Review round 2 added one screen unit and one shared
acceptance case; the complete sequence restarted from gate 1:
- `cargo fmt --check`: clean; - `cargo fmt --check`: clean;
- `cargo clippy --workspace --all-targets -- -D warnings`: clean; - `cargo clippy --workspace --all-targets -- -D warnings`: clean;
- default library: 1,660 passed, 3 ignored; - default library: 1,661 passed, 3 ignored;
- CRDT library: 1,836 passed, 3 ignored; - CRDT library: 1,837 passed, 3 ignored;
- Stage 1 acceptance: 8 default + 9 CRDT passed; - Stage 1 acceptance: 9 default + 10 CRDT passed;
- M4 acceptance: 114 passed, 3 ignored, 1 `basedpyright` filtered; - M4 acceptance: 114 passed, 3 ignored, 1 `basedpyright` filtered;
- required GPU: 109 passed; - required GPU: 109 passed;
- workspace: 2,767 passed across 79 suites, 19 ignored, 1 filtered; - workspace: 2,769 passed across 79 suites, 19 ignored, 1 filtered;
- `git diff --check`: clean. - `git diff --check`: clean.
`scripts/bite main src/lib.rs --test vterm_stage1_acceptance` returned `scripts/bite main src/lib.rs --test vterm_stage1_acceptance` returned
@ -140,6 +142,11 @@ behavioral assertion failure: the pre-dispatch parser left the cursor at row
zero/column four instead of applying NEL/RI/IND and landing at row one/column zero/column four instead of applying NEL/RI/IND and landing at row one/column
zero. zero.
`scripts/bite HEAD^ src/terminal/screen.rs --test vterm_stage1_acceptance
terminal_cells_reject_child_control_characters` returned `bite: OK` with a
clean behavioral failure: the pre-hardening screen stored control bytes in a
grapheme cluster rather than preserving the blank snapshot.
### 0.4 Downstream review findings (not implemented) ### 0.4 Downstream review findings (not implemented)
Stage 2 must derive PTY resize ownership from a durable accepted-input/focus Stage 2 must derive PTY resize ownership from a durable accepted-input/focus
@ -187,6 +194,27 @@ The Stage 2 Lua `open` surface must uniquify colliding default buffer names
(`*terminal:sh*`, `*terminal:sh*<2>`, and so on) before terminal creation (`*terminal:sh*`, `*terminal:sh*<2>`, and so on) before terminal creation
becomes user-visible. becomes user-visible.
### 0.6 Stage 1 review round 2
The second external review found no ownership, lifecycle, mutation-guard,
transactional-spawn, final-drain, parser-cap, or reflow defects and judged
Stage 1 merge-ready. Its renderer-boundary hardening and cheap cleanups are
resolved before Stage 2:
- `TerminalScreen::write_text` drops every `char::is_control()` value before
grapheme segmentation, so parser-produced C1 and direct-event C0/C1 bytes
cannot enter copyable or renderable cells. Unit and shared acceptance tests
pin a byte-identical blank snapshot.
- SGR mouse release reports retain the released left/middle/right button code
and use the lowercase `m` final.
- The dead `line_feed` mode parameter and contradictory wide-grapheme branch
are removed; all logical-line ID allocation saturates consistently; and
terminal prune clears stale round-trip input membership.
Out-of-range DECSTBM bottom clamping, CSI-intermediate clone removal, and a
separately named configuration-time scrollback-row cap remain explicit
deferrals in §11.
## 1. Problem and ownership boundary ## 1. Problem and ownership boundary
Pmacs can supervise a PTY and can parse enough ANSI to turn command output into Pmacs can supervise a PTY and can parse enough ANSI to turn command output into
@ -941,16 +969,22 @@ Not part of these three PRs:
origin mode is disabled; origin mode is disabled;
- combining a character into the preceding cell across intervening SGR or - combining a character into the preceding cell across intervening SGR or
cursor-control events; cursor-control events;
- DECSTBM clamping when an explicit bottom margin exceeds the current screen
height; the current core leaves the existing scrolling region unchanged;
- exact xterm `?1047` clear-on-exit and scroll-margin preservation across - exact xterm `?1047` clear-on-exit and scroll-margin preservation across
alternate-screen switches; alternate-screen switches;
- legacy X10 mouse byte encoding when a child enables mouse tracking without - legacy X10 mouse byte encoding when a child enables mouse tracking without
SGR mode; Stage 2 sends no report for that unsupported combination; SGR mode; Stage 2 sends no report for that unsupported combination;
- nonstandard `CSI 3 K` ignore semantics (the current core clears the line); - nonstandard `CSI 3 K` ignore semantics (the current core clears the line);
- the ASCII fast path that avoids grapheme-candidate allocation and - the ASCII fast path that avoids grapheme-candidate allocation and
segmentation for every printable character after another ASCII character; segmentation for every printable character after another ASCII character,
and avoiding the per-sequence `intermediates` clone in CSI dispatch;
- cleanup of the defensive impossible-state path where a terminal spawn - cleanup of the defensive impossible-state path where a terminal spawn
returns a process without a running PID, and borrow-tolerant `EditorState` returns a process without a running PID, and borrow-tolerant `EditorState`
drop; normal spawn/rollback/prune/shutdown paths remain covered; drop; normal spawn/rollback/prune/shutdown paths remain covered;
- a separately named configuration-time scrollback-row cap; the current
validation conservatively reuses the history-cell cap before the runtime
row and cell budgets enforce the effective limit;
- shell integration, prompt marks, command semantic zones, and cwd reporting; - shell integration, prompt marks, command semantic zones, and cwd reporting;
- ordinary document search over terminal history; - ordinary document search over terminal history;
- terminal session persistence/reconnect across editor restart; - terminal session persistence/reconnect across editor restart;