nix: add options docs outputs for host + agent surfaces (#616)
Auto-generate CommonMark references for hyperhive's two NixOS module surfaces via `pkgs.nixosOptionsDoc`: - `packages.<system>.docs-host` — operator-facing options exposed by `hyperhive.nixosModules.default` (`services.hive-c0re.*`, `hyperhive.domain`, `hyperhive.forge.*`, `hyperhive.matrix.*`). - `packages.<system>.docs-agent` — per-agent options declared in `nix/templates/harness-base.nix` (model, allowedRecipients, extraMcpServers, frontend, forge, matrix, gui, …). - `packages.<system>.docs` — both pages plus a thin `README.md` index, bundled for publishing. Declaration links are rewritten to point at the forge source tree instead of nix-store paths. Host options come from a stubbed `nixosSystem` eval that force-disables all hyperhive subsystems — only the *declarations* feed the doc renderer, no heavy build inputs end up in the closure. Agent options reuse `nixosConfigurations.agent-base.options` (already evaluated). Also wired as `checks.<system>.docs` so CI fails fast on eval breakage.
This commit is contained in:
parent
d074b25fac
commit
6a64770c79
2 changed files with 206 additions and 0 deletions
177
nix/docs.nix
Normal file
177
nix/docs.nix
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
{
|
||||
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
|
||||
walk =
|
||||
path: tree:
|
||||
if path == [ ] then
|
||||
lib.getAttrFromPath path options
|
||||
else
|
||||
lib.setAttrByPath path (lib.getAttrFromPath path tree);
|
||||
pick =
|
||||
path:
|
||||
let
|
||||
exists = lib.hasAttrByPath path options;
|
||||
in
|
||||
if exists 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
|
||||
'';
|
||||
}
|
||||
Loading…
Reference in a new issue