# ADR 0038: Non-Blocking Native Dialog Broker ## Status Accepted ## Context Blacksite opens native file, folder, Save As, and confirmation dialogs from editor workflows. Calling the synchronous `rfd` API inside a Bevy/egui system stops window event processing until the dialog returns. On Wayland compositors this can trigger an application-not-responding prompt even though the native dialog is operating normally. Path selection precedes stateful main-thread work such as scene serialization, imports, history changes, prefab relinking, collaborative revision checks, and project activation. Moving those operations to arbitrary worker threads would violate ECS ownership and weaken existing guards. ## Decision The editor owns one `NativeDialogBroker` resource. A workflow submits native dialog construction and a typed completion callback. The broker runs only the blocking native dialog wait on a worker thread, then queues the result. An exclusive Bevy system drains the queue and invokes each completion exactly once with `&mut World`. Only one native dialog may be active. Additional requests fail immediately with explicit status. Cancellation is delivered as the dialog API's empty or cancel result and remains non-mutating. Initiating workflows capture stable entity IDs or paths and revalidate them before applying a result. Native confirmation dialogs use the same broker. A requested close or project switch proceeds only after the confirmation result and any required save have completed; an incomplete asynchronous save pauses the transition rather than discarding content. ## Consequences - Blacksite continues rendering and answering compositor pings while native dialogs are open. - Project and ECS mutations remain on the Bevy main thread with their existing history, validation, and collaborative file-revision boundaries. - Workflows split dialog acquisition from result application and handle stale initiating state. - The one-dialog policy is intentionally global across the editor and Project Browser. - A future platform-specific async backend can replace the worker without changing completions.