Watch
0
0
Fork
You've already forked hyperhive
0

docs(agents): drop nonexistent-thing mentions, state current behaviour

This commit is contained in:
atlas 2026-10-02 09:20:57 +02:00 • committed by mara
commit 78aacf13ce
3 changed files with 39 additions and 45 deletions

View file

@ -2,16 +2,15 @@
<!-- vale write-good.Passive = NO --> <!-- vale write-good.Passive = NO -->
Agents are a **flat set**, with no parent/child tree: the `parent` field Agents are a **flat set**, with no parent/child tree: `topology.json`
`topology.json` used to carry is gone, along with every mechanism that carries no `parent` field, and the capability store — not tree
read it. The capability store scopes which agents can manage which position — scopes which agents can manage which others.
others; a tree position no longer scopes anything.
<!-- vale write-good.Passive = YES --> <!-- vale write-good.Passive = YES -->
This doc covers what the roster file is now, what the removal took with This doc covers what the roster file holds today, the map-shaped
it, and where the manager still gets special-cased, as a tracked alternative `topology::all_agents` still accepts, and where the manager
cleanup. still gets special-cased, as a tracked cleanup.
## Where the roster lives ## Where the roster lives
@ -49,11 +48,11 @@ agent's `state` read-write and `config` read-only; never `harness`). An
agent holding no capability sees its own dirs and nothing else. See agent holding no capability sees its own dirs and nothing else. See
[`persistence.md`](persistence.md)'s _Cross-agent access to state._ [`persistence.md`](persistence.md)'s _Cross-agent access to state._
### Reading the legacy format ### Reading the map-shaped format
`topology.json` used to be a map of `name → parent | null`. The reader `topology.json` may also be a map of `name → parent | null`; the reader
still accepts that shape and keeps its keys, so a hive upgrading across accepts that shape too and keeps its keys, so a hive with a file in that
the change reads the same roster rather than an empty one. An empty shape still reads the same roster rather than an empty one. An empty
roster costs more than a cosmetic gap: every capability holder loses its roster costs more than a cosmetic gap: every capability holder loses its
mounts until the next reconcile pass writes the array form. mounts until the next reconcile pass writes the array form.
@ -79,7 +78,7 @@ from which agents exist, so the next pass overwrites a hand edit.
See `hive-c0re/src/agent_config/topology.rs` and `hive-c0re/src/meta.rs`'s See `hive-c0re/src/agent_config/topology.rs` and `hive-c0re/src/meta.rs`'s
module docs for the exact call chain. module docs for the exact call chain.
## What the parent field used to do ## What replaced the parent field
Recorded so a reader who finds one of these in an old branch, an issue Recorded so a reader who finds one of these in an old branch, an issue
thread or a stale comment knows each one went away rather than moved: thread or a stale comment knows each one went away rather than moved:
@ -98,10 +97,10 @@ thread or a stale comment knows each one went away rather than moved:
<!-- vale write-good.Passive = NO --> <!-- vale write-good.Passive = NO -->
The last row is the one with teeth: an agent that used to reach a child's The last row is the one with teeth: reaching a child's state dir
state dir by virtue of being its parent no longer reaches it at all requires holding `ManageRootAgent`; parentage grants nothing. That
unless it holds `ManageRootAgent`. That narrowing is the intended narrowing is the intended consequence of removing the field, not a
consequence of removing the field, not a side effect of it. side effect of it.
<!-- vale write-good.Passive = YES --> <!-- vale write-good.Passive = YES -->
@ -141,12 +140,11 @@ everything below applies only when it doesn't:
manage any agent's state dir — config isn't authored there, since a manage any agent's state dir — config isn't authored there, since a
real config change is a PR from a clone), plus RO mounts for real config change is a PR from a clone), plus RO mounts for
`/applied` (diff against what's deployed) and `/meta` (system-wide `/applied` (diff against what's deployed) and `/meta` (system-wide
deploy log). That grant is the `ManageRootAgent` capability now, and deploy log). That grant is the `ManageRootAgent` capability, which
ruth holds it; no name check remains. hive-c0re will ruth holds; nothing checks the agent's name. hive-c0re will
gate RO `/meta` access on a "meta read" capability; no agent-facing gate RO `/meta` access on a "meta read" capability; no agent-facing
path writes `flake.lock` any more — `request_update_meta_inputs` was path writes `flake.lock` — the operator dashboard's `POST
removed, leaving the operator dashboard's `POST /api/meta-update` is the only entry point.
/api/meta-update` as the only entry point.
- **Prompt** — treated identically: `prompt::render` always filters for `agent`. `prompts/system.md` - **Prompt** — treated identically: `prompt::render` always filters for `agent`. `prompts/system.md`
still carries `<!-- role:agent -->` / `<!-- role:manager -->` marker still carries `<!-- role:agent -->` / `<!-- role:manager -->` marker
blocks, but `prompt::render` filters for `"agent"` unconditionally for blocks, but `prompt::render` filters for `"agent"` unconditionally for

View file

@ -91,12 +91,11 @@ angle-bracket and asterisk shapes below are structurally safe.
- `operator` — the human at the dashboard. Messages accumulate in the - `operator` — the human at the dashboard. Messages accumulate in the
inbox view; no agent ever `recv`'s them. inbox view; no agent ever `recv`'s them.
`<parent>` and `<children>` were two more, resolved against a `<parent>` and `<children>` aren't valid recipients: address
`topology.json` parent field. That field and both sentinels no longer `operator` directly instead of `<parent>`, and name the recipients (or
exist: address `operator` where you would have said broadcast to `*`) instead of `<children>`. Nothing rewrites a
`<parent>`, and name the recipients (or broadcast to `*`) where you recipient at send time — what an agent passes is what the broker
would have said `<children>`. Nothing rewrites a recipient at send time stores.
any more — what an agent passes is what the broker stores.
## Wire protocol ## Wire protocol
@ -225,8 +224,8 @@ the card out of the pending pane.
### Agent metadata ### Agent metadata
`AgentRequest::GetAgentMeta { name }` returns identity + status for `AgentRequest::GetAgentMeta { name }` returns identity + status for
an agent. Self-introspection when `name = None` (replaces the older an agent. Self-introspection when `name = None`; target query when
`Whoami` request); target query when `name = Some`. `name = Some`.
Response is `AgentMeta { name, running, hyperhive_rev, Response is `AgentMeta { name, running, hyperhive_rev,
status_text, status_set_at, hive_name, swarm_name, matrix_accounts }`: status_text, status_set_at, hive_name, swarm_name, matrix_accounts }`:
@ -238,9 +237,10 @@ status_text, status_set_at, hive_name, swarm_name, matrix_accounts }`:
`false`, the host clears `status_text` / `status_set_at` — `false`, the host clears `status_text` / `status_set_at` —
on-disk values from before the stop are stale snapshots, not on-disk values from before the stop are stale snapshots, not
live status. Defaults to `true` on the live status. Defaults to `true` on the
wire (older harnesses never serialised it, and the host only wire: the deserializer treats a payload lacking the field — from a
knew how to ask about live containers — keeps backwards-compat harness that never serialises it, or a host that only knows how to
with pre-running-field payloads). ask about live containers — as running, keeping compatibility with
pre-running-field payloads.
- `status_text` / `status_set_at`: last value written via - `status_text` / `status_set_at`: last value written via
`SetStatus`, plus its unix timestamp. Both `None` when the `SetStatus`, plus its unix timestamp. Both `None` when the
target has never set a status, when the agent name is unknown, target has never set a status, when the agent name is unknown,
@ -259,8 +259,8 @@ Timestamp fields that cross a JSON boundary (dashboard API + SSE,
the wire structs in hive-sh4re) serialize as **RFC 3339 UTC strings** the wire structs in hive-sh4re) serialize as **RFC 3339 UTC strings**
(`2026-07-02T18:30:00Z`) via `hive_sh4re::wire_time` — Rust keeps the (`2026-07-02T18:30:00Z`) via `hive_sh4re::wire_time` — Rust keeps the
fields as `i64` unix seconds internally, only the JSON representation fields as `i64` unix seconds internally, only the JSON representation
changes, and deserialization leniently accepts both the string form changes, and deserialization accepts both the string form and a bare
and the legacy bare integer (rolling-deploy skew, persisted blobs). integer (rolling-deploy skew, persisted blobs).
**Input-direction** fields agents compute as epoch (`first_fire_at_unix`, **Input-direction** fields agents compute as epoch (`first_fire_at_unix`,
schedule-edit `next_fire_at_unix`, `Wakeup::At`) stay integers. The schedule-edit `next_fire_at_unix`, `Wakeup::At`) stay integers. The
`*_unix` field *names* stay for now — renaming is the wire-types `*_unix` field *names* stay for now — renaming is the wire-types
@ -302,10 +302,10 @@ binary flavor.
| `meta` | `get_agent_meta` (`set_status` is always-on, see below) | | `meta` | `get_agent_meta` (`set_status` is always-on, see below) |
| `inbox` | `get_loose_ends`, `cancel_loose_end`, `remind` | | `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`. | | `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 — `list_containers` no longer exists, with no replacement; the variant survives only so existing grants parse. | | `lifecycle` | none — `list_containers` isn't a tool; the variant survives only so existing grants parse. |
| `approvals` | none — `request_update_meta_inputs` no longer exists, with no replacement. Still a live server-side gate: `cancel_loose_end`'s approval-cancel arm requires it. | | `approvals` | none — `request_update_meta_inputs` isn't a tool. Still a live server-side gate: `cancel_loose_end`'s approval-cancel arm requires it. |
| `scheduling` | `request_schedule_prompt`, `fire_schedule_now`, `cancel_schedule`, `edit_schedule`, `list_schedules` *(privileged)* | | `scheduling` | `request_schedule_prompt`, `fire_schedule_now`, `cancel_schedule`, `edit_schedule`, `list_schedules` *(privileged)* |
| `forge` | none — `create_repo` no longer exists, with no replacement; the variant survives only so existing grants parse. | | `forge` | none — `create_repo` isn't a tool; the variant survives only so existing grants parse. |
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) | | `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
**Always-on tools** — `ToolGroup::ALWAYS_ON_TOOLS` exposes `set_status`, **Always-on tools** — `ToolGroup::ALWAYS_ON_TOOLS` exposes `set_status`,
@ -411,7 +411,7 @@ rewrite — `PRIVATE_NETWORK=1`, `HOST_ADDRESS` = the bridge gateway IP,
sets `EXTRA_NSPAWN_FLAGS` — plus the systemd resource-limits drop-in) sets `EXTRA_NSPAWN_FLAGS` — plus the systemd resource-limits drop-in)
into the `Swap` node, then runs `nixos-container update` + stop + into the `Swap` node, then runs `nixos-container update` + stop +
start across the `StopForUpdate → Swap → RebuildBookkeeping` start across the `StopForUpdate → Swap → RebuildBookkeeping`
brace and the tail `Reconcile` node. `flake.nix` itself is no longer brace and the tail `Reconcile` node. `flake.nix` itself isn't
regenerated host-side on rebuild — it's tracked in the agent's regenerated host-side on rebuild — it's tracked in the agent's
proposed/applied repos and rides along on every fetch (see proposed/applied repos and rides along on every fetch (see
`docs/agent-lifecycle/approvals.md::Two repos per agent`). `docs/agent-lifecycle/approvals.md::Two repos per agent`).

View file

@ -80,8 +80,7 @@ transitions the job-queue scheduler or crash watcher drive directly —
stop/kill, destroy, a flake-rev login or logout state change — reach stop/kill, destroy, a flake-rev login or logout state change — reach
no individual agent: they publish onto a swarm-wide NATS no individual agent: they publish onto a swarm-wide NATS
JetStream stream (`swarm_notices::notify`, JetStream stream (`swarm_notices::notify`,
`hive-c0re/src/swarm_notices.rs`); every hive is swarm-controlled, so `hive-c0re/src/swarm_notices.rs`); every hive is swarm-controlled.
there is no manager-agent fallback to push an in-container todo to.
**Inbox** (`inbox` group): `get_loose_ends()`, **Inbox** (`inbox` group): `get_loose_ends()`,
`cancel_loose_end(kind, id)`, `remind(message, delay_seconds? | `cancel_loose_end(kind, id)`, `remind(message, delay_seconds? |
@ -153,16 +152,13 @@ hive_name?, swarm_name?, matrix_accounts? }`. `matrix_accounts` is a
default-on like bash execution (no tool group gates it yet). See default-on like bash execution (no tool group gates it yet). See
[`docs/tools/subagent.md`](../tools/subagent.md). [`docs/tools/subagent.md`](../tools/subagent.md).
- **Lifecycle + config** (`lifecycle`, `approvals`) — neither group - **Lifecycle + config** (`lifecycle`, `approvals`) — neither group
carries an MCP tool any more: `list_containers` and carries an MCP tool. `approvals` survives as a server-side gate on
`request_update_meta_inputs` no longer exist, with no
replacement. `approvals` survives as a server-side gate on
`cancel_loose_end`'s approval-cancel arm; `lifecycle` gates nothing. `cancel_loose_end`'s approval-cancel arm; `lifecycle` gates nothing.
Config changes go through a forge PR on `agent-configs/<name>` — see Config changes go through a forge PR on `agent-configs/<name>` — see
[`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md). [`docs/agent-lifecycle/approvals.md`](../agent-lifecycle/approvals.md).
- **Scheduling** (`scheduling`) — scheduled prompts. See - **Scheduling** (`scheduling`) — scheduled prompts. See
[`docs/tools/scheduling.md`](../tools/scheduling.md). [`docs/tools/scheduling.md`](../tools/scheduling.md).
- **Forge repos** (`forge`) — carries no MCP tool: `create_repo` no - **Forge repos** (`forge`) — carries no MCP tool; `forge` gates nothing.
longer exists, with no replacement; `forge` gates nothing.
- **Web egress** (`web_tools`) — enables Claude's built-in `WebFetch` - **Web egress** (`web_tools`) — enables Claude's built-in `WebFetch`
and `WebSearch` tools (not MCP tools; added directly to the and `WebSearch` tools (not MCP tools; added directly to the
`--allowedTools` list). Off by default; add the group in the `--allowedTools` list). Off by default; add the group in the