No description
  • Rust 97.5%
  • GLSL 1.9%
  • Shell 0.4%
  • Just 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-28 15:56:43 -04:00
.cargo Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
protocols Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
scripts Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
shaders Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
src Toggle the native shell from OpenXR controller system buttons 2026-09-28 15:43:52 -04:00
.gitignore Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
build.rs Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
Cargo.lock Run the native shell as a tracked Monado OpenXR overlay 2026-09-28 13:26:19 -04:00
Cargo.toml Run the native shell as a tracked Monado OpenXR overlay 2026-09-28 13:26:19 -04:00
justfile Add Vulkan Wayland compositor with unified dashboard 2026-09-27 22:59:38 -04:00
README.md Record successful Frame controller hardware probe 2026-09-28 15:56:43 -04:00

ambit-compositor

ambit-compositor is AmbitOS's Rust Wayland compositor with Vulkan rendering, with two presentation backends:

  • Steam Frame: a tracked OpenXR overlay shell. Monado owns tracking, optical calibration, reprojection and physical display presentation; Ambit owns the Wayland desktop and login-seat input.
  • Desktop development: a normal Wayland or X11 window with an undistorted perspective view, simulated head pose, and an independent spectator camera. No headset, calibration, login-seat takeover, or OpenXR runtime is required.

Both render a 1280×800 desktop of native Wayland application windows and optionally the GPU-rendered System UI. Ambit owns window focus, stacking, move/resize, minimize, maximize/fullscreen, restore and close. Native desktop and dock are world-locked quad layers, recentered in front of the wearer whenever the dashboard is shown. The current Frame runtime provides orientation tracking (3DoF), not positional tracking. Desktop development retains simulated head/world placement and spectator controls.

Architecture

greetd / logind → libseat → ambit-compositor
                            ├─ libinput → Wayland seat → application windows
                            ├─ private session D-Bus → application activation + owned tray
                            ├─ SHM / DMA-BUF desktop layers + client cursor
                            ├─ privileged System UI → GPU layers + spatial handle
                            └─ Vulkan quad swapchains → Monado/OpenXR → headset panels
  • src/session.rs: libseat input-device ownership, restricted libinput access and explicit disable acknowledgement. Ambit does not acquire a DRM display.
  • src/main.rs: backend selection, native seat/input event loop, compositor wakeups and VT switching.
  • src/desktop.rs: winit window, simulated viewing controls, spatial pointer mapping and desktop event scheduling.
  • src/process.rs: private session bus, sanitized application/UI launch environments, process groups, child status and signal handling.
  • src/compositor.rs: public application socket, XDG surfaces/popups, GPU/SHM buffers, synchronized subsurfaces, keyboard/pointer, selections and cursor composition.
  • src/window_server.rs: window identity, geometry, stacking/focus, interactive move/resize, state transitions, constraints and parent/modal relationships.
  • src/system_ui.rs and src/system_ui_server.rs: immutable desktop/UI snapshots, private authenticated shell connection, layer-shell and the Ambit window-management/dock/lifecycle protocol.
  • src/scene.rs: metre-scale scene, head/world reference spaces, independent head/spectator poses, and pointer ray intersection. Coordinates are right-handed: +X right, +Y up, -Z forward.
  • src/xr.rs: OpenXR overlay session, runtime-created Vulkan device, swapchains, predicted head pose and frame submission.
  • src/monado.rs: dynamically loaded libmonado client-state queries for primary-application visibility policy.
  • src/vulkan.rs, shaders/scene.vert and shaders/desktop.frag: shared scene rendering, offscreen OpenXR targets and ordinary window presentation.
  • src/vulkan_ui.rs and shaders/surface.frag: desktop/UI layer rendering, direct DMA-BUF import, synchronized premultiplied-alpha composition and the compositor-owned rounded drag handle.

Native scheduling follows xrWaitFrame even when hidden or unchanged. Desktop/UI pixels are redrawn only when dirty; previously released swapchain images are resubmitted at current world poses. A GPU fence completes both quad passes before release. System UI uses a transparent premultiplied-alpha layer; the desktop is opaque.

On seat disable, Ambit stops System UI, suspends input, releases held keys/buttons and submits no layers. The OpenXR session and GPU resources remain alive; Monado owns display lifecycle. Activation resumes input and relaunches configured System UI. The windowed backend retains event-driven rendering and FIFO presentation without present_wait.

