From a52d344600286f6425a458c477b20d3aa9c3732f Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 8 Sep 2026 15:10:01 +0200 Subject: [PATCH] docs: fix genuine passive-voice hits in docs/web-ui/dashboard.md (part 1/2) First half (lines 1-697) of dashboard.md's write-good.Passive backlog -- 31 of the file's 70 hits rewritten to name an actor (hive-c0re, the page, the operator, the table, the filter, builds.js, Provision, the matrix daemon, ...), reusing an actor already named nearby wherever one exists. 7 left alone in this half: a fixed idiom ("not to be confused with"), two false positives ("named buckets" / compound adjective; a field-is-set data-state conditional), a negative-capability idiom ("nothing is written"), and two established state-descriptor idioms ("is unchanged", "is tooltipped"). Part 2 (lines 762-1389, ~32 more hits) is a separate follow-up, not started -- dashboard.md is too big for one PR. --- docs/web-ui/dashboard.md | 117 ++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index 37b4414f..bd3753ff 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -4,7 +4,7 @@ > [Shape (shared)](shape.md) · [Per-agent page](agent.md) -The dashboard is served at `/dashboard.html` (with the home page at `/`). +hive-c0re serves the dashboard at `/dashboard.html` (with the home page at `/`). It has a fixed chrome header at the top and a `
` that shows exactly one tab pane at a time. The URL hash (`#swarm`, `#call`, `#system`, `#permissions`, `#schedules`) drives which pane is @@ -42,13 +42,13 @@ from the dashboard tab strip. 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, a - `(N)` prefix is prepended — `(3) pr1ma // h1ve-c0re` — so the + arrive in the state snapshot. When there are pending approvals, the + page prepends a `(N)` prefix — `(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` - SSE events; it's preserved when `hive_name` / `swarm_name` later - replace the raw title. + opening the dashboard. The page sets the prefix on the initial + `/api/state` cold-load and updates it live via `approval_added` / + `approval_resolved` SSE events; it's preserved when `hive_name` / + `swarm_name` later replace the raw title. The FL0W and L0GS pages use a slim header (a `← home` back-link + the page title) rather than the dashboard tab strip — they're standalone @@ -61,13 +61,13 @@ 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` +ASCII tree glyphs (`├─`, `└─`, `│ ` continuation columns) prefix +each container's row, showing the agent parent/child hierarchy. +When every container has `parent = null` (flat topology) the tree collapses to a plain list with no -glyphs. Children are sorted alphabetically within each parent; -roots likewise. Cycles in the parent graph are tolerated — -orphaned containers (not reachable from any root) are appended +glyphs. The tree sorts children alphabetically within each parent; +roots likewise. The tree tolerates cycles in the parent graph — +it appends orphaned containers (not reachable from any root) as roots so no agent disappears. Pulsing red banner at the top of this section if any two sub-agents hash to the same port (`port_conflicts` from `/api/state`): the operator must rename @@ -138,12 +138,12 @@ page — see below.) claude-creds badge). One action: `PURG3` (wipes state + applied dirs; `POST /api/purge-tombstone/{name}`). -⚠️ **Not only *destroyed* agents.** Nothing records a destroy: every -definition-side artifact (state subvolume, proposed + applied repos, -meta registration, topology entry) is written by `Provision` *before* -the container exists and survives `lifecycle::destroy`. An agent +⚠️ **Not only *destroyed* agents.** Nothing records a destroy: `Provision` +writes every definition-side artifact (state subvolume, proposed + applied +repos, meta registration, topology entry) *before* the container exists, +and that artifact set survives `lifecycle::destroy`. An agent part-way through a spawn is byte-identical on disk to a tombstone, and -both are listed. The pane carries a standing warning to that effect, and +the pane lists both. The pane carries a standing warning to that effect, and the row badge says `offline` rather than `destroyed` — the absence of a container is all the backend can actually prove. Fixing it properly needs a recorded destroy: **#3020**, deferred to the swarm-controller / @@ -169,8 +169,8 @@ files read-only (world-readable; no `hive-priv`) and skips agents whose scope dir is absent (= not running). Pull-only: `core.js` polls every 5 s **only while the C0NT41N3R L04D sub-tab is active** (CPU needs a fresh sample each refresh), and stops on sub-tab change. Disk size (`disk_bytes`) -rides the same row but is fed by a separate ~5 min background `du` sampler -(state dir + container writable rootfs, shared nix store excluded via +rides the same row, but a separate ~5 min background `du` sampler feeds +it (state dir + container writable rootfs, shared nix store excluded via `du -x`), so the 5 s poll stays cheap cgroup-only reads; the row carries the last-sampled value (`null` until the first sample). Network is intentionally omitted — agents share the host netns, so there is no per-container net @@ -231,8 +231,8 @@ calls the mount's `onCancel(id)` callback, and the page does the actual own domain concept (the component knows nothing about that endpoint). **Rows carry no source chip, kind label, timing, or build-log deep-link** — the generic graph wire doesn't carry those fields, and -rows are meant to present exactly what the endpoint provides rather -than reconstruct chrome the backend no longer sends. Settled entries +rows deliberately present exactly what the endpoint provides rather +than reconstructing chrome the backend no longer sends. Settled entries render their **full step tree**, not just a bare summary — the wire doesn't filter `Done` nodes out. @@ -243,12 +243,12 @@ operator narrow which root groups render; unchecking a state re-fetches hiding rows client-side, so the `onUpdate` callback's node list (and everything downstream of it — the count pill, the live-log panel) only ever sees what's actually shown. Filtering is by a **root's own** -state, which is already its subtree's rolled-up answer, so a group is -kept or dropped whole, never split mid-tree. Default selection is +state, which is already its subtree's rolled-up answer, so the filter +keeps or drops a whole group, never splitting mid-tree. Default selection is every state **except** `Done`/`Skipped` — a fresh queue view leads -with what's still moving or needs attention, not the settled tail; the -`states` param is omitted entirely (identical request to before this -filter existed) when every state is checked. Server-side: the query +with what's still moving or needs attention, not the settled tail; +builds.js omits the `states` param entirely (identical request to +before this filter existed) when every state is checked. Server-side: the query narrows [`Queue::graph_snapshot`]'s already-bounded (`MAX_HISTORY_DAGS`) root set — the history cap and the state filter are independent concerns, so a narrow filter never reaches further back in time to @@ -274,14 +274,14 @@ selectively `nix flake update`, rendered as an indented tree: every fetched input at every depth (`hyperhive`, `hyperhive/nixpkgs`, `agent-`, `agent-/mcp-`, …), each shown once at its shallowest path. `read_meta_inputs` walks the -lock graph with a `visited` set — `follows` aliases and rev-less -nodes are skipped. A `select all / select none` +lock graph with a `visited` set, skipping `follows` aliases and rev-less +nodes. A `select all / select none` control sits above the tree. Checking inputs + submitting bumps the lock in `/meta/` and rebuilds the selected agents in sequence; each outcome reaches the root agent as a `rebuilt` system event. `POST /meta-update`. While a lock-bump ripple runs, -the panel shows a pulsing "⏳ meta-update running" banner and the -update button is disabled (snapshot field `meta_update_running`, +the panel shows a pulsing "⏳ meta-update running" banner and disables +the update button (snapshot field `meta_update_running`, live event `meta_update_running`). **BUILD L0GS** — all-agents build log history (moved from `/logs.html`). @@ -318,9 +318,9 @@ An agent picker (populated from `state.containers`, the live roster) drives a li agent's accounts — name, homeserver, user id, and a status dot — read from `GET /api/matrix-accounts?agent=` → `{ accounts: [ { name, homeserver, token_present, live, user_id } ], as_of_unix }`. -`token_present` is whether a token is **stored**; `live`, `homeserver`, -and `user_id` are backfilled from the matrix daemon's -`matrix-accounts.json` snapshot — a host-visible file the daemon +`token_present` is whether a token is **stored**; the matrix daemon +backfills `live`, `homeserver`, and `user_id` from its +`matrix-accounts.json` snapshot — a host-visible file it **force-rewrites every ~30s** (a heartbeat), so `as_of_unix` (the snapshot mtime) advances while the daemon is alive and a *stalled* value genuinely means "stopped publishing," not just "old snapshot." An account @@ -357,7 +357,7 @@ privileged write path as the hive-internal `matrix-token`; the token is **never** echoed back, and the page clears the secret inputs on submit regardless of outcome. The account list reflects what's *provisioned* (an account with a stored token), so a config-declared-but-unprovisioned -account appears only once it has been provisioned through the form. +account appears only once the operator provisions it through the form. ### GITHUB tab @@ -445,19 +445,19 @@ The current capabilities are: Each row is one agent. Columns are the capability names returned by `GET /api/capabilities` as `caps: Vec`. Checking or unchecking boxes only stages the change in-browser; nothing is written until the -page-level **save all** button (described below) is selected. Row +operator selects the page-level **save all** button (described below). Row 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` — -`ToolGroup::AGENT_DEFAULT`; root agent is seeded to +`ToolGroup::AGENT_DEFAULT`; hive-c0re seeds the root agent to `ToolGroup::MANAGER_DEFAULT` — `messaging`, `meta`, `inbox`, `lifecycle`, `approvals`, `scheduling`, `diagnostics`, `execution`, that is 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` +`GET /api/tool-groups`. hive-c0re queues a rebuild so `HIVE_TOOL_GROUPS` takes effect. The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`, @@ -479,9 +479,10 @@ buttons exist. A single page-level `.perm-save-bar` with a **save all (N agents)** button sits at the bottom of the pane, enabled only when some checkbox diverges from its baseline. Selecting it diffs every checkbox across *both* matrices and POSTs one batch to `POST /api/permissions` as -`{ changes: [ { agent, tool_groups?, capabilities? } ] }` — only the -perm-types that actually changed for each agent are included (an omitted -field leaves that file untouched; an included array fully replaces it). +`{ changes: [ { agent, tool_groups?, capabilities? } ] }` — the batch +includes only the perm-types that actually changed for each agent (an +omitted field leaves that file untouched; an included array fully +replaces it). The backend coalesces an agent's capabilities + tool-groups into a single rebuild, so changing both for one agent is one rebuild, not two. The batch is atomic: it validates every change first and on any error @@ -493,8 +494,8 @@ isn't clobbered. ## SCH3DUL3S tab -Anything that fires at a future time. Operator-set schedules -are created inline in the table (last row); agent self-paced +Anything that fires at a future time. The operator creates schedules +inline in the table (last row); agent self-paced reminders surface at the bottom as a sibling list — they share enough conceptual ground to live together. @@ -519,13 +520,13 @@ headers tilt -45° via CSS so each column reads as a narrow Per-schedule action column: - **`↯ fire now`** — sends an out-of-band manual pulse to every - active target (recurring schedules keep their cadence; one-shots - are consumed after the manual fire). Disabled for paused schedules. + active target (recurring schedules keep their cadence; the manual + fire consumes one-shots). Disabled for paused schedules. - **`⏸` / `▶` pause/resume toggle** — only on recurring schedules - (one-shots may also be paused to delay a one-time fire, so the - button always appears). Paused rows show a `⏸ paused` badge in the - `next` column and are sorted to the middle bucket (after active, - before cancelled). A paused schedule doesn't fire regardless of + (the operator may also pause one-shots to delay a one-time fire, so + the button always appears). Paused rows show a `⏸ paused` badge in + the `next` column; the table sorts them to the middle bucket (after + active, before cancelled). A paused schedule doesn't fire regardless of `next_fire_at`; resuming (`▶`) clears the pause without adjusting the next-fire time. POSTs to `/api/schedules/{id}/pause` or `/api/schedules/{id}/resume`. @@ -598,15 +599,15 @@ Backed by `GET /api/stats-hive?window=` in `hive-c0re` `Coordinator::kept_state_names()` it opens `agent_harness_dir(name)/hyperhive-turn-stats.sqlite` read-only (with a 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, skipping missing / unreadable / zero-turn dbs so one bad db never fails the endpoint. This is a **pull** surface (no SSE): -the data is fetched on page load and on window change. Rendered +the page fetches the data on page load and on window change. Rendered with plain tables + CSS bars — the dashboard bundle ships no chart library. The cost figure is a deliberately rough estimate from a per-model -price table (`est_cost_usd`); it drifts with list pricing and is -labelled accordingly. The table is operator-tunable via the +price table (`est_cost_usd`); it drifts with list pricing and the page +labels it accordingly. The table is operator-tunable via the `services.hyperhive.c0re.modelPrices` nix option — each key is a model-family short name (matched case-insensitively as a substring of the model id, longest match wins) mapping to @@ -658,8 +659,8 @@ Cold load backfills the last ~200 messages from `/api/dashboard/history`; live frames arrive on `/api/dashboard/stream`. Each row is one broker event — `sent` or `delivered` — with `from → to: body`. When a `sent` and `delivered` event for the same message arrive within 3 seconds -(immediate delivery to a live recipient), the row is upgraded in place -(arrow becomes green ✓, title reads "sent + delivered") instead of +(immediate delivery to a live recipient), the page upgrades the row in +place (arrow becomes green ✓, title reads "sent + delivered") instead of rendering two near-identical lines — genuine delivery latency (recipient was busy) still appears as a second row. Each row carries `data-from` / `data-to` attributes; an **agent filter select in the FL0W header** narrows @@ -680,7 +681,7 @@ stream sits a terminal-style compose box: `@name` picks the recipient (sticky via localStorage; autocomplete from the live container list, Tab/Enter to confirm; `@*` broadcasts). `POST /api/op-send` drops `{from:"operator", to, body}` into the broker; the resulting SSE frame -re-renders the terminal row. The root agent is addressed as `@root`. +re-renders the terminal row. The operator addresses the root agent as `@root`. ## H0M3 page (`/`) @@ -693,8 +694,8 @@ from the shared theme (Catppuccin Mocha via `common.css` + `theme.css`). `home.js` fills the swarm/hive identity line at the top. All dashboard sub-pages include a `← Home` back-link for navigation. -No Matrix or Forge tile here — those surfaces (`/matrix/`, the forge's own -public URL) are reached directly, not linked from the dashboard UI. +No Matrix or Forge tile here — the operator reaches those surfaces +(`/matrix/`, the forge's own public URL) directly, not via the dashboard UI. ## L0GS page (`/logs.html`)