docs: suppress reviewed write-good.Passive false positives

133 hits across 38 files, all previously classified during #4548's sweep
and deliberately left un-rewritten (predicate-adjective state/necessity
description, design-intent idiom, structural/type-description idiom,
no-single-actor topology claim, parallel-triple exception, vale
substring-match artifact — see hyperhive#4548's per-PR bodies for the
per-hit reasoning).

Wraps each one in a scoped <!-- vale write-good.Passive = NO/YES -->
pair (the supported mechanism — TokenIgnores has a known offset-drift
bug) rather than a blanket per-file or per-rule silence, so a *new*
passive-voice hit anywhere in these files still fails once the rule
gates CI (next commit). Table/list false positives (docs/swarm/credentials.md's
renewal-table cells) wrap the whole block, not each cell.

Part of #4546.
This commit is contained in:
iris 2026-09-20 15:07:46 +02:00
commit 04e27c4fb6
38 changed files with 368 additions and 71 deletions

View file

@ -27,6 +27,7 @@ moment any row of badges/pills wrapped onto an extra line at some
viewport width; measuring instead of guessing closes that bug class
structurally rather than for one specific trigger. Two columns:
<!-- vale write-good.Passive = NO -->
- **Agent icon** (`<img class="agent-icon">`): fixed-size square
identity anchor — `width: 5em; height: 5em` with explicit pixel
sizing so the `<img>`'s intrinsic (large) dimensions don't push
@ -100,6 +101,7 @@ structurally rather than for one specific trigger. Two columns:
- No header cancel-turn button any more — `/cancel` (slash command,
below) is the only path; the turn-loop state badge already shows
`thinking` as the discoverability cue.
<!-- vale write-good.Passive = YES -->
Values throughout come from `GET /api/state`'s cold-load snapshot,
kept in sync afterwards by the SSE stream (see Live view below) —
@ -113,6 +115,7 @@ so two tabs from different hives are distinguishable; the header's own
**Main content** (`<main class="agent-main">`): fills the viewport
and scrolls behind the fixed header + footer.
<!-- vale write-good.Passive = NO -->
- `#status` overlay: empty when online; shows the login form / OAuth
URL when `status` is `needs_login_*`. The OAuth code input is
`type="password"` with a `👁 reveal` toggle that flips it back to
@ -135,6 +138,7 @@ and scrolls behind the fixed header + footer.
composites above the composer. Geometry is unchanged —
`.agent-main` and `.terminal-wrap` both `inset: 0` fill the same
area.
<!-- vale write-good.Passive = YES -->
## Footer / composer

View file