Local development

Install just, zsh, Rust/Cargo, glslangValidator, a Vulkan driver/loader, dbus-daemon, and the development libraries listed below. Install foot as the default Wayland client (sudo pacman -S --needed foot on Arch). A missing initial application executable is a startup error; an application exiting after launch does not close the compositor.

From the standalone compositor checkout:

just build
just run

No workspace checkout is required for native development. Direct cargo build --release also uses build/, configured by .cargo/config.toml. From the AmbitOS workspace root, just compositor build and just compositor run are equivalent conveniences. just compositor lists commands without building or launching anything. The executable implementations are scripts/{build,build-frame,run,test,fmt,check}.zsh; they also work when invoked from another directory.

run uses cargo run --locked --release -- --windowed and forwards all arguments to the compositor. For example, just -- compositor run --help prints runtime help without creating a window; just -- compositor run --window-system x11 -- foot -o 'font=monospace:size=20' selects X11 and a client command. Cargo build/test options and Cargo fmt options are forwarded by their respective recipes; use just -- compositor fmt -- --check to check formatting without changing files. just compositor check checks formatting and then runs the native release tests; any arguments to check are forwarded to test.

Or run the already-built executable:

build/release/ambit-compositor --windowed

The outer window automatically prefers Wayland. Use --window-system x11 or --window-system wayland to select explicitly; this option requires --windowed. A custom initial Wayland application command follows --, for example -- foot -o font=monospace:size=20. Applications receive Ambit's public WAYLAND_DISPLAY and private DBUS_SESSION_BUS_ADDRESS, not the outer desktop's display/bus. D-Bus activation uses the same environment. Inherited shell-only fds, X11 display and outer Gamescope bypass variables are removed from child environments.

Control Effect
F1 Toggle application input / camera controls
F2 Switch simulated Head / independent Spectator view
F3 Switch head-locked / world-locked plane; entering world-lock freezes its current pose
F4 Reset both poses and placement, keeping the selected view/anchor
F5 Show/dismiss the configured dock
F6 Show/dismiss the entire dashboard, preserving layout and dock preference
Left-drag the rounded dashboard grip Move the window stack and dock together
Alt+Tab / Alt+Shift+Tab Cycle application windows
Alt+F4 Close the focused application window
Alt+left-drag / Alt+right-drag Move / resize an application window
Client titlebar/border gestures Native client-side move, resize, maximize and close
Mouse, in camera mode Look around
WASD, in camera mode Move the selected view
Q / E, in camera mode Move down / up in camera coordinates
Shift, in camera mode Move faster
Escape, in camera mode Release capture and return to application input
Ctrl+Alt+Escape or window close Exit ambit-compositor and terminate its managed clients

F1–F6 are reserved except Alt+F4, which closes a window. Outside camera mode, typing, clicks and scroll target application windows or System UI. Transparent UI regions pass input through; the grip consumes its own drag gesture. Active pointer drags stay on their originating plane across overlays and edges. Pointer targeting uses the same planes as rendering, including spectator view. Losing window focus releases held client input, ends dashboard dragging and exits camera mode. Hiding the dashboard releases held application input and removes its surfaces from rendering and input targeting; showing it restores the remembered window focus.

The title identifies the simulated view and input mode. The window has a 70-degree vertical field of view, an initial simulated eye height of 1.6 m, and a metre-spaced floor grid. These are developer visualization settings, not measured tracking or a built-in environment application. In head view, a head-locked plane stays in front of you; switch to world-lock to approach or move around it. Moving the spectator never moves the simulated head.

Hosting System UI

For the compositor, hosted dock and desktop companion together, run just simulator from the workspace root. It builds both release binaries and forwards extra arguments to the compositor, for example just -- simulator --window-system x11 --width 1.8. Select the discovered instance in the companion and Connect. Closing the compositor or interrupting the launcher stops the companion as well.

To launch without the companion:

just systemui build
just -- compositor run --system-ui "$PWD/apps/systemui/build/linux/x64/release/bundle/ambit_systemui"

Both backends accept --system-ui EXECUTABLE. Omit it to run applications without the dock/tray. The UI initially appears below the desktop; F5 and its Close button dismiss it without exiting the process. F5 restores the same placement. Desktop F4 resets placement. A stopped UI can be launched again with F5 without closing applications or losing their window state.

