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.
This commit is contained in:
iris 2026-08-15 12:23:46 +02:00 committed by mara
commit 3e9f2f2fd5

View file

@ -27,22 +27,27 @@ from the dashboard tab strip.
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`) - **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
— sits below the tab strip. — sits below the tab strip.
- **Server-warnings banner** — a generic, sticky top-of-page strip shown - **Server-warnings banner** — a generic, sticky top-of-page strip shown
on **every** page (dashboard + the stand-alone FL0W / L0GS / H0M3 on **every** page (dashboard + every stand-alone page — FL0W, L0GS,
pages), injected at the top of `<body>` by `renderServerWarnings` in H0M3, C0R3, BU1LDS, CR3D3NTIALS, ST4TS, S3TT1NGS), injected at the top
`common.js`. Driven by `state.server_warnings` — a list of of `<body>` by `renderServerWarnings` in `common.js`. Driven by
`{ kind, level, message }` from hive-c0re's `host_stats::server_warnings` `state.server_warnings` — a list of `{ kind, level, message }` — and
— and coloured by `level` (`warn` amber / `crit` red). The backend owns coloured by `level` (`warn` amber / `crit` red). The backend owns the
the threshold + message, so adding a new system warning needs no threshold + message, so adding a new system warning needs no frontend
frontend change. The only producer today is the host disk-pressure change. Warnings are a push-based registry (`hive-c0re`'s
check (a `statvfs` probe of `/nix`: ≥85% used → `warn`, ≥95% → `crit`, `warnings.rs`): any subsystem raises/clears its own entry via an RAII
e.g. `⚠ host nix store N% full (G GiB free) — garbage-collect …`). guard, and `host_stats::server_warnings()` is just a cheap snapshot of
Hidden when there are no warnings. that registry. Producers today include the host disk-pressure check
- **Browser tab title**`hive / c0re` by default; updated to (a `statvfs` probe of `/nix`: ≥85% used → `warn`, ≥95% → `crit`, e.g.
`<swarm> / <hive>` once `hive_name` / `swarm_name` arrive in the `⚠ host nix store N% full (G GiB free) — garbage-collect …`), forge
state snapshot. When there are pending approvals or unanswered provisioning/CI-runner boot failures, and agent-state warnings
questions, a `(N)` prefix is prepended — `(3) pr1ma / hive-c0re` (`pending_logins`, `agents_crashing`) computed alongside the container
— so the operator can see the call count in an unfocused browser snapshot. Hidden when there are no warnings.
tab without opening the dashboard. The prefix is set on the - **Browser tab title**`hyperhive // h1ve-c0re` by default; updated
to `<swarm> / <hive> // 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 initial `/api/state` cold-load and updated live by
`approval_added` / `approval_resolved` / `question_added` / `approval_added` / `approval_resolved` / `question_added` /
`question_resolved` SSE events; it's preserved when `question_resolved` SSE events; it's preserved when
@ -55,7 +60,10 @@ surfaces, not tab panes.
## SW4RM tab ## SW4RM tab
**C0NTAINERS** — live containers rendered as a depth-first **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 (`├─`, Each container's row is prefixed with ASCII tree glyphs (`├─`,
`└─`, `│ ` continuation columns) showing the agent `└─`, `│ ` continuation columns) showing the agent
parent/child hierarchy. When every container has `parent = null` 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 **T00L GR0UPS** — per-agent tool-group permissions. Tool groups are
named buckets of MCP tools; each agent starts with a role default named buckets of MCP tools; each agent starts with a role default
(sub-agents: `messaging`, `meta`, `inbox`, `execution`; root agent: all (sub-agents: `messaging`, `meta`, `inbox`, `execution`
groups). Checking / unchecking stages which groups are active for the `ToolGroup::AGENT_DEFAULT`; root agent is seeded to
agent; the page-level **save all** button (below) commits it. Columns `ToolGroup::MANAGER_DEFAULT``messaging`, `meta`, `inbox`,
come from `GET /api/tool-groups`. A rebuild is queued so `lifecycle`, `approvals`, `scheduling`, `diagnostics`, `execution`,
`HIVE_TOOL_GROUPS` takes effect. 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`, The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`,
`approvals`, `scheduling`, `diagnostics`, `execution`, `web_tools`. All `approvals`, `scheduling`, `diagnostics`, `forge`, `execution`,
listed in `ToolGroup::ALL` in `hive-sh4re`. The `web_tools` group is `web_tools`. All listed in `ToolGroup::ALL` in `hive-sh4re`. The
special: it carries no MCP tools; instead it adds Claude's built-in `web_tools` group is special: it carries no MCP tools; instead it adds
`WebFetch` and `WebSearch` to `--tools` / `--allowedTools` for that Claude's built-in `WebFetch` and `WebSearch` to `--tools` /
agent session. `--allowedTools` for that agent session.
Both tables share the same visual shape: `.cap-table-wrap` / Both tables share the same visual shape: `.cap-table-wrap` /
`.tg-table-wrap` outer scroll container, `thead` with a label column `.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 `overdue X ago` once the deadline passes — without triggering a
full re-render of the list. full re-render of the list.
## ST4TS tab ## ST4TS page (`/stats.html`)
Hive-wide turn statistics, aggregated across every agent's 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 each agent's own `/stats` page (which carries the per-agent trend
charts): ST4TS is the swarm-level rollup. 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 - **Summary chips**: active agents, turns, total/input/output/cache-read
tokens, and a labelled **est cost**. tokens, and a labelled **est cost**.
- **Busiest agents** table — one row per agent (most turns first): - **Busiest agents** table — one row per agent (most turns first):
@ -614,7 +629,7 @@ Backed by `GET /api/stats-hive?window=<w>` in `hive-c0re`
500 ms `busy_timeout`, since `turn_stats` is rollback-journal) and rolls 500 ms `busy_timeout`, since `turn_stats` is rollback-journal) and rolls
the rows up — missing / unreadable / zero-turn dbs are skipped so one 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): 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 with plain tables + CSS bars — the dashboard bundle ships no chart
library. library.
@ -627,13 +642,16 @@ the model id, longest match wins) mapping to
`{ input, output, cache_read, cache_write }` USD-per-million-token `{ input, output, cache_read, cache_write }` USD-per-million-token
prices. Models not covered fall back to hive-c0re's built-in estimate. 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 `state.peer_hives` array from `/api/state` is empty — i.e. when
`services.hyperhive.swarm.hives` holds no hive other than this one. `services.hyperhive.swarm.hives` holds no hive other than this one.
When at least one peer is present the `hidden` attribute is removed 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 **P33R H1V3S** — each peer renders as a card row: a hexagon icon
(`⬡`), the peer's DNS domain as the primary name, and the peer (`⬡`), 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. full graph.
**Active model badge** (`model · <name>`, blue) appears when the **Active model badge** (`model · <name>`, blue) appears when the
container is running and the harness has persisted a model name container is running and the harness has persisted a model name (the
(`harness/hyperhive-model`). Read by hive-c0re's `ContainerView` `active_model` field of `hyperhive-harness.json`, the consolidated
(`read_active_model`); absent until the agent has completed at least harness state file in the agent's state dir). Read by hive-c0re's
one turn and stale values are suppressed for stopped containers. `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, **`ctx · Nk` chip** shows the agent's last-turn context size,
populated from `DashboardState.ctx_tokens` (absent until the populated from `DashboardState.ctx_tokens` (absent until the
@ -1019,7 +1039,7 @@ step-level counts instead, unused here.
### Themed dialogs ### Themed dialogs
All confirmations, prompts, and transient error notices use an 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 browser's native `confirm()` / `prompt()` / `alert()` chrome, so
they match the Catppuccin palette and can't be styled away by the they match the Catppuccin palette and can't be styled away by the
OS. Three primitives, all built on the `openDialog` core: 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. button takes focus). Backdrop click and `Esc` both cancel.
- `themedPrompt(...)` — a modal with a text input, resolving to the - `themedPrompt(...)` — a modal with a text input, resolving to the
entered string or `null`. 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 `info` / `error` / `ok`) for transient validation + action
failures, so an error doesn't trap the operator behind a modal. failures, so an error doesn't trap the operator behind a modal.
Single-action errors auto-dismiss; bulk / partial-failure 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/<name>?graceful=true` (the bulk path the action POSTs `/api/kill/<name>?graceful=true` (the bulk path
appends the flag per-agent); unticked is the instant hard stop appends the flag per-agent); unticked is the instant hard stop
(`/api/kill/<name>` with no query). The backend enqueues a (`/api/kill/<name>` with no query). The backend enqueues a
`GracefulStop` rebuild-queue transient: the harness runs one `Signal``Drain` job-queue node pair (`NodeKind::Signal` /
stop-checkpoint turn (so the agent can flush `/state`) and then `NodeKind::Drain`): `Signal` sets the graceful-stop fence and kicks
exits, with a 3-minute timeout that falls back to a hard stop. The the harness so it runs one stop-checkpoint turn (so the agent can
quiescing progress surfaces through the same rebuild-queue flush `/state`); `Drain` awaits the harness clearing that fence,
transient + build log the card already reads for a rebuild. (The bounded by a 3-minute timeout (`GRACEFUL_STOP_TIMEOUT`) that
`hivectl --graceful` CLI flag enqueues the same `GracefulStop`, so resolves either way and falls back to the downstream mechanical
the dashboard and CLI paths behave identically.) 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 ### Topology tree
@ -1434,9 +1459,10 @@ payload):
- `container_state_changed` (container: ContainerView) / - `container_state_changed` (container: ContainerView) /
`container_removed` (name) — per-row container mutations, `container_removed` (name) — per-row container mutations,
emitted by `Coordinator::rescan_containers_and_emit` from emitted by `Coordinator::rescan_containers_and_emit` from
every mutation site (`actions::approve` post-spawn, many mutation sites — post-spawn approval bookkeeping
`actions::destroy`, the lifecycle_action wrapper, (`actions::approve`), the job queue's own node execution
`auto_update::rebuild_agent`) and from the 10s (`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 `crash_watch` poll. Client upserts/removes by name; the
pending overlay is read from `transientsState` since the pending overlay is read from `transientsState` since the
payload doesn't carry it. payload doesn't carry it.