---
name: hd-workspace-monitoring
description: >
  How Hydrogen Desktop monitors and manages the local workspace machine
  (`Adom-Workspace`) and code-server. Covers the 15s workspace state poll, the
  two health levels (Lima VM up, machine running + code-server reachable), the
  floaty states (Lima VM not available, machine stopped), auto-start via setup_and_start,
  auto-reload of the VS Code iframe, and the lifecycle dialog system. Read BEFORE
  touching PanelVisualStudioCode.svelte, ContainerLifecycleDialog.svelte, or any
  workspace state handling code. Trigger words: workspace stopped, lima vm not available,
  workspace monitoring, machine poll, workspace floaty, start workspace, code-server
  reachable, lifecycle dialog, workspace state, Adom-Workspace running.
---

# HD Workspace Monitoring

> This is the machine-runtime version (default). The legacy Docker equivalent
> (`HD_RUNTIME=docker`) is in the docker/ bucket.

## Architecture

Under the machine runtime the workspace is the **`Adom-Workspace` machine** (a
systemd-nspawn machine imported via `machinectl import-tar`), not a Docker container.
HD monitors workspace health at two levels:

1. **Lima VM up** — is the `hd-builder` Lima VM itself up and responding on this Mac?
2. **Workspace healthy** — is `Adom-Workspace` present AND running AND is
   code-server reachable on host port **7380**?

The second level is a real reachability check, not just "is the machine present."
A resume reality-check (after sleep, or after an HD rebuild/relaunch) requires
code-server to actually answer before HD trusts the workspace as healthy — a machine
can be running while code-server is dead.

The VS Code panel (`PanelVisualStudioCode.svelte`) polls workspace state every 15s
and shows appropriate UI for each state. These frontend components survive unchanged
from the Docker era; they now front the machine runtime via the runtime trait.

## Workspace State Poll

`PanelVisualStudioCode.svelte` calls `get_container_status` (Tauri command) every 15s.
The command dispatches through the runtime trait to the machine impl. Returns a status
struct shaped like:
```rust
pub struct ContainerStatus {
    pub docker_available: bool,    // under the machine runtime: is the Lima VM hd-builder up?
    pub image_pulled: bool,        // is the Adom-Workspace tarball/machine present?
    pub container_exists: bool,    // is the machine present (running or stopped)?
    pub container_running: bool,   // is it running AND code-server reachable on :7380?
    pub container_id: Option<String>,
    pub error: Option<String>,
}
```
The field names are inherited from the Docker era; under the machine runtime they map
onto the two health levels above (Lima VM availability, then machine-present →
machine-running + code-server-reachable).

## Floaty States