The dashboard grip is drawn by Vulkan, not Flutter: a 120×8 logical-pixel rounded rectangle, eight pixels below the dock when expanded or below the window stack when the dock is collapsed. It remains usable without a dock client or application textures. Dragging translates the entire dashboard in its local X/Y axes; individual window positions and dock spacing are preserved. Menu/accessory panels and GTK popups follow their respective planes. Hiding the dashboard retains the dock's expanded/collapsed preference. Show dock also reveals the dashboard.

The compositor passes an authenticated socket pair as WAYLAND_SOCKET and sets AMBIT_SYSTEM_UI=1; only that connection can bind layer-shell and ambit_shell_v1. Ordinary applications use the public socket, with DMA-BUF feedback and viewporter support. The canonical window-management and metadata/lifecycle protocol is protocols/ambit-shell-v1.xml.

GPU applications and System UI require a Vulkan DRM render device with external DMA-BUF/modifier, foreign-queue and sync-file semaphore support. Advertised formats are supported packed 8-bit RGBA/BGRA modifiers, with modifier planes sharing one backing object. Imports are validated before protocol acceptance. Producer fences, Vulkan queue ownership and completion fences protect access; committed buffers stay retained through GPU completion. GTK SHM menu/cursor pixels upload only when changed. Unsupported GPUs fail explicitly when GPU import is required; there is no software or CPU-readback fallback.

Embedded System UI uses Ambit's window protocol, not KWin. Window groups expose activation, Minimize/Show, Maximize/Restore (including leaving fullscreen), and Close. Multiwindow groups open a picker; right-click, long press, Context Menu or Shift+F10 opens it for a single window. Cycling/activating windows does not dismiss the dock.

Ambit starts a private session dbus-daemon; embedded System UI owns org.kde.StatusNotifierWatcher there. Applications register StatusNotifier items normally, including D-Bus menus. Name/path aliases are deduplicated and disconnected owners removed. The initial application may exit without ending the session; menu-launched applications and activated services survive System UI restart. Standalone System UI keeps its KWin backend and consumes the host's tray watcher. Legacy XEmbed tray icons are not hosted.

Companion control channel

The desktop companion is part of System UI's existing bundle:

# From the workspace root, on your normal desktop:
just systemui control
# Or after just systemui build:
apps/systemui/build/linux/x64/release/bundle/ambit_systemui --companion

It sends compositor commands, not emulated keys. Dashboard and dock toggle/show/hide and placement/pose reset work on either backend while active. Show dock reveals the dashboard and can relaunch a stopped dock; --system-ui EXECUTABLE is required for dock commands. Windowed development also supports view/anchor toggles and captured Move/Look drag pads for the selected simulated view, without focusing the compositor window. Shift-drag in Move changes height. Mouse-up, Escape, focus loss and disconnect release capture. See companion controls for mappings and native capture requirements. Reset retains the chosen view/anchor and dashboard visibility. Native suspended sessions permit status but reject mutations until their VT is activated.

src/control.rs serves both backends through a bounded nonblocking worker. Commands execute on the owning event loop, with visibility acknowledged by the Wayland thread before replying. No socket I/O runs on the render thread; idle listeners sleep and replies wake the worker.

Options Listeners
None $XDG_RUNTIME_DIR/ambit/control-PID.sock
--control-unix PATH Specified Unix socket
--control-tcp ADDRESS:PORT --control-token-file FILE Default Unix plus TCP
Above plus --no-control-unix TCP only
--no-control-unix alone None

Use bracketed IPv6 addresses, such as [::1]:45454. Port zero selects an available TCP port; the actual address is logged. The companion discovers local default sockets or accepts a manual Unix path / TCP host, port and token.

Unix sockets use mode 0600 and same-UID peer credentials. Default runtime directories must be owned by the compositor user and private. Existing socket paths are never overwritten; cleanup removes only the instance's own inode. TCP requires an existing, owner-only, same-UID regular token file (no symlink), containing exactly 64 ASCII hexadecimal characters plus optional LF. Every TCP request, including status, must present that exact token.

TCP is plaintext, not TLS. Prefer 127.0.0.1 and SSH forwarding, or a trusted encrypted network. For token generation and SSH examples, see companion setup.

Protocol