@ -310,9 +310,11 @@ Three sub-tabs:
### MATRIX tab
<!-- vale write-good.Passive = NO -->
Provision / log in a per-agent **external** matrix account and store its
access token (this half is unchanged from the old `/matrix-accounts.html`
page it replaces — only the URL and surrounding chrome moved).
<!-- vale write-good.Passive = YES -->
An agent picker (populated from `state.containers`, the live roster) drives a list of that
agent's accounts — name, homeserver, user id, and a status dot —
@ -447,6 +449,7 @@ boxes only stages the change in-browser; the browser writes nothing until
the operator selects the page-level **save all** button (described below). Row
values follow the `effective`/`assignments` rule described above.
<!-- vale write-good.Passive = NO -->
**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`
@ -458,6 +461,7 @@ 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`. hive-c0re queues a rebuild so `HIVE_TOOL_GROUPS`
takes effect.
<!-- vale write-good.Passive = YES -->
The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`,
`approvals`, `scheduling`, `forge`, `execution`,
@ -746,6 +750,7 @@ falls back to the dimmed hyperhive mark (`/favicon.svg`). The card
body sits to the right with three stacked lines
(`assets/swarm.js::renderContainers`).
<!-- vale write-good.Passive = NO -->
**Icon layout + load strategy:** the `<img>` is absolutely
positioned (`inset: 0`) inside the `.container-icon` wrapper —
the wrapper is the flex child and sizes itself via `width: 5em` +
@ -762,7 +767,9 @@ the dashboard itself, always reachable) and adds the
already knows the container is stopped (`ContainerView.running = false`)
the fallback fires immediately, skipping the doomed `<url>/icon`
fetch entirely.
<!-- vale write-good.Passive = YES -->
<!-- vale write-good.Passive = NO -->
**Line 1** — agent name (link → new tab), m1nd/ag3nt chip, an
**icon-only nav strip** plus live agent-owned state, all populated
async from a single `GET /api/dashboard-state` call to the agent's
@ -793,7 +800,9 @@ that's unset — never guessed from `<host>:3000`. External links are
already absolute. The same base URL drives the primary agent-name
link + favicon fetch, so the whole row routes through the gateway
as a unit.
<!-- vale write-good.Passive = YES -->
<!-- vale write-good.Passive = NO -->
**When the container is stopped** (`ContainerView.running = false`),
the dashboard skips the async `dashboard-state` fetch entirely (the agent
web server is down), so a single badge replaces the badge chain,
@ -803,6 +812,7 @@ badges disappear. The agent icon goes straight to the dimmed
container's URL. Static fields — `needs_update`, `deployed_sha`,
`pending_reminders`, `parent`, `config` link — remain visible
regardless of run state.
<!-- vale write-good.Passive = YES -->
**Line 2** — status badges only (no per-card action buttons — actions
moved to the **selection bar** or the **per-agent `⋮` menu**, see
@ -1010,6 +1020,7 @@ When the operator selects one or more agents (via the icon), a sticky
frosted-mauve bar slides up from the bottom of the viewport
(`#selection-bar`, `position: fixed; bottom: 0`). It shows:
<!-- vale write-good.Passive = NO -->
- **Count + names** — "N agents selected · name1, name2, …"
- **Bulk action buttons** — only enabled when ALL selected agents
support the action; disabled with a tooltip naming the blockers
@ -1037,6 +1048,7 @@ frosted-mauve bar slides up from the bottom of the viewport
- **multiple agents**`POST /api/topology/set-parent-bulk`
(JSON `[{ child, new_parent }]`; all moves land in a single
`topology.json` commit instead of one per agent)
<!-- vale write-good.Passive = YES -->
Both write `topology.json` and re-emit a container snapshot so
the tree repaints without a page reload.
@ -1061,6 +1073,7 @@ renderApprovals`) with three stacked sections:
| `schedule_prompt` | `⏱` | `schedule` | — |
| `spawn` | `⊕` | `spawn` | — |
<!-- vale write-good.Passive = NO -->
The chip ticks live every second via a `data-requested-at`
attribute + client-side interval (no re-render). Turns amber once
the request has been pending ≥ 1h so a stale approval stands out;
@ -1076,6 +1089,7 @@ renderApprovals`) with three stacked sections:
- **decision actions**`◆ APPR0VE` and `DENY`. Deny pops a
`prompt()` for an optional reason carried to the submitting agent as
`HelperEvent::ApprovalResolved.note`.
<!-- vale write-good.Passive = YES -->
A `pending · N` / `history · N` tab pair switches the section
between the live queue and the last 30 resolved approvals.
@ -1091,6 +1105,7 @@ The toggle controls live in the Y3R C4LL tab's ◆ PR3F3R3NC3S ◆
section; see that section above for the user-facing shape. Dispatch
logic lives in `common.js::NOTIF`.
<!-- vale write-good.Passive = NO -->
First `/api/state` after page load seeds "seen" sets without
firing — only items that arrive while the page is open count.
Per-event tags (`hyperhive:approval:<id>`,
@ -1105,6 +1120,7 @@ permission. Requires a secure context (HTTPS or localhost); on
other origins the controls hide themselves. Browsers typically
suppress notifications while the originating tab is focused —
that's a browser-level decision, not the dashboard's.
<!-- vale write-good.Passive = YES -->
## Dashboard endpoints
@ -1183,6 +1199,7 @@ below — some endpoints aren't in it yet.
bodies at 1 MiB. Selection-time backing for the inline path-link
preview.
<!-- vale write-good.Passive = NO -->
The broker forwarder detects which tokens *are* path links
**server-side at broker-message ingest**, not client-side:
it calls `scan_validated_paths(body)`
@ -1298,6 +1315,7 @@ below — some endpoints aren't in it yet.
- `GET /api/dashboard/history` — last ~200 broker messages
(wrapped as `{ seq, events }`) for the message-flow
terminal's backfill on page load.
<!-- vale write-good.Passive = YES -->
## Dashboard event channel
@ -1378,6 +1396,7 @@ payload):
`nix flake update` ripple starts or completes. BU1LDS M3T4 1NPUTS
tab uses this to show/hide the "⏳ meta-update running" banner.
<!-- vale write-good.Passive = NO -->
`/api/state` is **only fetched on cold-load and on the few
forms that mutate non-event-derived state** (PURG3 +
meta-update, since tombstones + meta_inputs aren't event-
@ -1386,6 +1405,7 @@ transients, containers, operator inbox, message flow —
derives from `/api/dashboard/stream` after the initial snapshot,
maintaining its own client-side store and applying events on
top. The 5s periodic poll is gone.
<!-- vale write-good.Passive = YES -->
Generalised form helpers: `form[data-confirm="…"]` pops
`confirm()` before submit; `form[data-prompt="…"]` pops

View file

@ -45,6 +45,8 @@ home.js`, is the reference example — currently in the dashboard
## Motion
<!-- vale write-good.Passive = NO -->
**General rule, not case-by-case: every non-essential CSS animation
gates on `prefers-reduced-motion` and pauses when its tab/section is
hidden.** The dashboard's matrix-rain background (`packages/dashboard/
@ -54,6 +56,8 @@ though it lives in the dashboard package rather than swarm-ui; every
future swarm-ui animation follows the same pattern, not just whimsy
pieces.
<!-- vale write-good.Passive = YES -->
Prefer CSS-driven animation over JS-driven where possible, and avoid
jarring content swaps (layout shift, hard cuts) where a transition can
smooth them instead.
@ -88,6 +92,8 @@ The governing question for anything that shows time-sensitive data:
needs a refresh story; a value that's silently gone stale with no way to
tell is worse than one that's visibly stale.
<!-- vale write-good.Passive = NO -->
- **Relative-time labels must actually tick.** A label like "fresh (5s
ago)" derives from a stored timestamp and re-renders itself on an
interval — never a value frozen at fetch time that quietly goes stale
@ -97,9 +103,10 @@ tell is worse than one that's visibly stale.
1m / …" control the operator sets per page, paused while the tab is
backgrounded and resumed on foreground.
- **A refresh must never clobber input the operator is mid-edit on.**
Any polling component's contract needs to make this the caller's
problem to opt out of correctly, not something the next adopter
discovers by shipping a bug.
Any polling component's contract needs to make this the caller's
problem to opt out of correctly, not something the next adopter
discovers by shipping a bug.
<!-- vale write-good.Passive = YES -->
## Errors

