Skip to content

Add scoped backends and composable execution to Ghostwright - #18

Open
rauhryan wants to merge 3 commits into
spike/recording-cifrom
spike/ghostwright-backends
Open

rauhryan wants to merge 3 commits into
spike/recording-cifrom
spike/ghostwright-backends

Conversation

@rauhryan

@rauhryan rauhryan commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Ghostwright couples terminal emulation to Ghostty and routes native keyboard execution through its Promise facade. This change adds explicit backend and execution composition boundaries while preserving the existing terminal APIs.

A per-session backend factory, (options: BackendOptions) => Operation<TerminalBackend>, owns emulator acquisition and release. Ghostty remains the default and sole shipped implementation. Synchronous writes/resizes return immutable snapshots plus ordered effects; sessions retain transport, revisions, OSC pairing, CSS locators, and assertions. Live sessions, local components, and replay use the factory, and replay validates backend identity.

Keyboard execution now has a typed operation capability and an explicit driver/middleware factory. Middleware receives an argument tuple and a typed next continuation. Async and native keyboard APIs invoke the same composed operations once; native calls preserve caller context instead of crossing through the Promise facade. Session ordering, receipts, and shutdown guards remain in the driver.

TerminalProgram<T> = (terminal: ExecutionOperations) => Operation<T> supports reusable programs through terminal.run(program). captureProgram(options, body) wraps a continuation with the existing recording lifecycle. Capture-local middleware composes inside inherited middleware, nested scopes retain it, and cancellation awaits cleanup while preserving the parent session. The initial operation core covers keyboard input and capture; other APIs retain their existing adapters. No global port registry is introduced.

A scope audit against Sweatpants foundation’s Effection characterization tests also adds an explicit native withTerminal lifetime boundary, invocation-local bridges for native Promise APIs, and cancellation of legacy assertion/locator/revision waits. Native session cleanup completes before returning to a still-live caller; halting child work removes its timers and subscriptions. Documentation recommends ensure for yielding middleware cleanup and records Effection 4.2’s yielding-finally limitations.

Lifecycle verification also exposed races fixed here: preserving exit/EOF received during spawn, preventing queued commands from starting after CLOSE, and draining sidecar stdout before reporting a missing acknowledgement. README examples document backend decorators, keyboard middleware, and capture programs.

Stacked on #13 (spike/recording-ci).

Validation

  • Core suite: 146 tests passed, including 10 backend tests, 9 operation-composition tests, and 12 scope-ownership regression tests.
  • Sweatpants foundation reference suites: 83 scope/context/port/resolver tests passed.
  • Full source/example run: 163 passed; one Bash/vi example exceeded its five-second timeout. That example passed in 1.9 seconds on its focused rerun.
  • Composition coverage includes argument/result typing, middleware order and failure identity, real input transformation, native scope context, nested capture inheritance, escaped capabilities, cancellation cleanup, and interruption of blocked PTY writes.
  • Package build and Jest/Vitest runner contracts passed.
  • CSS adapter: 53 tests passed; linked UI integration: 9 tests passed.
  • Focused typecheck covering source, type tests, tests, and scripts passed, including negative type tests for middleware and program signatures. Lint has no errors; diff whitespace checks passed.

Full typecheck still reports five pre-existing Vim example errors, reproduced on the base commit. The default test discovery includes a standalone CI fixture whose journey.mjs is supplied by the CI workflow; source suites were run with explicit ./test ./examples paths. An earlier run hit the settlement test's timing-sensitive assumption that output arrives before its 10ms baseline-settlement deadline; its focused rerun and the final full suite passed. The larger Vim replay test also exceeded its five-second timeout in earlier backend verification, reproduced on the base commit.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Ghostwright CLI and Vim recordings

✅ Build + packaged CLI/Vim tests: success
PR head: edeac257015f710d241932179148c77125a9d8ad
Built revision (PR merge commit): 3e01d75039e92dcb814892a4759a7661abe72805
Test/encoding: success

Download CLI MP4
Download Vim MP4

Download all recording files — MP4, GIF, asciicast and JSON trace. Available for 14 days.

View Actions run

These tests install the Ghostwright tarball built by this run and drive a real CLI and Vim/netrw through PTYs. No UI/TTY sibling checkouts are used.

@rauhryan rauhryan changed the title Add scoped terminal backend factories to Ghostwright Add scoped backends and composable execution to Ghostwright Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant