docs/agent-hierarchy.md: scrub self-ref cookies (#719 batch 5)

This commit is contained in:
iris 2026-05-31 15:44:26 +02:00 committed by mara
commit 7bb55bca43

View file

@ -1,7 +1,7 @@
# Agent hierarchy & privileges # Agent hierarchy & privileges
Design + audit doc for milestone #6 (the Design + audit doc for the agent-privileges + tree-shape milestone
[issue](http://localhost:3000/hyperhive/hyperhive/issues/361) tree). (the [issue tree](http://localhost:3000/hyperhive/hyperhive/issues/361)).
The implementation lands in pieces; this doc tracks what's done, what's The implementation lands in pieces; this doc tracks what's done, what's
planned, and what currently special-cases the manager. planned, and what currently special-cases the manager.
@ -20,7 +20,7 @@ Topology lives in the hive-c0re-owned **meta repo**, alongside
`null` = root-level agent. Today only the manager qualifies by default. `null` = root-level agent. Today only the manager qualifies by default.
Other agents land under `"manager"` on first sync. Re-parenting is Other agents land under `"manager"` on first sync. Re-parenting is
operator-driven (#486 / #487): operator-driven:
- CLI: `hive-c0re set-parent <child> --parent <new>` (or `--root` to - CLI: `hive-c0re set-parent <child> --parent <new>` (or `--root` to
promote). Exactly one of `--parent` / `--root` is required. promote). Exactly one of `--parent` / `--root` is required.
@ -34,11 +34,11 @@ validation rules to a pure `apply_set_parent` helper. Refuses:
- self-parenting, - self-parenting,
- cycles (32-hop ancestor walk, mirroring `is_descendant_of`). - cycles (32-hop ancestor walk, mirroring `is_descendant_of`).
Post-#743 the manager is reparentable like any other agent — the The manager is reparentable like any other agent — there's no
"structurally root" carve-out was historical paranoia; the manager's "structurally root" carve-out; the manager's privileges live on its
privileges live on its MCP socket, not its tree position, and the MCP socket, not its tree position, and the cycle walk above catches
cycle walk above catches the only real safety concern (moving the the only real safety concern (moving the manager under one of its
manager under one of its own descendants). own descendants).
Idempotent no-op fast path skips the disk write when the parent is Idempotent no-op fast path skips the disk write when the parent is
already what's requested. After a successful write the surfaces call already what's requested. After a successful write the surfaces call
@ -46,13 +46,12 @@ already what's requested. After a successful write the surfaces call
viewers see the tree repaint without polling viewers see the tree repaint without polling
(`ContainerView.parent` is sourced from `topology.json`). (`ContainerView.parent` is sourced from `topology.json`).
**Today's caveat (#361 follow-up):** the move is purely a JSON edit. **Today's caveat:** the move is purely a JSON edit. Only the
Only the top-level manager (`hm1nd`) gets `/var/lib/hyperhive/agents` top-level manager (`hm1nd`) gets `/var/lib/hyperhive/agents`
bind-mounted at `/agents` in its container, so sub-agents don't yet bind-mounted at `/agents` in its container, so sub-agents don't yet
see their would-be children's state. Once sub-manager bind mounts see their would-be children's state. Once sub-manager bind mounts
land alongside #361 enforcement, `set_parent` grows a companion land alongside cap enforcement, `set_parent` grows a companion
umount-old / mount-new / restart-cascade step (tracked via the umount-old / mount-new / restart-cascade step.
cross-ref comment on #361).
### Why meta, not per-agent `agent.nix` ### Why meta, not per-agent `agent.nix`
@ -78,7 +77,7 @@ where system-level facts live.
so the harness / claude prompts can see it. so the harness / claude prompts can see it.
4. **Surface**: `container_view::build_all` reads `topology.json` and 4. **Surface**: `container_view::build_all` reads `topology.json` and
populates `ContainerView.parent: Option<String>` on every rescan. populates `ContainerView.parent: Option<String>` on every rescan.
The dashboard renders the field as a tree (#363 follow-up). The dashboard renders the field as a tree.
## Target topology semantics ## Target topology semantics
@ -150,7 +149,7 @@ Tree-shape version:
- `request_update_meta_inputs` is the only path that actually writes - `request_update_meta_inputs` is the only path that actually writes
`flake.lock`, gated by the cap; everyone else stays RO. `flake.lock`, gated by the cap; everyone else stays RO.
### D — drop legacy `/state` for manager ✓ done (#604) ### D — drop legacy `/state` for manager ✓ done
`lifecycle.rs` no longer binds `/state` for the manager. `lifecycle.rs` no longer binds `/state` for the manager.
`HYPERHIVE_STATE_DIR` is now injected uniformly via `HYPERHIVE_STATE_DIR` is now injected uniformly via
@ -165,8 +164,8 @@ read.
- `prompts/system.md` with `<!-- role:agent -->` / `<!-- role:manager -->` - `prompts/system.md` with `<!-- role:agent -->` / `<!-- role:manager -->`
marker blocks, assembled by `hive_ag3nt::prompt::render` based on marker blocks, assembled by `hive_ag3nt::prompt::render` based on
flavor (closes #519). **Per-agent cap list** of what the agent can flavor. **Per-agent cap list** of what the agent can do — already
do — already a single parametrised prompt; once #513 lands the a single parametrised prompt; once per-agent cap groups land the
marker grammar grows `cap:<group>` blocks the renderer reads from marker grammar grows `cap:<group>` blocks the renderer reads from
the per-agent ToolGroup set. the per-agent ToolGroup set.
- `mcp.rs::Flavor::{Agent, Manager}` controls which MCP tools claude - `mcp.rs::Flavor::{Agent, Manager}` controls which MCP tools claude
@ -182,8 +181,7 @@ read.
descendants'. descendants'.
- `operator_questions.rs` + `broker.rs`: "manager can cancel any - `operator_questions.rs` + `broker.rs`: "manager can cancel any
question" override on the owner check. **Topology** — agents can question" override on the owner check. **Topology** — agents can
moderate threads of their descendants. (per mara's moderate threads of their descendants.
https://localhost:3000/hyperhive/hyperhive/issues/361#issuecomment-3344)
- `reminder_scheduler.rs`: same override pattern for reminder cancel. - `reminder_scheduler.rs`: same override pattern for reminder cancel.
**Topology** — descendants only. **Topology** — descendants only.
- `actions.rs`: `destroy` refuses to act on `MANAGER_NAME` (no - `actions.rs`: `destroy` refuses to act on `MANAGER_NAME` (no
@ -196,9 +194,9 @@ read.
### G — sub-agents inside the same container ### G — sub-agents inside the same container
Future work mentioned in #361: when enabled for an agent, it can spawn Future work: when enabled for an agent, it can spawn temporary
temporary "sub-agents" that run inside its own container. Lighter than "sub-agents" that run inside its own container. Lighter than a full
a full nspawn agent. Open questions, not yet wired: nspawn agent. Open questions, not yet wired:
- Inherit caps from parent, or take an explicit narrower set? - Inherit caps from parent, or take an explicit narrower set?
- Survive container restart, or always ephemeral? - Survive container restart, or always ephemeral?
@ -301,7 +299,7 @@ bit set` regardless of `hyperhive.user.passwordlessSudo`.
## Cross-references ## Cross-references
- Milestone: [#361 "Agent privileges and sub-agents"](http://localhost:3000/hyperhive/hyperhive/issues/361) - Milestone: ["Agent privileges and sub-agents"](http://localhost:3000/hyperhive/hyperhive/issues/361)
- Dashboard render: [#363 "show agent topology in container list"](http://localhost:3000/hyperhive/hyperhive/issues/363) - Dashboard render: ["show agent topology in container list"](http://localhost:3000/hyperhive/hyperhive/issues/363)
- Audit table source: [comment 3335 on #361](http://localhost:3000/hyperhive/hyperhive/issues/361#issuecomment-3335) - Audit table source: [milestone comment](http://localhost:3000/hyperhive/hyperhive/issues/361#issuecomment-3335)
- Operator/agent trust boundary (orthogonal axis): [`boundary.md`](boundary.md) - Operator/agent trust boundary (orthogonal axis): [`boundary.md`](boundary.md)