{ stdenv, self, optionsMd, }: # The repo `docs/` markdown tree, shipped as a standalone derivation so # agents can read the reference docs in-container (added as a claude # additional directory by the harness) WITHOUT pulling the branding + # prompt assets they don't need, and so the `hyperhive/website` repo can # reuse the exact same tree as a flake input. # # The docs/ tree is copied verbatim. Two more subdirs are virtualized on # top of it, same reasoning for both: project an external source of # truth into the tree instead of hand-copying (and drifting) it. # `docs.nix` (website repo) needs no changes to pick either up — it # already walks every subdirectory generically. # # For crates that is `$out/crates/.md`, one per workspace crate # with a README.md (mara's ask: "behaves as if hive-core/README.md lives # at docs/crates/hive-core.md" — lint:allow, a path this derivation # creates in $out, so the repo has no such file). The crate's own README # stays the single source of truth. # # Output layout: # $out/ — the repo docs/ tree verbatim # $out/crates/.md — one per workspace crate README # $out/options/*.md — the nixosOptionsDoc bundle (`packages.docs`, # nix/docs/default.nix), copied verbatim — # already self-contained CommonMark, unlike # the crate READMEs below, so no rewriting. let cargoToml = builtins.fromTOML (builtins.readFile ../../Cargo.toml); members = cargoToml.workspace.members; in stdenv.mkDerivation { pname = "hyperhive-docs"; version = "0.1.0"; # Narrow src (just docs/) keeps the *base tree*'s input hash decoupled # from the rest of the workspace — a doc edit only re-hashes this half. # The crates/ generation below necessarily widens that: it reads # each crate's own README.md via `self`, so this derivation's hash now # also tracks the whole repo tree (Nix has no cheaper way to depend on # "just these few files" out of a flake `self`). Accepted trade-off — # the alternative is hand-copying READMEs into docs/ and letting them # drift, which is the exact duplication this issue exists to avoid. src = ../../docs; inherit self optionsMd members; dontBuild = true; dontConfigure = true; # The per-crate rewrite is a loop at build time, so this phase's text # stays the same size as crates are added: each attribute reaches the # builder as one environment variable, and Linux refuses to exec with # a single one over 128 KiB. installPhase = '' runHook preInstall mkdir -p $out cp -r ./* $out/ mkdir -p "$out/crates" cp -r "$optionsMd" "$out/options" for member in $members; do [ -f "$self/$member/README.md" ] || continue # Rewrite relative links that were correct from the crate's own # position in the repo tree but aren't once the file is # virtually one level under docs/ instead: # ../docs/x.md (crate root -> repo docs/) -> ../x.md lint:allow (stand-in name) # (crates/ -> docs/ is one directory shallower than # / -> docs/ was, so the leading docs/ segment drops) # ../ (that crate's own directory, no file; forge # renders it as a directory listing) -> ./.md, # since every crate README lives flat beside it under crates/. fixups=(-e 's,\]\(\.\./docs/,](../,g') for other in $members; do [ "$other" != "$member" ] || continue fixups+=(-e "s,\]\(\.\./$other(/)?\),](./$other.md),g") done sed -E "''${fixups[@]}" "$self/$member/README.md" >"$out/crates/$member.md" done runHook postInstall ''; dontFixup = true; meta = { description = "hyperhive reference docs (the repo docs/ tree, plus virtual crates/.md and options/*.md subdirs)"; homepage = "https://forge.darkest.space/hyperhive/hyperhive"; }; }