{ stdenv, lib, 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; # A member-name relative link (`../`, no specific file — # forge's browser renders that as a directory listing today) becomes a # sibling crates/.md link once every crate README # lives flat in the same directory. Built once, applied per file below, # rather than a fresh `lib.concatMapStrings` per crate's own transform — # every crate needs the exact same substitution list (every *other* # member), so this only differs on the `member != other` filter. siblingLinkFixups = member: lib.concatMapStrings ( other: lib.optionalString (other != member) '' -e 's,\]\(\.\./${other}(/)?\),](./${other}.md),g' \ '' ) 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; dontBuild = true; dontConfigure = true; installPhase = '' runHook preInstall mkdir -p $out cp -r ./* $out/ mkdir -p "$out/crates" cp -r "$optionsMd" "$out/options" ${lib.concatMapStrings (member: '' if [ -f "$self/${member}/README.md" ]; then # 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) # -> ./.md, once that sibling also has a # crates page every crate README lives flat beside it. sed -E \ -e 's,\]\(\.\./docs/,](../,g' \ ${siblingLinkFixups member} \ "$self/${member}/README.md" \ > "$out/crates/${member}.md" fi '') members} 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"; }; }