One UTF-8 JSON line per connection, maximum 4096 bytes including LF; one JSON response line, then close. Add "token":"..." to TCP requests. There is no automatic command replay on reconnect.

{"action":"toggle_dock"}

Actions without arguments: status, toggle_dashboard, show_dashboard, hide_dashboard, toggle_dock, show_dock, hide_dock, reset_scene, toggle_view, toggle_anchor. move_view takes x, y, z in local-view metres, each finite and within ±10. rotate_view takes yaw and pitch in radians, each finite and within ±π. View/anchor/move/look commands are desktop-only. Unknown actions/fields and missing or invalid arguments fail.

Success is {"ok":true,"state":{...}}. State contains pid, backend (desktop/native), active, dashboard_visible, dock_configured, dock_running, dock_visible, tracked, view (Head/Spectator) and anchor (Head-locked/World-locked). tracked reports a valid native OpenXR head pose; it is false in desktop simulation. dock_visible is the retained dock preference; effective visibility also requires dashboard_visible. Failure is {"ok":false,"error":"..."}. A reply timeout does not prove a command was unapplied; read status after reconnecting rather than replaying a mutation. Each transport has independent connection/dispatch limits. Read, reply and write deadlines prevent an incomplete client from blocking the other listener. The API does not execute shell commands or inject arbitrary input.

Runtime-owned XR boundary

The selected architecture is runtime-owned XR, not a new OpenXR runtime inside Ambit. The XR runtime owns tracking, controller input, frame timing, reprojection and final headset presentation. Ambit owns the privileged system shell/dashboard, Wayland windows and shell policy. Environment applications remain separate OpenXR clients; they must not relay system-button input for the shell or own the dashboard's lifecycle.

The native backend requires XR_EXTX_overlay, XR_KHR_vulkan_enable2 and XR_MNDX_system_buttons. Desktop and System UI are separate quad layers in LOCAL space. Environments remains an independent primary OpenXR application: its startup automatically hides the dashboard, and its exit restores/recenters it. Manual show/toggle continues to work while that application runs. If libmonado is unavailable, automatic transitions are disabled with a warning; manual controls remain usable.

The headset's gpio-keys KEY_SELECT (353) toggles the dashboard on press and is never forwarded to Wayland clients. F6 and companion/control-channel commands use the same visibility policy. Controller Steam clicks use a dedicated OpenXR boolean action with left/right subaction paths under khr/simple_controller. Only released-to-pressed transitions toggle; initially held or inactive actions do not, and both hands pressing in one frame produce one toggle. This requires the Monado fork's system-button extension of the simple-controller profile.

For independent environment development, use Godot's standard OpenXR support with an existing runtime, Vulkan Mobile rendering, XROrigin3D / XRCamera3D, and metre-scale content. Do not bake Steam Frame distortion or sensor access into the environment.

No Ambit SDK or environment-role registration API is implemented. Shell policy stays outside environment scenes and OpenXR's graphics/tracking contract. Passthrough, positional Frame tracking and Frame controller tracking are not provided by this integration.

Build

From the AmbitOS repository root on the workstation:

rustup target add aarch64-unknown-linux-gnu
just compositor build-frame

Host tools: just, zsh, Rust/Cargo, aarch64-linux-gnu-gcc, and glslangValidator. The scripts/build-frame.zsh implementation links against the extracted ARM64 AmbitOS userspace at the sibling <platform>/build/rootfs; set AMBITOS_SYSROOT to use an independent sysroot from a standalone checkout. The sysroot needs libxkbcommon, libseat, libinput and libudev development metadata, plus the OpenXR loader for runtime loading. Native build/run/test and cross-build artifacts go to <compositor>/build unless CARGO_TARGET_DIR is set. Standard Cargo environment settings are inherited; cross-build sets the ARM64 GCC linker, cross pkg-config paths and encoded sysroot/link search flags.

The executable is:

compositor/build/aarch64-unknown-linux-gnu/release/ambit-compositor

No Rust toolchain is needed on the headset. For native numerical regression tests, install the host development packages for those libraries, then run:

just compositor test

