clusterflux-public/operator_panel_notes.md
Disasmer release dry run f22d0a5791 Public dry run dryrun-309831e1e021
Source commit: 309831e1e021f962c118452336776fd9a94025f9

Public tree identity: sha256:6fa95c1745579bd6256dbeb3d476db0b07c2f24aa9213b0f7783ce1adfc8aca5
2026-07-03 16:07:13 +02:00

208 lines
4.3 KiB
Markdown

# 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
```