View file

@ -110,6 +110,8 @@ shapes the renderers call:
- `api.fromHistory``true` while backfill replay is running; renderers
use it to suppress live-only side effects.
<!-- vale write-good.Passive = NO -->
**`create(opts)` options:** `logEl` (log container element), `streamUrl`
(SSE endpoint), `historyUrl?` (optional replay endpoint — skipped if absent
or if the fetch fails), `renderers` (kind→fn map; unknown kinds fall through
@ -126,6 +128,8 @@ than captured once — lets a page default otherwise-collapsed panels open
per a live browser-local preference; renderers that force a row open
regardless, for example message-bearing tool_use, are unaffected either way).
<!-- vale write-good.Passive = YES -->
**Sticky-bottom + snap animation.** `stickToBottom` is the
operator's intent: true means "keep snapping to bottom on every
mutation," false means "I scrolled up, leave me alone." The flag
@ -238,6 +242,8 @@ checkboxes use a lighter snapshot-then-restore pattern (snapshot
before `replaceChildren`, restore after) since they're single
values rather than per-row caches.
<!-- vale write-good.Passive = NO -->
**`<details>` open-state preservation:** any collapsible element
tagged with `data-restore-key="<stable-key>"` survives the
refresh. `snapshotOpenDetails()` walks managed sections before
@ -250,6 +256,8 @@ dashboard's own answered-questions history list was the only
nothing to restore, kept in place for the next collapsible section
that needs it rather than ripped out along with their one caller.
<!-- vale write-good.Passive = YES -->
**Side panel (dashboard):** long content opens in a drawer that
swipes in from the right — a singleton `#side-panel` with a
titled header, a close button, and a scrollable body. Closes on