Source commit: 309831e1e021f962c118452336776fd9a94025f9 Public tree identity: sha256:6fa95c1745579bd6256dbeb3d476db0b07c2f24aa9213b0f7783ce1adfc8aca5
208 lines
4.3 KiB
Markdown
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
|
|
```
|
|
|