Adds crates/weft-appd/src/compositor_client.rs: async Tokio client that connects to the
compositor's Unix socket (/weft/compositor.sock or WEFT_COMPOSITOR_SOCKET),
retrying every 2s on failure and 500ms on write error. Incoming CompositorToAppd frames are
decoded and logged (SurfaceReady, ClientDisconnected).
Wires compositor_tx into SessionRegistry. The supervise task now sends AppSurfaceCreated
(with child PID) immediately after process spawn, and AppSurfaceDestroyed when the process
exits. All three existing supervisor tests updated to pass None for compositor_tx.
runtime.rs — process lifecycle manager:
- supervise(session_id, app_id, registry): spawns the weft-runtime child
process identified by WEFT_RUNTIME_BIN env var. If unset, logs debug
and returns immediately (no-op until runtime binary is available).
- Child process invoked as: <WEFT_RUNTIME_BIN> <app_id> <session_id>
with stdout/stderr piped, stdin closed.
- wait_for_ready(): reads stdout line-by-line; returns Ok(()) on first
line matching 'READY'; returns Err if stdout closes without it.
- 30-second READY_TIMEOUT via tokio::time::timeout; on expiry, kills
the child and transitions session to Stopped.
- On success: sets session state to Running, broadcasts AppReady to all
connected WebSocket clients via registry broadcast channel.
- drain_stderr(): async task that forwards child stderr lines to tracing
at WARN level for observability.
- On process exit: sets session state to Stopped regardless of exit code.
main.rs — wiring:
- SessionRegistry now owns broadcast::Sender<Response>; Default creates
the channel internally. Added set_state(), subscribe(), broadcast()
methods. Removed standalone broadcast_tx from run(); WS handlers
subscribe via registry.lock().await.subscribe().
- dispatch::LaunchApp spawns a tokio task calling runtime::supervise
immediately after creating the session. supervise is a no-op when
WEFT_RUNTIME_BIN is unset, so existing tests are unaffected.
Cargo.toml: added tokio 'process' and 'time' features.
Implements the weft-appd WebSocket server that allows the system-ui.html
page running inside Servo to send requests and receive push notifications
without requiring custom SpiderMonkey bindings.
ws.rs — WebSocket connection handler:
- Accepts a tokio TcpStream, performs WebSocket handshake via
tokio-tungstenite accept_async.
- Reads JSON Text frames, deserializes as Request (serde_json), calls
dispatch(), sends Response as JSON Text.
- Subscribes to a broadcast::Receiver<Response> for server-push
notifications (APP_READY, etc.); forwards to client via select!.
- Handles close frames, partial errors, and lagged broadcast gracefully.
main.rs — server changes:
- broadcast::channel(16) created at startup; WebSocket handlers
subscribe for push delivery.
- TcpListener bound on 127.0.0.1:7410 (default) or WEFT_APPD_WS_PORT.
- ws_port() / write_ws_port(): port written to
XDG_RUNTIME_DIR/weft/appd.wsport for runtime discovery.
- WS accept branch added to the main select! loop alongside Unix socket.
ipc.rs — Response and AppStateKind now derive Clone (required by
broadcast::Sender<Response>).
system-ui.html — appd WebSocket client:
- appdConnect(): opens ws://127.0.0.1:<port>/appd with exponential
backoff reconnect (1s → 16s max).
- On open: sends QUERY_RUNNING to populate taskbar with live sessions.
- handleAppdMessage(): maps LAUNCH_ACK and RUNNING_APPS to taskbar
entries; APP_READY shows a timed notification; APP_STATE::stopped
removes the taskbar entry.
- WEFT_APPD_WS_PORT window global overrides the default port.
New deps: tokio-tungstenite 0.24, futures-util 0.3 (sink+std),
serde_json 1.
New crate implementing the application daemon entry point:
- crates/weft-appd/Cargo.toml: tokio (current-thread runtime), anyhow,
sd-notify, tracing dependencies
- crates/weft-appd/src/main.rs: async run() resolves IPC socket path
from WEFT_APPD_SOCKET or XDG_RUNTIME_DIR/weft/appd.sock; stubs for
AppRegistry, IpcServer, CompositorClient, RuntimeSupervisor,
CapabilityBroker, ResourceController per WEFT-OS-APPD-DESIGN.md;
sd_notify(READY=1) to be sent after IpcServer bind + CompositorClient
connect
- infra/systemd/weft-appd.service: Type=notify, Requires+After
weft-compositor.service, After servo-shell.service
Also fix two winit backend issues that were present in the working tree:
- remove spurious mut on display binding (never mutated after init)
- wrap std::env::set_var in unsafe block (required since Rust 1.80)