From 41eb3f806ca70cbe1bc697933810ed3787873e4f Mon Sep 17 00:00:00 2001 From: damocles Date: Thu, 4 Jun 2026 12:40:24 +0200 Subject: [PATCH] =?UTF-8?q?refactor:=20remove=20hyperhive.role=20option=20?= =?UTF-8?q?=E2=80=94=20there=20is=20only=20one=20role:=20agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 11 ++-- docs/agent-hierarchy.md | 54 +++++--------------- docs/turn-loop.md | 13 ++--- hive-ag3nt/Cargo.toml | 8 ++- hive-ag3nt/src/bin/hive.rs | 1 - hive-ag3nt/src/prompt.rs | 32 ++---------- hive-ag3nt/src/web_ui.rs | 7 ++- hive-bash-mcp/src/runner.rs | 23 +++++---- hive-c0re/src/actions.rs | 9 ++-- hive-c0re/src/agent_server.rs | 5 +- hive-c0re/src/auto_update.rs | 9 ++-- hive-c0re/src/bin/hivectl.rs | 6 +-- hive-c0re/src/dashboard.rs | 11 ++-- hive-c0re/src/manager_server.rs | 7 ++- hive-c0re/src/migrate.rs | 4 +- hive-c0re/src/scheduled_prompts_worker.rs | 2 - hive-c0re/src/server.rs | 3 +- hive-forge/src/verbs/pr_reviews.rs | 30 +++-------- hive-sh4re/src/lib.rs | 8 ++- nix/modules/hive-network.nix | 3 +- nix/templates/agent-base.nix | 8 +-- nix/templates/harness-base.nix | 61 ++++------------------- nix/templates/manager.nix | 19 +++---- 23 files changed, 105 insertions(+), 229 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4405782d..5fb6c70c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -328,11 +328,12 @@ nix/ `services.hyperhive.domain`; gateway serves `.well-known/matrix/{client,server}` for auto-discovery; federation on, e2ee deferred - templates/harness-base.nix shared harness for all containers; `hyperhive.role` - (`"agent"` | `"manager"`) drives service unit + forge - defaults; `hyperhive.model` option (HIVE_DEFAULT_MODEL) - templates/agent-base.nix thin role-setter (`hyperhive.role = "agent"`) - templates/manager.nix thin role-setter (`hyperhive.role = "manager"`) + templates/harness-base.nix shared harness for all containers; single + `hive-ag3nt` service unit; `hyperhive.model` + option (HIVE_DEFAULT_MODEL) + templates/agent-base.nix entry-point for sub-agent containers + templates/manager.nix entry-point for ruth; adds forge noise-reduction + defaults (keepSubscriptions=false etc.) templates/weston-vnc.nix optional `hyperhive.gui.enable` — weston + VNC backend systemd unit; writes /etc/hyperhive/gui.json (vnc_port + auth) for diff --git a/docs/agent-hierarchy.md b/docs/agent-hierarchy.md index 087326f6..2e3ce4b7 100644 --- a/docs/agent-hierarchy.md +++ b/docs/agent-hierarchy.md @@ -202,46 +202,19 @@ nspawn agent. Open questions, not yet wired: - Filesystem: share parent's `/state` RW, or a sub-dir? - Identity: distinct broker recipient name, or address the parent? -## Harness systemd unit shape (per-role) +## Harness systemd unit shape -One harness binary (`hive`), one `harness-base.nix` template, two -systemd units depending on `hyperhive.role`: +One harness binary (`hive`), one `harness-base.nix` template, one +service unit (`systemd.services.hive-ag3nt`) for all agents. There +is no longer a separate manager service name or role distinction in +the harness — privilege differences live server-side in the broker +socket (which tool groups and manager-surface calls each agent +receives). -- `agent-base.nix` (`role = "agent"`) → `systemd.services.hive-ag3nt` -- `manager.nix` (`role = "manager"`) → `systemd.services.hive-m1nd` - -The unit names diverge but the binary is the same. `HIVE_ROLE` env -var picks the surface at startup (agent vs manager); naming the -units after the historical per-role binaries keeps dashboard log -queries, ExecStartPre paths, and ancestor PR diffs working without a -rename cascade. - -### Manager-only defaults - -`harness-base.nix` flips these when `hyperhive.role == "manager"`, -via `lib.mkDefault` so any agent can invert if needed: - -- `hyperhive.forge.keepSubscriptions = false` -- `hyperhive.forge.skipNotifyReasons = [ "subscribed" "participating" ]` - -Skips the subscription / participation firehose so the manager's -inbox only carries direct mentions, reviews, and assignments. Sub- -agents keep the noisier defaults so they see anything aimed at the -repos they're working on. - -### Standalone-eval fallbacks - -`nixosConfigurations.manager` must build standalone (without the -meta-flake's per-agent flake.nix wrapper). For the manager unit -that means a hardcoded `HIVE_LABEL` env value: - -- `HIVE_LABEL = "ruth"` — logical agent name; matches what `meta.rs` - injects at deploy time. - -Real deploys never read these — `meta::render_flake` overrides them -via the generated wrapper. They exist so the manager -`nixosConfigurations` evaluates cleanly even outside the meta-flake -boundary. +`agent-base.nix` and `manager.nix` both import `harness-base.nix`. +`manager.nix` additionally sets forge defaults to suppress the +subscription/participation firehose so ruth's inbox stays focused +on direct mentions, reviews, and assignments. ### Environment variables set on the unit @@ -256,8 +229,6 @@ boundary. directly on the unit, **not** via `environment.variables`, because the latter only populates `/etc/profile` which systemd services don't inherit. -- `HIVE_ROLE = config.hyperhive.role` — picks the binary surface - (agent / manager) at startup. ### `PATH` setup (the wrapper-dir trick) @@ -278,8 +249,7 @@ bit set` regardless of `hyperhive.user.passwordlessSudo`. ### `serviceConfig` highlights -- `ExecStart = pkgs.hyperhive/bin/hive serve` — single binary, - surface picked from `HIVE_ROLE`. +- `ExecStart = pkgs.hyperhive/bin/hive serve` — single binary. - `Restart = on-failure`, `RestartSec = 2` — keeps the harness resilient across transient crashes without thundering retries. - `RuntimeDirectory = "hive-config"` → `/run/hive-config/` owned by diff --git a/docs/turn-loop.md b/docs/turn-loop.md index 88ac9b82..9e5955ad 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -5,8 +5,7 @@ claude has access to in return. ## The loop -Each agent harness (`hive serve`, role set via `$HIVE_ROLE` — always -`"agent"`, one binary) runs: +Each agent harness (`hive serve` — one binary for all agents) runs: 1. Long-poll `Recv` on its socket. The host-side broker (`broker.rs::recv_blocking_batch`) returns immediately if there's @@ -57,15 +56,11 @@ Each agent harness (`hive serve`, role set via `$HIVE_ROLE` — always ## Harness binary shape -One `hive` binary serves both roles. The split into +One `hive` binary for all agents. The earlier split into `hive-ag3nt` + `hive-m1nd` was collapsed because the privilege boundary lives server-side at the broker socket -(`/run/hive/mcp.sock`): an agent-flavor socket refuses -`ManagerRequest` calls regardless of who sends them, so there's no -escalation risk in shipping the same code to both. `main()` reads -`$HIVE_ROLE` (set by `harness-base.nix` from `hyperhive.role`; -defaults to `"agent"` for standalone `nix run` invocations) and -dispatches. +(`/run/hive/mcp.sock`): `ManagerRequest` calls are refused by the +standard agent socket regardless of who sends them. Three subcommands: diff --git a/hive-ag3nt/Cargo.toml b/hive-ag3nt/Cargo.toml index ed5de53b..655b5ab3 100644 --- a/hive-ag3nt/Cargo.toml +++ b/hive-ag3nt/Cargo.toml @@ -28,10 +28,8 @@ tracing-subscriber.workspace = true tempfile = "3" [[bin]] -# Unified harness binary: both `agent` and `manager` code paths live -# here; the binary picks its role at startup from `HIVE_ROLE` (set by -# `harness-base.nix` from `hyperhive.role`). The privilege boundary is -# enforced server-side at the socket, so shipping both surfaces in one -# binary is safe. See `docs/turn-loop.md::Harness binary shape`. +# Unified harness binary for all agents. Privilege boundary is +# enforced server-side at the socket (tool groups / manager surface). +# See `docs/turn-loop.md::Harness binary shape`. name = "hive" path = "src/bin/hive.rs" diff --git a/hive-ag3nt/src/bin/hive.rs b/hive-ag3nt/src/bin/hive.rs index b90494ca..a565b6ce 100644 --- a/hive-ag3nt/src/bin/hive.rs +++ b/hive-ag3nt/src/bin/hive.rs @@ -198,7 +198,6 @@ trait Surface { struct AgentSurface; impl Surface for AgentSurface { - async fn ack_turn(socket: &Path) { match client::request::<_, AgentResponse>(socket, &AgentRequest::AckTurn).await { Ok(AgentResponse::Ok) => {} diff --git a/hive-ag3nt/src/prompt.rs b/hive-ag3nt/src/prompt.rs index 8173fc7e..a86d9054 100644 --- a/hive-ag3nt/src/prompt.rs +++ b/hive-ag3nt/src/prompt.rs @@ -269,13 +269,7 @@ shared closer // Real template's first agent line — keeps the renderer // honest about the {label} / {operator_pronouns} pair the // harness already relied on. - let rendered = render( - &PRODUCTION_TEMPLATE, - "alice", - "they/them", - None, - None, - ); + let rendered = render(&PRODUCTION_TEMPLATE, "alice", "they/them", None, None); assert!(rendered.contains("hyperhive agent `alice`")); assert!(rendered.contains("**they/them** pronouns")); assert!(!rendered.contains("{label}")); @@ -285,13 +279,7 @@ shared closer #[test] fn render_no_role_markers_in_output() { // No raw role markers should survive into the rendered prompt. - let rendered = render( - &PRODUCTION_TEMPLATE, - "alice", - "she/her", - None, - None, - ); + let rendered = render(&PRODUCTION_TEMPLATE, "alice", "she/her", None, None); assert!(!rendered.contains("