Files
lumbridge-code/docs/UI_SPIKE_SCORECARD.md
T
Metal AgentandClaude Opus 5 b6dc70f9fa Give the elements that carry meaning something to say
The adapter is only worth having if the call sites exist, so this wires the
ten elements `UX_VERTICAL_SLICE.md` actually names and stops there. The
shell root is an application; the sidebar, its row list and the workspace
are named regions; every workspace panel is a pane carrying its label, its
execution target, its waiting state and whether it owns the keyboard; every
live terminal surface is a terminal; the command palette and the add-panel
chooser are dialogs; the footer's usage strip is a status. Seven elements
gained a stable GPUI id along the way, because an element worth naming to a
screen reader is an element worth keeping state on.

The other 137 divs are left alone deliberately. Fixed-width slots, meters,
chips, borders and painted terminal cell runs have no identity to hang a
node on, and publishing 80x24 nodes a frame would be a tree nobody can
navigate and a cost on every repaint.

No new strings were invented for the screen reader where the model already
had one. `describe()` labels each sidebar row -- that is its caller, so its
`#[allow(dead_code)]` is deleted rather than carried, as decision 0023
requires. The three words in a pane header's corner and the three words its
description leads with now come from one function. The two lines a pane
header prints about where it runs and what its process is doing moved out of
`pane_context` into `pane_header_lines`, because the pane's semantic node is
built one level up in `workspace_panel` and recomputing them there would
have meant two expressions that agree today and disagree after the first
edit. The add-panel chooser's heading and its accessible name are one
constant.

Four labels are new strings, because nothing on screen names these areas:
"Lumbridge", "Workspace", "Sidebar" and "Harness usage". Each is the name
the code and the docs already use for the thing it labels.

The scorecard's accessibility row now reads fail rather than a hedge. The
call sites are wired; the semantics are absent, because the adapter no-ops.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPYebLiN2w4TqnHUYGdECq
2026-09-01 13:14:01 -07:00

