docs: fix genuine passive-voice hits in docs/web-ui (small files)
agent.md, css-vars.md, design-guide.md, shape.md, terminal-rendering.md --
26 of 40 write-good.Passive hits rewritten to name the actor (hive-agent,
browsers, the harness, the client, lifecycle::{spawn,rebuild}, CSS, the
router, ...), reusing an actor already named nearby wherever one exists.
14 left alone: established config-state conditionals ("when X is
set/enabled/given/called"), negative-capability/state-descriptor idioms
("is gone", "is hidden", "is unchanged"), one false-positive
("typed slash commands" as a compound noun, not a passive action), a
backward-looking changelog fact with no actor worth naming, and two
deliberately-parallel rhetorical contrasts (sanitized vs XSS-safe;
cache-hit vs cache-miss) left symmetric on purpose.
dashboard.md (70 more hits) is the next docs/web-ui/ batch, not part of
this one -- big enough to deserve its own PR.
This commit is contained in:
parent
767f87610a
commit
e9d59f3d10
5 changed files with 43 additions and 43 deletions
|
|
@ -21,8 +21,8 @@ output, not something a selector reaches by id).
|
|||
glass — `backdrop-filter: blur` lets scrolled terminal rows show
|
||||
through. Measures its own rendered height via `ResizeObserver`
|
||||
(`Header.tsx`) and writes it to a CSS custom property the content
|
||||
below reads for its offset — a fixed `6em` guess used to be baked into
|
||||
`agent.css`, which silently broke (content overlapping the header) the
|
||||
below reads for its offset — `agent.css` used to bake in a fixed `6em`
|
||||
guess, which silently broke (content overlapping the header) the
|
||||
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:
|
||||
|
|
@ -77,8 +77,8 @@ structurally rather than for one specific trigger. Two columns:
|
|||
extras) — all as real `<a>` elements, not a `Dropdown`-style
|
||||
command list, so ctrl/middle-click and "copy link address" keep
|
||||
working. Each `AgentLink.kind` resolves differently: `container` →
|
||||
same-origin path; `forge` → `state.forge_public_url + url`, and the
|
||||
link is dropped entirely when that's unset (never guessed from
|
||||
same-origin path; `forge` → `state.forge_public_url + url`, and
|
||||
hive-agent drops the link entirely when that's unset (never guessed from
|
||||
`<host>:3000`); `external` → already absolute. Same source
|
||||
(`GET /api/state`'s `links` field) also feeds
|
||||
`DashboardState.links` for the dashboard card's icon strip —
|
||||
|
|
@ -121,7 +121,7 @@ and scrolls behind the fixed header + footer.
|
|||
shoulder-surfers or screenshots. `autocomplete="one-time-code"`
|
||||
is the semantic value for OAuth codes (per WHATWG): browsers may
|
||||
silently ignore `autocomplete="off"` on `type="password"`, but
|
||||
`one-time-code` is honoured and suppresses the "save password
|
||||
browsers honour `one-time-code` and suppress the "save password
|
||||
for this site?" prompt that would otherwise fire on submit.
|
||||
- Terminal-wrap: live event tail (sticky-bottom autoscroll +
|
||||
`↓ N new` pill when not at bottom). The pill is **anchored in
|
||||
|
|
@ -154,8 +154,8 @@ journald logs). Inbox flyout: unread messages addressed to this agent
|
|||
with `↳ reply ·` in amber. A `✓ mark all read` button appears in the
|
||||
flyout header when the inbox is non-empty; selecting it confirms then
|
||||
POSTs cross-origin to the core dashboard's `POST
|
||||
/api/agent/{name}/mark-all-read` — all pending messages for this agent
|
||||
are acked, the harness won't receive wake-prompts for them. A `{
|
||||
/api/agent/{name}/mark-all-read`, which acks all pending messages for
|
||||
this agent so the harness won't receive wake-prompts for them. A `{
|
||||
marked: N }` pill surfaces the count. After the drain the inbox list
|
||||
empties on reload (the filter is `acked_at IS NULL`, so drained
|
||||
messages disappear). Todos flyout ("loose-ends v2"): the harness-local
|
||||
|
|
@ -219,7 +219,7 @@ the full row taxonomy and dispatch logic):
|
|||
`compact_boundary` emit muted notes; `commands_changed` emits an
|
||||
expandable details row listing slash commands; `thinking_tokens`
|
||||
updates a single in-place `🧠` counter; `init`, `result`, and
|
||||
`rate_limit_event` are dropped (noise / used elsewhere); other
|
||||
`rate_limit_event` drop silently (noise / used elsewhere); other
|
||||
subtypes → muted `⚙ <subtype>` note.
|
||||
- `Note` → `· text`.
|
||||
- `TurnStart` → `◆ TURN ← <from>` with the wake-prompt body; a
|
||||
|
|
@ -259,8 +259,8 @@ Slash commands today:
|
|||
Arms a one-shot on the Bus; next turn runs without
|
||||
`--continue`, dropping the resume session entirely.
|
||||
- `/logout` — `POST /api/logout` (confirms first). Wipes OAuth
|
||||
credential files, parks the agent in `needs_login`. Session
|
||||
history (`~/.claude/projects/`) is preserved.
|
||||
credential files, parks the agent in `needs_login`, and preserves
|
||||
session history (`~/.claude/projects/`).
|
||||
|
||||
Unknown `/foo` shows an error row instead of being silently sent.
|
||||
|
||||
|
|
@ -314,17 +314,17 @@ shaped).
|
|||
session continuity — logout must stay narrowed to just the
|
||||
credential files.
|
||||
3. Flip `LoginState::NeedsLogin` + emit a `LiveEvent::Note`
|
||||
describing exactly what was wiped, then emit
|
||||
naming the files it just deleted, then emit
|
||||
`needs_login_idle`. The turn-loop's next iteration parks
|
||||
into `wait_for_login`, which snapshots the credential dir
|
||||
(now missing the wiped files) and resumes when a fresh
|
||||
credentials file appears via the dashboard's `/login/code`
|
||||
flow (the same mtime-resumption path manual re-login uses).
|
||||
|
||||
Always returns 200 with a body describing what happened —
|
||||
per-file errors are folded into the response + the Note so the
|
||||
Always returns 200 with a body describing what happened — it
|
||||
folds per-file errors into the response + the Note so the
|
||||
operator sees them in the live panel rather than as an HTTP
|
||||
error. Missing files (already logged out) are treated as
|
||||
error. Missing files (already logged out) count as
|
||||
idempotent.
|
||||
- `GET /api/state` — cold-load snapshot (`StateSnapshot`) consumed by
|
||||
the frontend (`useAgentState.ts`) on page load and, on a poll, while
|
||||
|
|
@ -374,7 +374,7 @@ shaped).
|
|||
dimensions; enabled once the server advertises the
|
||||
`ExtendedDesktopSize` pseudo-encoding (`-308` rect in the header).
|
||||
Fit-mode state persists in `localStorage` (`screen-fit`); default
|
||||
is on. Pointer coordinates are rescaled in `sendPointer` so clicks
|
||||
is on. `sendPointer` rescales pointer coordinates so clicks
|
||||
land on the right pixel regardless of CSS scale.
|
||||
- `GET /screen/ws` — raw RFB byte relay: proxies WebSocket
|
||||
frames to the weston VNC server at `127.0.0.1:<vnc_port>`.
|
||||
|
|
@ -400,8 +400,8 @@ Bus events (new vocabulary on `/events/stream`):
|
|||
|
||||
- `status_changed { status }` — `online` / `rate_limited` /
|
||||
`needs_login_idle` / `needs_login_in_progress`. Drives the
|
||||
alive-badge. `rate_limited` is set when the harness detects a
|
||||
429 response and cleared when the retry sleep expires.
|
||||
alive-badge. The harness sets `rate_limited` when it detects a
|
||||
429 response and clears it when the retry sleep expires.
|
||||
- `model_changed { model }` — drives the model chip.
|
||||
- `effort_changed { effort }` — drives the effort picker chip.
|
||||
Emitted from `Bus::set_effort` on `POST /api/effort`; applies on
|
||||
|
|
@ -452,7 +452,7 @@ input tokens of the most recent fresh claude session's first turn —
|
|||
a proxy for system-prompt + CLAUDE.md sprawl (a fresh session's first
|
||||
turn pays the full static prefix uncached). It's derived in `stats.rs`
|
||||
(`first_turn_ctx`: the first turn, `ORDER BY started_at LIMIT 1`, of
|
||||
the latest `sessions` row in the window) and is omitted from the JSON
|
||||
the latest `sessions` row in the window) and stays out of the JSON
|
||||
until the `sessions` / `turn_stats.session_id` capture has rows — so
|
||||
the chip stays hidden on older dbs (inert-until-capture).
|
||||
`stats.rs` opens the sqlite db read-only and degrades to an
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ for the raw `--baseNN` slots directly. (`base.css` holds only the shared
|
|||
|
||||
`colors.css` declares each palette's 16 hex values exactly once —
|
||||
`--mocha-baseNN` (dark, Catppuccin Mocha) and `--latte-baseNN` (light,
|
||||
Catppuccin-Latte-derived; `base08`-`base0F` are darkened from stock
|
||||
Catppuccin-Latte-derived; `base08`-`base0F` run darker than stock
|
||||
Latte to actually clear WCAG AA against how this app uses them — real
|
||||
contrast failures found in review, see the comment above those
|
||||
declarations in `colors.css` for the numbers and why). Everything else
|
||||
|
|
@ -43,8 +43,8 @@ them **first** (`colors.css` then `theme.css`) ahead of the page CSS. Note
|
|||
`theme.css` does **not** `@import` `colors.css` — that would bake the
|
||||
slots back into it; they're two separate output files so a swap replaces
|
||||
just `colors.css`. (Load order doesn't actually affect resolution —
|
||||
custom properties resolve at computed-value time — but `colors.css` is
|
||||
linked first for clarity.)
|
||||
custom properties resolve at computed-value time — but each page still
|
||||
links `colors.css` first for clarity.)
|
||||
|
||||
## Semantic palette (`theme.css`)
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ needs a refresh story; a value that's silently gone stale with no way to
|
|||
tell is worse than one that's visibly stale.
|
||||
|
||||
- **Relative-time labels must actually tick.** A label like "fresh (5s
|
||||
ago)" is computed from a stored timestamp and re-renders itself on an
|
||||
ago)" derives from a stored timestamp and re-renders itself on an
|
||||
interval — never a value frozen at fetch time that quietly goes stale
|
||||
while still reading as current. Pauses while its tab is hidden.
|
||||
- **Pages that poll get a refresh-interval control, not silent
|
||||
|
|
@ -143,8 +143,8 @@ just bare column headers floating over nothing.
|
|||
## Component-first design
|
||||
|
||||
Build the `src/ui/` primitive before or alongside the first real page
|
||||
that needs it, not after it's been styled inline and left for later —
|
||||
a page reaching for a component that's already there has ready-made
|
||||
that needs it, not after a contributor styles it inline and leaves it
|
||||
for later — a page reaching for a component that's already there has ready-made
|
||||
blocks to build with, instead of the next contributor duplicating
|
||||
ad-hoc styling that someone then has to hunt down and consolidate.
|
||||
`Panel`/`Badge`/`Table`/`TextField`/`SelectField`/`Button` are the
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
- `GET /` → `index.html` from the bundled frontend dist (see
|
||||
`frontend/`). Both binaries' routers declare their dynamic
|
||||
endpoints first and then `fallback_service(ServeDir::new(...))`
|
||||
pointed at `HIVE_STATIC_DIR` — anything not matched by an API or
|
||||
action route is served from the dist. Dashboard dist lives at
|
||||
pointed at `HIVE_STATIC_DIR` — that fallback serves anything not
|
||||
matched by an API or action route from the dist. Dashboard dist lives at
|
||||
`${frontend}/dashboard`; per-agent dist is the merged
|
||||
`hyperhive.frontend.mergedDist` (default agent dist + per-agent
|
||||
`extraFiles` overlay).
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
to `target="_blank"`.
|
||||
- `GET /api/state` → JSON snapshot the JS app renders into the
|
||||
DOM. Includes a top-level `seq` (the dashboard event channel's
|
||||
high-water mark at the moment the snapshot was assembled);
|
||||
high-water mark at the moment the server assembled the snapshot);
|
||||
clients use it to dedupe their buffered SSE traffic against
|
||||
the snapshot (drop frames with `seq <= snapshot.seq`).
|
||||
- `GET /api/dashboard/stream` (dashboard) / `GET /events/stream`
|
||||
|
|
@ -88,9 +88,9 @@
|
|||
|
||||
## Shared terminal pane
|
||||
|
||||
Both surfaces' scrollable log streams (`#msgflow` on the dashboard,
|
||||
`#live` on the per-agent page) are backed by the shared terminal
|
||||
factory in `@hive/shared/terminal.js`. The factory wires up
|
||||
The shared terminal factory in `@hive/shared/terminal.js` backs both
|
||||
surfaces' scrollable log streams (`#msgflow` on the dashboard, `#live`
|
||||
on the per-agent page). The factory wires up
|
||||
sticky-bottom autoscroll, a "↓ N new" pill, history backfill, and
|
||||
SSE replay. Pages register a `kind → renderer` map; unknown kinds
|
||||
fall through to a JSON-dump note row. The factory ships three row
|
||||
|
|
@ -175,8 +175,8 @@ initial visual lag to one frame instead of one microtask + frame.
|
|||
|
||||
**Backfill + SSE.** Cold load fetches `historyUrl` (replay), then
|
||||
subscribes to `streamUrl` (live tail). Both endpoints return
|
||||
`{ seq, events }` so the client can dedupe — events with
|
||||
`seq <= snapshot.seq` from the SSE stream are dropped silently
|
||||
`{ seq, events }` so the client can dedupe — the client silently
|
||||
drops events with `seq <= snapshot.seq` from the SSE stream
|
||||
(the snapshot already covers them). History rows render with a
|
||||
`.no-anim` class so they don't stagger in like live events. The
|
||||
optional `streamFactory(url)` callback lets the dashboard hand
|
||||
|
|
@ -221,8 +221,8 @@ leave it empty for a paint (on async builders) or a whole frame (on
|
|||
large synchronous ones), which reads as a visible flash on every
|
||||
poll cycle. Builders receive the fragment as their
|
||||
`root`, so existing renderer code carries over unchanged; early
|
||||
returns inside the builder still commit whatever was appended
|
||||
before they returned.
|
||||
returns inside the builder still commit whatever it appended
|
||||
before returning.
|
||||
|
||||
**Keyed DOM caching:** for sections whose rows hold interactive state
|
||||
(textarea drafts, checkboxes, focused inputs) `paintAtomic` isn't
|
||||
|
|
@ -260,8 +260,8 @@ the left edge captures pointer events, resizes the drawer in
|
|||
real-time (pointer capture keeps dragging even if the cursor
|
||||
outpaces the handle), and persists the chosen width to
|
||||
`localStorage` (key `hyperhive:side-panel-width`) so it
|
||||
survives page reload. Width is clamped to CSS `min-width: 320px`
|
||||
/ `max-width: 96vw`; the viewport-resize handler re-clamps
|
||||
survives page reload. CSS clamps the width between `min-width: 320px`
|
||||
and `max-width: 96vw`; the viewport-resize handler re-clamps
|
||||
persisted values after a window shrink. File
|
||||
previews are type-aware:
|
||||
|
||||
|
|
@ -286,9 +286,9 @@ Both bind their TCP listener with `SO_REUSEADDR` via
|
|||
the previous process's socket release resolves itself, but the two
|
||||
binaries differ on the attempt budget. The dashboard's
|
||||
`bind_with_retry` (`hive-c0re/src/dashboard/mod.rs`) has **no
|
||||
attempt cap** — retrying forever is deliberate, since genuine port
|
||||
collisions are preflighted host-side (`lifecycle::{spawn,rebuild}`
|
||||
refuses with a clear error, surfaced on the dashboard as a banner),
|
||||
attempt cap** — retrying forever is deliberate, since
|
||||
`lifecycle::{spawn,rebuild}` preflights genuine port collisions
|
||||
host-side (refuses with a clear error, surfaced on the dashboard as a banner),
|
||||
so at this layer a persistent `AddrInUse` always reflects a
|
||||
recoverable stale socket. Its first 12 attempts log at WARN; after
|
||||
that the level drops to INFO so a long-held stale socket doesn't
|
||||
|
|
@ -325,10 +325,10 @@ at without rebuilding the dist. The cases that matter:
|
|||
The gateway upstream config strips the prefix before forwarding to
|
||||
the per-agent server, so the agent's Rust routes (`api/state`,
|
||||
`events/stream`, `screen/ws`, `login/start`, …) keep their absolute
|
||||
paths server-side. Only the browser-facing URLs are gated on the
|
||||
paths server-side. Only the browser-facing URLs key off the
|
||||
mount prefix.
|
||||
|
||||
Subpages (`stats`, `screen`) are served without a trailing slash so
|
||||
The router serves subpages (`stats`, `screen`) without a trailing slash so
|
||||
the relative-path resolution stays correct: `static/stats.js` from
|
||||
`/stats` becomes `/static/stats.js` (last segment `stats` gets
|
||||
replaced), not `/stats/static/stats.js`. Adding a trailing slash to
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ The per-agent web UI's live pane renders one row per `TermMsg`
|
|||
(`hive-agent/src/term_msg.rs`): `{icon?, level: debug|info|warn|error,
|
||||
summary, body?, body_format?: markdown|diff, coalesce_key?}`. Classification
|
||||
(icon, summary text, whether a tool call gets an expandable body) happens
|
||||
server-side, once — `term_msg.rs` + `stream_enrich.rs` — and is served
|
||||
identically by both `GET /api/events/history` and `GET /api/events/stream`
|
||||
server-side, once — `term_msg.rs` + `stream_enrich.rs` — and both
|
||||
`GET /api/events/history` and `GET /api/events/stream` serve it identically
|
||||
as `TermEnvelope { ts, seq?, msgs: TermMsg[] }` frames
|
||||
(`hive-agent/src/web_ui/stream.rs`).
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue