Compare commits

...
Author SHA1 Message Date
iris
fae2025247 docs(approvals): update helper-events routing to reflect shipped behavior
notify_manager (always-root) has been replaced by notify_submitter
(routes to the approval submitter, with root fallback for legacy rows).
Update three locations:

- Step 6 of end-to-end flow: "root agent's inbox" →
  "submitting agent's inbox"; explain notify_submitter + submitter column.
- InitConfig paragraph: remove limitation note; "to the root agent's inbox
  (current limitation...)" → "to the submitting agent's inbox via notify_submitter".
- Section header + prose: "Helper events to the root agent" →
  "Helper events to the submitting agent"; rewrite lead paragraph around
  notify_submitter semantics (approvals.submitter column, legacy fallback).
2026-06-23 22:45:43 +02:00
iris
60403fd27c docs(approvals): drop tracker-tag refs; add topology.rs pointer for role
Remove three bare #NNN tracker-tag references in docs/approvals.md
(hive-rules: no #NNN in code/comments/docs):

- Step 6 of end-to-end flow: "tracked in #1953" → "a known limitation
  under active development"
- InitConfig paragraph: same rewrite
- Helper events section: same rewrite

Also add a code pointer for `can_manage_top_level_agents`: the role is
defined as ROLE_CAN_MANAGE_TOP_LEVEL_AGENTS in hive-c0re/src/topology.rs,
now noted inline so reviewers can verify the name is real.
2026-06-23 22:45:43 +02:00
iris
136102cd27 docs(approvals): reframe stale 'the manager' as the root agent
The last docs/ piece of the manager-cleanup. The manager is no longer a
structural role — root-ness is purely topological. Reframe:
- title 'Approvals + manager + helper events' -> 'Approvals + helper events'
- section headers: 'Manager view of applied'/'Manager policy'/'Manager
  (ruth) is hive-c0re-managed'/'Helper events to the manager' ->
  root-agent / root-bootstrap-container equivalents
- body prose: 'the manager (ruth)' -> 'the root agent' (or 'the submitter'
  in the approval-flow steps)
- authority semantics: 'manager-only' -> approvals are submitted by an
  agent with the approvals tool group, for its direct children
- dropped the stale 'the manager refuses to destroy itself' line (the
  bootstrap container is now destroyable + transient; recreated on startup)

Kept the genuine code/protocol identifiers (nixosConfigurations.manager,
manager_server, role:manager prompt block, notify_manager, the
/run/hyperhive/manager/ socket path) — renaming those would diverge from
the source (de-hardcoding is its own backend cleanup).
2026-06-23 22:45:43 +02:00

View file

@ -11,9 +11,12 @@ informed about what happens after a decision lands.
## End-to-end approval flow
1. The submitting agent (the child's parent, holding the `approvals`
tool group) edits files under the child's `/agents/<name>/config/`
(any tracked path, but `agent.nix` is the contract entry point) and
commits with its own git identity.
tool group) edits files in the child's proposed config repo
(any tracked path, but `agent.nix` is the contract entry point)
and commits with its own git identity. The parent's container has
the child's proposed config repo bind-mounted read-write at
`/agents/<name>/config/` (topology-driven via `set_nspawn_flags`;
the agent's *own* config at `/agents/<self>/config/` is read-only).
2. The submitting agent submits the commit sha via `request_apply_commit(agent,
commit_ref)`. `commit_ref` must be a commit **sha** (7-40 hex
chars, short or full) — a branch or tag name is rejected so the
@ -63,11 +66,11 @@ informed about what happens after a decision lands.
failure, main stays put and the working tree resets back to
the previous deployed commit.
6. `HelperEvent::ApprovalResolved` (and `Rebuilt` for the
ApplyCommit kind) land in the root agent's inbox, carrying both
the canonical sha and the terminal tag. (Helper events currently route
to the root agent via `notify_manager` regardless of which agent
submitted the approval; routing them to the submitting agent is tracked
in #1953.)
ApplyCommit kind) land in the **submitting agent's** inbox, carrying
both the canonical sha and the terminal tag. Helper events route to
the submitting agent via `notify_submitter` (the approval row carries
a `submitter` column recording which agent called `request_apply_commit`
or `request_init_config`).
### Withdrawing a pending approval
@ -88,7 +91,8 @@ without it has nothing of its own to withdraw.
`InitConfig` approvals are the first step in a two-step spawn
flow. On approve, hive-c0re seeds the proposed config repo with
a default `agent.nix` template and sends `HelperEvent::ConfigReady { agent }`
to the root agent. The submitting agent then reviews,
to the submitting agent's inbox via `notify_submitter`. The submitting
agent then reviews,
edits, and commits the template before calling `request_apply_commit`
to proceed to an `ApplyCommit` approval. The first `ApplyCommit`
creates the container; subsequent ones rebuild it with new config.
@ -400,26 +404,33 @@ 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`.
### Root-agent view of applied + meta
### Submitting agent's view of config repos
The root agent container gets three host-side bind mounts via
`set_nspawn_flags`:
Every parent agent's container has its **direct children's** proposed
config repos bind-mounted read-write (topology-driven: `lifecycle.rs`
calls `bind_child_agent_dirs` for each entry in
`topology::children_of(agent_name)`). An agent with the `approvals`
tool group can therefore edit, commit, and submit changes for any of
its direct children directly inside its container at `/agents/<child>/config/`.
- `/var/lib/hyperhive/agents/``/agents/` (RW) — proposed
repos. The root agent edits + commits per-agent config here.
- `/var/lib/hyperhive/applied/``/applied/` (RO) — every
agent's authoritative applied repo, including `.git`.
Agents holding the `can_manage_top_level_agents` topology role
(defined as `ROLE_CAN_MANAGE_TOP_LEVEL_AGENTS` in `hive-c0re/src/topology.rs`)
get additional host-side bind mounts via `set_nspawn_flags`:
- `/var/lib/hyperhive/agents/``/agents/` (RW) — all top-level
agents' proposed repos (not just direct children).
- `/var/lib/hyperhive/applied/``/applied/` (RO) — every agent's
authoritative applied repo, including `.git`.
- `/var/lib/hyperhive/meta/``/meta/` (RO) — the swarm-wide
deploy flake.
This is the **root agent's** view — RW over *every* agent's config. An
agent with the `approvals` group that owns a subtree (a sub-manager) has
the equivalent RW scoped to its own children's config repos.
The root agent holds this role; a sub-manager that only manages a
subtree does not, and only has its direct children's config dirs.
Each proposed repo (`/agents/<n>/config/`) is pre-configured
with `applied` as a git remote pointing at
`/applied/<n>/.git`. Useful incantations from inside the
root agent's container:
`/applied/<n>/.git`. Useful incantations from inside an agent with
the full `/applied` mount:
```sh
git -C /agents/<n>/config fetch applied
@ -433,9 +444,8 @@ git -C /meta log --oneline # swarm-wide deplo
cat /meta/flake.lock | jq '.nodes | with_entries(select(.key | startswith("agent-")))'
```
The RO binds block push at the kernel level, so the root agent
can only fetch / read — git plumbing inside the container
cannot corrupt either authoritative repo.
The RO binds block push at the kernel level — git plumbing inside the
container cannot corrupt either authoritative repo.
## Migration from the pre-tag / pre-meta schemes
@ -495,25 +505,25 @@ updates the root agent itself.
## Root-agent policy
From `hive-ag3nt/prompts/system.md` (`<!-- role:manager -->` block,
rendered via `hive_ag3nt::prompt::render`): the root agent does NOT
rubber-stamp sub-agent config requests. It verifies (role match,
package legitimacy, cheaper alternative, blast radius) before
committing and calling `request_apply_commit`.
The system prompt (`hive-ag3nt/prompts/system.md`, rendered via
`hive_ag3nt::prompt::render`) is the **same for every agent**; what
varies is which MCP tools are surfaced (gated by tool groups and
capabilities in `agent.nix`). There is no `role:manager` block that
renders only for the root agent. The root agent's approval-gating
behaviour comes from its CLAUDE.md / agent-specific instructions, not
the system prompt template.
For ambiguous cases or anything that needs human signal, the
the root agent calls `ask(question, options?, multi?, ttl_seconds?, to?)`
queues the question and returns the id immediately. When `to` is
omitted (or `"operator"`) the question shows up on the dashboard;
when `to` is a sub-agent's name, the recipient receives a
`ask(question, options?, multi?, ttl_seconds?, to?)` is available to
**any agent** — it queues a question and returns the id immediately.
When `to` is omitted (or `"operator"`) the question shows up on the
dashboard; when `to` is another agent's name, the recipient receives a
`HelperEvent::QuestionAsked` and answers via their own `answer`
tool. Either way the answer arrives back as
`HelperEvent::QuestionAnswered { id, question, answer, answerer }`
in the asker's inbox. Storage is `hive-c0re::operator_questions`
(sqlite) — same table, with a nullable `target` column
(NULL = operator). Dispatch goes through
`hive-c0re/src/questions.rs::{handle_ask, handle_answer}` so both
the agent + root-agent surfaces stay aligned. The answer flow is:
`hive-c0re/src/questions.rs::{handle_ask, handle_answer}`. The answer flow is:
```
POST /answer-question/{id} agent: Answer { id, answer }
@ -526,22 +536,21 @@ POST /answer-question/{id} agent: Answer { id, answer }
Two more paths resolve a pending question with a sentinel answer:
- `POST /cancel-question/{id}` (✗ CANC3L button on the dashboard)
resolves with `[cancelled]`. The root agent sees a terminal state
resolves with `[cancelled]`. The asking agent sees a terminal state
and can fall back.
- `ttl_seconds` deadline: a tokio watchdog spawned at submit time
fires `answer(id, "[expired]")` once the ttl runs out. Already-
resolved races no-op. The dashboard surfaces a `⏳ MM:SS` chip
on each pending question with a deadline.
## Helper events to the root agent
## Helper events to the submitting agent
`Coordinator::notify_manager(&HelperEvent)` enqueues an inbox
message from sender `system` with the event JSON in the body. The
root agent's harness no longer short-circuits these — they drive a
regular claude turn so the root agent can react. (Today these go to the
root agent regardless of which agent submitted the approval — routing to
the submitting agent is tracked in #1953.) Variants
(`hive_sh4re::HelperEvent`):
`Coordinator::notify_submitter(approval_id, &HelperEvent)` routes the
event to the agent that originally submitted the approval (looked up from
the `submitter` column on the `approvals` table). The harness delivers it
as a regular `system` inbox message so it drives a normal claude turn.
Legacy approval rows that predate the submitter column fall back to the
root agent. Variants (`hive_sh4re::HelperEvent`):
- `ApprovalResolved { id, agent, commit_ref, status, note }`
fired by `actions::approve` + `actions::deny` whenever an