# Disasmer Operator Panel Notes Disasmer programs should be able to expose a small human-facing UI through the coordinator web page. This is useful for long-running build systems, repo watchers, task dashboards, and manual controls. ## Core idea ```text Disasmer program renders UI state Coordinator displays it in a webpage Human clicks/types/selects Coordinator sends typed events back to the program Program reacts by spawning, stopping, restarting, or debugging tasks ``` The browser is only a view. The Disasmer program owns the state and logic. ## Terminology ```text Operator Panel A small immediate-mode UI exposed by a virtual process. Widget A built-in UI element such as a button, textbox, dropdown, progress bar, or task table. UI Event A typed event sent from the coordinator webpage back into the virtual process. ``` ## Example use case A long-running build program can expose: ```text repo picker branch dropdown parallelism input start/stop buttons running task table progress bars log tail artifact links debug/restart/cancel buttons per task ``` This makes the build system controllable without external YAML, dashboards, or proprietary CI UI. ## Rust sketch ```rust use disasmer::prelude::*; #[disasmer::main] async fn main() -> Result<()> { let panel = ui::panel("Repo builder").await?; let mut cfg = BuildConfig { repo: None, branch: "main".into(), parallelism: 4, }; let mut builds = BuildState::load().await?; loop { let action = panel.draw(|ui| { ui.heading("Repo builder"); cfg.repo = ui.git_repo_picker("Repository", cfg.repo.clone()); cfg.branch = ui.git_branch_dropdown("Branch", cfg.repo.as_ref(), &cfg.branch); cfg.parallelism = ui.number("Parallel builds", cfg.parallelism); if ui.button("Start watcher").clicked() { ui.emit(Action::Start(cfg.clone())); } if ui.button("Stop").clicked() { ui.emit(Action::Stop); } ui.progress("Current build", builds.current_progress()); ui.task_table("Running tasks", builds.running_tasks()); ui.log_tail("Recent output", builds.log_stream()); }).await?; match action { Some(Action::Start(cfg)) => builds.start_watcher(cfg).await?, Some(Action::Stop) => builds.stop_watcher().await?, Some(Action::RestartTask(id)) => builds.restart_task(id).await?, Some(Action::CancelTask(id)) => builds.cancel_task(id).await?, None => {} } builds.poll().await?; } } ``` ## What this proves A Disasmer build system can be expressed as one normal program containing: ```text build logic repo watching branch selection parallel task spawning human controls progress reporting logs artifact links debug hooks ``` The build loop is just normal program logic. Build tasks are virtual threads. ## Task controls A task table should support simple per-task actions: ```text Debug Restart Cancel View logs Open artifacts ``` Example row: ```text commit abc123 | linux-x64 | running | 72% | Debug | Restart | Cancel ``` ## Debugging behavior When the virtual process is running: ```text operator panel is interactive button clicks become UI events program handles events normally ``` When the virtual process is stopped in a debugger: ```text panel shows last rendered state program-level UI events are disabled or queued control-plane actions may remain available ``` For the MVP, prefer: ```text running process -> interactive panel stopped process -> read-only panel plus control-plane actions ``` This avoids executing program code while the debugger says the process is stopped. ## MVP widget set Start with: ```text text heading button textbox number input checkbox dropdown progress bar task table log tail artifact link git repo picker git branch picker ``` Avoid initially: ```text custom HTML custom JavaScript complex layout live charts drag/drop workflow editors browser-side business logic ``` ## Design rule The operator panel should stay boring, typed, and immediate-mode. ```text One source file can define: distributed execution build orchestration environment selection filesystem/artifact behavior debugging behavior human operator UI ```