The AmbitOS image builder also cross-compiles and installs ambit-compositor. It selects the source checkout with AMBITOS_COMPOSITOR_DIR (default: sibling compositor/) and uses that checkout's build/ unless CARGO_TARGET_DIR is set. Platform artifacts default to <platform>/build, overridden with AMBITOS_WORK_DIR; private inputs remain separate in <platform>/storage, overridden with STORAGE_DIR. See ../platform/README.md for image construction and private calibration provisioning.

Runtime and login session

Calibration belongs to Monado's Frame driver, not Ambit. Fetch this headset's private vendor inputs with just platform fetch-frame-vendor; the image/deploy tools install device_config.json and xrservice.json under ~/.config/ambitos/frame/, mode 0600. Do not commit them.

frame-dsp.service
  → greetd initial session on tty1
    → ambitos-session
      → monado-service
      → ambit-compositor → foot + ARM64 System UI

The launcher exports FRAME_CONFIG_DIR and XR_RUNTIME_JSON, waits for Monado's IPC socket, and selects the logind input-seat backend. It clears inherited display variables and sets panel brightness. Logs are under ~/.local/state/ambitos/; the runtime is stopped when the shell exits. Applications inherit the OpenXR runtime selection, including Environments launched from its installed desktop entry.

For a manual launch, use an active local login seat with Monado already running:

export XR_RUNTIME_JSON=/usr/share/openxr/1/openxr_monado.json
/usr/local/bin/ambit-compositor --distance 1.2 --width 1.0 \
  --system-ui /usr/local/lib/ambit-systemui/ambit_systemui \
  -- foot -o font=monospace:size=18

Desktop defaults: distance 1.2 m, width 1.0 m, aspect 1280:800. Monado owns eye geometry, panel orientation and distortion. The removed --calibration, --drm-device, --connector and --ipd-mm options are not accepted.

Input, exit, and recovery

  • Physical keyboard and mouse devices are discovered by libinput/udev; starting without a keyboard or pointer is supported.
  • Native mouse coordinates directly target desktop/UI pixels, independently of head movement. Dashboard dragging changes its local metre-space offset. Windowed simulation retains ray-based picking.
  • Ctrl+Alt+F1–F12 switches VT through libseat; returning resumes the same application clients.
  • F5 toggles the configured dock; F6 and the headset's Steam/KEY_SELECT button toggle the entire dashboard. These shell keys are not forwarded to clients.
  • Ctrl+Alt+Escape, SIGINT, or SIGTERM closes ambit-compositor and releases its devices. Closing the initial application does not end the session.
  • With the supplied greetd configuration, exiting reaches agreety, not another compositor. That text greeter is not a stereo VR interface.

For logs over SSH:

cat ~/.local/state/ambitos/ambit-compositor.log
sudo journalctl -u greetd -b --no-pager

To restart the autologin session over SSH:

sudo systemctl stop greetd
sudo rm -f /run/greetd.run
sudo systemctl start greetd

The runfile records that greetd already used its once-per-boot initial session. A plain service restart otherwise shows the greeter instead of autologging in. For a binary update on an AmbitOS installation, stop greetd first, install the new binary at /usr/local/bin/ambit-compositor, then reset the runfile and start greetd. No Sway fallback is installed by the new image configuration.

Runtime limits

Frame's calibrated DISTORT_BSPLINE optics and IMU fusion now live in openxr/monado/src/xrt/drivers/frame/. Ambit contains neither vendor firmware nor private calibration values. Tracking is currently 3DoF: world-lock follows head rotation, but walking/leaning is not position-tracked.

Native Wayland toplevels, popups/subsurfaces, decorations, viewports, activation and dialog relationships remain supported. Xwayland client serving, independent 3D placement of each application window, tracked Frame controller poses and passthrough are not implemented. The outer development window can run under X11/XWayland. The keyboard uses a US keymap. Fractional-scaling, cursor-shape, toplevel-icon and IME protocols are not advertised; client cursor surfaces work.

Host OpenXR composition does not prove Frame scanout or optical comfort. The historical through-lens results below belong to the previous standalone renderer. The platform QEMU script proves boot/SSH only, not physical display.

Verification

