diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md index a2bf199..2b97c8b 100644 --- a/docs/agent-handoff.md +++ b/docs/agent-handoff.md @@ -1,8 +1,8 @@ # Agent handoff — cross-machine continuity -**Last updated: 2026-07-21, with Vterm Stage 1 implemented and fully gated on -the `vterm-core` feature branch (awaiting review; not merged). Vterm Stages 2 -and 3 are not implemented.** This file is the bridge between development +**Last updated: 2026-07-21, after Vterm Stage 1 review round 1 was addressed +and fully gated on `vterm-core` (awaiting follow-up; not merged). 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 plus the `docs/*-framing.md` files ARE your memory. Read this fully before taking on work, seed persistent memory from it, and **update this @@ -121,11 +121,11 @@ next machine reads it the way you just did. `basedpyright` filtered); `git diff --check` clean. Stage 3 landed as #125 and completed Arc 4 on `main`. - **Vterm Stage 1 terminal core IMPLEMENTED ON `vterm-core`, FULLY GATED, - AWAITING REVIEW, NOT MERGED** (`docs/vterm-framing.md` rev 3). - - Implementation commits: `bbc1f33` (Stage 1) and `962944b` (Darwin PTY - signal normalization); pull request: #126, - (open, non-draft, - targeting `main`). + AWAITING REVIEW FOLLOW-UP, NOT MERGED** (`docs/vterm-framing.md` rev 4). + - Implementation commits: `bbc1f33` (Stage 1), `962944b` (Darwin signal + normalization), and review fixes `f0a235f`, `28f2e6c`, `bf972a7`; pull + request: #126, (open, + non-draft, targeting `main`). - `AnsiParserProfile::{LineOriented, FullScreen}` preserves compile/REPL behavior while terminal PTYs emit the full cursor/mode/device operation set. `src/terminal/{screen,input,session}.rs` owns the state machine, @@ -147,15 +147,23 @@ next machine reads it the way you just did. output before exact PID/outcome annotation. One-row annotation visibility, TERM-ignoring shutdown, spawn rollback, buffer-kill prune, and immutable empty CRDT bootstrap are pinned. - - Final from-start rerun after the portability fix: Clippy clean; 1,658 - default + 1,834 CRDT library tests (3 ignored each); 8 default + 9 CRDT - vterm acceptance; M4 114 passed (3 ignored, 1 filtered); required GPU 109; - workspace 2,765 passed across 79 suites (19 ignored, 1 filtered); diff - check clean. The first gate pass found only missing crate docs in the new - acceptance; PR CI then exposed Darwin's numeric `strsignal` suffix. Both - fixes were followed by a complete restart from gate 1. - `scripts/bite main src/lib.rs --test vterm_stage1_acceptance` is green only - as the helper's explicitly weaker compile-time API bite. + - Review round 1 added typed IND/NEL/RI with margin-correct screen behavior, + defaults absent `TERM` to `xterm-256color`, makes shutdown liveness + acceptance portable with `kill(pid, 0)`, and preserves custom tab stops on + resize. Stage 2 must uniquify default terminal buffer names. Exact CUU/CUD + margin clamping, combining across controls, xterm alternate-screen details, + legacy non-SGR mouse, and the printable ASCII allocation fast path are + explicit post-arc deferrals in the framing. + - Final from-start rerun after review round 1: Clippy clean; 1,660 default + + 1,836 CRDT library tests (3 ignored each); 8 default + 9 CRDT vterm + acceptance; M4 114 passed (3 ignored, 1 filtered); required GPU 109; + workspace 2,767 passed across 79 suites (19 ignored, 1 filtered); diff + check clean. The first review Clippy pass found only identical LF/IND match + arms; after consolidation the complete sequence restarted at gate 1. + `scripts/bite HEAD^ src/ansi.rs --lib + parser_split_points_produce_identical_screen` is a clean behavioral bite; + the original `main`/crate-root bite remains explicitly weaker compile-time + API evidence. - Stage 2 reviews require a durable focus/input resize owner, owning `FrontendId` for the global `C-c` continuation, and local clipboard/BEL signal drainage. Stage 3 additionally owns `pmacs-gpu/src/attach.rs`, diff --git a/docs/roadmap-2026-07.md b/docs/roadmap-2026-07.md index 64d974d..5555413 100644 --- a/docs/roadmap-2026-07.md +++ b/docs/roadmap-2026-07.md @@ -92,12 +92,13 @@ faces, and semantic/GPU transport through protocol v18. - **Compile-mode landed** in #113: line-oriented PTY/ANSI output, error-regex navigation, and `M-x compile`. -- **Vterm Stage 1 terminal core** is implemented and fully gated on - `vterm-core`, awaiting review and **not merged**. It adds the compatibility - parser profiles, bounded VT screen/scrollback/reflow state machine, input - encoders, internal `TerminalManager`, read-only identity-buffer invariant, - process lifecycle/final annotations, and headless real-PTY acceptance. It - intentionally adds no interactive Lua command or frontend rendering. +- **Vterm Stage 1 terminal core** is implemented, review round 1 is addressed, + and the branch is fully gated on `vterm-core`; PR #126 awaits review + follow-up and is **not merged**. It adds compatibility parser profiles, + bounded VT screen/scrollback/reflow state, IND/NEL/RI, input encoders, + internal `TerminalManager`, read-only identity buffers, process lifecycle, + and headless real-PTY acceptance. It intentionally adds no interactive Lua + command or frontend rendering. - **Vterm Stage 2 TUI** starts only after Stage 1 merges: terminal-window composition, input/resize, per-context scroll/selection/copy, and the Lua surface. diff --git a/docs/vterm-framing.md b/docs/vterm-framing.md index 61006a1..bc1cdc7 100644 --- a/docs/vterm-framing.md +++ b/docs/vterm-framing.md @@ -1,16 +1,19 @@ # Vterm — framing (Arc 5 stage 2, three-PR delivery) -**Revision 3 — 2026-07-21. Status: Stage 1 terminal core implemented and fully -gated on `vterm-core`, awaiting review; not merged. Stages 2 and 3 are not -implemented.** +**Revision 4 — 2026-07-21. Status: Stage 1 review round 1 fixes implemented +and fully gated on `vterm-core`; awaiting review follow-up, not merged. Stages +2 and 3 are not implemented.** -Revision 3 records the Stage 1 implementation and downstream consumer reviews. -The architecture remains 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 remain with an Emacs-style process message; protocol -v19 is additive with complete frames; shared `Style` stays unchanged; and one -`BufferId` owns one shared process/screen whose most recently active frontend -controls size. +Revision 4 closes the first Stage 1 review: full-screen parsing now implements +IND/NEL/RI and terminal children default to `TERM=xterm-256color`; shutdown +acceptance probes process liveness portably; resize preserves application tab +stops; the line-oriented EOF flush is explicit; and remaining VT-fidelity, +performance, and lifecycle nits are recorded below. The architecture remains +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 +remain with an Emacs-style process message; protocol v19 is additive with +complete frames; shared `Style` stays unchanged; and one `BufferId` owns one +shared process/screen whose most recently active frontend controls size. This framing follows the compile-mode terminal substrate that landed in PR #113. `src/process.rs` already owns PTY creation, process groups, bounded @@ -32,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 later stage starts only after the preceding stage lands on `main`. -## 0. Revision 3 — Stage 1 implementation record +## 0. Revision 4 — Stage 1 implementation and review record -The first of the three vterm PRs is implemented on `vterm-core`, fully gated, -and awaiting review. Feature commit `bbc1f33` is published as open, non-draft -PR #126, , targeting `main`. +The first of the three vterm PRs is implemented and fully gated on +`vterm-core`, awaiting review follow-up. Initial feature commit `bbc1f33` and +review fixes through `bf972a7` are published as open, non-draft PR #126, +, targeting `main`. It is deliberately headless: there is no `pmacs.terminal` Lua module, interactive terminal command, TUI paint branch, or GPU/protocol surface yet. @@ -110,20 +114,19 @@ All fourteen Stage 1 criteria are implemented: ### 0.3 Final gates and bite -The initial gate run found and fixed missing module documentation in the new -acceptance crate, then restarted from gate 1. After PR #126 opened, its macOS -Lua 5.4 job exposed Darwin's numeric `strsignal` suffix (`"Terminated: 15"`); -commit `962944b` normalizes both Darwin and glibc descriptions to the same -symbolic signal. The complete sequence restarted from gate 1 again: +The initial delivery gate run fixed missing acceptance-crate documentation; +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, +consolidated in `bf972a7`; the complete sequence restarted from gate 1: - `cargo fmt --check`: clean; - `cargo clippy --workspace --all-targets -- -D warnings`: clean; -- default library: 1,658 passed, 3 ignored; -- CRDT library: 1,834 passed, 3 ignored; +- default library: 1,660 passed, 3 ignored; +- CRDT library: 1,836 passed, 3 ignored; - Stage 1 acceptance: 8 default + 9 CRDT passed; - M4 acceptance: 114 passed, 3 ignored, 1 `basedpyright` filtered; - required GPU: 109 passed; -- workspace: 2,765 passed across 79 suites, 19 ignored, 1 filtered; +- workspace: 2,767 passed across 79 suites, 19 ignored, 1 filtered; - `git diff --check`: clean. `scripts/bite main src/lib.rs --test vterm_stage1_acceptance` returned @@ -131,6 +134,12 @@ symbolic signal. The complete sequence restarted from gate 1 again: API. This is explicitly the helper's weaker compile-time API bite, not a clean behavioral assertion failure. +`scripts/bite HEAD^ src/ansi.rs --lib +parser_split_points_produce_identical_screen` returned `bite: OK` with a clean +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. + ### 0.4 Downstream review findings (not implemented) Stage 2 must derive PTY resize ownership from a durable accepted-input/focus @@ -152,6 +161,32 @@ as large as the legal worst case (review estimate at least 80 MiB), or add a shared aggregate payload bound. It must never silently chunk the locked complete-frame protocol. +### 0.5 Stage 1 review round 1 + +The first external review found no ownership, mutation-guard, parser-cap, or +security regressions. This round resolves its three merge-adjacent findings: + +- `ESC D` (IND), `ESC E` (NEL), and `ESC M` (RI) are typed full-screen + operations. RI scrolls down only at the top margin; IND/NEL scroll up at the + bottom margin, with NEL additionally returning to column zero. The parser's + every-byte-split matrix and focused screen-margin test pin the complete path. +- Terminal children no longer inherit an arbitrary host `TERM`; absent a + caller override, their process environment gets `TERM=xterm-256color`. +- The TERM-ignoring shutdown acceptance uses `kill(pid, 0)` through `nix` + instead of Linux-only `/proc`, so macOS now exercises the assertion. +- Resize retains every surviving application tab stop and installs default + stops only in newly added columns. + +`spawn_ansi_parser` intentionally calls `AnsiParser::finish()` on channel +disconnect for both profiles. For existing line-oriented compile/REPL +consumers, EOF therefore delivers trailing partial text and required synthetic +style/alternate-screen balancing that older code dropped. This is an +intentional latent-bug fix and an observable compatibility contract. + +The Stage 2 Lua `open` surface must uniquify colliding default buffer names +(`*terminal:sh*`, `*terminal:sh*<2>`, and so on) before terminal creation +becomes user-visible. + ## 1. Problem and ownership boundary Pmacs can supervise a PTY and can parse enough ANSI to turn command output into @@ -774,10 +809,10 @@ Per-stage utilization: ## 8. Branch and PR plan -Stage 1 is implemented and fully gated on `vterm-core` at `bbc1f33`, published -as open, non-draft PR #126 (), -targeting `main` and not merged. Continue the approved plan only after the -preceding PR lands: +Stage 1 is implemented and fully gated on `vterm-core`; review fixes through +`bf972a7` are published in open, non-draft PR #126 +(), targeting `main` and not +merged. Continue the approved plan only after the preceding PR lands: 1. review PR #126; merge only when the user says; 2. after stage 1 merges, create `pmacs-vterm-tui`, branch `vterm-tui`, from the @@ -794,8 +829,9 @@ base-branch deletion/auto-close risk and makes each PR's gate evidence honest. ### Stage 1 — terminal core -1. Feed every supported CSI/OSC/DEC sequence at every byte split; whole-feed - and split-feed screens are identical. +1. Feed every supported CSI/OSC/DEC sequence, including IND/NEL/RI, at every + byte split; whole-feed and split-feed screens are identical. RI and + forward-index operations additionally pin exact scrolling-margin behavior. 2. Split UTF-8, malformed UTF-8, truncated escape, over-cap control string, and unknown private sequences recover without panic, unbounded growth, or visible escape leakage. @@ -811,8 +847,9 @@ base-branch deletion/auto-close risk and makes each PR's gate evidence honest. glyphs across split feeds. 7. SGR indexed/truecolor/underline/reverse survives screen operations; ignored attributes leave supported fields unchanged. -8. Main-screen resize reflows only soft wraps and preserves cursor/logical-line - identity; alternate-screen resize clips/pads without reflow. +8. Main-screen resize reflows only soft wraps, preserves cursor/logical-line + identity and application tab stops, and adds defaults only in new columns; + alternate-screen resize clips/pads without reflow. 9. Scrollback obeys both row and cell budgets, evicts oldest rows, and keeps the visible grid exact. 10. DA/DSR/CPR query events produce bounded exact response bytes; unsupported @@ -899,6 +936,21 @@ Not part of these three PRs: - kitty keyboard protocol, key release events, media keys, and IME preedit; - cursor-shape/blink rendering and numeric-keypad distinction absent from the current normalized input/cursor protocol; +- RIS (`ESC c`), DECALN (`ESC # 8`), and DEC cursor save/restore mode `?1048`; +- CUU/CUD region clamping when the cursor starts inside scroll margins while + origin mode is disabled; +- combining a character into the preceding cell across intervening SGR or + cursor-control events; +- exact xterm `?1047` clear-on-exit and scroll-margin preservation across + alternate-screen switches; +- legacy X10 mouse byte encoding when a child enables mouse tracking without + SGR mode; Stage 2 sends no report for that unsupported combination; +- nonstandard `CSI 3 K` ignore semantics (the current core clears the line); +- the ASCII fast path that avoids grapheme-candidate allocation and + segmentation for every printable character after another ASCII character; +- cleanup of the defensive impossible-state path where a terminal spawn + returns a process without a running PID, and borrow-tolerant `EditorState` + drop; normal spawn/rollback/prune/shutdown paths remain covered; - shell integration, prompt marks, command semantic zones, and cwd reporting; - ordinary document search over terminal history; - terminal session persistence/reconnect across editor restart;