Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

UI Dashboard - Information Architecture and Desktop Shell

Information Architecture

Global Layout

Top Navigation Bar

  • Logo/brand (pam)
  • Activity feed button (right side, notification badge for recent events)
  • Orchestrator status indicator (green/red dot)
  • Hosts summary chip (online/total worker hosts — click navigates to /hosts)
  • Settings button

Main Content Area

  • Single-page application with client-side routing
  • Persistent activity feed drawer (collapsible, right side)

Page Hierarchy

1. Projects List Page (/projects)

Purpose: Overview and navigation to all projects.

Layout: Grid of project cards.

Per Project Card:

  • Project name (click to navigate to project detail)
  • Slug badge
  • Status indicator (active/archived)
  • Task count (total, broken down by status: todo/doing/done)
  • Last activity timestamp
  • Quick action button (menu: archive, settings)

Empty State: “No projects yet. Create your first project to get started.”

Sorting: Default by last activity, option to sort by name or creation date.

2. Project Detail Page (/projects/{id})

Purpose: Project work items hierarchy and Kanban board.

Layout: Split view.

Left Panel - Work Items Tree:

  • Hierarchical tree of milestones → epics → tasks → subtasks
  • Expand/collapse nodes
  • Status icons per item
  • Click to navigate to task detail
  • Filter controls (by kind, by status, by assignee)

Right Panel - Kanban Board:

  • Four columns: Todo, Doing, Done, Cancelled
  • Cards show: title, assignee badge, run count (if any), subtask count
  • Drag-and-drop between columns (PATCH status via API); legal drops follow the work-item transition table in 002-data-model.md, including a direct Todo → Done drag — a task completed without entering Doing (finished out-of-band, or its run completed while auto_mark_done is off) skips the intermediate column
  • Click card to navigate to task detail
  • “New Task” button (opens modal for quick creation)

Breadcrumbs: Projects → {project name}

3. Task Detail Page (/tasks/{id})

Purpose: Task information, run history, and live terminal pane.

Layout: Vertical sections.

Header:

  • Task title (editable inline)
  • Status badge (todo/doing/done/cancelled) - clickable to change
  • Assignee field (editable)
  • Kind badge (task/subtask)
  • Path display (parent hierarchy links)

Description Section:

  • Markdown editor/view toggle
  • Empty state: “Add a description…”

Runs Section:

  • List of runs (table: provider, session name, status, timestamps, actions)
  • “Start Run” button (opens modal: provider selection)
  • Per-run actions: logs, stop button (if running), attach button

Live Terminal Pane:

  • Embedded xterm.js terminal (read-only)
  • Connects to WS /api/v1/runs/{id}/pane/ws
  • Shows latest pane snapshot
  • Auto-updates on server push
  • Empty state: “No active terminal session”

Metadata Footer:

  • Created/updated timestamps
  • Parent/child relationship links

Breadcrumbs: Projects → {project} → {task} or Projects → {project} → {milestone} → {epic} → {task}

4. Run View Page (/runs/{id})

Purpose: Detailed run information and interactive terminal access.

Layout: Split vertical.

Top Section - Run Info:

  • Run ID (copy button)
  • Task link (navigation)
  • Provider badge (claude/codex/grok/gemini)
  • Host badge (executing worker host name; offline hosts tinted with a warning)
  • Session name (display: pam-<8hex>)
  • Status badge (pending/spawning/running/exited/failed/stopped)
  • Working directory path (on the executing host)
  • Started/finished timestamps
  • Exit code (if exited/failed)
  • Actions: stop button (if running)

Middle Section - Interactive Terminal:

  • xterm.js terminal (full interactive)
  • “Attach” button (disabled if lease held by another client)
  • “Detach” button (active when attached)
  • Single-writer lease enforcement
  • Connects to WS /api/v1/runs/{id}/attach/ws

Bottom Section - Run Logs:

  • Scrollable log history (pane snapshots over time)
  • “Download Logs” button

Breadcrumbs: Projects → {project} → {task} → Run {id}

5. Hosts Page (/hosts)

Purpose: Worker fleet overview (multi-host topology, ADR-012).

Layout: Table of worker hosts.

