refactor: nix/host-modules + nix/agent-modules layout, update doc paths
This commit is contained in:
parent
cb755b677c
commit
4a48ce5024
52 changed files with 48 additions and 44 deletions
16
CLAUDE.md
16
CLAUDE.md
|
|
@ -63,12 +63,16 @@ hand-maintained per-file tree drifts out of sync with the code.
|
|||
### Other top-level dirs
|
||||
|
||||
- **`frontend/`** — npm workspaces → static dashboard + per-agent UI
|
||||
dist, built hermetically by `nix/frontend.nix`. Packages: `shared`
|
||||
(terminal pane + Catppuccin palette), `dashboard` (the operator SPA),
|
||||
`agent` (the default per-container UI).
|
||||
- **`nix/`** — NixOS modules (`modules/hive-{c0re,forge,gateway,matrix,
|
||||
ci,network}.nix`) + per-container templates (`templates/{harness-base,
|
||||
agent-base,manager,weston-vnc}.nix`) + the options-doc derivation.
|
||||
dist, built hermetically by `nix/packages/frontend.nix`. Packages:
|
||||
`shared` (terminal pane + Catppuccin palette), `dashboard` (the
|
||||
operator SPA), `agent` (the default per-container UI).
|
||||
- **`nix/`** — `host-modules/` (the host stack: hyperhive core options,
|
||||
`hive-{c0re,priv,forge,gateway,matrix,network,tls,ci}`, otel, swarm),
|
||||
`agent-modules/` (the per-agent harness feature modules),
|
||||
`templates/{agent,ruth}.nix` (container entry points), `packages/`
|
||||
(flake package outputs), `docs/` (the options-doc derivation), plus
|
||||
`sources.nix` / `rust.nix` / `checks.nix` / `devshell.nix` /
|
||||
`treefmt.nix` behind the thin `flake.nix`.
|
||||
- **`docs/`** — subsystem reference docs (see *Reading paths* below).
|
||||
- **`branding/`**, **`scripts/`** — static assets + helper scripts.
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ Tree-shape version:
|
|||
`HYPERHIVE_STATE_DIR` is now injected uniformly via
|
||||
`systemd.globalEnvironment` in `meta.rs` for every container
|
||||
(manager included), so all token/state paths resolve through
|
||||
`$HYPERHIVE_STATE_DIR`. The harness-base shell scripts
|
||||
`$HYPERHIVE_STATE_DIR`. The agent-module shell scripts
|
||||
(tea-login, forge-avatar-sync) simplified from glob+for loops to a
|
||||
direct `$HYPERHIVE_STATE_DIR/<token>` read.
|
||||
|
||||
|
|
@ -215,15 +215,15 @@ nspawn agent. Open questions, not yet wired:
|
|||
## Harness systemd unit shape
|
||||
|
||||
One harness serve binary (`hive-agent`, with its `hive-agent-mcp` /
|
||||
`hive-agent-wake` siblings), one `harness-base.nix` template, one
|
||||
`hive-agent-wake` siblings), one shared `nix/agent-modules/` tree, 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` and `manager.nix` both import `harness-base.nix`.
|
||||
`manager.nix` additionally sets forge defaults to suppress the
|
||||
`agent.nix` and `ruth.nix` both import the shared `nix/agent-modules/`.
|
||||
`ruth.nix` additionally sets forge defaults to suppress the
|
||||
subscription/participation firehose so ruth's inbox stays focused
|
||||
on direct mentions, reviews, and assignments.
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,6 @@ GC on the coordinator host won't reclaim space on the builder.
|
|||
|
||||
## References
|
||||
|
||||
- `nix/modules/hive-ci.nix`: runner configuration, auto-registration script, container setup.
|
||||
- `nix/host-modules/hive-ci.nix`: runner configuration, auto-registration script, container setup.
|
||||
- `.forgejo/workflows/ci.yml`: workflow definition.
|
||||
- `docs/gotchas.md`: nix sandboxing limitations in containers.
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ socket without needing a clean reinstall.
|
|||
## `claude-code` is unfree
|
||||
|
||||
`claude-code` comes from the flake's main `nixpkgs` (nixos-26.05).
|
||||
It's unfree, so `harness-base.nix` sets `config.allowUnfreePredicate`
|
||||
It's unfree, so the agent modules set `config.allowUnfreePredicate`
|
||||
at the container level to whitelist `claude-code` specifically —
|
||||
scoped, only this one package. This is needed because each per-agent
|
||||
`nixosConfiguration` evaluates its own nixpkgs instance and the
|
||||
|
|
@ -204,7 +204,7 @@ containers don't get user-namespaces by default, so `nix build`
|
|||
invocations _inside_ the container can't set up the build sandbox
|
||||
and fail outright if the host daemon's
|
||||
`nix.settings.sandbox-fallback` is `false` (nixpkgs default).
|
||||
`nix/templates/harness-base.nix` does `lib.mkForce true` so builds
|
||||
`nix/agent-modules/default.nix` does `lib.mkForce true` so builds
|
||||
fall back to unsandboxed local builds rather than failing. Security
|
||||
implications: `docs/security.md`.
|
||||
|
||||
|
|
@ -284,7 +284,7 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
|||
inherit it.
|
||||
- **Fixed Wayland socket name (`--socket=wayland-0`)**: weston is
|
||||
launched with `--socket=wayland-0` so the socket path is
|
||||
deterministic. `harness-base.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
||||
deterministic. `nix/agent-modules/weston-vnc.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
||||
and `XDG_RUNTIME_DIR=/run/gui` as global system environment
|
||||
variables (gated on `hyperhive.gui.enable`) so every systemd service
|
||||
in the container inherits them. Without this, services starting
|
||||
|
|
@ -311,7 +311,7 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
|||
must never block on weston signalling readiness. A misconfigured
|
||||
weston degrades to a `Restart=on-failure` loop visible in
|
||||
`journalctl`, it does not abort the `nixos-container update`.
|
||||
Same reasoning as the `tea-login` unit in `harness-base.nix`.
|
||||
Same reasoning as the `tea-login` unit in `nix/agent-modules/forge.nix`.
|
||||
- **`[core] idle-time=0`**: disables weston's 300-second idle
|
||||
timeout. Without it the VNC desktop fades to black and
|
||||
desktop-shell shows its click-to-unlock screen — useless for an
|
||||
|
|
@ -325,7 +325,7 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
|||
`pkgs.nixosOptionsDoc` over two evaluated module trees:
|
||||
`hostEval` (a stub NixOS system loading `hive-c0re.nix` with every
|
||||
hyperhive subsystem `mkForce false` so heavy build inputs stay out of
|
||||
the eval) and `agentEval` (evaluates `agent-base.nix` fresh for the
|
||||
the eval) and `agentEval` (evaluates `agent.nix` fresh for the
|
||||
per-agent options tree).
|
||||
|
||||
Three output trees consumed by `flake.nix`, all **markdown**:
|
||||
|
|
@ -333,7 +333,7 @@ Three output trees consumed by `flake.nix`, all **markdown**:
|
|||
- `docs-host` — operator-facing host module options
|
||||
(`services.hyperhive.*`)
|
||||
- `docs-agent` — per-agent harness options (`hyperhive.*`
|
||||
declared in `nix/templates/harness-base.nix`)
|
||||
declared in `nix/agent-modules/`)
|
||||
- `docs` — bundle of `index.md` + `host.md` + `agent.md`
|
||||
|
||||
Pipeline:
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ which has two upstream gaps for fluffychat's web target:
|
|||
- `native_imaging`'s C source isn't built — emscripten isn't a
|
||||
flutter-builder native build input.
|
||||
|
||||
Both fixed in `nix/modules/hive-matrix.nix` via two derivations:
|
||||
Both fixed in `nix/host-modules/hive-matrix.nix` via two derivations:
|
||||
|
||||
- **`fluffychat-web-imaging`** builds `Imaging.{js,wasm}` from the
|
||||
`native_imaging` C source via `pkgs.emscripten`. Source comes
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ address arithmetic.
|
|||
and `HOST_BRIDGE=<bridgeName>` via `lifecycle::set_nspawn_flags` when
|
||||
creating or updating containers. `LOCAL_ADDRESS` is left empty so the
|
||||
container's dhcpcd acquires an address from the bridge dnsmasq pool
|
||||
(`networking.useDHCP = true` in `harness-base.nix`). This applies uniformly
|
||||
(`networking.useDHCP = true` in `nix/agent-modules/network.nix`). This applies uniformly
|
||||
to all containers — agents and service containers alike.
|
||||
|
||||
`HOST_ADDRESS` is the bridge gateway IP (the address part of
|
||||
|
|
@ -154,7 +154,7 @@ wiring is runtime:
|
|||
|
||||
- `hive-priv` drops a marker file (`/etc/hyperhive-bridge-dns`, carrying the
|
||||
gateway IP) into each container's `/etc`.
|
||||
- the `hyperhive-isolated-dns` oneshot (harness-base.nix), gated on that
|
||||
- the `hyperhive-isolated-dns` oneshot (`nix/agent-modules/network.nix`), gated on that
|
||||
marker, rewrites `/etc/resolv.conf` to `nameserver <gateway-ip>` at boot.
|
||||
It is ordered `before` the harness (`hive-ag3nt`), the matrix daemon, and
|
||||
`tea-login` so the resolver is correct before the first DNS lookup.
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ state dirs need a one-time data shuffle so they don't lose their claude
|
|||
session.
|
||||
|
||||
`system.activationScripts.hive-agent-user-migrate` (in
|
||||
`nix/templates/harness-base.nix`) runs on every activation,
|
||||
`nix/agent-modules/user.nix`) runs on every activation,
|
||||
marker-guarded so the substantive moves only happen once per
|
||||
container lifetime:
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ component can't traverse.
|
|||
Agent containers bind-mount the host's `nix-daemon` socket. The host daemon may
|
||||
have `sandbox-fallback = false` (strict NixOS defaults), which causes `nix build`
|
||||
inside nspawn containers to fail — containers lack kernel user namespaces, so nix
|
||||
cannot set up its build sandbox. `harness-base.nix` sets `sandbox-fallback = true`
|
||||
cannot set up its build sandbox. the agent modules set `sandbox-fallback = true`
|
||||
so that builds fall back to unsandboxed execution rather than failing outright.
|
||||
|
||||
### Threat model
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Background shell execution via `hive-bash-mcp`. Tools land as
|
||||
`mcp__bash__<tool>` (the MCP server name is `bash`, not `hyperhive`).
|
||||
Available on every agent unconditionally — `harness-base.nix` always
|
||||
Available on every agent unconditionally — `nix/agent-modules/mcp.nix` always
|
||||
injects bash into `hyperhive.extraMcpServers` (with `allowedTools =
|
||||
["*"]`), so `mcp__bash__*` is in `--allowedTools` for every claude
|
||||
invocation regardless of tool groups.
|
||||
|
|
@ -96,7 +96,7 @@ The bash tooling follows the same daemon + stdio-bridge pattern as the
|
|||
matrix MCP:
|
||||
|
||||
- **`hive-bash-daemon`** — long-running process (one per agent container,
|
||||
systemd service in `harness-base.nix`). Owns subprocess management,
|
||||
systemd service in `nix/agent-modules/mcp.nix`). Owns subprocess management,
|
||||
output file writing, `mcp-loose-ends/` state, and wake signal delivery.
|
||||
Listens on `/run/hive-bash/socket` inside the container.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# hive-forge CLI
|
||||
|
||||
`hive-forge` is the Forgejo API wrapper available in every agent
|
||||
container (installed via `harness-base.nix`; lives in `/hive-forge`
|
||||
container (installed via `nix/agent-modules/forge.nix`; lives in `/hive-forge`
|
||||
as a proper Rust binary). Use it instead of ad-hoc curl pipelines.
|
||||
|
||||
## Credentials and repo defaults
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ parsed from a turn (usage, cost, context window, resolved model) as
|
|||
|
||||
Hive-enforced settings ship at `/etc/claude-code/managed-settings.json`
|
||||
(claude-code's canonical managed-settings path — precedence #1,
|
||||
read-only, un-overridable), wired in `nix/templates/harness-base.nix`
|
||||
read-only, un-overridable), wired in `nix/agent-modules/claude-settings.nix`
|
||||
from the `prompts/claude-settings.json` asset. `effortLevel` is
|
||||
deliberately not in that file — effort is controlled live via the
|
||||
`--effort` flag (`HIVE_DEFAULT_EFFORT` / the per-agent UI slider), which
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ sentence into the agent's system prompt so it knows the docs exist and
|
|||
where to find them. The tree is served by `claude --add-dir` so the full
|
||||
markdown is readable during every turn.
|
||||
|
||||
Enabled by default only for the root/manager agent (`manager.nix`). Any
|
||||
Enabled by default only for the root/manager agent (`nix/templates/ruth.nix`). Any
|
||||
agent can opt in by adding the line above to its `agent.nix`.
|
||||
|
||||
The `docs/` source is a narrow flake input (`hyperhive-docs`) tracked
|
||||
|
|
|
|||
12
flake.nix
12
flake.nix
|
|
@ -20,7 +20,7 @@
|
|||
# nix/checks.nix flake checks
|
||||
# nix/devshell.nix dev shell
|
||||
# nix/treefmt.nix formatter config
|
||||
# nix/modules/, nix/templates/ the NixOS module + container trees
|
||||
# nix/host-modules/, nix/agent-modules/, nix/templates/ the NixOS module trees
|
||||
outputs =
|
||||
inputs@{
|
||||
self,
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
let
|
||||
# Package wiring for agent containers — the harness modules
|
||||
# consume hyperhive's own packages via the `hyperhive.packages`
|
||||
# option (see nix/templates/harness/packages.nix); no overlay.
|
||||
# option (see nix/agent-modules/packages.nix); no overlay.
|
||||
# `mkDefault` so a per-agent override of an individual key wins.
|
||||
agentPackages =
|
||||
{ lib, pkgs, ... }:
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
./nix/templates/ruth.nix
|
||||
agentPackages
|
||||
];
|
||||
# The full host stack (nix/modules/default.nix aggregator) plus
|
||||
# The full host stack (nix/host-modules/default.nix aggregator) plus
|
||||
# the package/source wiring from this flake. The wiring is a
|
||||
# plain config module setting the `services.hyperhive.c0re.*`
|
||||
# package options via `lib.mkDefault` — no overlay involved, and
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
default =
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [ ./nix/modules ];
|
||||
imports = [ ./nix/host-modules ];
|
||||
services.hyperhive.c0re = {
|
||||
package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
frontend = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.frontend;
|
||||
|
|
@ -136,8 +136,8 @@
|
|||
managerToplevel = lib.mkDefault self.packages.x86_64-linux.ruth-toplevel;
|
||||
};
|
||||
};
|
||||
hive-ci = ./nix/modules/hive-ci.nix;
|
||||
hive-forge = ./nix/modules/hive-forge;
|
||||
hive-ci = ./nix/host-modules/hive-ci.nix;
|
||||
hive-forge = ./nix/host-modules/hive-forge;
|
||||
};
|
||||
|
||||
nixosConfigurations =
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ let
|
|||
in
|
||||
{
|
||||
# OTEL stats export is configured ONCE at host level via
|
||||
# `services.hyperhive.otel.*` (see nix/modules/hive-c0re.nix) and
|
||||
# `services.hyperhive.otel.*` (see nix/host-modules/hive-c0re.nix) and
|
||||
# injected into every agent's build by the meta-flake renderer
|
||||
# (`hive-c0re/src/meta.rs::otel_config`). These per-agent options are
|
||||
# the build-time implementation surface that injection writes into;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
# Shared scaffolding for every hyperhive harness container.
|
||||
# `../agent.nix` and `../ruth.nix` both import this; all
|
||||
# `../templates/agent.nix` and `../templates/ruth.nix` both import
|
||||
# agents use the same service unit regardless of which entry-point
|
||||
# they came from.
|
||||
#
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
`$HIVE_DOCS_DIR/`, and appends a single pointer sentence to the agent's
|
||||
system prompt so it knows the docs exist (see
|
||||
`hive-ag3nt::prompt::render`). Default-on for the root/manager agent
|
||||
(see `../ruth.nix`), off elsewhere; any agent can flip it from its
|
||||
(see `../templates/ruth.nix`), off elsewhere; any agent can flip it from its
|
||||
`agent.nix`.
|
||||
'';
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ in
|
|||
- runs `hive-matrix-daemon` as a systemd unit that holds a
|
||||
matrix-sdk Client + sync against the homeserver at
|
||||
`HIVE_MATRIX_URL` (default `http://localhost:8008` — the
|
||||
in-host tuwunel from `nix/modules/hive-matrix.nix`). The
|
||||
in-host tuwunel from `nix/host-modules/hive-matrix.nix`). The
|
||||
daemon auto-skips when `<state>/matrix-token` is missing,
|
||||
and a `systemd.paths` watcher restarts it the moment
|
||||
hive-c0re provisions the token (same path-trigger shape
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
# the hyperhive-isolated-dns oneshot owns resolv.conf. (Same "take
|
||||
# resolvconf out of the loop" approach the matrix container uses.)
|
||||
# All agent containers receive their bridge IP via DHCP from the hive
|
||||
# dnsmasq pool (see nix/modules/hive-gateway.nix). useDHCP runs dhcpcd
|
||||
# dnsmasq pool (see nix/host-modules/hive-gateway.nix). useDHCP runs dhcpcd
|
||||
# on every interface (just eth0 in practice — the nspawn bridge veth).
|
||||
config = {
|
||||
networking.useDHCP = true;
|
||||
|
|
@ -33,7 +33,7 @@ let
|
|||
hostEval = nixosSystem {
|
||||
system = pkgs.stdenv.hostPlatform.system;
|
||||
modules = [
|
||||
"${nixSrc}/modules"
|
||||
"${nixSrc}/host-modules"
|
||||
(
|
||||
{ lib, ... }:
|
||||
{
|
||||
|
|
@ -51,7 +51,7 @@ let
|
|||
};
|
||||
|
||||
# Agent module eval from the content-addressed nixSrc. Relative
|
||||
# imports inside agent.nix (the ./harness module dir) resolve
|
||||
# imports inside agent.nix (the ../agent-modules dir) resolve
|
||||
# correctly against the nixSrc directory tree. `hyperhive.packages`
|
||||
# stays unset — every option default that references it carries a
|
||||
# `defaultText`, so the doc walk never forces the packages.
|
||||
|
|
@ -155,7 +155,7 @@ let
|
|||
`hyperhive.nixosModules.default` to operator host configurations
|
||||
(`services.hyperhive.{enable,domain,c0re,forge,matrix,gateway}.*`).
|
||||
- [per-agent options](agent.md) — options declared in
|
||||
`nix/templates/harness/`, visible from every `agent.nix`
|
||||
`nix/agent-modules/`, visible from every `agent.nix`
|
||||
(`hyperhive.model`, `hyperhive.allowedRecipients`,
|
||||
`hyperhive.extraMcpServers`, `hyperhive.frontend.*`,
|
||||
`hyperhive.forge.*`, `hyperhive.matrix.*`, `hyperhive.gui.*`).
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ in
|
|||
# so operators can `nix build .#agent-base-toplevel` (or wire
|
||||
# them into their host system closure via the
|
||||
# `preBuildAgentTemplates` option on the hive-c0re module —
|
||||
# see nix/modules/hive-c0re.nix). Speeds up the first agent
|
||||
# see nix/host-modules/hive-c0re.nix). Speeds up the first agent
|
||||
# spawn dramatically because the heavy lifting (nixpkgs +
|
||||
# claude-code + hive-ag3nt binary) is already in the store
|
||||
# when the meta evaluator goes to build the container.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{ ... }:
|
||||
{
|
||||
imports = [ ./harness ];
|
||||
imports = [ ../agent-modules ];
|
||||
# Entry-point for sub-agent containers. Referenced from `flake.nix`
|
||||
# (`nixosConfigurations.agent-base`) and the meta-flake's
|
||||
# `applied/<name>/flake.nix`.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# Entry-point for the privileged root agent (ruth). Referenced from
|
||||
# `flake.nix` (`nixosConfigurations.ruth`) and the meta-flake's
|
||||
# `applied/ruth/flake.nix`.
|
||||
imports = [ ./harness ];
|
||||
imports = [ ../agent-modules ];
|
||||
|
||||
# The root/manager bootstraps a fresh hive, so it gets the hyperhive
|
||||
# reference docs made available by default (readable at
|
||||
|
|
|
|||
Loading…
Reference in a new issue