구조
ADR-0003: Workspace/UI capabilities go through a request queue serviced by the frame loop
이 페이지는 영어입니다. 하나의 언어로 유지된 사양은 하나의 내용만 말합니다.
Status: accepted (2026-10-09)
Context#
Scripts need to read the workspace (charts, symbols, timeframes) and to
change it. The state lives in App on the UI thread; egui state is not
Sync and must not be touched from a worker. TTT already applies
UI-originated actions inside App::ui and services each window's shared
state once per frame.
Decision#
- A host operation whose contract says
execution: ui_threadis turned by the bridge into aUiRequest { op, args, reply }pushed on a channel; the worker then waits for the reply, checking cancellation and a timeout. App::uicallst0_host::Bridge::service_ui(&mut port)once per frame; the app implements the narrowUiPorttrait (list charts, active chart, set a chart's symbol/timeframe). The bridge never seesApp.- The worker asks for a repaint when it enqueues a request, because the terminal does not repaint while idle.
- Components are addressed by semantic handles (
ChartRef = { epoch, id }), never by pointers or widget instances. The epoch is chosen per terminal process; a handle from another process, or for a chart that has since closed, fails with a typed error that says which.
Alternatives#
- Lock
Appstate from the worker -- requiresArc<Mutex>around state the whole UI reads every frame; contention and deadlock risk in the hottest path of the application. - Expose the palette
Commandenum directly -- internal and unversioned; binding scripts to it would freeze it.
Consequences#
- A UI operation costs at most one frame of latency plus the wait for the next repaint (normally milliseconds).
- If the window is not being drawn (minimised and not repainting), UI
requests time out with
E-HOST-UI-TIMEOUTinstead of hanging.
Amendment (2026-10-10): charts and panels#
Programs open, inspect and focus charts and the application's panels
through the same queue (workspace 0.1.2). The port does what the
terminal's own controls do and nothing else: open_chart uses the one
function the terminal's "new chart" uses (terminal_app::t0::spawn_chart);
open_panel opens only kinds from the terminal's own registry of panels a
person can open (terminal_ui::openable_panels, the Workspace window's
list). Panel handles are pane identities, stale once the pane closes. No
program reaches a widget, an id it invented, or a private type.