From 3e9f2f2fd5ba4bcd0b8a7f0164892c6076b390c9 Mon Sep 17 00:00:00 2001 From: iris Date: Sat, 15 Aug 2026 12:23:46 +0200 Subject: [PATCH] docs(dashboard): fix stale facts found in source-verification sweep - server-warnings banner: was described as disk-pressure-only; it's now a push-based registry with multiple producers (forge/CI boot failures, agent-state warnings), and shown on more standalone pages than listed - browser tab title: actual default/format is "hyperhive // h1ve-c0re", not "hive / c0re" - SW4RM container tree: ContainerView.parent comes from agent_config/topology.rs, not the ambiguous dashboard/topology.rs (which only holds set-parent endpoints) - T00L GR0UPS: tool-group enumeration was missing "forge"; root agent's default (MANAGER_DEFAULT) is not literally "all groups" -- it excludes forge and web_tools - ST4TS moved to its own /stats.html page a while back; section still called it a dashboard tab - P33RS is a headline block within the SW4RM tab, not its own tab -- contradicted the doc's own chrome-header description - active model badge: reads hyperhive-harness.json's active_model field, not a bare harness/hyperhive-model file - themed dialogs: modal.js lives in the shared package (@hive/shared/modal.js), and themedToast takes (message, opts) not a single options object - graceful stop: backend uses a Signal/Drain job-queue node pair, not a "GracefulStop" transient kind; hivectl flag is `stop --graceful`, not a bare `--graceful` - container_state_changed event: named a nonexistent auto_update::rebuild_agent as an emit site; actual sites are actions::approve and the job queue's own node execution Verified against hive-c0re/src (dashboard/, stats/, job_queue/, container_view.rs), hive-sh4re/src/permissions.rs, and the dashboard frontend package (tabs.js, stats.js, swarm.js, builds.js, modal.js). No structural/prose changes beyond what the fact corrections required. --- docs/web-ui/dashboard.md | 126 +++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 50 deletions(-) diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index 46132f25..1428aff2 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -27,22 +27,27 @@ from the dashboard tab strip. - **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`) — sits below the tab strip. - **Server-warnings banner** — a generic, sticky top-of-page strip shown - on **every** page (dashboard + the stand-alone FL0W / L0GS / H0M3 - pages), injected at the top of `` by `renderServerWarnings` in - `common.js`. Driven by `state.server_warnings` — a list of - `{ kind, level, message }` from hive-c0re's `host_stats::server_warnings` - — and coloured by `level` (`warn` amber / `crit` red). The backend owns - the threshold + message, so adding a new system warning needs no - frontend change. The only producer today is the host disk-pressure - check (a `statvfs` probe of `/nix`: ≥85% used → `warn`, ≥95% → `crit`, - e.g. `⚠ host nix store N% full (G GiB free) — garbage-collect …`). - Hidden when there are no warnings. -- **Browser tab title** — `hive / c0re` by default; updated to - ` / ` once `hive_name` / `swarm_name` arrive in the - state snapshot. When there are pending approvals or unanswered - questions, a `(N)` prefix is prepended — `(3) pr1ma / hive-c0re` - — so the operator can see the call count in an unfocused browser - tab without opening the dashboard. The prefix is set on the + on **every** page (dashboard + every stand-alone page — FL0W, L0GS, + H0M3, C0R3, BU1LDS, CR3D3NTIALS, ST4TS, S3TT1NGS), injected at the top + of `` by `renderServerWarnings` in `common.js`. Driven by + `state.server_warnings` — a list of `{ kind, level, message }` — and + coloured by `level` (`warn` amber / `crit` red). The backend owns the + threshold + message, so adding a new system warning needs no frontend + change. Warnings are a push-based registry (`hive-c0re`'s + `warnings.rs`): any subsystem raises/clears its own entry via an RAII + guard, and `host_stats::server_warnings()` is just a cheap snapshot of + that registry. Producers today include the host disk-pressure check + (a `statvfs` probe of `/nix`: ≥85% used → `warn`, ≥95% → `crit`, e.g. + `⚠ host nix store N% full (G GiB free) — garbage-collect …`), forge + provisioning/CI-runner boot failures, and agent-state warnings + (`pending_logins`, `agents_crashing`) computed alongside the container + snapshot. Hidden when there are no warnings. +- **Browser tab title** — `hyperhive // h1ve-c0re` by default; updated + to ` / // h1ve-c0re` once `hive_name` / `swarm_name` + arrive in the state snapshot. When there are pending approvals or + unanswered questions, a `(N)` prefix is prepended — `(3) pr1ma // + h1ve-c0re` — so the operator can see the call count in an unfocused + browser tab without opening the dashboard. The prefix is set on the initial `/api/state` cold-load and updated live by `approval_added` / `approval_resolved` / `question_added` / `question_resolved` SSE events; it's preserved when @@ -55,7 +60,10 @@ surfaces, not tab panes. ## SW4RM tab **C0NTAINERS** — live containers rendered as a depth-first -tree using `ContainerView.parent` (populated by `topology.rs`). +tree using `ContainerView.parent` (populated by +`hive-c0re/src/agent_config/topology.rs` — not to be confused with +`hive-c0re/src/dashboard/topology.rs`, which only holds the +set-parent endpoints). Each container's row is prefixed with ASCII tree glyphs (`├─`, `└─`, `│ ` continuation columns) showing the agent parent/child hierarchy. When every container has `parent = null` @@ -470,18 +478,22 @@ values follow the `effective`/`assignments` rule described above. **T00L GR0UPS** — per-agent tool-group permissions. Tool groups are named buckets of MCP tools; each agent starts with a role default -(sub-agents: `messaging`, `meta`, `inbox`, `execution`; root agent: all -groups). Checking / unchecking stages which groups are active for the -agent; the page-level **save all** button (below) commits it. Columns -come from `GET /api/tool-groups`. A rebuild is queued so -`HIVE_TOOL_GROUPS` takes effect. +(sub-agents: `messaging`, `meta`, `inbox`, `execution` — +`ToolGroup::AGENT_DEFAULT`; root agent is seeded to +`ToolGroup::MANAGER_DEFAULT` — `messaging`, `meta`, `inbox`, +`lifecycle`, `approvals`, `scheduling`, `diagnostics`, `execution`, +i.e. every group except `forge` and `web_tools`). Checking / +unchecking stages which groups are active for the agent; the +page-level **save all** button (below) commits it. Columns come from +`GET /api/tool-groups`. A rebuild is queued so `HIVE_TOOL_GROUPS` +takes effect. The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`, -`approvals`, `scheduling`, `diagnostics`, `execution`, `web_tools`. All -listed in `ToolGroup::ALL` in `hive-sh4re`. The `web_tools` group is -special: it carries no MCP tools; instead it adds Claude's built-in -`WebFetch` and `WebSearch` to `--tools` / `--allowedTools` for that -agent session. +`approvals`, `scheduling`, `diagnostics`, `forge`, `execution`, +`web_tools`. All listed in `ToolGroup::ALL` in `hive-sh4re`. The +`web_tools` group is special: it carries no MCP tools; instead it adds +Claude's built-in `WebFetch` and `WebSearch` to `--tools` / +`--allowedTools` for that agent session. Both tables share the same visual shape: `.cap-table-wrap` / `.tg-table-wrap` outer scroll container, `thead` with a label column @@ -588,14 +600,17 @@ attribute; a shared 1s ticker rewrites it in-place — showing `overdue X ago` once the deadline passes — without triggering a full re-render of the list. -## ST4TS tab +## ST4TS page (`/stats.html`) Hive-wide turn statistics, aggregated across every agent's -`hyperhive-turn-stats.sqlite` for the selected window. Distinct from +`hyperhive-turn-stats.sqlite` for the selected window. Not a dashboard +tab — a standalone page reached from the **Stats** tile on the H0M3 +hub, same minimal chrome as `/flow.html` / `/logs.html`. Distinct from each agent's own `/stats` page (which carries the per-agent trend charts): ST4TS is the swarm-level rollup. -- **Window selector** (`1h`–`30d`) re-fetches on change. +- **Window selector** (`1h`, `4h`, `24h`, `3d`, `7d`, `30d`, `all`) — + a hash-routed tab strip (`#1h` / `#24h` / …) — re-fetches on change. - **Summary chips**: active agents, turns, total/input/output/cache-read tokens, and a labelled **est cost**. - **Busiest agents** table — one row per agent (most turns first): @@ -614,7 +629,7 @@ Backed by `GET /api/stats-hive?window=` in `hive-c0re` 500 ms `busy_timeout`, since `turn_stats` is rollback-journal) and rolls the rows up — missing / unreadable / zero-turn dbs are skipped so one bad db never fails the endpoint. This is a **pull** surface (no SSE): -the data is fetched on tab activation and on window change. Rendered +the data is fetched on page load and on window change. Rendered with plain tables + CSS bars — the dashboard bundle ships no chart library. @@ -627,13 +642,16 @@ the model id, longest match wins) mapping to `{ input, output, cache_read, cache_write }` USD-per-million-token prices. Models not covered fall back to hive-c0re's built-in estimate. -## P33RS tab +## P33R H1V3S (within the SW4RM tab) -Peer hives in this swarm. The tab is hidden when the +Peer hives in this swarm. Not its own tab — a headline block +(`#peers-block`) rendered under the SW4RM tab's container list (see +"Chrome header" above: "Peer hives render as a headline under SW4RM +rather than a tab"). The block is hidden when the `state.peer_hives` array from `/api/state` is empty — i.e. when `services.hyperhive.swarm.hives` holds no hive other than this one. When at least one peer is present the `hidden` attribute is removed -and the tab becomes active. +and the cards render. **P33R H1V3S** — each peer renders as a card row: a hexagon icon (`⬡`), the peer's DNS domain as the primary name, and the peer @@ -964,10 +982,12 @@ and it reads the narrow `/api/jobq/rollup` endpoint rather than the full graph. **Active model badge** (`model · `, blue) appears when the -container is running and the harness has persisted a model name -(`harness/hyperhive-model`). Read by hive-c0re's `ContainerView` -(`read_active_model`); absent until the agent has completed at least -one turn and stale values are suppressed for stopped containers. +container is running and the harness has persisted a model name (the +`active_model` field of `hyperhive-harness.json`, the consolidated +harness state file in the agent's state dir). Read by hive-c0re's +`ContainerView` (`read_active_model`); absent until the agent has +completed at least one turn and stale values are suppressed for +stopped containers. **`ctx · Nk` chip** shows the agent's last-turn context size, populated from `DashboardState.ctx_tokens` (absent until the @@ -1019,7 +1039,7 @@ step-level counts instead, unused here. ### Themed dialogs All confirmations, prompts, and transient error notices use an -in-app themed dialog system (`assets/modal.js`) rather than the +in-app themed dialog system (`@hive/shared/modal.js`) rather than the browser's native `confirm()` / `prompt()` / `alert()` chrome, so they match the Catppuccin palette and can't be styled away by the OS. Three primitives, all built on the `openDialog` core: @@ -1031,7 +1051,7 @@ OS. Three primitives, all built on the `openDialog` core: button takes focus). Backdrop click and `Esc` both cancel. - `themedPrompt(...)` — a modal with a text input, resolving to the entered string or `null`. -- `themedToast({ type, ... })` — a non-blocking toast (top-right, +- `themedToast(message, { type, ... })` — a non-blocking toast (top-right, `info` / `error` / `ok`) for transient validation + action failures, so an error doesn't trap the operator behind a modal. Single-action errors auto-dismiss; bulk / partial-failure @@ -1047,13 +1067,18 @@ and flush state before the container stops` checkbox. When ticked, the action POSTs `/api/kill/?graceful=true` (the bulk path appends the flag per-agent); unticked is the instant hard stop (`/api/kill/` with no query). The backend enqueues a -`GracefulStop` rebuild-queue transient: the harness runs one -stop-checkpoint turn (so the agent can flush `/state`) and then -exits, with a 3-minute timeout that falls back to a hard stop. The -quiescing progress surfaces through the same rebuild-queue -transient + build log the card already reads for a rebuild. (The -`hivectl --graceful` CLI flag enqueues the same `GracefulStop`, so -the dashboard and CLI paths behave identically.) +`Signal` → `Drain` job-queue node pair (`NodeKind::Signal` / +`NodeKind::Drain`): `Signal` sets the graceful-stop fence and kicks +the harness so it runs one stop-checkpoint turn (so the agent can +flush `/state`); `Drain` awaits the harness clearing that fence, +bounded by a 3-minute timeout (`GRACEFUL_STOP_TIMEOUT`) that +resolves either way and falls back to the downstream mechanical +stop. The quiescing progress surfaces through the same +rebuild-queue pending-badge mechanism the card already reads for a +rebuild — there's no build log, since a graceful stop runs no nix +build. (The `hivectl stop --graceful` CLI flag enqueues the same +`Signal`/`Drain` pair, so the dashboard and CLI paths behave +identically.) ### Topology tree @@ -1434,9 +1459,10 @@ payload): - `container_state_changed` (container: ContainerView) / `container_removed` (name) — per-row container mutations, emitted by `Coordinator::rescan_containers_and_emit` from - every mutation site (`actions::approve` post-spawn, - `actions::destroy`, the lifecycle_action wrapper, - `auto_update::rebuild_agent`) and from the 10s + many mutation sites — post-spawn approval bookkeeping + (`actions::approve`), the job queue's own node execution + (`job_queue::exec`, e.g. after a rebuild's stop/swap/start + steps or a destroy's teardown step) — and from the 10s `crash_watch` poll. Client upserts/removes by name; the pending overlay is read from `transientsState` since the payload doesn't carry it.