diff --git a/nix/assets.nix b/nix/assets.nix index a623607c..e726c0f3 100644 --- a/nix/assets.nix +++ b/nix/assets.nix @@ -12,21 +12,28 @@ # Output layout: # $out/share/hyperhive/branding/{hyperhive,agent-configs}.{svg,png} # $out/share/hyperhive/prompts/{system.md, claude-settings.json} +# $out/share/hyperhive/docs/ — the repo docs/ tree stdenv.mkDerivation { pname = "hyperhive-assets"; version = "0.1.0"; - # Narrow `srcs` (branding/ + hive-ag3nt/prompts/) is what decouples - # this derivation's input hash from the rest of the tree. + # Narrow `srcs` (branding/ + hive-ag3nt/prompts/ + docs/) is what + # decouples this derivation's input hash from the rest of the tree. + # Including docs/ surfaces the reference docs in-container at + # `$HIVE_ASSETS_DIR/docs/` (no host mount, pulled from the nix store); + # a docs/ edit re-hashes this asset, the accepted tradeoff for shipping + # the docs declaratively. srcs = [ ../branding ../hive-ag3nt/prompts + ../docs ]; unpackPhase = '' runHook preUnpack cp -r ${../branding} branding cp -r ${../hive-ag3nt/prompts} prompts - chmod -R u+w branding prompts + cp -r ${../docs} docs + chmod -R u+w branding prompts docs runHook postUnpack ''; @@ -47,6 +54,7 @@ stdenv.mkDerivation { mkdir -p $out/share/hyperhive cp -r branding $out/share/hyperhive/branding cp -r prompts $out/share/hyperhive/prompts + cp -r docs $out/share/hyperhive/docs runHook postInstall ''; @@ -54,7 +62,7 @@ stdenv.mkDerivation { dontFixup = true; meta = { - description = "hyperhive static assets (branding + claude prompts)"; + description = "hyperhive static assets (branding + claude prompts + docs)"; homepage = "https://forge.darkest.space/hyperhive/hyperhive"; license = lib.licenses.mit; }; diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index 1da1bf1a..f3027205 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -70,6 +70,24 @@ let iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } '' rsvg-convert -f png -w 512 -h 512 ${config.hyperhive.icon} -o $out ''; + # Generic, agent-agnostic `~/.claude/CLAUDE.md` installed when + # `hyperhive.docs.enable` is on (root/manager default-on; see + # `manager.nix`). claude auto-loads this user-global memory file every + # session, so it's the discovery hook for the docs asset — no + # per-agent prompt injection. It references the STABLE `$HIVE_ASSETS_DIR` + # env var (not the hashed nix-store path) which the agent resolves at + # read time. + docsClaudeMd = pkgs.writeText "hive-docs-claude.md" '' + # Hyperhive reference docs + + The hyperhive subsystem docs ship read-only inside this container at + `$HIVE_ASSETS_DIR/docs/` (resolve the env var, e.g. + `ls "$HIVE_ASSETS_DIR/docs"`). + + On a fresh deploy, read `$HIVE_ASSETS_DIR/docs/setup.md` first for the + first-run hive bootstrap commands (forge / gateway / matrix + provisioning, spawning the first sub-agents). + ''; in { # Shared scaffolding for every hyperhive harness container. @@ -210,6 +228,18 @@ in ''; }; + options.hyperhive.docs.enable = lib.mkEnableOption '' + install a generic `~/.claude/CLAUDE.md` pointing this agent at the + hyperhive reference docs shipped read-only at `$HIVE_ASSETS_DIR/docs/` + (the repo `docs/` tree, packaged into the assets derivation). claude + auto-loads the file every session, so the docs are discoverable + without any per-agent prompt injection. The docs themselves are + always present at `$HIVE_ASSETS_DIR/docs/`; this option only controls + the auto-loaded pointer. Default-on for the root/manager agent (see + `manager.nix`), off elsewhere; any agent can flip it from its + `agent.nix`. + ''; + options.hyperhive.allowedBashPatterns = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; @@ -1011,6 +1041,14 @@ in [ -d "$configDir" ] || continue chown -hR "$userName:$userName" "$configDir" 2>/dev/null || true done + ${lib.optionalString config.hyperhive.docs.enable '' + # hyperhive.docs.enable: point this agent at the hyperhive docs + # via a managed `~/.claude/CLAUDE.md` (claude auto-loads it every + # session). Symlink → always reflects the current flake; the + # chown -h below sets the link's ownership. + mkdir -p "$homeDir/.claude" + ln -sfn ${docsClaudeMd} "$homeDir/.claude/CLAUDE.md" + ''} if [ -d "$homeDir/.claude" ]; then chown -hR "$userName:$userName" "$homeDir/.claude" 2>/dev/null || true # 0755 so hive-core (a different unix user) can list the dir and diff --git a/nix/templates/manager.nix b/nix/templates/manager.nix index 370bd9e1..04fee81d 100644 --- a/nix/templates/manager.nix +++ b/nix/templates/manager.nix @@ -1,7 +1,13 @@ -{ ... }: +{ lib, ... }: { # 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-base.nix ]; + + # The root/manager bootstraps a fresh hive, so it gets the hyperhive + # reference docs surfaced by default (the `~/.claude/CLAUDE.md` pointer + # → `$HIVE_ASSETS_DIR/docs/setup.md`). `mkDefault` so a manager's own + # `agent.nix` can still turn it off. Other agents default off. + hyperhive.docs.enable = lib.mkDefault true; }