docs: refresh for the dashboard rework + recent harness commits

- web-ui.md: side panel, approval card + 3-way diff base, stats
  page, forge config links, removed agent.nix viewer, per-agent
  loose-ends inline answer.
- approvals.md: forge mirror section + diff base toggle.
- turn-loop.md: recv(max), get_logs, remind, loose-ends, whoami.
- agent.md / manager.md prompts: recv(max), remind, get_logs.
- CLAUDE.md: forge.rs / stats.rs / hive-forge.nix in the file
  map, scratchpad refresh.

also: forgejo migrations.ALLOW_LOCALNETWORKS = true so an in-hive
mirror of the hyperhive repo can import from a localhost source.
This commit is contained in:
müde 2026-05-20 11:34:43 +02:00
parent 94781ccd08
commit 6ab3810e18
7 changed files with 205 additions and 36 deletions

View file

@ -7,6 +7,8 @@ scratchpad.
- High-level project intro: **[README.md](README.md)**.
- Open work + backlog: **[TODO.md](TODO.md)**.
- Deployment / ops / boundaries / gateway backlog:
**[TODO-ops.md](TODO-ops.md)**.
## File map
@ -69,6 +71,10 @@ hive-c0re/ host daemon + CLI (one binary, subcommand-dispatched)
prepare/finalize/abort, lock_update_*
src/migrate.rs startup auto-migration from pre-meta layout
(idempotent, marker-guarded phase 4)
src/forge.rs optional Forgejo wiring: per-agent users +
tokens, the `agent-configs` org, and
`push_config` — mirrors each applied repo
into `agent-configs/<n>` on the local forge
src/dashboard.rs axum HTTP: static shell + /api/state JSON + actions
+ journald viewer + bind-with-retry (SO_REUSEADDR)
+ deployed_sha chip per container +
@ -107,6 +113,9 @@ hive-ag3nt/ in-container harness crate; produces TWO binaries
src/turn_stats.rs per-turn analytics sink (one sqlite row per
turn at /state/hyperhive-turn-stats.sqlite);
schema + best-effort writer
src/stats.rs read-side aggregations over turn-stats.sqlite
backing the /stats page (bucketed Snapshot:
turns / duration / tokens / model mix)
src/events.rs LiveEvent + broadcast Bus + sqlite-backed history
(/state/hyperhive-events.sqlite) + TurnState +
model selection (persisted at /state/hyperhive-model)
@ -116,7 +125,8 @@ hive-ag3nt/ in-container harness crate; produces TWO binaries
src/login_session.rs drives `claude auth login` over stdio pipes
src/bin/hive-ag3nt.rs sub-agent main (Serve + Mcp subcommands)
src/bin/hive-m1nd.rs manager main (Serve + Mcp subcommands)
assets/ index.html, agent.css, app.js (include_str!)
assets/ index.html, agent.css, app.js, stats.html,
stats.js (include_str!)
prompts/ static role/tools/settings for claude (include_str!):
agent.md — sub-agent system prompt
manager.md — manager system prompt
@ -126,7 +136,10 @@ hive-sh4re/ wire types (HostRequest/Response, AgentRequest/Response,
ManagerRequest/Response, Message, Approval, HelperEvent)
nix/
modules/hive-c0re.nix systemd service + firewall + git wiring
modules/hive-c0re.nix systemd service + firewall + git wiring;
imports hive-forge.nix
modules/hive-forge.nix optional in-container Forgejo
(`hyperhive.forge.enable`, default on)
templates/harness-base.nix shared scaffolding for sub-agents + manager
templates/agent-base.nix sub-agent nixosConfiguration
templates/manager.nix manager nixosConfiguration
@ -185,6 +198,33 @@ read them à la carte.
In-flight or recent context that hasn't earned a section yet.
Prune freely.
- **Just landed:** dashboard side panel + forge-linked
config/approvals + per-bucket model stats. (a) Long content
(file previews, approval diffs, journald logs) opens in a
right-side slide-in panel instead of expanding inline;
markdown `.md` previews render through the vendored `marked`
bundle (`/static/marked.js` route added to the dashboard).
(b) the container-row `agent.nix` viewer + `/api/agent-config`
are gone — each row links to the agent's `agent-configs/<n>`
repo on the forge instead. (c) pending approvals render as a
card (identity / what-changed / decision actions) with a
`commit on forge` deep-link and a 3-way diff base toggle — vs
applied / vs last-approved / vs previous proposal — served by
the new `/api/approval-diff/{id}?base=` endpoint. (d) the
`/stats` page gained a per-bucket turns-by-model stacked bar
(`Snapshot.models` + `Bucket.model_counts`) since model
choice drives token cost. `/api/state` carries `forge_present`
so the links only show when the forge is up. Docs refreshed:
web-ui.md, approvals.md, turn-loop.md, agent.md, manager.md.
- **Just landed:** `hyperhive.forge.enable` (default **true**) —
the forge option moved out of `services.hive-forge.*` into the
`hyperhive.*` namespace, and `hive-c0re.nix` imports
`hive-forge.nix` so the forge ships with the standard core
install. Forgejo settings gained
`migrations.ALLOW_LOCALNETWORKS = true` so an in-hive mirror
of the hyperhive repo can import from a `localhost` source
(Forgejo blocks loopback/RFC-1918 migration sources by
default).
- **Just landed:** failed `nixos-container update` self-documents.
`lifecycle::run` now appends the tail (40 lines) of the target
container's own journal to the bail message when an `update`
@ -565,11 +605,9 @@ Prune freely.
agent_web_port + collision banner + spawn/rebuild preflight,
browser notifications, focus-preserving refresh, generalised
<details data-restore-key> survival, prompt-on-submit pattern.
- **Open threads:** custom per-agent MCP tools (groundwork for
moving bitburner-agent into hyperhive), two-step spawn,
per-agent send allow-list, telemetry/charts, notes
compaction, unprivileged containers, Bash allow-list,
xterm.js. **Known bug** (in TODO.md): question id=5 was
queued but didn't render — likely a `pending()` row-decode
error swallowed by `unwrap_or_default`; investigate by curl
/api/state | jq '.questions' + browser console.
- **Open threads:** two-step spawn, notes compaction,
unprivileged containers, Bash allow-list, xterm.js. The
deployment / gateway / privsep cluster is tracked in
`TODO-ops.md`. (Landed since this note was first written:
extra per-agent MCP servers, per-agent send allow-list,
telemetry + the `/stats` page.)

