CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
126 lines
5.4 KiB
Markdown
126 lines
5.4 KiB
Markdown
# Mirage Dashboard – User Stories
|
||
|
||
The dashboard is the visual control plane for `mirage`. The goal is a
|
||
desktop-class experience inspired by **Docker Desktop** (resource cards,
|
||
prominent status, persistent left rail, command bar) and the **iOS
|
||
Simulator** (single hero device card, scoped device-detail toolbar, plays
|
||
of subtle motion when state changes).
|
||
|
||
Every story has acceptance criteria. The `e2e/dashboard.spec.ts` Playwright
|
||
suite covers each one end-to-end via the same daemon binary the user runs.
|
||
|
||
## Personas
|
||
|
||
- **DevOps Diego** — runs a long-lived `mirage daemon` and uses the
|
||
dashboard to inspect profiles and clean up stale sessions.
|
||
- **Researcher Rita** — wants to launch a one-off session, attach to a
|
||
command, see its output stream, and tear it down.
|
||
- **Plugin author Pat** — needs to see what emulator backends are
|
||
installed on this host and which plugins they expose.
|
||
|
||
## 1. Overview at a glance (Diego)
|
||
|
||
**As a** dashboard user **I want** the first screen to show me how many
|
||
profiles and sessions exist, the health of each running session, and
|
||
where on disk mirage stores its data **so that** I can confirm the
|
||
daemon is healthy in under three seconds.
|
||
|
||
### Acceptance criteria
|
||
|
||
- The route `/` renders a 4-card metric strip: `Profiles`, `Sessions`,
|
||
`Healthy`, `Execs running` (last number aggregates across sessions).
|
||
- Every metric card is keyboard-focusable and links to its detail page.
|
||
- A `Storage` panel lists the five XDG-derived paths in a copy-friendly
|
||
table.
|
||
- A `System` panel shows the daemon version + the list of detected
|
||
emulator backends (each with an `installed` / `not installed` badge).
|
||
- The page polls `/api/sessions` every 3 s and updates without a full
|
||
reload.
|
||
|
||
## 2. Browse and create profiles (Pat)
|
||
|
||
**As a** plugin author **I want** to pick the emulator backend from a
|
||
dropdown (showing which are installed locally) and choose plugins from
|
||
a multi-select **so that** I never have to remember which emulator
|
||
strings the daemon accepts.
|
||
|
||
### Acceptance criteria
|
||
|
||
- `/profiles` lists every profile in a sortable table with: name, emulator
|
||
badge, nodes, GPUs/node, exec mode, description.
|
||
- A primary `New profile…` button opens a modal with:
|
||
- Name field (required, lowercased automatically).
|
||
- Emulator dropdown populated from `/api/emulators` (shows installed
|
||
badge per entry; defaults to the daemon's `default_emulator`).
|
||
- Nodes / GPUs per node number steppers.
|
||
- Exec mode segmented control (`Functional` / `Clocked`).
|
||
- Plugins multi-select fed by the chosen emulator's
|
||
`available_plugins` list.
|
||
- Description textarea.
|
||
- The modal validates the name, disables submit while inflight, surfaces
|
||
daemon errors inline, and closes on success while triggering a table
|
||
refresh.
|
||
- Each profile row exposes a kebab menu with `Duplicate`, `Edit JSON`,
|
||
`Delete` (Delete asks for confirmation in a modal, not a `confirm()`).
|
||
|
||
## 3. Launch a session and watch it boot (Rita)
|
||
|
||
**As a** researcher **I want** to start a session against a profile and
|
||
watch the health badge transition from `pending` → `starting` → `ready`
|
||
**so that** I know exactly when I can attach an exec.
|
||
|
||
### Acceptance criteria
|
||
|
||
- `/sessions` shows every session as a card (iOS-simulator-style),
|
||
not just a row: profile name, ID, age, health badge, exec count.
|
||
- Cards expose `Open`, `Stop`, and `Copy ID`.
|
||
- A persistent toolbar carries `New session…`, a profile filter
|
||
dropdown, and a `Refresh` button.
|
||
- Starting a session opens a modal pre-filled with the most-recently
|
||
used profile. While the session is starting the card shows an animated
|
||
badge and a progress shimmer.
|
||
- The status badge derives from `health.state` plus `health.healthy`
|
||
(`pending`/`starting`/`ready`/`unhealthy`/`terminal`).
|
||
|
||
## 4. Drive an exec with live output (Rita)
|
||
|
||
**As a** researcher **I want** to type a shell command, hit run, and
|
||
see streamed output in a real terminal pane (xterm) **so that** I can
|
||
iterate on a debug command without leaving the browser.
|
||
|
||
### Acceptance criteria
|
||
|
||
- `/sessions/:id` shows session metadata in a hero card, then a
|
||
two-column layout: exec list on the left, attached terminal on the
|
||
right.
|
||
- The terminal is an `xterm.js` instance bound to the daemon
|
||
`/attach` WebSocket. Resize the column → terminal resizes.
|
||
- A command palette at the bottom: command input, `+` env-var chip
|
||
input (KEY=VALUE), `keep` checkbox, `Run` button. Submitting selects
|
||
the new exec automatically.
|
||
- Each exec row shows: id, started timestamp, runtime, exit code (red
|
||
if non-zero, green if 0, neutral while running), kebab menu (`Attach`,
|
||
`Send SIGINT`, `Send SIGKILL`, `Remove`).
|
||
- The kebab is keyboard-navigable.
|
||
|
||
## 5. Trust the dashboard's status (Diego)
|
||
|
||
**As an** operator **I want** transient daemon failures (network blip,
|
||
500 from the API) to show as a toast that I can dismiss **so that** I
|
||
don't lose state when one request fails.
|
||
|
||
### Acceptance criteria
|
||
|
||
- Every page registers a global toast handler. API errors push a toast
|
||
with the HTTP status + message; toasts auto-dismiss after 6 s.
|
||
- Toasts stack bottom-right, are keyboard-dismissable (`Esc`).
|
||
- A success toast appears after profile create, session create, session
|
||
destroy, and exec remove.
|
||
|
||
## 6. Keyboard-first navigation (everyone)
|
||
|
||
- `g o`, `g p`, `g s` navigate to Overview / Profiles / Sessions.
|
||
- `Cmd/Ctrl-K` opens a command palette (out of scope for this PR, but
|
||
the layout reserves the slot in the header).
|
||
- Sidebar links are reachable via `Tab` and respect `:focus-visible`.
|