Per Host Row:

  • Host name + platform badge (macos/linux)
  • Status (registered/online/offline/disabled)
  • Last-seen timestamp, active run count
  • Actions: disable/enable dispatch

Empty State: “No worker hosts registered. Run pam host add <name> --platform <platform> and start pam worker on that host.”

6. Activity Feed (Global Drawer)

Purpose: Real-time event journal across all resources.

Layout: Collapsible right drawer.

Feed Items (per event from SSE stream):

  • Timestamp
  • Event topic (project.created, work_item.updated, run.started, etc.)
  • Resource links (clickable to navigate to relevant page)
  • Contextual details (e.g., “Task ‘Fix bug’ moved to Done”)

Filters: Toggle by event type (project., work_item., run.*)

Empty State: “No recent activity”

7. Command Palette (Future Ambition)

Trigger: Cmd+K (or Ctrl+K)

Purpose: Quick navigation and action execution.

Features:

  • Fuzzy search across projects, tasks, runs
  • Quick actions: “Create task…”, “Start run…”, “Move to Done…”
  • Keyboard navigation
  • Deferred to post-MVP

SPA Stack

Core Technologies

  • Leptos: Rust/WASM UI framework (CSR mode; fine-grained reactivity — no virtual DOM, no separate state library)
  • wasm-bindgen / web-sys: browser interop layer
  • xterm.js: the ONLY JavaScript dependency — browser terminal emulation has no mature Rust/WASM replacement; wrapped as a component driven through wasm-bindgen interop

State Management

  • Leptos resources/signals: server-state synchronization
    • Resources fetch projects, work items, runs; refetch on mutation
    • Fine-grained reactivity drives board and live-view updates without manual cache invalidation (replaces TanStack Query)
    • Optimistic updates for drag-and-drop board moves
  • Leptos Router: client-side routing with typed params (replaces TanStack Router)

Terminal Rendering

  • xterm.js (sole JS dependency, see Core Technologies): terminal emulator
    • ANSI escape sequence rendering
    • Read-only pane display (WS /api/v1/runs/{id}/pane/ws)
    • Interactive attach session (WS /api/v1/runs/{id}/attach/ws)
    • Canvas-based rendering (performance optimized)

Real-Time Features

  • Server-Sent Events (SSE): activity feed event stream
    • web_sys::EventSource connection to /api/v1/events/stream
    • Topic filtering support
    • Reconnect with Last-Event-ID cursor
  • WebSocket: terminal pane and attach (web_sys::WebSocket)
    • Auto-reconnect on disconnect
    • Lease state tracking for attach

Development Mode

trunk dev server:

  • Runs on port 5173 (default) with /api proxied to 127.0.0.1:PAM_PORT
  • Hot rebuild of the WASM bundle
  • CORS not needed (same-origin after proxy)

Command: trunk serve (from the SPA workspace member under web/)

Production Build

Build Process:

  1. trunk build --release compiles the WASM bundle into web/dist/
  2. Rust-embed includes dist/ in the binary
  3. Axum serves embedded files at /
  4. API routes at /api/v1 (unaffected)

Embedded File Structure:

  • web/dist/index.html/
  • web/dist/assets/*/assets/* (WASM + the xterm.js bundle)
  • Fallback: all non-API routes serve index.html (SPA routing)

Desktop Shell (Tauri v2 — Confirmed)

Shell Role: Monitoring Thin Client, Never an Execution Node

  • Monitors the central orchestrator: hosts, runs, events, live terminals
  • Views projects, work items, and other resources (board, detail, logs)
  • User actions are forwarded as API requests ONLY — the orchestrator and its workers perform all work (spawning, supervision, provider execution stay in tmux on worker hosts)
  • No local filesystem or shell capabilities required: configure Tauri capabilities with everything disabled (see 061-security.md)
  • Target platforms: macOS and Linux desktops — matching the execution-node targets (ADR-011); Windows is out of scope and mobile is excluded. The shell itself is platform-independent by construction (it only loads the orchestrator URL), so no platform-specific shell code is anticipated

Comparison Record: Electron vs Tauri v2

Decision: Tauri v2 (Accepted 2026-08-29)

Decision: Ship web-first (embedded SPA in single binary) for MVP; the desktop shell is Tauri v2 — confirmed, no longer deferred. Web-first delivery still stands; only the shell implementation is scheduled for Phase 6.

Rationale:

  1. Web-first suffices for single-operator local use case: Embedded SPA in binary already provides “app-like” experience without overhead
  2. Size and memory: OS webview reuse (5-10 MB shell) vs ~150 MB bundled Chromium
  3. Rust alignment: single-language stack; Tauri’s Rust core matches the existing architecture with no Node.js sidecar
  4. Security surface: no Node.js runtime; a monitoring-only shell needs no local capabilities

Architecture Keeps Both Viable:

  • SPA uses only standard web APIs (localStorage, fetch, WebSocket, EventSource)
  • No Electron-specific APIs (ipcRenderer, remote) or Tauri-specific APIs (invoke) in SPA code
  • Desktop shell is a thin wrapper that loads the same embedded UI
  • Optionally runs pam serve as a background process (sidecar mode)

Electron Fallback Preserved:

  • If Tauri ecosystem gaps emerge (e.g., auto-update issues on macOS), Electron remains a drop-in fallback
  • No lock-in: SPA is pure web, can be wrapped in either

Implementation Note (Phase 6):

  • Tauri app loads the orchestrator URL (PAM_API_URL — same artifact the browser uses)
  • Optionally spawns pam serve as a child process (sidecar mode) — process management only; no execution logic in the shell
  • IPC bridge for tray icon, notifications, window management
  • Rust core reused directly (no sidecar FFI needed)

Live Pane Rendering

Rendering Approach

Strategy: Server-sent full snapshots, client renders via xterm.js.

Server Behavior:

  • Monitors tmux session output
  • Detects pane changes (debounced 100ms)
  • Sends full snapshot over WS pane WebSocket
  • Includes sequence number for ordering

Client Behavior:

  • Connects to WS /api/v1/runs/{id}/pane/ws
  • Receives {type: "pane_snapshot", seq, capture, timestamp} frames
  • Clears and rewrites terminal on each frame
  • xterm.js handles ANSI escape sequences

Sequence namespace note (do not conflate): the pane seq on pane_snapshot frames and the run-signal seq carried by progress signals are two separate sequences in unrelated namespaces. The pane seq orders WebSocket snapshot frames for the terminal view; the signal seq orders repeated progress signals at the central ingest edge (030-http-api.md). Neither field is renamed — the distinction is deliberate.

Justification:

  • Full snapshot simpler than delta encoding (no diff synchronization)
  • Terminal pane size bounded (actual spawn size 220×50 ≈ 11,000 chars, ~11 KB per full snapshot)
  • xterm.js efficiently handles full rewrites
  • Delta complexity not worth it for small pane size

Throttling and Coalescing

Server-Side:

  • Source capture polling is 1 Hz (snapshots emitted only on change)
  • Coalesce rapid updates within 100ms window
  • Max 10 frames per second for the interactive attach WS relay’s frame coalescing (prevents client overload)
  • Priority to latest state (drops intermediate frames if lagging)

Client-Side:

  • Request animation frame for rendering (60fps max)
  • Skip frames if backpressure detected

Read-Only vs Attach UX Distinction

Read-Only Pane (embedded in task detail page):

  • WS /api/v1/runs/{id}/pane/ws
  • No input capability
  • Always available (no lease enforcement)
  • Purpose: Monitoring without interaction

Interactive Attach (run view page):

  • WS /api/v1/runs/{id}/attach/ws
  • Bidirectional PTY relay
  • Single-writer lease (only one client at a time)
  • Full terminal takeover
  • Purpose: Interactive debugging and intervention

Visual Differentiation:

  • Read-only pane: Smaller height, no input prompt visual cues
  • Attach pane: Full-height, clear focus border, “Attached” badge

Accessibility Considerations

  • Keyboard Navigation: All interactive elements keyboard-accessible (Tab, Enter, Space)
  • Screen Reader Support: ARIA labels on dynamic content, live regions for terminal updates
  • Color Contrast: WCAG AA compliant (dark/light mode support)
  • Focus Management: Logical tab order, visible focus indicators
  • Terminal Accessibility: xterm.js provides screen reader announcements for pane changes