View file

@ -28,7 +28,10 @@ happens after a decision lands.
force-push, or `rm -rf` the proposed repo and the queued
approval still points at an immutable git object inside
applied.
4. Operator sees the diff on the dashboard, clicks ◆ APPR0VE (or
4. Operator sees the proposal as a card on the dashboard — a
full multi-file diff, toggleable between three bases (vs the
running tree / vs the last approved proposal / vs the
previous queued proposal) — and clicks ◆ APPR0VE (or
`hive-c0re approve <id>` on the CLI).
5. hive-c0re moves the working tree to `proposal/<id>` and runs
the build under a sequence of tags (see below). On success,
@ -158,6 +161,30 @@ approval id to retry. Because tags are first-class git objects,
rejected and failed trees stay browsable forever — `git log
--tags` in the applied repo is the audit trail.
### Forge mirror
When the bundled `hive-forge` container is running — on by
default, `hyperhive.forge.enable` — hive-c0re mirrors every
agent's applied repo into a private `agent-configs` Forgejo
org. `forge::push_config(<name>)` pushes `applied/main` plus
every tag to `agent-configs/<name>` after each ref mutation:
the spawn that seeds `deployed/0`, every `request_apply_commit`
(which plants `proposal/<id>`), every approve / deny, and a
sweep at startup. Pushes are best-effort — a missing or stopped
forge never blocks a deploy.
The org is private and agents are not members, so only the
`core` user (a Forgejo site admin) can read it: an agent can't
reach another agent's config — or even its own — through the
forge. The tokenised push URL is passed inline to `git push`,
never written into `applied/<n>/.git/config`; that repo is
RO-bind-mounted into the manager, and a stored token would leak
core's admin credential to an agent.
The dashboard deep-links into this org — a `config repo` link
per container row and a `commit on forge` link per approval
card. See `docs/web-ui.md`.
### Manager view of applied + meta
The manager container gets three host-side bind mounts via

View file

@ -102,11 +102,14 @@ it as a stdio child via `--mcp-config`. The hyperhive socket name is
- `send(to, body)` — message a peer (logical agent name), another
agent, or the operator (recipient `operator`, surfaces in the
dashboard inbox).
- `recv(wait_seconds?)` — drain one inbox message. Without
- `recv(wait_seconds?, max?)` — drain inbox messages. Without
`wait_seconds` (or with `0`) returns immediately, a cheap
"anything pending?" peek. Positive value parks the turn up
to that many seconds (cap 180) — incoming messages wake
instantly, otherwise returns empty at the timeout.
instantly, otherwise returns empty at the timeout. `max`
(default 1, server-side cap 32) drains up to N popped rows
in one round-trip; `wait_seconds` applies to the *first*
message, then the call drains up to `max` total.
- `ask(question, options?, multi?, ttl_seconds?, to?)`
surface a structured question. Same shape as the manager's;
recipient defaults to the operator (dashboard) but can be set
@ -119,6 +122,21 @@ it as a stdio child via `--mcp-config`. The hyperhive socket name is
routed to this agent. Authorisation is strict: only the
declared target (or the operator via the dashboard) can
answer.
- `get_loose_ends()` — list everything still pending against
this agent: unanswered questions it asked / was asked, plus
reminders it scheduled. Each row carries an id + kind for
`cancel_loose_end`.
- `cancel_loose_end(kind, id)` — withdraw a `question`
(posts `[cancelled by <self>]` to unblock the asker) or a
`reminder` (hard-delete before fire). Sub-agents may only
cancel rows they own.
- `remind(message, due)` — schedule a reminder that lands in
this agent's own inbox at a future time (sender shows as
`reminder`). Large payloads spill to
`/agents/<self>/state/reminders/` with the inbox message a
short pointer.
- `whoami()``{ name, role, pronouns, hyperhive_rev }` for
self-identification without scraping the system prompt.
### Waking the agent from inside the container
@ -191,6 +209,16 @@ meta's.
that was routed to the manager (a sub-agent did
`ask(to: "manager", ...)`). Surfaces in the asker's inbox as
the same `question_answered` event.
- `get_logs(agent, lines?)` — fetch recent journal lines for a
sub-agent container (diagnose MCP-registration failures,
startup crashes, etc.). Pass the plain logical agent name;
hive-c0re resolves the machine name (`h-<name>`, manager
`hm1nd`). `lines` defaults to 50, host-capped at 500.
- `remind` / `get_loose_ends` / `cancel_loose_end` / `whoami`
same as the sub-agent tools above, but `get_loose_ends` is
hive-wide (every agent's pending questions + reminders, not
just the manager's) and `cancel_loose_end` may cancel any
agent's row.
The boundary: lifecycle ops on *existing* sub-agents
(`kill`/`start`/`restart`) are at the manager's discretion — no

View file

@ -54,12 +54,21 @@ soon as they blur.
**`<details>` open-state preservation:** any collapsible element
tagged with `data-restore-key="<stable-key>"` survives the
refresh. `snapshotOpenDetails()` walks managed sections before
render, `restoreOpenDetails()` re-applies after. Used today for
the journald viewer (`journal:<container>`), the agent-config
viewer (`agent-config:<name>`), and approval diff blocks
(`approval-diff:<id>`). Setting `.open = true` programmatically
also fires the `toggle` event, so any lazy-fetch wired to it
re-runs cleanly on restore.
render, `restoreOpenDetails()` re-applies after. Long-content
drill-ins (file previews, diffs, journald logs) now open in the
**side panel** (see below) rather than expanding inline, so the
only restore-keyed `<details>` left is the answered-questions
history list.
**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
the button, a backdrop click, or `Escape`. `Panel.open(title,
node)` swaps the body; the JS builders for file previews,
approval diffs, and journald logs all render into it. Markdown
file previews (`.md` / `.markdown`) render through the vendored
`marked` bundle (`GET /static/marked.js`) into a `.md` block;
other files stay raw in a `<pre>`.
Both bind their listeners with `SO_REUSEADDR` via
`tokio::net::TcpSocket` plus a retry loop on `AddrInUse` (12 tries,
@ -136,21 +145,50 @@ Two-line layout (`assets/app.js::renderContainers`):
on sub-agents, `↺ R3ST4RT` + (sub-agents) `■ ST0P` when running,
`▶ ST4RT` when stopped. Buttons dim + disable while a transient
lifecycle action is in flight.
- Plus two collapsible `<details>` blocks:
- `↳ logs · <container>` — lazy-fetches journald output via
`GET /api/journal/{name}?unit=...&lines=...` (`journalctl -M
<container> -b --no-pager --output=short-iso`). A unit
dropdown switches between the harness service (default) and
the full machine journal; refresh button re-fetches.
- `↳ agent.nix · <name>` — lazy-fetches the applied config
file via `GET /api/agent-config/{name}` (read-only mirror of
`/var/lib/hyperhive/applied/<name>/agent.nix`). Mutating
this still requires `request_apply_commit` + approval.
- Line 3: drill-in triggers —
- `↳ logs · <container>` — opens the side panel and lazy-
fetches journald via `GET /api/journal/{name}?unit=&lines=`
(`journalctl -M <container> -b --no-pager --output=short-iso`).
A unit dropdown (harness service / full machine journal) and
a refresh button live in the panel.
- `↳ config repo ↗` — link to the agent's applied config repo
on the bundled forge (`agent-configs/<name>`), opened in a
new tab. Shown only when `forge_present`. Replaces the old
one-file `agent.nix` viewer — the forge shows the full repo
with history. Mutating config still requires
`request_apply_commit` + approval.
`↻ UPD4TE 4LL` button appears above the containers list when any
agent is stale. Banner pulses on each broker SSE event
(`pulseBanner` with a 4s grace timer).
### Approval card
Each pending approval renders as a card (`assets/app.js::
renderApprovals`) with three stacked sections:
- **identity header** — glyph, `#id`, agent, kind chip, and (for
`apply_commit`) the short proposal sha as `<code>`.
- **what-changed body** — the manager's description, then
drill-in triggers: `↳ view diff` opens the diff in the side
panel; `↳ commit on forge ↗` deep-links the proposal commit
into `agent-configs/<agent>` (shown only when `forge_present`).
Spawn approvals show a one-line "container will be created"
note instead.
- **decision actions**`◆ APPR0VE` and `DENY`. Deny pops a
`prompt()` for an optional reason carried to the manager as
`HelperEvent::ApprovalResolved.note`.
The diff panel has a 3-way base toggle — **vs applied** (the
running tree, served instantly from the diff already on the
approval), **vs last-approved**, **vs previous proposal** — the
latter two fetched on click from `GET /api/approval-diff/{id}
?base=approved|previous`. Each line is classified client-side
(`+` / `-` / `@@` / `--- ` / `+++ ` → add / del / hunk / file).
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). Three signals trigger them:
@ -198,9 +236,13 @@ not ours.
the operator inbox without a snapshot refetch. Used by the
compose textbox under MESS4GE FL0W.
- `GET /api/journal/{name}?unit=&lines=` — journalctl viewer for
a managed container.
- `GET /api/agent-config/{name}` — read-only view of the applied
`agent.nix`.
a managed container; rendered in the side panel.
- `GET /api/approval-diff/{id}?base=applied|approved|previous`
on-demand unified diff for an `ApplyCommit` approval against
the chosen base (running tree / last approved proposal /
previous queued proposal). Raw diff text, classified
client-side. `GET /static/marked.js` serves the vendored
`marked` bundle the side panel uses for markdown previews.
- `GET /api/state-file?path=<host-or-container-path>` — bounded
text read of a file under the per-agent `state/` subtree or
the shared `/var/lib/hyperhive/shared/`. Accepts the
@ -343,8 +385,16 @@ Layout, top to bottom:
- Inbox `<details>` block (collapsed): `inbox · N` — last 30
messages addressed to this agent, fetched via
`AgentRequest::Recent { limit: 30 }`. (Separate from
`AgentRequest::Recv { wait_seconds }` which the harness uses
internally to long-poll the broker.)
`AgentRequest::Recv { wait_seconds, max }` which the harness
uses internally to long-poll the broker.)
- Loose-ends `<details>` block: `loose ends · N` — questions,
approvals, and reminders pending against this agent (the
`get_loose_ends` data, via `GET /api/loose-ends`). Question
rows carry an inline answer form (textarea — Enter submits,
Shift+Enter newlines); submitting POSTs cross-origin to the
core dashboard's `/answer-question/{id}` so the operator
answers *as operator*. The per-agent socket deliberately gets
no operator-authority path — see `TODO-ops.md`.
- Terminal-wrap: live event tail (sticky-bottom auto-scroll +
`↓ N new` pill when not at bottom) followed by an
operator-input textarea acting as a prompt.
@ -454,3 +504,19 @@ Bus events (new vocabulary on `/events/stream`):
totals).
- `turn_state_changed { state, since_unix }` — drives the
state badge (`idle`/`thinking`/`compacting`).
### Stats page
`GET /stats` is a separate per-agent page (served by the
harness, linked from the per-agent page's `📊 stats →` and from
each dashboard container row). Turn analytics, read-only, from
`/state/hyperhive-turn-stats.sqlite`. `GET /api/stats?window=
24h|7d|30d` returns a time-bucketed `Snapshot`; the page renders
it with Chart.js (vendored from a CDN). Charts: turns,
duration (p50 · p95 · avg), context tokens, token cost per
bucket, a **turns-by-model** stacked bar (model choice drives
token cost, so it sits directly under the cost chart), and
doughnuts for tool / wake-source / result mix. A summary chip
row carries window totals. `stats.rs` opens the sqlite db
read-only and degrades to an empty snapshot on any error — the
page is decorative, never authoritative.

