diff --git a/docs/agent-lifecycle/approvals.md b/docs/agent-lifecycle/approvals.md index c0cebf14..25aa1ab4 100644 --- a/docs/agent-lifecycle/approvals.md +++ b/docs/agent-lifecycle/approvals.md @@ -448,7 +448,7 @@ Two visible consequences: on every `rebuild_queue_changed` tick), not on the approvals panel (which already moved the row to "approved"). A long meta-update cascade renders as a parent DAG with one child rebuild per affected - agent — see `docs/web-ui.md` for the layout. + agent — see `docs/web-ui/dashboard.md` for the layout. - **Cancellation**: the dashboard's *× cancel* button on a still-queued DAG calls `POST /api/rebuild-queue/{id}/cancel`, which flips it to `Cancelled` before any node runs (and fails the approval row instead @@ -485,7 +485,7 @@ agent. The dashboard deep-links into this org — a `config repo` link per container row and a `review PR on forge` link per config-PR -approval card. See `docs/web-ui.md`. +approval card. See `docs/web-ui/dashboard.md`. ### Submitting agent's view of config repos diff --git a/docs/process/conventions.md b/docs/process/conventions.md index a8cc4d41..aafcd2b3 100644 --- a/docs/process/conventions.md +++ b/docs/process/conventions.md @@ -111,7 +111,7 @@ JSON line-delimited over unix sockets in both directions (host admin / manager / agent). SSE streams (`/dashboard/stream` on hive-c0re, `/events/stream` on the per-agent web UIs) are `text/event-stream`; each frame carries a `seq` field for the snapshot-dedupe dance -(see `docs/web-ui.md`). Request/response types live in `hive-sh4re` +(see `docs/web-ui/shape.md`). Request/response types live in `hive-sh4re` — change them in one place. The dashboard event vocabulary lives in `hive-c0re::dashboard_events::DashboardEvent`. diff --git a/docs/web-ui.md b/docs/web-ui.md deleted file mode 100644 index 877322a6..00000000 --- a/docs/web-ui.md +++ /dev/null @@ -1,59 +0,0 @@ -# Web UI - -Two web surfaces share the same skeleton: the dashboard (port 7000) -and the per-agent UIs (each container's port is a deterministic hash -in :8100-8999 — see -[`gotchas.md#web-ui-ports-collide-on-hash`](process/gotchas.md#web-ui-ports-collide-on-hash) -for the mechanics and the collision caveat). -Both are SPAs — `GET /` returns a static shell, `/api/state` -returns JSON, JS renders. No full-page reloads. - -This doc has been split for readability. Pick the section you need — -or, if you're the operator looking for how to actually _use_ the -dashboard rather than how it's built, start at -**[web-ui/README.md](web-ui/README.md)** instead. - -- **[Shape (shared by both)](web-ui/shape.md)** — shared SPA - skeleton, SSE multiplexing, terminal pane, listener bind, - per-agent relative paths, `data-async` form pattern, side panel, - atomic repaint. -- **[Dashboard layout](web-ui/dashboard.md)** — tab contents - (SW4RM, Y3R C4LL, P3RM1SS10NS, SCH3DUL3S) + standalone pages - (C0R3 `/core.html`, BU1LDS `/builds.html`, L0GS `/logs.html`, - CR3D3NTIALS `/credentials.html`), container row, - topology tree, selection bar, approval card, browser - notifications, dashboard endpoints + event channel. -- **[Per-agent page](web-ui/agent.md)** — header, main terminal, - composer, side panel + inbox, live view, slash commands, - per-agent endpoints, stats page. -- **[CSS theme variables](web-ui/css-vars.md)** — the Catppuccin - Mocha custom properties declared once in `base.css` and the rule - that per-page stylesheets reference (never redeclare) them. -- **[swarm-ui design guide](web-ui/design-guide.md)** — visual - language, motion, theming, error-UX, and component-first principles - for the swarm-level Preact app specifically (not this doc's - dashboard/agent UIs). `/components` on a running swarm-ui is the - companion living demo of every primitive it references. - -## Reading paths - -- **"How does the dashboard SPA stay live without polling?"** → - [`web-ui/shape.md`](web-ui/shape.md) (SSE multiplexing, - Worker-death self-heal, atomic repaint). -- **"What does a container row contain?"** → - [`web-ui/dashboard.md`](web-ui/dashboard.md) (Container row, - Topology tree, Selection bar). -- **"What endpoints does the dashboard expose?"** → - [`web-ui/dashboard.md`](web-ui/dashboard.md) (Dashboard - endpoints, Dashboard event channel). -- **"How does the per-agent terminal render tool calls?"** → - [`terminal-rendering.md`](web-ui/terminal-rendering.md) (full row - taxonomy + dispatch walkthrough); for a high-level summary see - [`web-ui/agent.md`](web-ui/agent.md) (Per-stream rendering). -- **"What slash commands does the agent accept?"** → - [`web-ui/agent.md`](web-ui/agent.md) (Terminal-embedded prompt). -- **"What are the per-agent HTTP endpoints?"** → - [`web-ui/agent.md`](web-ui/agent.md) (Per-agent endpoints). -- **"Which CSS variable do I use / where are colours defined?"** → - [`web-ui/css-vars.md`](web-ui/css-vars.md) (Palette, single-source - `base.css` rule). diff --git a/docs/web-ui/README.md b/docs/web-ui/README.md index 04c989c3..4fd2e8ee 100644 --- a/docs/web-ui/README.md +++ b/docs/web-ui/README.md @@ -85,12 +85,49 @@ that agent's config repo. ## More depth +Both the dashboard and the per-agent pages are SPAs sharing one +skeleton: `GET /` returns a static shell, `/api/state` returns JSON, +JS renders — no full-page reloads. + - **[Dashboard layout](dashboard.md)** — every tab and standalone page, in full implementation detail: endpoint shapes, event wiring, exact badge-derivation rules. - **[Per-agent page](agent.md)** — the per-agent terminal, composer, side panel, slash commands, and per-agent endpoints. - **[Shape (shared by both)](shape.md)** — the SPA skeleton, SSE - multiplexing, and other plumbing shared across every page. -- **[CSS theme variables](css-vars.md)** — the colour system, for - anyone touching the frontend's CSS. + multiplexing, terminal pane, listener bind, per-agent relative + paths, `data-async` form pattern, side panel, atomic repaint. +- **[CSS theme variables](css-vars.md)** — the Catppuccin Mocha custom + properties declared once in `base.css` and the rule that per-page + stylesheets reference (never redeclare) them. +- **[swarm-ui design guide](design-guide.md)** — visual language, + motion, theming, error-UX, and component-first principles for the + swarm-level Preact app specifically (not this page's dashboard/agent + UIs). `/components` on a running swarm-ui is the companion living + demo of every primitive it references. + +### Implementation reading paths + +Task-oriented jumps straight to the relevant section, for when you're +touching the code rather than using the UI: + +- **"How does the dashboard SPA stay live without polling?"** → + [`shape.md`](shape.md) (SSE multiplexing, Worker-death self-heal, + atomic repaint). +- **"What does a container row contain?"** → + [`dashboard.md`](dashboard.md) (Container row, Topology tree, + Selection bar). +- **"What endpoints does the dashboard expose?"** → + [`dashboard.md`](dashboard.md) (Dashboard endpoints, Dashboard event + channel). +- **"How does the per-agent terminal render tool calls?"** → + [`terminal-rendering.md`](terminal-rendering.md) (full row taxonomy + and dispatch walkthrough); for a high-level summary see + [`agent.md`](agent.md) (Per-stream rendering). +- **"What slash commands does the agent accept?"** → + [`agent.md`](agent.md) (Terminal-embedded prompt). +- **"What are the per-agent HTTP endpoints?"** → + [`agent.md`](agent.md) (Per-agent endpoints). +- **"Which CSS variable do I use / where are colours defined?"** → + [`css-vars.md`](css-vars.md) (Palette, single-source `base.css` + rule). diff --git a/docs/web-ui/agent.md b/docs/web-ui/agent.md index 7156589e..1a4e5eca 100644 --- a/docs/web-ui/agent.md +++ b/docs/web-ui/agent.md @@ -1,6 +1,6 @@ # Per-agent page -> Part of [Web UI](../web-ui.md). See also: +> Part of [Web UI](README.md). See also: > [Shape (shared)](shape.md) · [Dashboard layout](dashboard.md) diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index 77fc50a2..b84f014a 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -1,6 +1,6 @@ # Dashboard layout -> Part of [Web UI](../web-ui.md). See also: +> Part of [Web UI](README.md). See also: > [Shape (shared)](shape.md) · [Per-agent page](agent.md) diff --git a/docs/web-ui/shape.md b/docs/web-ui/shape.md index 2159f968..84e34dea 100644 --- a/docs/web-ui/shape.md +++ b/docs/web-ui/shape.md @@ -1,6 +1,6 @@ # Shape (shared by both) -> Part of [Web UI](../web-ui.md). See also: +> Part of [Web UI](README.md). See also: > [Dashboard layout](dashboard.md) · [Per-agent page](agent.md) ## Shared routes diff --git a/frontend/packages/agent/src/agent.css b/frontend/packages/agent/src/agent.css index 767690ad..b0b8ec7a 100644 --- a/frontend/packages/agent/src/agent.css +++ b/frontend/packages/agent/src/agent.css @@ -16,7 +16,7 @@ /* ─── full-screen layout overrides ───────────────────────────────── The agent page mounts a full-viewport terminal under a fixed - frosted-glass header + composer pair. See docs/web-ui.md::Per-agent + frosted-glass header + composer pair. See docs/web-ui/agent.md::Per-agent page for the layer / pill / side-panel structure; rules below override the in-page defaults from @hive/shared. */ @@ -175,7 +175,7 @@ h3 { } .agent-icon { /* Square identity anchor — explicit 5em sizing + align-self. - See docs/web-ui.md::Per-agent page (Agent icon) for the + See docs/web-ui/agent.md::Per-agent page (Agent icon) for the intrinsic-dim-pushes-parent-flex-open + sticks-to-top rationale. */ width: 5em; @@ -702,7 +702,7 @@ pre.diff { the composer (z-30) so the pill sits on the top layer instead of being clipped by the floating chrome. (Pill is anchored in `.agent-main` rather than `.terminal-wrap` — see - docs/web-ui.md::Per-agent page Terminal-wrap paragraph for the + docs/web-ui/agent.md::Per-agent page Terminal-wrap paragraph for the backdrop-filter stacking-context rationale.) */ .agent-main .tail-pill { bottom: calc(var(--agent-composer-h) + 0.6em); diff --git a/frontend/packages/agent/src/screen.html b/frontend/packages/agent/src/screen.html index cae99525..b4be39a7 100644 --- a/frontend/packages/agent/src/screen.html +++ b/frontend/packages/agent/src/screen.html @@ -61,7 +61,7 @@ }); // --- Fit-to-window toggle --- - // See docs/web-ui.md::Per-agent endpoints (GET /screen) for the + // See docs/web-ui/agent.md::Per-agent endpoints (GET /screen) for the // localStorage persistence + canvas-intrinsic-resolution + // pointer-rescale model. let fitMode = localStorage.getItem("screen-fit") !== "off"; @@ -105,7 +105,7 @@ // Sends an RFB SetDesktopSize request so the VNC server (weston) // changes its actual output resolution to match the browser // viewport — sharper than fit-mode's CSS downscale. Gated on the - // server's ExtendedDesktopSize advert; see docs/web-ui.md::Per-agent + // server's ExtendedDesktopSize advert; see docs/web-ui/agent.md::Per-agent // endpoints (GET /screen). let extDesktopSupported = false; let screenId = 1; // captured from the server's ExtendedDesktopSize advert diff --git a/frontend/packages/dashboard/src/call.js b/frontend/packages/dashboard/src/call.js index 6a2fac0c..470e40ff 100644 --- a/frontend/packages/dashboard/src/call.js +++ b/frontend/packages/dashboard/src/call.js @@ -270,7 +270,7 @@ export function renderApprovals() { if (isMergePr && a.sha_short) head.append(el("code", {}, a.sha_short)); // When the approval was requested — relative time, right-aligned. // Goes amber once it's been pending an hour so a stale request is - // obvious at a glance (see docs/web-ui.md::Approval card). + // obvious at a glance (see docs/web-ui/dashboard.md::Approval card). if (a.requested_at != null) { const requestedSec = epochSec(a.requested_at); const ageSec = Math.max(0, Math.floor(Date.now() / 1000 - requestedSec)); diff --git a/frontend/packages/dashboard/src/common.css b/frontend/packages/dashboard/src/common.css index befa714c..a1e272e4 100644 --- a/frontend/packages/dashboard/src/common.css +++ b/frontend/packages/dashboard/src/common.css @@ -253,7 +253,7 @@ code { } /* M0V3 affordance (selection bar) — mauve reads as "structural change" rather than the destructive red / amber chrome of - destroy / rebuild. See docs/web-ui.md::Selection bar. */ + destroy / rebuild. See docs/web-ui/dashboard.md::Selection bar. */ .btn-move { color: var(--purple); border-color: var(--purple); diff --git a/frontend/packages/dashboard/src/common.js b/frontend/packages/dashboard/src/common.js index f7d703ca..956207b5 100644 --- a/frontend/packages/dashboard/src/common.js +++ b/frontend/packages/dashboard/src/common.js @@ -68,7 +68,7 @@ export const form = ( // ─── shared-worker SSE pipe ───────────────────────────────────────────── // Returns an EventSource-shaped facade backed by a SharedWorker that // holds one upstream `new EventSource(url)` and fans events out to -// every connected tab. See docs/web-ui.md (SSE multiplexing paragraph) +// every connected tab. See docs/web-ui/shape.md (SSE multiplexing paragraph) // for the design + Firefox throttling motivation; graceful fallback to // direct EventSource on environments without SharedWorker. // @@ -105,7 +105,7 @@ function getSharedPort() { // SharedWorker death detection: pings from the worker bump the // activity clock; a visibility-gated watchdog polls and re-subscribes // on a fresh port if the page has been silent past the threshold. -// See docs/web-ui.md (Worker-death self-heal paragraph) for the +// See docs/web-ui/shape.md (Worker-death self-heal paragraph) for the // timing rationale + Firefox reclaim symptom. const WORKER_DEAD_THRESHOLD_MS = 90_000; const WORKER_WATCHDOG_INTERVAL_MS = 15_000; diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index 3c5f38b6..93552780 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -12,7 +12,7 @@ /* ─── tabbed dashboard chrome ────────────────────────────────────── Top-of-page sticky header with banner + tab strip. SSE stays alive across tab switches so count pills update live on inactive - tabs. See docs/web-ui.md::Chrome header + Tab strip for the + tabs. See docs/web-ui/dashboard.md::Chrome header + Tab strip for the routing model. */ body.dashboard-shell { @@ -200,7 +200,7 @@ body.dashboard-shell { opacity 200ms ease, border-color 200ms ease; } -/* Topology indent ladder. See docs/web-ui.md::Topology tree (Indent +/* Topology indent ladder. See docs/web-ui/dashboard.md::Topology tree (Indent + lane geometry paragraph) for the 1.8em-per-depth-level rationale + CSS-attr()-not-yet-portable caveat. */ .container-row[data-depth] { diff --git a/frontend/packages/dashboard/src/dashboard.html b/frontend/packages/dashboard/src/dashboard.html index 4682766e..06925f31 100644 --- a/frontend/packages/dashboard/src/dashboard.html +++ b/frontend/packages/dashboard/src/dashboard.html @@ -294,7 +294,7 @@ for per-target / whole-row cancel. Live updates via `schedules_changed` SSE; tab activation re-fetches as a safety net for disconnect windows. - See docs/web-ui.md::SCH3DUL3S tab. --> + See docs/web-ui/dashboard.md::SCH3DUL3S tab. -->
per lane) rather than text-glyph-painted. function treePrefixDom({ depth, ancestorIsLast, isLast }) { if (depth === 0) return null; @@ -650,7 +650,7 @@ function buildContainerLi(c, node, opts) { // Per-card action buttons (R3ST4RT / ST0P / ST4RT / R3BU1LD / // DESTR0Y / PURG3) live on the selection bar, not here — see - // docs/web-ui.md::Selection bar. The contextual `needs update ↻` + // docs/web-ui/dashboard.md::Selection bar. The contextual `needs update ↻` // chip in the head row stays — it's a state-hint, not an // action button. @@ -830,7 +830,7 @@ export function renderContainers(s) { // ─── selection bar ─────────────────────────────────────────────────────────── // Sticky-bottom strip; visible when >=1 agent selected on the SW4RM -// tab. See docs/web-ui.md::Selection bar for the interaction model +// tab. See docs/web-ui/dashboard.md::Selection bar for the interaction model // and the per-action availability rules (disabled-with-tooltip for // actions that don't apply to the full selection). Actions POST per // agent in a loop (endpoints are individually idempotent / diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 13eda44b..54fe2979 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -2,7 +2,7 @@ // + notification deltas. Reads /api/state on cold load and after every // async-form submit; live updates run through `applyXxx` mutation // handlers triggered by the dashboard event stream (subscribed via -// `openStream` from common.js). See docs/web-ui.md::Shape (shared by +// `openStream` from common.js). See docs/web-ui/shape.md::Shape (shared by // both) for the broader contract. // // Pure helpers (DOM, side panel, OS notifications, path linkification) diff --git a/frontend/packages/shared/src/side-panel/hive-side-panel.js b/frontend/packages/shared/src/side-panel/hive-side-panel.js index c3676f20..5a9b66ea 100644 --- a/frontend/packages/shared/src/side-panel/hive-side-panel.js +++ b/frontend/packages/shared/src/side-panel/hive-side-panel.js @@ -31,7 +31,7 @@ import { el } from "../dom.js"; import { attachShadowCss } from "../shadow-css.js"; import sidePanelCss from "./hive-side-panel.css"; -// See docs/web-ui.md::Side panel for the hit-strip + pointer-capture + +// See docs/web-ui/agent.md::Side panel for the hit-strip + pointer-capture + // localStorage persistence model; CSS clamps the stored value to min // 320px / max 96vw and out-of-range stored values are dropped silently. // Shared by both packages deliberately — see module header. diff --git a/frontend/packages/shared/src/terminal/terminal.js b/frontend/packages/shared/src/terminal/terminal.js index 259d381c..ae659279 100644 --- a/frontend/packages/shared/src/terminal/terminal.js +++ b/frontend/packages/shared/src/terminal/terminal.js @@ -12,7 +12,7 @@ const NEAR_BOTTOM_PX = 48; // "load older" fetch — fires via the scroll event handler so the operator // never has to click the pill; the pill stays as a visual indicator. const LOAD_MORE_SCROLL_PX = 80; -// Snap-to-bottom animation duration. See docs/web-ui.md::Shared +// Snap-to-bottom animation duration. See docs/web-ui/shape.md::Shared // terminal pane (Sticky-bottom + snap animation) for the 140ms-vs- // 500ms-browser-default + 24px short-circuit rationale. const SCROLL_ANIM_MS = 140; @@ -128,7 +128,7 @@ export function create(opts) { // immediately so the MutationObserver stops re-firing snapToBottom() // and the animation-guard window can expire naturally. Without this, // live events arriving < 220ms apart permanently block scroll-to-top - // and loadMore() never fires. See docs/web-ui.md::Shared terminal + // and loadMore() never fires. See docs/web-ui/shape.md::Shared terminal // pane (Mid-animation scroll-event guard). const inAnim = Date.now() < smoothScrollingUntil; const nearBottom = isNearBottom(); @@ -571,7 +571,7 @@ export function create(opts) { } // Build a DocumentFragment from `text`, turning bare http(s) URLs into -// clickable links that open in a new tab. See docs/web-ui.md::Shared +// clickable links that open in a new tab. See docs/web-ui/shape.md::Shared // terminal pane (linkify) for the text-node-only / no-innerHTML // XSS-safety + trailing-punctuation strip. const LINKIFY_URL_RE = /https?:\/\/[^\s<>"']+/g;