Watch
0
0
Fork
You've already forked hyperhive
0

docs: the hive has no approval queue

config-changes.md (was approvals.md) describes config PRs, the meta flake
and helper events; the approval queue, its kinds, the withdraw path, the
job-queue dispatch and ApprovalResolved go. Every other page drops the
approvals table, endpoints, event, tool group, hivectl verbs, dashboard
section and the loose-end/cancel kind, and links to the renamed page.
This commit is contained in:
atlas 2026-10-04 23:55:14 +02:00
commit e4b170f8c6
18 changed files with 122 additions and 327 deletions

View file

@ -24,7 +24,7 @@ from the dashboard tab strip.
standalone **C0R3** page (`/core.html`), and FL0W / L0GS / ST4TS
live on their own pages too, all reachable from the
H0M3 hub (not the tab strip). Count pills on SW4RM
(container count), Y3R C4LL (pending approvals + unread
(container count), Y3R C4LL (unread
operator messages), and SCH3DUL3S (active schedules left to copy).
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
— sits below the tab strip.
@ -46,13 +46,12 @@ from the dashboard tab strip.
snapshot. Hidden when there are no warnings.
- **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, the
page prepends a `(N)` prefix — `(3) pr1ma // h1ve-c0re` — so the
arrive in the state snapshot. When there are unread operator messages,
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 page sets the prefix on the initial
`/api/state` cold-load and updates it live via
`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 operator-inbox
cold-load and updates it live as broker `sent` events arrive; 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
@ -74,12 +73,7 @@ agent is stale.
## Y3R C4LL tab
Things blocked on operator decision — the approval queue.
**P3NDING APPR0VALS** — the queue (see "Approval card" below). A
`pending · N` / `history · N` tab pair switches between the live
queue and the last 30 resolved approvals (see "Approval card" for
the history row shape).
Things blocked on operator decision — the operator inbox.
**0PER4T0R 1NB0X** — messages agents have sent to `to="operator"` but
the operator hasn't read yet. Cold-loaded from `/api/operator-inbox` on
@ -332,7 +326,7 @@ named buckets of MCP tools; each agent starts with a role default
(sub-agents: `messaging`, `meta`, `inbox`, `execution` —
`ToolGroup::AGENT_DEFAULT`; hive-c0re seeds the root agent to
`ToolGroup::MANAGER_DEFAULT` — `messaging`, `meta`, `inbox`,
`lifecycle`, `approvals`, `execution`,
`lifecycle`, `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
@ -341,8 +335,7 @@ takes effect.
<!-- vale write-good.Passive = YES -->
The current tool groups are: `messaging`, `meta`, `inbox`, `lifecycle`,
`approvals`, `forge`, `execution`,
`web_tools`. All listed in `ToolGroup::ALL` in `hive-sh4re`. The
`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.
@ -739,19 +732,17 @@ that wants step-level counts instead, unused here.
### Themed dialogs
All confirmations, prompts, and transient error notices use an
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 the OS can't style them away.
Three primitives, all built on the `openDialog` core:
All confirmations and transient error notices use an in-app themed
dialog system (`@hive/shared/modal.js`) rather than the browser's
native `confirm()` / `alert()` chrome, so they match the Catppuccin
palette and the OS can't style them away. Two primitives, both built
on the `openDialog` core:
- `themedConfirm({ message, danger, confirmLabel, checkboxes })`
— a modal confirm that resolves to `null` on cancel or an object
of checkbox states on confirm. Destructive actions pass
`danger: true` (the confirm button turns red and the cancel
button takes focus). Selecting the backdrop and `Esc` both cancel.
- `themedPrompt(...)` — a modal with a text input, resolving to the
entered string or `null`.
- `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.
@ -816,51 +807,18 @@ frosted-mauve bar slides up from the bottom of the viewport
Every render prunes stale selections (agents destroyed while
selected) before the bar appears.
## Approval card
Each pending approval renders as a card (`assets/call.js::
renderApprovals`) with three stacked sections:
- **identity header** — glyph, `#id`, agent, kind chip, and a
right-aligned `requested <N> ago` relative time from
`ApprovalView.requested_at`. Glyph and chip vary by kind:
| kind | glyph | chip |
|---|---|---|
| `update_meta_inputs` | `↻` | `meta-update` |
<!-- 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;
the `.stale` class flips precisely at the 3600s boundary rather
than at the next `renderApprovals` call.
- **what-changed body** — the submitting agent's description, then the
kind's payload: the inputs to bump (`update_meta_inputs`).
- **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.
## Browser notifications
Pure frontend (`Notification` API). Two signals trigger them:
- new pending approval (per id, delta on `/api/state`)
- new broker message sent `to: "operator"` (live via SSE)
Pure frontend (`Notification` API), triggered by a new broker message
sent `to: "operator"` (live via SSE).
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>`,
`hyperhive:msg:<at>:<rand>`) so distinct events stack in the OS
Only messages that arrive while the page is open count. Per-event tags
(`hyperhive:msg:<at>:<rand>`) so distinct events stack in the OS
notification center instead of overwriting each other.
`console.debug` logs at every block point (unsupported,
permission ungranted, muted) for in-browser debugging. Selecting it
@ -880,17 +838,6 @@ the H0M3 hub's **API** tile), with the raw spec at `/api/openapi.json`.
It's a growing supplement, not yet a full replacement for the list
below — some endpoints aren't in it yet.
- `POST /api/approve/{id}` — approve a pending approval. Fires
`ApprovalResolved` on the dashboard event channel; client
updates derived approvals state from the event.
- `POST /api/deny/{id}` (`note=<reason>`, optional) — deny a pending
approval with an optional operator-supplied reason. The reason
travels to the submitting agent as `HelperEvent::ApprovalResolved.note`
and also rides on the dashboard's `ApprovalResolved` event.
Dashboard prompts via the themed `themedPrompt()` dialog on
selection — a resizable `<textarea>` where Enter submits and
Shift+Enter inserts a newline (so multi-sentence rejection
notes are possible).
- `POST /api/{rebuild,kill,restart,start,destroy}/{name}` — lifecycle.
`destroy` accepts `purge=on` to also wipe state dirs.
- `POST /api/purge-tombstone/{name}` — wipe a tombstone's state dirs.
@ -1046,10 +993,6 @@ payload):
rows with a `↳ reply` tag that scroll-highlights the parent
row on selection. Used by the message-flow terminal renderer and
the operator-inbox derived state.
- `approval_resolved` (id, agent, approval_kind, status,
resolved_at, note, description) — moves a row from the pending
queue to history. Client mutates a derived store and
re-renders only the approvals section.
- `transient_set` (name, transient_kind, since_unix) /
`transient_cleared` (name) — lifecycle action spinners. The
client ticks the elapsed-seconds badge off `since_unix`
@ -1104,15 +1047,13 @@ payload):
`/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-
shaped yet). Every other section — approvals,
transients, containers, operator inbox, message flow —
shaped yet). Every other section — 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.
<!-- vale write-good.Passive = YES -->
Generalised form helpers: `form[data-confirm="…"]` pops
`confirm()` before submit; `form[data-prompt="…"]` pops
`prompt()` and stashes the answer in a hidden input named by
`data-prompt-field` (default `note`).
Generalised form helper: `form[data-confirm="…"]` pops
`confirm()` before submit.