View file

@ -2,13 +2,14 @@ You are hyperhive agent `{label}` in a multi-agent system. The operator (recipie
Tools (hyperhive surface):
- `mcp__hyperhive__recv(wait_seconds?)` — drain one more message from your inbox (returns `(empty)` if nothing pending). Without `wait_seconds` (or with `0`) it returns immediately — a cheap "anything pending?" peek you can sprinkle between tool calls. To **wait** for work when you have nothing else useful to do this turn, call with a long wait (e.g. `wait_seconds: 180`, the max) — incoming messages wake you instantly, otherwise the call returns empty at the timeout. That's strictly better than a fixed `sleep` shell command: lower latency on new work, no busy-loop.
- `mcp__hyperhive__recv(wait_seconds?, max?)` — drain inbox messages (returns `(empty)` if nothing pending). Without `wait_seconds` (or with `0`) it returns immediately — a cheap "anything pending?" peek you can sprinkle between tool calls. To **wait** for work when you have nothing else useful to do this turn, call with a long wait (e.g. `wait_seconds: 180`, the max) — incoming messages wake you instantly, otherwise the call returns empty at the timeout. That's strictly better than a fixed `sleep` shell command: lower latency on new work, no busy-loop. `max` (default 1, cap 32) drains several queued messages in one call — the wake prompt tells you the pending count.
- `mcp__hyperhive__send(to, body)` — message a peer (by their name) or the operator (recipient `operator`, surfaces in the dashboard). Use `to: "*"` to broadcast to all agents (they receive a hint that it's a broadcast and may not need action). Some agents have a per-agent allow-list (`hyperhive.allowedRecipients` in their `agent.nix`) — if so the tool refuses recipients outside the list with a clear error; route through the manager (`send(to: "manager", …)`) which is always reachable.
- (some agents only) **extra MCP tools** surfaced as `mcp__<server>__<tool>` — these are agent-specific (matrix client, scraper, db connector, etc.) declared in your `agent.nix` under `hyperhive.extraMcpServers`. Treat them as first-class tools alongside the hyperhive surface; the operator already auto-approved them at deploy time.
- `mcp__hyperhive__ask(question, options?, multi?, ttl_seconds?, to?)` — surface a structured question to the human operator (default, or `to: "operator"`) OR a peer agent (`to: "<agent-name>"`). Returns immediately with a question id — do NOT wait inline. When the recipient answers, a system message with event `question_answered { id, question, answer, answerer }` lands in your inbox; handle it on a future turn. Use this for clarifications, permission for risky actions, choice between options, or peer Q&A without burning regular inbox slots. `options` is advisory: a short fixed-choice list when applicable, otherwise leave empty for free text. `multi: true` lets the answerer pick multiple (checkboxes), answer comes back comma-joined. `ttl_seconds` auto-cancels with answer `[expired]` (and `answerer: "ttl-watchdog"`) when the decision becomes moot.
- `mcp__hyperhive__answer(id, answer)` — answer a question that was routed to YOU. You'll see one in your inbox as a `question_asked { id, asker, question, options, multi }` system event when a peer or the manager calls `ask(to: "<your-name>", ...)`. The answer surfaces in the asker's inbox as a `question_answered` event. Strict authorisation: you can only answer questions where you are the declared target.
- `mcp__hyperhive__get_loose_ends()` — list your loose ends: unanswered questions where you're asker (waiting on someone) or target (owing a reply), plus reminders you've scheduled that haven't fired. No args, cheap server-side sweep. Useful at turn start to remember what's outstanding without scanning inbox archaeology.
- `mcp__hyperhive__cancel_loose_end(kind, id)` — cancel one of your own open threads. `kind` is `"question"` (the asker — you, in this case — gets a `[cancelled by <you>]` answer so the waiter unblocks) or `"reminder"` (hard-deleted before it fires). `id` from the matching `get_loose_ends` row or the original submission reply.
- `mcp__hyperhive__remind(message, delay_seconds? | at_unix_timestamp?, file_path?)` — schedule a message to land in your *own* inbox at a future time (sender shows as `reminder`). Set exactly one of `delay_seconds` (relative) or `at_unix_timestamp` (absolute). Use for self-paced follow-ups instead of blocking a whole turn on a long `recv` wait. A large `message` auto-spills to a file under `/agents/{label}/state/reminders/`; pass `file_path` to point at one yourself.
- `mcp__hyperhive__whoami()` — self-introspection: returns your canonical agent name (from socket identity, not the prompt-substituted label), role, and current hyperhive rev. No args. Use it when you want a trustworthy identity stamp for state files, commit messages, or cross-agent attribution that won't drift across renames.
Need new packages, env vars, or other NixOS config for yourself? You can't edit your own config directly — message the manager (recipient `manager`) describing what you need + why. The manager evaluates the request (it doesn't rubber-stamp), edits `/agents/{label}/config/agent.nix` on your behalf, commits, and submits an approval that the operator can accept on the dashboard; on approve hive-c0re rebuilds your container with the new config.

View file

@ -2,18 +2,20 @@ You are the hyperhive manager `{label}` in a multi-agent system. You coordinate
Tools (hyperhive surface):
- `mcp__hyperhive__recv(wait_seconds?)` — drain one more message from your inbox. Without `wait_seconds` (or with `0`) it returns immediately — a cheap inbox peek you can drop between actions. To **wait** when you have nothing else to do, call with a long wait (e.g. `wait_seconds: 180`, the max) — you'll wake instantly on new work, otherwise return after the timeout. Use that instead of ending the turn or sleeping in a Bash command.
- `mcp__hyperhive__recv(wait_seconds?, max?)` — drain inbox messages. Without `wait_seconds` (or with `0`) it returns immediately — a cheap inbox peek you can drop between actions. To **wait** when you have nothing else to do, call with a long wait (e.g. `wait_seconds: 180`, the max) — you'll wake instantly on new work, otherwise return after the timeout. Use that instead of ending the turn or sleeping in a Bash command. `max` (default 1, cap 32) drains several queued messages in one call.
- `mcp__hyperhive__send(to, body)` — message an agent (by name), another peer, or the operator (`operator` surfaces in the dashboard). Use `to: "*"` to broadcast to all agents (they receive a hint that it's a broadcast and may not need action).
- `mcp__hyperhive__request_spawn(name, description?)` — queue a brand-new sub-agent for operator approval (≤9 char name). Pass an optional `description` and it appears on the dashboard approval card — no need to send a separate message explaining the request.
- `mcp__hyperhive__kill(name)` — graceful stop on a sub-agent. No approval required.
- `mcp__hyperhive__start(name)` — start a stopped sub-agent. No approval required.
- `mcp__hyperhive__restart(name)` — stop + start a sub-agent. No approval required.
- `mcp__hyperhive__update(name)` — rebuild a sub-agent (re-applies the current hyperhive flake + agent.nix, restarts the container). No approval required — idempotent. Use when you receive a `needs_update` system event.
- `mcp__hyperhive__get_logs(agent, lines?)` — fetch recent journal lines for a sub-agent container. Use to diagnose MCP-server registration failures, startup crashes, or harness issues you can't see from inside. Pass the plain logical agent name; `lines` defaults to 50 (capped at 500).
- `mcp__hyperhive__request_apply_commit(agent, commit_ref, description?)` — submit a config change for any agent (`hm1nd` for self) for operator approval. Pass an optional `description` and it appears on the dashboard approval card so the operator knows what changed without opening the diff. At submit time hive-c0re fetches your commit into the agent's applied repo and pins it as `proposal/<id>`; from that moment your proposed-side commit can be amended or force-pushed freely without changing what the operator will build.
- `mcp__hyperhive__ask(question, options?, multi?, ttl_seconds?, to?)` — surface a structured question to the operator (default, or `to: "operator"`) OR a sub-agent (`to: "<agent-name>"`). Returns immediately with a question id; the answer arrives later as a system `question_answered { id, question, answer, answerer }` event in your inbox. Options are advisory: the dashboard always lets the operator type a free-text answer in addition. Set `multi: true` to render options as checkboxes (operator can pick multiple); the answer comes back as `, `-separated. Set `ttl_seconds` to auto-cancel after a deadline (capped at 6h server-side) — on expiry the answer is `[expired]` and `answerer` is `"ttl-watchdog"`. Do not poll inside the same turn — finish the current work and react when the event lands.
- `mcp__hyperhive__answer(id, answer)` — answer a question that was routed to YOU (a sub-agent did `ask(to: "manager", ...)`). The triggering event in your inbox is `question_asked { id, asker, question, options, multi }`. The answer surfaces in the asker's inbox as a `question_answered` event.
- `mcp__hyperhive__get_loose_ends()` — hive-wide loose ends: every pending approval + every unanswered question + every pending reminder across the swarm. Cheap server-side sweep, no args. Use to find stalled threads (sub-agent A asked B something three days ago and B never answered) before they rot.
- `mcp__hyperhive__cancel_loose_end(kind, id)` — cancel any question or reminder in the swarm (manager bypasses the owner check used on sub-agents). Use for hive-wide cleanup when a sub-agent is offline / can't withdraw its own ask / reminder.
- `mcp__hyperhive__remind(message, delay_seconds? | at_unix_timestamp?, file_path?)` — schedule a message to land in your own inbox at a future time (sender shows as `reminder`). Set exactly one of `delay_seconds` (relative) or `at_unix_timestamp` (absolute). Good for deadline follow-ups — "check whether agent X answered the question I relayed". Large payloads auto-spill to a file under `/state/reminders/`; pass `file_path` to control the destination.
- `mcp__hyperhive__whoami()` — self-introspection: canonical name (`manager`), role, current hyperhive rev. No args. Useful for boot announcements and cross-agent attribution that won't drift across config reloads.
Approval boundary: lifecycle ops on *existing* sub-agents (`kill`, `start`, `restart`) are at your discretion — no operator approval. *Creating* a new agent (`request_spawn`) and *changing* any agent's config (`request_apply_commit`) still go through the approval queue. The operator only signs off on changes; you run the day-to-day.

View file

@ -137,6 +137,13 @@ in
DEFAULT_BRANCH = "main";
DEFAULT_PRIVATE = "private";
};
# Repo migrations / pull-mirrors fetch from the source
# URL *inside* Forgejo. hyperhive code is synced from
# `localhost` (and the host LAN), which Forgejo's
# migration guard blocks by default ("cannot import from
# disallowed hosts"). Allow loopback + RFC-1918 sources
# so an in-hive mirror of the hyperhive repo works.
migrations.ALLOW_LOCALNETWORKS = true;
log.LEVEL = "Warn";
# F3 (federation) computes its data dir relative to the
# forgejo binary, which lands in the read-only nix