Add bounded runtime actor and live PTY pane
CI / rust (push) Successful in 3m26s

This commit is contained in:
2026-08-31 16:32:50 -07:00
parent ab7543b9c6
commit 32d190c6c6
15 changed files with 1111 additions and 39 deletions
+9 -2
View File
@@ -41,8 +41,8 @@ messages should be real from the beginning.
- `lumbridge`: installable application entry point.
The scaffold currently contains `lumbridge-core`, `lumbridge-storage`,
`lumbridge-buzz`, `lumbridge-pty`, and the entry point. Larger runtime crates are
added after their architecture spikes pass.
`lumbridge-buzz`, `lumbridge-pty`, `lumbridge-runtime`, and the entry point.
Larger runtime crates are added after their architecture spikes pass.
## Terminal path
@@ -55,6 +55,13 @@ scrollback. The terminal engine turns output into immutable render snapshots and
bounded deltas for the UI. Scrollback is chunked and persisted separately from
the live screen to prevent large agent transcripts from blocking input.
The first `lumbridge-runtime` actor now owns one `PtySession` on a dedicated
thread. Bounded command and event queues serialize input, resize, close, and
shutdown against ordered raw-byte output. The GPUI slice consumes one actor
session while five surfaces retain deterministic comparison output. This actor
still runs in-process; moving the same framework-neutral contract behind local
authenticated IPC is the next durability step. See decision 0004.
We should evaluate, not blindly copy, WezTerm, Zellij, RMUX, tmux, and cmux. The
first spike must compare a reusable terminal crate with a small first-party layer.
Correctness cases include alternate screen, bracketed paste, OSC 8 links, Kitty
+5
View File
@@ -109,6 +109,11 @@ who already have the final cargo-watch release installed.
- `lumbridge-pty` runs synthetic `/bin/sh` tests for raw output, non-zero exits,
input, resize, one-chunk backpressure, hung-process termination, invalid
dimensions, and exclusion of provider credentials from the child environment.
- `lumbridge-runtime` tests ordered actor output, serialized input and resize,
event polling, invalid configuration, and bounded-time cleanup of a hung PTY.
- The GPUI slice tests byte line-framing across CRLF, chunk boundaries, split
UTF-8, and invalid bytes. It renders one real actor-owned PTY and keeps five
surfaces deterministic; line framing is explicitly not VT emulation.
- The current-GPUI probe compile-checks real AccessKit element wiring and real
platform input-handler installation. Unit tests cover its semantic tree and
UTF-16/UTF-8 composed-text mutations. OS screen readers, IME candidate windows,
+8 -7
View File
@@ -83,10 +83,11 @@ fallback.
## Measurement semantics
Both renderers consume the same deterministic six-surface action stream. Each
tick invalidates six surfaces, appends one bounded line to each of the three
terminal fixtures, and records stable event/revision counters. The GPUI footer
currently reports dispatch-to-element-build p50/p95 over a bounded 256-sample
window. It is deliberately not called key-to-present or frame-present latency:
neither candidate exposes a reliable public cross-platform post-present
callback. True present latency requires an external platform probe.
Both renderers retain the same all-deterministic six-surface action stream for
comparison. The GPUI integration mode replaces one terminal fixture with a real
actor-owned PTY and leaves five deterministic surfaces running. Counters
separate external PTY batches/lines from total model updates. The GPUI footer
reports dispatch-to-element-build p50/p95 over a bounded 256-sample window. It
is deliberately not called key-to-present or frame-present latency: neither
candidate exposes a reliable public cross-platform post-present callback. True
present latency requires an external platform probe.
+7 -4
View File
@@ -84,16 +84,19 @@ receive the same state transitions and tests.
## Decisive workload
- One deterministic tick invalidates all six surfaces and appends bounded output
to the three terminal panes. Framework adapters consume the same event trace.
- In the first actor integration, one terminal pane consumes ordered output from
a real local PTY while each deterministic tick updates the other five
surfaces. The all-deterministic constructor remains available for framework
comparison and replay tests.
- One pane enters and leaves `needs input` through a deterministic event.
- Markdown, browser-boundary, and review panes update counters without using a
web application shell.
- The model records actions, revisions, six-surface updates, and bounded terminal
line counts. Framework adapters label each measured timing stage explicitly;
element-build timing is never presented as display-present timing.
- A later PTY adapter replaces one synthetic stream without changing the UI
contract. Synthetic streams stay available for repeatable performance tests.
- The PTY actor replaces exactly one synthetic stream without changing focus or
layout contracts. Synthetic streams stay available for repeatable performance
tests. Raw lines do not claim terminal-emulation fidelity.
## Hard gates
@@ -0,0 +1,26 @@
# 0004: A bounded runtime actor owns each PTY
Status: accepted for the first local runtime slice.
The desktop UI never owns or directly polls `PtySession`. A single runtime
actor owns the PTY, child process, input ordering, resize ordering, output
sequence, and process-tree cleanup. Its command and event channels are bounded,
so a slow UI produces explicit backpressure instead of unbounded transcript
memory.
The first implementation runs this actor on a dedicated thread in the GPUI
process. That is an implementation step, not the final deployment boundary. The
commands and events remain free of GPUI types so they can move behind the
versioned local IPC connection when the standalone `lumbridge-runtime` process
arrives. Process-local session IDs are correlation IDs only; durable IDs are
assigned by the persisted runtime protocol later.
Runtime events contain ordered raw PTY bytes. The UI spike may line-frame plain
fixture output for display, but ANSI/VT parsing, screen state, cursor behavior,
scrollback, and terminal input modes belong to `lumbridge-terminal`. The UI must
not infer terminal semantics from raw strings.
Dropping the UI-side actor disconnects its bounded channels, releases an actor
blocked by event backpressure, terminates the process group through
`lumbridge-pty`, and joins the actor thread. Tests use only synthetic shell
fixtures and never provider credentials or real transcripts.