docs: address mara review on #1936

- Drop the redundant 'including the root/bootstrap container' /
  'sub-agents + root' enumerations in the port-range + state-dir
  uniformity statements — 'every agent' / 'all agents' is enough (and
  calling out '+ root' reintroduces the special-case framing).
- Stop describing the root agent's privileged (manager-flavour) socket
  as a current thing (it's being removed): drop the conventions.md
  capability clause, the network.md per-agent-privileged-socket list
  entry, and the persistence.md /run/hyperhive/manager/mcp.sock
  runtime-dir bullet.
This commit is contained in:
iris 2026-06-23 12:31:38 +02:00 committed by mara
commit 7e0190e27c
6 changed files with 15 additions and 19 deletions

View file

@ -10,7 +10,7 @@ exist because something already went wrong without them.
- One agent is the bootstrap/root container, with a fixed name (`ruth` today). - One agent is the bootstrap/root container, with a fixed name (`ruth` today).
- `MAX_AGENT_NAME` in `lifecycle.rs` enforces the cap. - `MAX_AGENT_NAME` in `lifecycle.rs` enforces the cap.
- Per-agent web UI port = `WEB_PORT_BASE + FNV1a(name) % WEB_PORT_RANGE` - Per-agent web UI port = `WEB_PORT_BASE + FNV1a(name) % WEB_PORT_RANGE`
(8100..8999) for every agent including the bootstrap/root container; dashboard (8100..8999) for every agent; dashboard
`cfg.dashboardPort` (default 7000). `cfg.dashboardPort` (default 7000).
## Hive identity (label + domain + display names) ## Hive identity (label + domain + display names)
@ -55,9 +55,8 @@ peer's name when the caller knows it's hive-local.
There are no auth tokens on the per-agent unix sockets. The socket There are no auth tokens on the per-agent unix sockets. The socket
*path* identifies the principal; perms come from "who has the *path* identifies the principal; perms come from "who has the
bind-mount." A sub-agent only sees its own `/run/hive/mcp.sock`; the bind-mount." A sub-agent only sees its own `/run/hive/mcp.sock`;
root agent additionally has access to its privileged (manager-flavour) hive-c0re owns the host admin socket.
socket; hive-c0re owns the host admin socket.
### Wake injection ### Wake injection

View file

@ -269,9 +269,8 @@ firewall-open would defeat the single-front-door story.
`httpsPort` — the gateway always terminates TLS (self-signed floor), so `httpsPort` — the gateway always terminates TLS (self-signed floor), so
both are always served. both are always served.
The root/bootstrap container hashes into the same port range as Every agent hashes into the same port range (no special case), so
sub-agents (no special case), so one range opening covers every one range opening covers every container.
container.
The dashboard port (`cfg.dashboardPort`, default 7000) is *not* The dashboard port (`cfg.dashboardPort`, default 7000) is *not*
listed in either case — it binds `127.0.0.1` only, so a firewall listed in either case — it binds `127.0.0.1` only, so a firewall

View file

@ -96,7 +96,7 @@ across `destroy`/recreate (`--purge` wipes them).
## Persistent notes dir per agent ## Persistent notes dir per agent
`/var/lib/hyperhive/agents/<name>/state/` bind-mounts to `/var/lib/hyperhive/agents/<name>/state/` bind-mounts to
`/agents/<name>/state` (RW; uniform for all agents — sub-agents + root). `/agents/<name>/state` (RW; uniform for all agents).
The harness exposes the same path The harness exposes the same path
via `$HYPERHIVE_STATE_DIR`. System prompts tell agents to keep via `$HYPERHIVE_STATE_DIR`. System prompts tell agents to keep
durable knowledge here (`notes.md`, anything else). The harness also durable knowledge here (`notes.md`, anything else). The harness also
@ -111,8 +111,8 @@ collision rate gets meaningful; at 23 agents you can still get
unlucky. Operator resolves a collision by renaming the offending unlucky. Operator resolves a collision by renaming the offending
agent (different hash → different port) and rebuilding. No state agent (different hash → different port) and rebuilding. No state
file, no probing, no port-allocation drift — the value is file, no probing, no port-allocation drift — the value is
reproducible from just the name. Every agent — including the reproducible from just the name. Every agent hashes into
root/bootstrap container — hashes into 8100..8999 via the same FNV-1a; dashboard 8100..8999 via the same FNV-1a; dashboard
at `cfg.dashboardPort` (default 7000). at `cfg.dashboardPort` (default 7000).
## Restart races on TCP bind ## Restart races on TCP bind

View file

@ -130,7 +130,7 @@ address arithmetic.
`lifecycle::set_nspawn_flags` when creating or updating containers. Each `lifecycle::set_nspawn_flags` when creating or updating containers. Each
agent gets a deterministic IP derived from its name so the address is agent gets a deterministic IP derived from its name so the address is
reproducible across destroy/recreate. This applies uniformly to all reproducible across destroy/recreate. This applies uniformly to all
containers including the root/bootstrap container — no special case. containers — no special case.
`HOST_ADDRESS` is the bridge gateway IP (the address part of `HOST_ADDRESS` is the bridge gateway IP (the address part of
`HIVE_NETWORK_SUBNET`, via `lifecycle::bridge_gateway_ip` — taken verbatim `HIVE_NETWORK_SUBNET`, via `lifecycle::bridge_gateway_ip` — taken verbatim
@ -163,9 +163,9 @@ wiring is runtime:
an instant no-op in shared-netns mode (the marker is absent, so an instant no-op in shared-netns mode (the marker is absent, so
`ConditionPathExists` skips it). `ConditionPathExists` skips it).
**Why isolation is safe for the root agent**: all hive-c0re communication goes **Why isolation is safe**: all hive-c0re communication goes
through unix domain sockets (`/run/hive/mcp.sock` for agent requests, through unix domain sockets (`/run/hive/mcp.sock` for agent requests,
`/run/hive/priv.sock` for privileged ops, per-agent privileged sockets). `/run/hive/priv.sock` for privileged ops).
These are bind-mounted into containers via the nspawn conf. UDS paths These are bind-mounted into containers via the nspawn conf. UDS paths
traverse the VFS, not the network stack, so `PRIVATE_NETWORK=1` does not traverse the VFS, not the network stack, so `PRIVATE_NETWORK=1` does not
affect them. affect them.

View file

@ -189,7 +189,7 @@ Under `/var/lib/hyperhive/agents/<name>/`:
`/home/<name>/.claude` inside the container. `/home/<name>/.claude` inside the container.
- `state/` — durable notes and `hyperhive-harness.json`. Bind-mounted - `state/` — durable notes and `hyperhive-harness.json`. Bind-mounted
to `/agents/<name>/state` inside the container (uniform for to `/agents/<name>/state` inside the container (uniform for
all agents — sub-agents + root). The `$HYPERHIVE_STATE_DIR` env var exposes all agents). The `$HYPERHIVE_STATE_DIR` env var exposes
the same path to in-container scripts. Notable files written here the same path to in-container scripts. Notable files written here
by the harness: by the harness:
- `hyperhive-status` — single-line free-text status string written - `hyperhive-status` — single-line free-text status string written
@ -323,9 +323,7 @@ Without that, every restart wipes bind sources and existing
containers can't be started. containers can't be started.
- `/run/hyperhive/host.sock` — admin socket (host-side CLI). - `/run/hyperhive/host.sock` — admin socket (host-side CLI).
- `/run/hyperhive/manager/mcp.sock` — the root agent's privileged - `/run/hyperhive/agents/<name>/mcp.sock` — per-agent socket
(manager-flavour) socket.
- `/run/hyperhive/agents/<name>/mcp.sock` — per-sub-agent socket
(bind-mounted into the container as `/run/hive/mcp.sock`). (bind-mounted into the container as `/run/hive/mcp.sock`).
On startup, `Coordinator::register_agent` drops any prior socket On startup, `Coordinator::register_agent` drops any prior socket

View file

@ -1,8 +1,8 @@
# Web UI # Web UI
Two web surfaces share the same skeleton: the dashboard (port 7000) Two web surfaces share the same skeleton: the dashboard (port 7000)
and the per-agent UIs (every container — including the root/bootstrap and the per-agent UIs (every container hashes into :8100-8999 via
container — hashes into :8100-8999 via `lifecycle::agent_web_port`'s FNV-1a). `lifecycle::agent_web_port`'s FNV-1a).
Both are SPAs — `GET /` returns a static shell, `/api/state` Both are SPAs — `GET /` returns a static shell, `/api/state`
returns JSON, JS renders. No full-page reloads. returns JSON, JS renders. No full-page reloads.