hyperhive/nix/docs.nix
atlas 24f61f3386 nix/docs: drop dead walk helper + dedupe checks.docs eval
argus review notes on #618:

- `walk` in `pickSubtrees` was leftover from an earlier traversal
  design; `pick` does everything we need. drop it.
- `checks.docs` was re-importing `nix/docs.nix` independently of
  `packages.docs`; the comment claimed they shared eval but they
  didn't (nix's lazy eval + import caching made the *result*
  identical, not the eval). switch to `inherit (self.packages.\${system}) docs;`
  so the check is literally the package output, no second import.
2026-05-29 23:46:39 +02:00

171 lines
5.6 KiB
Nix

{
pkgs,
lib,
self,
nixosSystem,
}:
# Options documentation for hyperhive's NixOS module surfaces.
# Closes #616.
#
# Two output trees:
# docs-host — operator-facing options exposed by the meta module
# (`hyperhive.nixosModules.default`). Covers
# `hyperhive.*` (domain, enable, c0re, forge, matrix)
# plus the deprecated `services.hive-c0re.*` alias.
# docs-agent — per-agent options declared by the shared harness
# module (`nix/templates/harness-base.nix`, transitively
# imported by `agent-base.nix` and `manager.nix`).
# Covers `hyperhive.*` (model, allowedRecipients,
# extraMcpServers, frontend, forge, matrix, gui, …).
#
# Both render as CommonMark via `pkgs.nixosOptionsDoc`. `docs` bundles
# them into one derivation alongside a small `README.md` index so it
# can be published verbatim.
let
# Evaluate the host module under a stub NixOS system. Stubs satisfy
# the few hard-required options (filesystems, stateVersion) without
# actually enabling the hive — we only want the option *declarations*
# to evaluate, not the config.
hostEval = nixosSystem {
system = pkgs.stdenv.hostPlatform.system;
modules = [
self.nixosModules.default
(
{ lib, ... }:
{
nixpkgs.overlays = [ self.overlays.default ];
fileSystems."/" = {
device = "/dev/null";
fsType = "tmpfs";
};
boot.loader.grub.enable = false;
system.stateVersion = "25.11";
# Force-disable every hyperhive subsystem so config evaluation
# doesn't pull in heavy build inputs (matrix container, forge,
# etc.). Options are still fully declared either way — that's
# what nixosOptionsDoc traverses.
services.hive-c0re.enable = lib.mkForce false;
hyperhive.forge.enable = lib.mkForce false;
hyperhive.matrix.enable = lib.mkForce false;
}
)
];
};
# Agent options live in the already-evaluated `agent-base` container
# config. Reusing it avoids re-evaluating the harness module against
# a fresh stub — the options tree is identical to what a real agent
# container sees.
agentEval = self.nixosConfigurations.agent-base;
# Strip the nix-store prefix from option declaration paths and rewrite
# them as forge URLs so the rendered docs link back to the source.
forgeRoot = "https://forge.darkest.space/hyperhive/hyperhive/src/branch/main";
storePrefix = toString self + "/";
transformOptions =
opt:
opt
// {
declarations = map (
decl:
let
declStr = toString decl;
relPath =
if lib.hasPrefix storePrefix declStr then
lib.removePrefix storePrefix declStr
else
baseNameOf declStr;
in
{
url = "${forgeRoot}/${relPath}";
name = relPath;
}
) opt.declarations;
};
# Filter an evaluated `options` tree down to a set of top-level
# subtrees we care about. Anything outside the listed roots is
# dropped — keeps the rendered docs focused on hyperhive's surface
# instead of NixOS's 10k+ default options.
pickSubtrees =
options: roots:
let
pick =
path:
if lib.hasAttrByPath path options then
lib.setAttrByPath path (lib.getAttrFromPath path options)
else
{ };
in
lib.foldl' lib.recursiveUpdate { } (map pick roots);
hostOptions = pickSubtrees hostEval.options [
[ "hyperhive" ]
[
"services"
"hive-c0re"
]
];
agentOptions = pickSubtrees agentEval.options [
[ "hyperhive" ]
];
hostDoc = pkgs.nixosOptionsDoc {
options = hostOptions;
inherit transformOptions;
};
agentDoc = pkgs.nixosOptionsDoc {
options = agentOptions;
inherit transformOptions;
};
mkPage =
name: title: doc:
pkgs.runCommand "hyperhive-${name}-options.md" { } ''
{
echo "# ${title}"
echo
echo "<!-- Auto-generated from the hyperhive flake."
echo " Source: nix/docs.nix · regenerate with"
echo " \`nix build .#${name}\` -->"
echo
cat ${doc.optionsCommonMark}
} > $out
'';
in
{
host = mkPage "docs-host" "hyperhive host options" hostDoc;
agent = mkPage "docs-agent" "hyperhive per-agent options" agentDoc;
# Bundle both pages plus a thin index so the whole thing can be
# published as a single static tree.
bundle = pkgs.runCommand "hyperhive-options-docs" { } ''
mkdir -p $out
cp ${mkPage "docs-host" "hyperhive host options" hostDoc} $out/host.md
cp ${mkPage "docs-agent" "hyperhive per-agent options" agentDoc} $out/agent.md
cat > $out/README.md <<'EOF'
# hyperhive nix options reference
auto-generated from the hyperhive flake.
- [host.md](./host.md) options exposed by `hyperhive.nixosModules.default`
to operator host configurations (`services.hive-c0re.*`,
`hyperhive.domain`, `hyperhive.forge.*`, `hyperhive.matrix.*`).
- [agent.md](./agent.md) per-agent options declared in
`nix/templates/harness-base.nix` and visible from every `agent.nix`
(`hyperhive.model`, `hyperhive.allowedRecipients`,
`hyperhive.extraMcpServers`, `hyperhive.frontend.*`,
`hyperhive.forge.*`, `hyperhive.matrix.*`, `hyperhive.gui.*`).
regenerate:
```sh
nix build .#docs # bundled tree
nix build .#docs-host # host page only
nix build .#docs-agent # agent page only
```
EOF
'';
}