Skip to content

Commit 16fe0da

Browse files
docs: add terminal images VRS
agent-identity: dev3.direct.omp.2gz9tcpa agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.1.2 agent-runtime: OMP 18.1.2 tooling-profile: dotfiles@7534055
1 parent 180c09b commit 16fe0da

7 files changed

Lines changed: 266 additions & 5 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ Where the port stands against the Node `pty`, surface by surface, is in
7373
[docs/parity.md](docs/parity.md); the work packages that close the gap are in
7474
[docs/parity-plan.md](docs/parity-plan.md).
7575

76+
What must stay true of terminal images — the Kitty graphics protocol state a
77+
session holds and replays — is in
78+
[docs/vrs/01-images/requirements.md](docs/vrs/01-images/requirements.md); how
79+
the session meets it is in
80+
[docs/vrs/01-images/spec.md](docs/vrs/01-images/spec.md).
81+
7682
## Install
7783

7884
With Nix (flakes), from a checkout or straight from GitHub:

crates/pty-conformance/tests/output_activity.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! `lastOutputAtMs`: the daemon records when the child last printed.
22
//!
3-
//! The Node tool grew this field in its PR #168, merged on 2026-08-29
4-
//! (`docs/vrs/requirements.md` R14, `docs/disk-layout.md`). The contract is:
3+
//! The Node tool grew this field in its PR #168, merged on 2026-08-29 (the
4+
//! Node pty repository's `docs/vrs/requirements.md` R14 and
5+
//! `docs/disk-layout.md`, not this repository's `docs/`). The contract is:
56
//!
67
//! - absent until the session produces output, and absent on a record an
78
//! older daemon wrote — never zero, and never a claim of idleness;

