From 136102cd27e96fde6165b3588c3c364a45299362 Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 23 Jun 2026 17:56:32 +0200 Subject: [PATCH 1/3] docs(approvals): reframe stale 'the manager' as the root agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- docs/approvals.md | 74 +++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/docs/approvals.md b/docs/approvals.md index 55627689..78662383 100644 --- a/docs/approvals.md +++ b/docs/approvals.md @@ -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//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//config/` (topology-driven via `set_nspawn_flags`; + the agent's *own* config at `/agents//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 @@ -88,7 +91,9 @@ 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 root agent's inbox (current limitation — all helper events route +to the root agent via `notify_manager` regardless of which agent +submitted; tracked in #1953). 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 +405,32 @@ 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//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 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//config/`) is pre-configured with `applied` as a git remote pointing at -`/applied//.git`. Useful incantations from inside the -root agent's container: +`/applied//.git`. Useful incantations from inside an agent with +the full `/applied` mount: ```sh git -C /agents//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` (`` 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,7 +536,7 @@ 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- From 60403fd27cf91ed5555f1cbb41eb98dd4828562e Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 23 Jun 2026 22:10:08 +0200 Subject: [PATCH 2/3] docs(approvals): drop tracker-tag refs; add topology.rs pointer for role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- docs/approvals.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/approvals.md b/docs/approvals.md index 78662383..cba19a2a 100644 --- a/docs/approvals.md +++ b/docs/approvals.md @@ -69,8 +69,8 @@ informed about what happens after a decision lands. 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.) + submitted the approval; routing them to the submitting agent is a + known limitation under active development.) ### Withdrawing a pending approval @@ -93,7 +93,8 @@ 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's inbox (current limitation — all helper events route to the root agent via `notify_manager` regardless of which agent -submitted; tracked in #1953). The submitting agent then reviews, +submitted; routing to the submitting agent is under active development). +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. @@ -414,8 +415,9 @@ calls `bind_child_agent_dirs` for each entry in tool group can therefore edit, commit, and submit changes for any of its direct children directly inside its container at `/agents//config/`. -Agents holding the `can_manage_top_level_agents` topology role get -additional host-side bind mounts via `set_nspawn_flags`: +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). @@ -550,7 +552,7 @@ 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 +the submitting agent is a known limitation under active development.) Variants (`hive_sh4re::HelperEvent`): - `ApprovalResolved { id, agent, commit_ref, status, note }` — From fae2025247209e7c12c8d6cc0083bf7cecd347a9 Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 23 Jun 2026 22:13:28 +0200 Subject: [PATCH 3/3] docs(approvals): update helper-events routing to reflect shipped behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- docs/approvals.md | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/docs/approvals.md b/docs/approvals.md index cba19a2a..b0274283 100644 --- a/docs/approvals.md +++ b/docs/approvals.md @@ -66,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 a - known limitation under active development.) + 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 @@ -91,10 +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's inbox (current limitation — all helper events route -to the root agent via `notify_manager` regardless of which agent -submitted; routing to the submitting agent is under active development). -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. @@ -545,15 +543,14 @@ Two more paths resolve a pending question with a sentinel answer: 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 a known limitation under active development.) 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