From 32148179e6788d37780301a9842a9c0a87244b45 Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 29 May 2026 23:23:58 +0200 Subject: [PATCH] refactor: move hive-c0re options to hyperhive namespace (#612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move options.services.hive-c0re → options.hyperhive.c0re - Add options.hyperhive.enable to auto-enable c0re + subsystems - Add deprecation alias for services.hive-c0re.enable (backward compat) - Update doc references in README, flake.nix, docs, harness-base.nix - Simplifies config: 'hyperhive.enable = true' now enables everything Existing operator configs using services.hive-c0re.enable will continue to work but emit a deprecation warning. Aligns the option namespace with the existing hyperhive.* family (matrix, forge, domain). fixes #612 --- README.md | 6 +- docs/turn-loop.md | 4 +- flake.nix | 6 +- nix/modules/hive-c0re.nix | 177 +++++++++++++++++++-------------- nix/templates/harness-base.nix | 4 +- 5 files changed, 113 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 83aa3084..5cac0715 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ Minimal `flake.nix` for a host that runs hive-c0re: modules = [ hyperhive.nixosModules.default # hive-c0re + hive-forge in one import ({ ... }: { - services.hive-c0re.enable = true; - # services.hive-c0re.operatorPronouns = "they/them"; # default: "she/her" + hyperhive.enable = true; + # hyperhive.c0re.operatorPronouns = "they/them"; # default: "she/her" # ... rest of your host config system.stateVersion = "25.11"; @@ -78,7 +78,7 @@ manager container, and auto-rebuilds any container whose hyperhive rev goes stale. `claude-code` is unfree — hyperhive scopes the whitelist to itself, nothing for the operator to set. -Optional: set `services.hive-c0re.preBuildAgentTemplates = true;` +Optional: set `hyperhive.c0re.preBuildAgentTemplates = true;` to pre-fetch the per-container system closures into your host's /nix/store as part of `nixos-rebuild`. First-agent-spawn then completes in seconds instead of minutes (no nixpkgs/claude-code diff --git a/docs/turn-loop.md b/docs/turn-loop.md index de3c3297..324dff12 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -76,7 +76,7 @@ match wins): 1. `HIVE_CONTEXT_WINDOW_TOKENS_` env var, where `KEY` (lowercased) is a substring of the active model name. Injected - by the meta flake from `services.hive-c0re.contextWindowTokens` + by the meta flake from `hyperhive.c0re.contextWindowTokens` (host-level NixOS option, defaults: haiku=200k, sonnet=1M, opus=1M). Override these for all agents at once without a per-agent config change. @@ -178,7 +178,7 @@ socket at `/run/hive/` once at startup: #519); everything else is shared. Then `{label}` and `{operator_pronouns}` get substituted in the assembled output. Pronouns come from `HIVE_OPERATOR_PRONOUNS` env (set by the meta - flake from `services.hive-c0re.operatorPronouns`, default + flake from `hyperhive.c0re.operatorPronouns`, default `she/her`). Passed via `--system-prompt-file`. The shared per-turn plumbing lives in `hive_ag3nt::turn::{write_mcp_config, diff --git a/flake.nix b/flake.nix index ad424a7e..964a15f3 100644 --- a/flake.nix +++ b/flake.nix @@ -225,7 +225,7 @@ agent-base = ./nix/templates/agent-base.nix; manager = ./nix/templates/manager.nix; # The hive-c0re module wants `pkgs.hyperhive` for its default - # `services.hive-c0re.package`. To avoid making operators apply an + # `hyperhive.c0re.package`. To avoid making operators apply an # overlay (which would also pollute their host pkgs with our # build), we thread the package straight from this flake's # `packages..default` via a `hyperhivePackage` argument. @@ -237,7 +237,7 @@ hyperhiveAssets = system: self.packages.${system}.assets; hyperhiveFlake = "${self}"; # Per-container toplevels — wired into `system.extraDependencies` - # when `services.hive-c0re.preBuildAgentTemplates` is on so the + # when `hyperhive.c0re.preBuildAgentTemplates` is on so the # host system closure pre-fetches the heavy build inputs (#97). # Defined only for x86_64-linux because nixosConfigurations are # hardcoded to that system; the option's default keeps the @@ -252,7 +252,7 @@ # in hive-forge). Intended usage: # # imports = [ hyperhive.nixosModules.default ]; - # services.hive-c0re.enable = true; + # hyperhive.enable = true; # default = self.nixosModules.hive-c0re; }; diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index ae288a34..f6c7753d 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -13,7 +13,7 @@ ... }: let - cfg = config.services.hive-c0re; + cfg = config.hyperhive.c0re; in { # The forge is part of the standard install — hive-c0re mirrors @@ -26,6 +26,10 @@ in ./hive-matrix.nix ]; + # Top-level hyperhive enable flag. When true, automatically enables + # hive-c0re and hyperhive subsystems. + options.hyperhive.enable = lib.mkEnableOption "hyperhive — the agent swarm coordinator"; + # Top-level option shared by any hyperhive subsystem that needs a # stable hostname (matrix server_name today, forge ROOT_URL likely # next). Type is nullable + default null so existing operator @@ -46,8 +50,23 @@ in ''; }; - options.services.hive-c0re = { - enable = lib.mkEnableOption "hive-c0re — hyperhive coordinator daemon"; + # Deprecated alias for backward compatibility. Remove in v0.2. + options.services.hive-c0re.enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + **DEPRECATED** (as of #612). Use `hyperhive.enable = true` or + `hyperhive.c0re.enable = true` instead. This option is maintained + for backward compatibility and will be removed in a future release. + ''; + }; + + options.hyperhive.c0re = { + enable = lib.mkOption { + type = lib.types.bool; + default = config.hyperhive.enable; + description = "Enable hive-c0re coordinator daemon (auto-enabled by hyperhive.enable)."; + }; package = lib.mkOption { type = lib.types.package; default = hyperhivePackage pkgs.stdenv.hostPlatform.system; @@ -166,77 +185,87 @@ in }; }; - config = lib.mkIf cfg.enable { - environment.systemPackages = [ - cfg.package - pkgs.git - ]; - - # Pull the per-container toplevels into the host system closure - # (#97). `system.extraDependencies` adds paths to the system build - # without referencing them at runtime — nixos-rebuild fetches / - # builds them, they end up in /nix/store, and the first - # nixos-container update + start for an agent has nothing left to - # do. Gated because the closure is sizeable and pinned to x86_64. - system.extraDependencies = lib.optionals cfg.preBuildAgentTemplates [ - agentBaseToplevel - managerToplevel - ]; - - # Dashboard + per-container web UIs share the host's network namespace and - # need their ports reachable. Dashboard: `cfg.dashboardPort` (default 7000). - # Manager: 8000. Sub-agents: 8100..8999 (deterministic hash; see - # `lifecycle::agent_web_port`). - networking.firewall.allowedTCPPorts = [ - cfg.dashboardPort - 8000 - ]; - networking.firewall.allowedTCPPortRanges = [ - { - from = 8100; - to = 8999; - } - ]; - - systemd.services.hive-c0re = { - description = "hyperhive coordinator daemon"; - wantedBy = [ "multi-user.target" ]; - path = [ - pkgs.git - "/run/current-system/sw" + config = lib.mkMerge [ + # Backward-compatibility redirect for deprecated services.hive-c0re.enable + (lib.mkIf config.services.hive-c0re.enable { + hyperhive.c0re.enable = true; + warnings = [ + "services.hive-c0re.enable is deprecated (as of #612). Use 'hyperhive.enable = true' or 'hyperhive.c0re.enable = true' instead." ]; - environment = { - HYPERHIVE_GIT = "${pkgs.git}/bin/git"; - # Path to the dashboard static dist. The hive-c0re axum router - # serves this via `tower_http::ServeDir` for any path it doesn't - # match against an API/action route. - HIVE_STATIC_DIR = "${cfg.frontend}/dashboard"; - # Path to the static runtime asset tree (branding + claude - # prompts). `hive_sh4re::assets::*` reads paths underneath. - # `forge.rs` reads the avatar PNGs from here on startup. - HIVE_ASSETS_DIR = "${cfg.assets}/share/hyperhive"; - } - // lib.optionalAttrs config.hyperhive.forge.enable { - # Agents poll this URL for Forgejo notifications. Derived from - # hyperhive.forge.{domain,httpPort} so it tracks forge config changes. - HIVE_FORGE_URL = "http://${config.hyperhive.forge.domain}:${toString config.hyperhive.forge.httpPort}"; - } - // lib.optionalAttrs config.hyperhive.matrix.gui.enable { - # Optional matrix-GUI static dist mounted at /matrix/ by the - # dashboard router (#607 v0). Pre-#15 / pre-nginx-front: this is - # the simplest same-origin shape — fluffychat-web ships as a - # static dist, no runtime daemon needed. - HIVE_MATRIX_GUI_DIR = "${config.hyperhive.matrix.gui.package}"; + }) + # Main config block + (lib.mkIf cfg.enable { + environment.systemPackages = [ + cfg.package + pkgs.git + ]; + + # Pull the per-container toplevels into the host system closure + # (#97). `system.extraDependencies` adds paths to the system build + # without referencing them at runtime — nixos-rebuild fetches / + # builds them, they end up in /nix/store, and the first + # nixos-container update + start for an agent has nothing left to + # do. Gated because the closure is sizeable and pinned to x86_64. + system.extraDependencies = lib.optionals cfg.preBuildAgentTemplates [ + agentBaseToplevel + managerToplevel + ]; + + # Dashboard + per-container web UIs share the host's network namespace and + # need their ports reachable. Dashboard: `cfg.dashboardPort` (default 7000). + # Manager: 8000. Sub-agents: 8100..8999 (deterministic hash; see + # `lifecycle::agent_web_port`). + networking.firewall.allowedTCPPorts = [ + cfg.dashboardPort + 8000 + ]; + networking.firewall.allowedTCPPortRanges = [ + { + from = 8100; + to = 8999; + } + ]; + + systemd.services.hive-c0re = { + description = "hyperhive coordinator daemon"; + wantedBy = [ "multi-user.target" ]; + path = [ + pkgs.git + "/run/current-system/sw" + ]; + environment = { + HYPERHIVE_GIT = "${pkgs.git}/bin/git"; + # Path to the dashboard static dist. The hive-c0re axum router + # serves this via `tower_http::ServeDir` for any path it doesn't + # match against an API/action route. + HIVE_STATIC_DIR = "${cfg.frontend}/dashboard"; + # Path to the static runtime asset tree (branding + claude + # prompts). `hive_sh4re::assets::*` reads paths underneath. + # `forge.rs` reads the avatar PNGs from here on startup. + HIVE_ASSETS_DIR = "${cfg.assets}/share/hyperhive"; + } + // lib.optionalAttrs config.hyperhive.forge.enable { + # Agents poll this URL for Forgejo notifications. Derived from + # hyperhive.forge.{domain,httpPort} so it tracks forge config changes. + HIVE_FORGE_URL = "http://${config.hyperhive.forge.domain}:${toString config.hyperhive.forge.httpPort}"; + } + // lib.optionalAttrs config.hyperhive.matrix.gui.enable { + # Optional matrix-GUI static dist mounted at /matrix/ by the + # dashboard router (#607 v0). Pre-#15 / pre-nginx-front: this is + # the simplest same-origin shape — fluffychat-web ships as a + # static dist, no runtime daemon needed. + HIVE_MATRIX_GUI_DIR = "${config.hyperhive.matrix.gui.package}"; + }; + serviceConfig = { + ExecStart = "${cfg.package}/bin/hive-c0re --socket /run/hyperhive/host.sock serve --hyperhive-flake ${cfg.hyperhiveFlake} --dashboard-port ${toString cfg.dashboardPort} --operator-pronouns ${lib.escapeShellArg cfg.operatorPronouns} --context-window-tokens ${lib.escapeShellArg (builtins.toJSON cfg.contextWindowTokens)}"; + Restart = "on-failure"; + RestartSec = 2; + RuntimeDirectory = "hyperhive"; + RuntimeDirectoryMode = "0750"; + RuntimeDirectoryPreserve = "yes"; + StateDirectory = "hyperhive"; + }; }; - serviceConfig = { - ExecStart = "${cfg.package}/bin/hive-c0re --socket /run/hyperhive/host.sock serve --hyperhive-flake ${cfg.hyperhiveFlake} --dashboard-port ${toString cfg.dashboardPort} --operator-pronouns ${lib.escapeShellArg cfg.operatorPronouns} --context-window-tokens ${lib.escapeShellArg (builtins.toJSON cfg.contextWindowTokens)}"; - Restart = "on-failure"; - RestartSec = 2; - RuntimeDirectory = "hyperhive"; - RuntimeDirectoryMode = "0750"; - RuntimeDirectoryPreserve = "yes"; - StateDirectory = "hyperhive"; - }; - }; - }; + }) + ]; } diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index 720b6633..8cf9a68f 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -36,7 +36,7 @@ `"haiku"`, `"sonnet"`, `"opus"` (or any future identifier). Context window sizes are looked up at runtime from the `HIVE_CONTEXT_WINDOW_TOKENS_` env vars injected by the - meta flake; override sizes via `services.hive-c0re.contextWindowTokens` + meta flake; override sizes via `hyperhive.c0re.contextWindowTokens` on the host. ''; }; @@ -595,7 +595,7 @@ # both the harness binary and any user-shell `cargo run` inside the # container resolve them from the same path. # HIVE_CONTEXT_WINDOW_TOKENS_* are injected by the meta flake from the - # host-level `services.hive-c0re.contextWindowTokens` option — not set here. + # host-level `hyperhive.c0re.contextWindowTokens` option — not set here. environment.variables = { HIVE_DEFAULT_MODEL = config.hyperhive.model; HIVE_ASSETS_DIR = "${pkgs.hyperhive-assets}/share/hyperhive";