Monado overlay integration

  • Native build and Frame ARM64 cross-build succeeded; the ARM64 CLI ran under QEMU against the target sysroot. just compositor test passed all 20 tests.
  • A real host Monado service with its simulated HMD rendered Ambit's desktop and Flutter System UI as stereo quads. Control status reported native, world-locked and tracked. Hide/show/recenter and clean shell teardown worked.
  • The actual Godot Environments application became primary and automatically hid Ambit. Manual show composited the terminal and transparent dock over the loft; that choice survived subsequent primary-state polls. Exiting Godot restored the previously hidden shell.
  • The workstation preview was raised from 320×360 to 1280×1440 per eye using XRT_COMPOSITOR_SCALE_PERCENTAGE=200; this does not change Frame deployment settings.
  • just simulator ran on a private headless Gamescope/Xwayland display. Actual F5/F6 input toggled dock/dashboard; the companion connected with the additive status field and its buttons changed live visibility. Head/spectator and anchor commands worked, and the rendered desktop/dock were inspected. The outer Gamescope harness exited 139 during teardown, matching the earlier isolated-desktop verification; the simulator control socket was removed.
  • Plain debug-mode cargo test hits Smithay's negative-Size assertion in the existing resize_constraints_keep_opposite_corner_stationary test. The repository's release-mode test recipe passes; that unrelated fixture is unchanged.
  • Controller-enabled native and ARM64 builds passed. A non-visible Monado null compositor run exercised actual extension negotiation, action binding, attachment and frame-by-frame synchronization; shell status remained tracked and manual hide/show worked. Captured reports replayed through the actual Monado controller receiver produced one Steam press/release per slot. A user-paced ARM64 hardware probe then verified real left/right identity replies and Steam, select and menu press/release events on both controllers through Monado's actual device callbacks, with SteamVR stopped. Physical controller-to-shell toggling still requires booted AmbitOS.

Captures are under storage/agents/frame-monado-shell/. These host checks do not establish physical Frame scanout, headset Steam-button delivery or through-lens tracking/comfort. Those require the booted AmbitOS device.

Historical desktop window and System UI integration

The Linux release build and all sixteen Rust tests pass. Flutter analysis and the System UI Linux release build pass on the pinned SDK.

Isolated headless Gamescope/Xwayland sessions on an NVIDIA RTX 4070 Ti SUPER exercised the actual Vulkan compositor, foot, GTK4 GskVulkanRenderer applications and Flutter release app:

  • Transparent GPU rendering with Impeller enabled.
  • F5 and embedded Close dismiss/restore without restarting System UI.
  • Handle dragging moves the dock and panels while the terminal remains fixed; placement survives hide/show, and F4 resets it.
  • Launcher search receives keyboard input even while the pointer is over the terminal.
  • Native GTK tray menus open on first use, including an initially empty submenu populated by AboutToShow; selecting either fixture's action reaches its service.
  • F5 dismisses an active native popup along with System UI.
  • Compositor shutdown with a popup open exits 0. The outer Gamescope process exits 1 during Xwayland teardown with Broken pipe.
  • Multiple live application windows with keyboard focus, Alt+Tab, titlebar move/maximize, Alt move/resize and native application popups.
  • Grouped and single-window dock actions: minimize/show, maximize/restore, fullscreen restore and close; Alt+F4 closes a client, not the compositor.
  • The private tray watcher deduplicates name/path registration, dispatches a dynamically populated menu action and removes disconnected applications.
  • Real D-Bus activation starts a GPU application on Ambit's public socket and private bus without inheriting System UI's privileged fd.
  • Applications survive System UI termination; F5 relaunch restores their task list and tray registration. Exiting the initial command leaves the session alive.
  • Window cycling and dock activation preserve dock visibility.

Screenshots and event evidence are under storage/agents/window-management/; earlier spatial-UI captures are under storage/agents/systemui-compositor/. No input was sent to the user's desktop. The current compositor and Flutter UI have since been built for ARM64 and packaged into the untracked platform image. Their shared-library dependencies and the compositor CLI were exercised under QEMU user emulation; current headset rendering/input remain unverified. The headset results below are historical.

The companion revision also exercised Unix-only, TCP-only and simultaneous listeners against real GPU compositor instances. The desktop GUI changed dock visibility, relaunched a stopped dock, selected view/anchor modes, moved/looked around and reset the rendered scene. Its live status followed F5; authentication and connection failures disabled controls. Unix status remained responsive with sixteen incomplete TCP clients. Oversized requests, out-of-range movement and missing TCP credentials were rejected. Socket cleanup was observed on shutdown. The compositor and companion exited 0; the outer Gamescope harness exited 139 during teardown. Captures are under storage/agents/companion-control/. Native headset control/VT behavior has not been exercised on hardware.