crates/pty-core/src/registry/metadata.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ pub struct SessionMetadata {
8989
/// nothing to take; it is persisted at most once a second while output
9090
/// flows.
9191
///
92-
/// node: src/sessions.ts (`lastOutputAtMs`), docs/vrs/requirements.md R14
92+
/// node: src/sessions.ts (`lastOutputAtMs`), the Node pty repository's
93+
/// `docs/vrs/requirements.md` R14 (not this repository's `docs/vrs`)
9394
#[serde(default, skip_serializing_if = "Option::is_none")]
9495
pub last_output_at_ms: Option<i64>,
9596
/// Every field this version does not model, round-tripped verbatim.

crates/pty/src/daemon/lifecycle.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ pub(crate) struct Daemon {
104104

105105
/// How long the activity write waits after the first chunk of a burst.
106106
///
107-
/// node: src/server.ts `scheduleActivityPersist` (1 s), docs/vrs R14.
107+
/// node: src/server.ts `scheduleActivityPersist` (1 s), the Node pty
108+
/// repository's `docs/vrs` R14 (not this repository's `docs/vrs`).
108109
const ACTIVITY_PERSIST_DEBOUNCE: Duration = Duration::from_secs(1);
109110

110111
/// 32 hex characters, Node's `randomBytes(16).toString("hex")`.

docs/parity.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,8 @@ looked.
489489
| Mixed-fleet rig (section 11) | M |
490490
| Packaging and completions (section 14) | M |
491491

492-
Sources for this map: the Node source and its tests at `500eab2`, `docs/vrs`,
492+
Sources for this map: the Node source and its tests at `500eab2`, and — all in
493+
the `compoundingtech/pty` (Node) repository — its `docs/vrs`,
493494
`docs/disk-layout.md`, `docs/client.md`, `docs/testing.md`; this repository at
494495
`e4d6cda`; the `st2`, `pty-relay`, `deskset`, `ding`, `smalltalk`, and `evals`
495496
call sites; issues #1, #3, #4 here and the open issues and PRs on the Node

docs/vrs/01-images/requirements.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Terminal images — Requirements
2+
3+
## Context
4+
5+
This node defines the durable terminal-image contract for pty-rust. The implementation uses the Kitty graphics protocol and libghostty. The rationale for the protocol and replay shape remains in [decision 0012](../../decisions/0012-kitty-graphics-replay.md).
6+
7+
## Assumptions
8+
9+
- **PTY.IMG-A01 Typed terminal ownership:** The terminal actor is the single owner of parsed image state. Clients read typed image descriptions, bytes, placements, and generations rather than untrusted escape sequences.
10+
- **PTY.IMG-A02 Cell-relative composition:** An embedding client composes terminal images in character-cell coordinates and needs the same effective cell metrics that the terminal used.
11+
12+
## Constraints
13+
14+
- **PTY.IMG-C01 Library enumeration:** libghostty does not enumerate an image that was transmitted but never placed; it exposes image lookup by identifier.
15+
- **PTY.IMG-C02 Pixel formats:** Kitty has no `f=` value for grayscale pixels, so a grayscale raw-pixel transmission cannot be represented as a typed replay image without conversion.
16+
- **PTY.IMG-C03 Scrolled direct placements:** A cursor-positioned placement that is entirely above the active area cannot be re-emitted because restoring its position requires a cursor cell inside the active area.
17+
- **PTY.IMG-C04 Protocol scope:** SIXEL and iTerm2 output do not provide the typed placement contract required for client-side reprojection and are outside this node.
18+
- **PTY.IMG-C05 Cross-runtime conformance:** The Node implementation has no equivalent typed image state, so graphics behavior has no Node/Rust conformance pair.
19+
20+
## Acceptable Tradeoffs
21+
22+
- **PTY.IMG-T01 Complete bounded replay:** A session may retain up to 32 MiB of image state, and a replay may carry all retained bytes. The limit is a cap, not an eager allocation.
23+
- **PTY.IMG-T02 Latest cell declaration wins:** Cell metrics use the newest client declaration rather than multi-client negotiation.
24+
25+
## Requirements
26+
27+
### Must bound accepted image state
28+
29+
- **PTY.IMG-R01 Opt-in bounded storage:** Image storage is disabled until an owner enables it. The effective storage limit must not exceed 32 MiB and must be observable through the typed terminal API.
30+
- **PTY.IMG-R08 Inline-only transmission:** The terminal must accept image bytes only from inline transmissions. File, temporary-file, and shared-memory media must remain disabled so a child cannot name an owner-unapproved path.
31+
- **PTY.IMG-R09 Bounded PNG normalization:** PNG (`f=100`) input must be bounded before decoding and normalized to 8-bit RGBA before it enters retained image storage.
32+
33+
### Must survive replay
34+
35+
- **PTY.IMG-R02 Complete late-client replay:** Every retained image reported for a placement must be carried in full by ATTACH and PEEK replay. The replay must not impose a smaller byte cap than the reported retained state.
36+
- **PTY.IMG-R04 Crop fidelity:** Replay must preserve the resolved, image-bounded source rectangle and offsets for each placement.
37+
- **PTY.IMG-R06 Image-free compatibility:** A session that has accepted no image must retain the pre-image replay byte shape; its image replay block is empty.
38+
- **PTY.IMG-R07 Screen and reset lifecycle:** Normal and alternate screens must retain separate image state. Terminal reset must preserve the configured graphics capability needed to replay retained state into its owning screen.
39+
40+
### Must support cell-relative composition
41+
42+
- **PTY.IMG-R03 Window-relative placements:** A graphics read and a grid read taken at the same scroll offset must describe the same terminal window and align cell for cell. Virtual placements follow bounded placeholder cells; direct placements use their screen-space rectangle. Placements outside the requested window must not be reported as visible.
43+
- **PTY.IMG-R05 Declared cell metrics:** ATTACH and RESIZE may append backward-compatible cell width and height fields. An absent declaration must stay explicit and use a deterministic 8×16 fallback. Explicit placement coordinates must not move when cell metrics change.
44+
- **PTY.IMG-R10 Observable content generation:** Image-content changes must advance an observable generation used to fence cached pixels. Scroll and resize may reproject placements without advancing the content generation.

0 commit comments

Comments
 (0)