M8: client terminal engine (ghostty-web) and local echo #9

Open
opened 2026-10-02 00:16:05 +00:00 by jhgaylor · 0 comments
Owner

Trigger: ghostty-web passes the S1/S5 fixture corpus in a browser (phone included) and its rendering bugs are fixed upstream. S10 (2026-10-01): not met.

From PLAN.md, section "M8".


Swaps xterm.js for ghostty-web behind the BlockView terminal renderer, so
client and server run the same engine. This is Superlogical's replica model.

  • S10 (2026-10-01): the trigger is not met. See spikes/s10-ghostty-web.
    • ghostty-web (coder/ghostty-web 0.4.0) looks stalled. It embeds a
      Ghostty from December 2025, has no snapshot API, and its upgrade PR is a
      work in progress.
    • Fidelity: it matched the daemon on 6 of 7 fixtures in Chromium and
      WebKit, including emulated phones. On the seventh, it turns grapheme
      clustering (mode 2027) on by default and the daemon has it off, so emoji
      with modifiers take a different width. It also ignores OSC 4 palette
      changes. Its scrollback option is in bytes.
    • Blockers:
      • a new terminal shows stale cells from a disposed one;
      • write('') throws, and any render error stops rendering for good;
      • it answers terminal queries itself, which would double the daemon's
        replies;
      • no parser hooks (needed for OSC 133/633 marks and to swallow queries),
        no markers or decorations, no modes/onBinary, no WebGL, and no
        buffer API that keeps blanks and graphemes;
      • IME is broken for CJK and Korean, and there's no screen-reader support.
    • Upstream's own wasm (the VT core only, no renderer) builds at the
      daemon's Ghostty commit (262 KB gzipped). It decodes every fixture's
      GHOSTSNP to text identical to the daemon's. For 64k rows it's ready in
      5–20 ms, with the history in a further 70–300 ms. That is the more
      promising route:
      our own renderer, or a maintained ghostty-web, over
      upstream's wasm.
    • Re-check when ghostty-web ships a current Ghostty, or when a renderer
      over upstream wasm exists.
  • Trigger: ghostty-web passes the S1/S5 fixture corpus in a browser,
    including the phone, and its rendering bugs are fixed upstream. Re-check
    each time libghostty-rs is bumped.
  • Wire.
    • snapshot can carry GHOSTSNP, negotiated per client in hello. xterm
      clients keep formatter VT bytes.
    • Attach becomes visible-first: screen, then READY, then history newest
      first (the protocol already has part: screen|history).
  • Predictive local echo (Mosh-style), for the phone on cellular and for
    remote hosts.
    • Typed printable characters are drawn at once and underlined until the
      server's output confirms them; mismatches are rolled back.
    • It is off in alt-screen apps and when a password prompt is detected (echo
      off).
    • It's a per-host setting that is on automatically when the measured round
      trip exceeds about 80ms.
  • Done when:
    • the web client runs ghostty-web on desktop and phone, and the S1 fixture
      corpus renders identically to the daemon's plain_text();
    • a 64k-row pane is usable within 50ms of attach;
    • typing in a Fly-hosted shell from the phone on cellular feels local,
      with underlined predictions that settle correctly.
**Trigger:** ghostty-web passes the S1/S5 fixture corpus in a browser (phone included) and its rendering bugs are fixed upstream. S10 (2026-10-01): not met. _From PLAN.md, section "M8"._ --- Swaps xterm.js for ghostty-web behind the `BlockView` terminal renderer, so client and server run the same engine. This is Superlogical's replica model. - **S10 (2026-10-01): the trigger is not met.** See [spikes/s10-ghostty-web](https://git.inevitable.fyi/jhgaylor/illogical/src/branch/main/spikes/s10-ghostty-web/README.md). - **ghostty-web (coder/ghostty-web 0.4.0) looks stalled.** It embeds a Ghostty from December 2025, has no snapshot API, and its upgrade PR is a work in progress. - **Fidelity:** it matched the daemon on 6 of 7 fixtures in Chromium and WebKit, including emulated phones. On the seventh, it turns grapheme clustering (mode 2027) on by default and the daemon has it off, so emoji with modifiers take a different width. It also ignores OSC 4 palette changes. Its `scrollback` option is in bytes. - **Blockers:** - a new terminal shows stale cells from a disposed one; - `write('')` throws, and any render error stops rendering for good; - it answers terminal queries itself, which would double the daemon's replies; - no parser hooks (needed for OSC 133/633 marks and to swallow queries), no markers or decorations, no `modes`/`onBinary`, no WebGL, and no buffer API that keeps blanks and graphemes; - IME is broken for CJK and Korean, and there's no screen-reader support. - **Upstream's own wasm** (the VT core only, no renderer) builds at the daemon's Ghostty commit (262 KB gzipped). It decodes every fixture's GHOSTSNP to text identical to the daemon's. For 64k rows it's ready in 5–20 ms, with the history in a further 70–300 ms. **That is the more promising route:** our own renderer, or a maintained ghostty-web, over upstream's wasm. - Re-check when ghostty-web ships a current Ghostty, or when a renderer over upstream wasm exists. - **Trigger:** ghostty-web passes the S1/S5 fixture corpus in a browser, including the phone, and its rendering bugs are fixed upstream. Re-check each time libghostty-rs is bumped. - **Wire.** - `snapshot` can carry GHOSTSNP, negotiated per client in `hello`. xterm clients keep formatter VT bytes. - Attach becomes visible-first: screen, then READY, then history newest first (the protocol already has `part: screen|history`). - **Predictive local echo** (Mosh-style), for the phone on cellular and for remote hosts. - Typed printable characters are drawn at once and underlined until the server's output confirms them; mismatches are rolled back. - It is off in alt-screen apps and when a password prompt is detected (echo off). - It's a per-host setting that is on automatically when the measured round trip exceeds about 80ms. - **Done when:** - the web client runs ghostty-web on desktop and phone, and the S1 fixture corpus renders identically to the daemon's `plain_text()`; - a 64k-row pane is usable within 50ms of attach; - typing in a Fly-hosted shell from the phone on cellular feels local, with underlined predictions that settle correctly.
Sign in to join this conversation.
No description provided.