Previously deployed Steam Frame build

The standalone ARM64 build preceding desktop development was exercised on XerOS with kernel 6.18.0-g8790bd420211 and stock Mesa 26.2.3 / Turnip Adreno 750:

  • Direct DSI-1 acquisition at 4320×2160, 120 Hz, with no Sway process.
  • Actual KMS framebuffer captures of the stereo terminal and client I-beam cursor.
  • Hot-plugged kernel uinput keyboard/mouse events through libinput and Ambit's Wayland seat; the terminal shell wrote the expected proof files.
  • Five seconds of continuous terminal output, followed by successful shell input, without a display-loss error.
  • Ctrl+Alt+F2 suspension and return to tty1: Vulkan presentation was recreated, the same foot/shell processes survived, and keyboard input still worked.
  • Ctrl+Alt+Escape, SIGTERM, and terminal exit: Ambit and foot stopped and greetd returned to the text greeter. The final session was then relaunched.
  • The numerical regressions and build/session shell syntax checks passed. Missing calibration was rejected before image-build side effects.

Historical evidence remains local under ~/Projects/steamframe/storage/agents/ambit-standalone/. The syscall tracer, kernel-input injector and modifier-aware framebuffer capture helper were temporary diagnostics, not compositor dependencies. No system Mesa patch was installed. The image-build integration was updated, but a complete fresh image rebuild and the boot-only QEMU smoke were not rerun for this change.

Desktop development revision

  • Native x86-64 release build and ARM64 cross-build succeeded; all five numerical tests pass.
  • An actual desktop window rendered on the workstation's NVIDIA RTX 4070 Ti SUPER.
  • Subsequent interactive verification used private Xvfb :97 + Lavapipe, private Xauthority and a separate XDG_RUNTIME_DIR, not the user's desktop.
  • A real foot client received keyboard input; camera controls did not leak movement keys. Releasing Shift through a focus loss allowed normal subsequent typing.
  • Head and spectator rendering were visually inspected. After moving only the spectator, the restored head-view image was pixel-identical with the pointer off the plane.
  • World-lock/approach and resize changed the rendered projection correctly. Mouse clicks at the plane centre before and after resize produced identical terminal mouse coordinates; an outside-plane click produced no event.
  • Scrollback, unmap/remap, two seconds of continuous output, normal terminal exit, a real WM_DELETE_WINDOW request and SIGTERM were exercised. The signal scenario left neither terminal nor shell running. An immediately failing client propagated exit status 1.
  • The Wayland window path was exercised by nesting it inside the isolated compositor and typing through to a real foot client.
  • The idle compositor used zero process CPU ticks during a one-second sample.
  • A private-calibration comparison covered 383,958 visible triangle samples: maximum old/new interpolation change 0.0084 terminal pixels, and vertex error below 0.0002 pixels.

Historical evidence remains under ~/Projects/steamframe/storage/agents/ambit-desktop/. The temporary virtual display and test processes were stopped after verification. Automated host-desktop input requires explicit user permission; use an isolated display by default.

The new ARM64 executable was cross-built but not deployed or hardware-run. Direct display reacquisition, native performance and through-lens behavior of this revision still require a deliberate headset verification session; the working installed version was left untouched.

Source rename and existing installations

The repository is now ~/Projects/ambitos, with compositor sources in compositor/ and OS sources in platform/. New builds produce only ambit-compositor; the Rust crate and logging target are ambit_compositor (for example, RUST_LOG=ambit_compositor=info,warn). There are no old-name executable or environment-variable compatibility aliases.

Existing deployed headset binaries, calibration, sysroots, images and verification artifacts have not been renamed or redeployed. The historical XerOS installation still uses its old names until an explicit redeployment or new AmbitOS image build. The runtime commands above describe the new installation, not that untouched headset. The xer login identity and password are unchanged.

The existing extracted sysroot can be reused explicitly, without moving or rebuilding it:

AMBITOS_SYSROOT="$HOME/Projects/steamframe/storage/xer-os/rootfs" \
  just compositor build-frame

Old standalone optical calibration alone is insufficient for the tracked runtime. Use just platform fetch-frame-vendor and the platform builder's --frame-secrets option to provision the complete private input set.