133 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Native UI spike scorecard
The GPUI and Floem programs under `spikes/` consume the same six-pane fixture.
No product framework decision is accepted until both rows contain measurements
from macOS and Linux and the hard gates pass.
| Criterion | Hard gate | GPUI | Floem |
|---|---:|---:|---:|
| Builds on macOS Apple Silicon | yes | pending | pending |
| Builds on Ubuntu | yes | conditional | pass |
| Builds on Omarchy/Arch | yes | pending | pending |
| Dependency/license closure permits Apache-2.0 distribution | yes | pending | pending |
| Keyboard navigation + AccessKit tree | yes | fail: keyboard passes and the call sites are wired, but the adapter no-ops on 0.2.2, so no accessibility tree is produced | fail: no AccessKit integration at pinned revision |
| IME and composed Unicode input | yes | framework API exists; end-to-end pending | editor API exists; end-to-end pending |
| Isolated system browser child | yes | pending | pending |
| Cold startup, p50/p95 | record | pending | pending |
| Idle RSS / six-stream RSS | record | pending | pending |
| Key-to-present p50/p95 | record | pending | pending |
| Six-stream frame p95/p99 | record | pending | pending |
| Release binary/package size | record | pending | pending |
| Native menu/window/clipboard/drag-and-drop | review | pending | pending |
| API clarity and maintenance burden | review | pending | pending |
The current programs establish dependency, build, launch, and interaction
baselines. GPUI now routes a real PTY through a VT engine and keyboard encoder,
paints coalesced styled cell runs and cursor shapes, and derives PTY rows/columns
from the 60% terminal region inside each responsive one/three/five-panel layout
when the window or attached panel count changes. Retained-history
page/top/bottom navigation is wired. Panel detach/reattach keeps background
surface updates alive and exposes detached sessions in the sidebar. Text
selection, mouse modes, a native Markdown editor, and one isolated browser child
remain.
## Ubuntu baseline — metal, 2026-08-31
Host: Ubuntu 24.04 x86_64, Rust 1.94.1. Both candidates used the same 1280×800
six-pane fixture and were launched under the active X11 desktop.
| Observation | GPUI 0.2.2 | Floem `778bb5f2` |
|---|---:|---:|
| `cargo check` from downloaded dependency cache | 20.76 s, 1.04 GiB max RSS | 24.26 s first attempt + 4.06 s after enabling required editor feature, 753 MiB max RSS |
| Debug executable link | pass with a user-local linker symlink for installed `libxkbcommon-x11.so.0` | pass |
| Debug executable size | 442 MiB | 475 MiB |
| Native window launch and six-pane render | pass | pass |
| Root workspace CI | 8/8 tests, strict Clippy and doctests pass in 10.79 s | shared result |
These are cold-development baselines, not startup, release-size, or runtime
performance numbers. GPUI's Ubuntu row remains conditional because the host has
the runtime `libxkbcommon-x11.so.0` but lacks the unversioned development linker
name normally supplied by `libxkbcommon-x11-dev`. Floem current main also
requires its `editor` feature for the style/label modules used by this shell;
that feature is now explicit in the spike. Neither build result by itself
decides the UI stack.
## Accessibility gate and provisional direction
The published `gpui 0.2.2` used by the visual shell has focus and keyboard
actions but does not expose the current AccessKit element API. An isolated probe
therefore pins GPUI directly to Zed commit
`ce48461eaadd16c65c31f835511ab96bd3b6e746` with its matching Rust 1.97.1
toolchain. The real element wiring compiles with stable accessibility IDs,
workspace/pane/terminal roles, selected state, focus tracking, and a needs-input
description. The same probe installs real `EntityInputHandler` and
`ElementInputHandler` implementations and tests marked-text commit, a composed
accent, and a multi-codepoint emoji without splitting UTF-8. Three deterministic
tests pass. AT-SPI/OS IME on Linux and VoiceOver/IME on macOS remain end-to-end
gates.
### Where the adapter has got to, and what it does not do
`apps/lumbridge/src/a11y.rs` is the adapter decision 0017 promised and never
wrote, landed as the first stage of decision 0023. Ten elements now declare what
they mean — the shell root, the sidebar and its row list, every sidebar row,
the workspace region, every workspace pane, every live terminal surface, the
command palette, the add-panel chooser, and the footer's usage strip — using the
role, label, description, selected-state and stable-identity vocabulary the probe
proves exists at Zed `ce48461e`. `sidebar::model::describe`, written and tested
under decision 0017 and called by nothing for the whole life of that record, is
now what labels a sidebar row, and its `#[allow(dead_code)]` is deleted.
**The gate is still failed, and this work does not move it.** The adapter's
bodies take the value they are given and drop it, because published `gpui 0.2.2`
has no AccessKit dependency to hand it to. Nothing reaches AT-SPI or VoiceOver;
there is no accessibility tree to inspect. What has changed is that the four
facts `UX_VERTICAL_SLICE.md` requires — which pane, its selected state, its
execution target, its waiting state — are now derived in one tested place
instead of being absent from the code entirely, so stage 5 of decision 0023 is a
change to one file rather than a pass over the renderer. Eight unit tests cover
the derivation. None of them is an assistive-technology claim.
The pinned Floem revision has keyboard focus and editor IME plumbing but no
AccessKit dependency or semantic tree. That fails Lumbridge's accessibility
gate without a maintained framework fork or adapter. The provisional direction
is therefore **GPUI-first using current Zed GPUI behind a narrow Lumbridge UI
adapter**. The published GPUI shell remains the lightweight interaction and
visual benchmark until the dependency/toolchain migration is accepted.
This is not the final cross-platform release decision. Current-GPUI validation
on amd-server required a 624 MiB Rust 1.97.1 toolchain, a 691-package lockfile,
and 4.4 GiB of debug artifacts across check, test, Clippy, and build. Packaging,
license closure, IME, platform assistive technology, browser parenting, macOS,
and Omarchy still have to pass.
The comparable Floem shell passes build, test, strict Clippy, live rendering,
streaming, mouse selection, and numeric pane selection on metal. Its command
palette opens through the visible clickable affordance and uses Floem's native
`TextInput`, but Ctrl/Cmd+K did not reach the handler in the X11 automation
probe. That unresolved focus/event-routing behavior is another current strike
against adopting Floem; it is recorded rather than hidden behind the clickable
fallback.
## Measurement semantics
Both renderers retain the same all-deterministic six-surface action stream for
comparison. GPUI now layers an unbounded, SQLite-snapshotted panel registry over
that benchmark and presents one, three, or five vertical panels, each with its
own 20/60/20 context/work/decision composition. The Add Panel chooser creates
Terminal, Browser, Markdown, and Review panels beside the selection or
reattaches an existing session. Every Terminal panel receives an independent
actor-owned VT session; the three seed non-terminal surfaces keep deterministic
updates running. Counters
separate external PTY batches/lines from total model updates. The GPUI footer's
usage zone is no longer a constant string: it renders a `lumbridge-core`
projection for the selected panel's account profile, with a provenance chip and
explicit unavailable phrases, and its sidebar attention count and runtime rows
are derived from live panel and ledger state. The Floem shell still renders the
static footer fixtures, so the two candidates are no longer comparable on that
strip. The GPUI footer also
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.