All floaties appear INSIDE the VS Code panel only — not as full-app modals.
They are draggable (grab header to move). The rest of the app (wiki tab, menu, etc.)
remains fully interactive. The old Docker floaties ("Docker Desktop not installed/
running") become Lima-VM / machine states under this runtime.

### 1. Lima VM Not Available (red dot)
- **When**: the `hd-builder` Lima VM itself is not up / not responding (level-1 health fails)
- **Message**: "The HD utility VM (hd-builder) is required but not available."
- **Action**: "Run Setup Steps" button → dispatches `hd-show-setup` event (which walks
  the user through provisioning the Lima VM)
- **Color**: Red dot in header

### 2. Workspace Stopped / Not Ready (red dot)
- **When**: the Lima VM is up but `Adom-Workspace` isn't running, or it's running but
  code-server isn't reachable on :7380 (`container_running == false`)
- **Message**: "The Adom workspace is not running."
- **Action**: "Start Workspace" button → calls `setup_and_start` Tauri command
- **Lifecycle dialog**: Shows the draggable lifecycle dialog with live setup output
- **Auto-reload**: After the machine + code-server come up, waits for code-server
  health, then reloads the VS Code iframe

There is no separate "daemon not running" middle state like Docker had — the machine
runtime has no always-on daemon to launch. Either the Lima VM is up or it isn't
(state 1), and the workspace is either healthy or it isn't (state 2).

## Auto-Start via `setup_and_start`

The "Start Workspace" path calls Tauri `setup_and_start`, which (in machine mode)
delegates to `MacosVmRuntime::setup_and_start`:
- If the machine isn't present yet, `fresh_import` = download the golden
  `adom-golden.tar.gz` (from the `adom-inc/hd-lima-image` release) + `machinectl
  import-tar Adom-Workspace` + start code-server.
- If the machine is present but code-server is down, it just (re-)starts code-server.

Importantly, code-server runs as an **HD-owned child process** (not a detached
`nohup`) — it dies with HD. So HD also **re-ensures code-server on every launch**
(look for `[macos-startup] re-ensured code-server on launch` in the log). Without that,
a freshly relaunched HD would show the machine running but the editor stuck on
"Starting AI Environment" forever, because the previous HD's code-server child was
orphaned. See [hd-workspace-lifecycle](../hd-workspace-lifecycle/SKILL.md) for the
full lifecycle detail.

## Lifecycle Dialog

`ContainerLifecycleDialog.svelte` — a draggable floating card (no background blur)
that shows live command output for start/stop/restart operations on the machine.

### Events
Listens for `hd-container-lifecycle` CustomEvents on `window`:
- `action: 'restart' | 'stop' | 'start'` — opens dialog, starts spinner
- `action: 'step', step: string` — appends a log line
- `action: 'done'` — stops spinner, shows Close button, auto-reloads VS Code
- `action: 'stopped'` — stops spinner (for stop-only operations)
- `action: 'error', message: string` — shows error state

### Title
Dynamic based on `actionType`:
- Restarting: "Workspace Restarting..." → "Restart Complete"
- Stopping: "Stopping Workspace..." → "Workspace Stopped"
- Starting: "Starting Workspace..." → "Workspace Started"
- On error: "Restart/Stop/Start Failed"

### VS Code Auto-Reload
After the `done` event, the dialog polls code-server health (`/proxy/8080/`) every 5s
for up to 2 minutes. When healthy, it reloads all iframes whose src points at
`localhost:7380` (the host-side code-server port), then shows "VS Code iframe reloaded"
and stops.

## Tauri Commands

| Command | What it does (machine mode) |
|---|---|
| `get_container_status` | Returns workspace status — Lima VM up, machine present, running + code-server reachable |
| `setup_and_start` | `MacosVmRuntime::setup_and_start` — `fresh_import` (import machine) + start code-server, up to 10 min timeout |
| `stop_container` | Stops the workspace (`machinectl terminate Adom-Workspace`) |
| `toggle_console` | Show/hide the debug console window |
| `is_console_visible` | Returns true if console window exists |

There is no `launch_docker_desktop` equivalent under the machine runtime — there's no daemon to start.

## Menu Items (Adom Menu → Workspace Section)
- **Restart Workspace** — `machinectl terminate Adom-Workspace` + re-ensure code-server; emits lifecycle events, shows dialog
- **Stop Workspace** — terminates the machine; emits lifecycle events, shows dialog, triggers stopped floaty
- **Start Workspace** — available when stopped (from floaty button or menu)

## Settings (Desktop section in Settings dialog)
- `desktop.show_console_on_startup` — boolean, default false
- `desktop.launch_on_boot` — boolean, default true (auto-start HD when the Mac logs in)

## Related skills

- [hd-workspace-lifecycle](../hd-workspace-lifecycle/SKILL.md) — import/export/remove/terminate, the never-do-a-global-teardown rule, control endpoints
- [hd-container-stats](../hd-container-stats/SKILL.md) — the title-bar CPU/RAM bars and `workspace_stats()` probe
- [hd-networking](../hd-networking/SKILL.md) — port 7380 code-server, control port 47084
