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

@ -163,27 +163,18 @@ the dashboard's "mark all read" (unbounded, per-agent).
### Loose-ends wire shape
`LooseEnd` is the per-row response shape for `GetLooseEnds` — one
request shape, no per-socket flavours. Tagged enum so
new thread kinds (forge PRs, long-running approvals from a
privileged bot, etc.) can land later without breaking existing
handlers. Each row carries enough context that the caller renders
request shape, no per-socket flavours. Tagged enum so new thread kinds
(forge PRs, etc.) can land later without breaking existing handlers.
Each row carries enough context that the caller renders
it directly as a bulleted list, no follow-up fetch needed.
`GetLooseEnds` takes no target — it always returns the caller's own
rows, on both the agent and manager sockets alike (the manager, `ruth`,
is a normal agent here, just deployed automatically with different
default capabilities). `Approval` rows only appear when the calling agent is
the manager (sub-agents don't submit approvals). `Reminder` rows always
carry `owner == self`.
default capabilities). `Reminder` rows always carry `owner == self`.
Per-variant fields:
- `Approval { id, agent, commit_ref, description?, age_seconds }`
— `agent` is the affected agent (target of the spawn / config
commit), not the asker. `description` is the manager's free-text
blurb shown on the dashboard card. `commit_ref` is the
kind-specific payload (see `docs/agent-lifecycle/approvals.md::Approval kinds
(wire shapes)`).
- `Reminder { id, owner, message, due_at, age_seconds }` —
`due_at` is the absolute time the scheduler is targeting (RFC
3339 on the wire, see *Timestamps on the wire* below); clients
@ -205,16 +196,9 @@ Per-variant fields:
unsynchronised wall clock, etc.) so the bulleted list never
shows nonsense ages.
`CancelLooseEnd { kind, id }` is the matching write surface. The
`kind` enum (`Reminder` / `Approval`) selects which underlying store
the dispatcher reaches into. `Reminder` cancels from either surface
subject to an ownership check (the scheduling agent).
`Approval` is manager-only — sub-agents don't submit approvals
so they have nothing of their own to withdraw; their wire
surface returns a clear error if they try. Cancelling an approval
transitions the row to `ApprovalStatus::Cancelled` and fires
`ApprovalResolved { status: "cancelled" }` so the dashboard pulls
the card out of the pending pane.
`cancel_loose_end` is the matching write surface, handled in the
harness without a hive-c0re round-trip: `reminder` deletes one of the
caller's own pending reminders, `todo` clears one of its todos.
### Agent metadata
@ -296,7 +280,6 @@ binary flavor.
| `inbox` | `get_loose_ends`, `cancel_loose_end`, `remind` |
| `execution` | vestigial — `mcp__bash__run` / `mcp__bash__status` are always available unconditionally via `extraMcpServers`; this group's entries expand to non-existent `mcp__hyperhive__run` / `mcp__hyperhive__status` and have no effect. See `docs/tools/bash.md`. |
| `lifecycle` | none |
| `approvals` | none — gates `cancel_loose_end`'s approval-cancel arm server-side. |
| `forge` | none |
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
@ -316,7 +299,7 @@ clear them.
meta repo alongside `topology.json`). Format: `{ "alice": ["messaging", "meta",
"inbox", "lifecycle"], "bob": ["messaging", "meta", "inbox"] }`. An absent entry
means "use role default." Tool permissions are intentionally NOT configurable
from `agent.nix` — that file goes through the manager's approval flow, so
from `agent.nix` — that file changes through config PRs the manager opens, so
letting it declare its own groups would let the manager grant itself any tool by
submitting a config commit, bypassing the operator gate.
@ -385,9 +368,7 @@ dashboard and `app.js` on the per-agent UI) intercepts, shows a spinner,
POSTs `application/x-www-form-urlencoded` (axum's `Form` extractor
rejects multipart), calls `refreshState()` on success. New mutating
forms should add `data-async` and optionally `data-confirm` (for a
JS-side `confirm()` prompt) or `data-prompt="…"` (for a
`window.prompt()` whose answer goes into a hidden input named by
`data-prompt-field`, default `note`).
JS-side `confirm()` prompt).
`refreshState` defers automatically when `document.activeElement`
sits inside a managed section so the operator's typing isn't lost;
@ -404,7 +385,7 @@ into the `Swap` node, then runs `nixos-container update` + stop +
start across the `StopForUpdate → Swap → RebuildBookkeeping`
brace and the tail `Reconcile` node. `flake.nix` itself lives in the agent's
proposed/applied repos and rides along on every fetch (see
`docs/agent-lifecycle/approvals.md::Two repos per agent`).
`docs/agent-lifecycle/config-changes.md::Two repos per agent`).
Anything that changes per-container state on the host should be
re-applied here so a manual `↻ R3BU1LD` from the dashboard is
@ -412,7 +393,7 @@ sufficient to recover.
## Actions live in one place
`approve` / `deny` / `destroy` (and the lifecycle helper) live in
`destroy` (and the lifecycle helper) live in
`actions.rs` / `hive-c0re/src/dashboard/`. The admin socket and the dashboard
POST handlers both call into them so the two surfaces never drift.

View file

@ -218,15 +218,6 @@ overlap" case. REUSEADDR does **not** allow two simultaneous
`LISTEN` sockets on the same port (that would be `SO_REUSEPORT`,
not used here) — it preserves exclusivity.
## Approvals
### Orphan approvals
If test scripts or a manual `rm -rf` wipe state dirs out from under a
pending approval, the dashboard's next render marks them
`failed` with note `"agent state dir missing"` so they fall out of
`pending`. They stay in sqlite for audit.
## Gateway / SPA serving
### SPA fallback: use `Accept` header map, not `try_files ... /index.html`