argus on #622 comment 7419 🟡:
> monospace h2 on index — the CSS styles `h2` with `ui-monospace`
> font (intended for option-name headings in the per-option pages).
> on the index page, "host options" / "agent options" / "Regenerate"
> headings also get monospace treatment. cosmetic; reads as
> intentional if not, easy to scope.
Index page now uses h3 for section headers, leaves h2 free for the
auto-generated option-name headings on host.html / agent.html where
the monospace styling is appropriate.
(Other argus nit — stale namespace text in indexHTML's option
listings — will be addressed when this branch rebases post-#615
merge, same as #620.)
mara on mara/internal-requests#8:
> nix/docs.nix currently only emits CommonMark via doc.optionsCommonMark;
> add HTML output alongside.
Renders host + agent option pages as standalone HTML using cmark-gfm
(stock nixpkgs, no pandoc). Each page is wrapped in a minimal
inline-CSS template — no external stylesheets, no second HTTP fetch.
New bundle layout (consumed by nginx at `hyperhive.darkest.space/options/`):
index.html — landing page with cross-links + regenerate snippet
host.html — services.hive-c0re.* / hyperhive.{domain,forge,matrix}.*
agent.html — hyperhive.{model,allowedRecipients,extraMcpServers,…}
host.md — same content, CommonMark source-of-truth
agent.md — same content, CommonMark source-of-truth
All asset paths inside the rendered HTML are relative (`./host.html`
etc.) per mara's spec — the bundle mounts at any URL prefix without
rebuild. Forge source links from `transformOptions` are preserved
as proper `<a href>` (verified: `forge.darkest.space/.../nix/...`).
`packages.<system>.docs` now emits HTML primarily; `docs-host` and
`docs-agent` outputs flip from .md to .html (the .md content is still
in the `docs` bundle for callers that want the source shape).
The native nixos-render-docs `options html` subcommand doesn't exist
(only `manpage` / `commonmark` / `asciidoc`). The `manual html` path
exists but needs a full manual structure for what we're treating as
two standalone pages — overkill. cmark-gfm over the existing
CommonMark output is the leanest path.
Verified:
nix flake check --no-build
nix build .#docs # bundled site (5 files)
nix build .#docs-host # standalone HTML page
nix build .#docs-agent # standalone HTML page
Per [mara on PR #615 comment 7349](http://localhost:3000/hyperhive/hyperhive/pulls/615#issuecomment-7349):
> follow nix conventions, services.hyperhive it is. the earlier we
> change this, the less breakage.
Renames the entire host-side option tree under `services.hyperhive.*`:
- `services.hive-c0re.*` → `services.hyperhive.c0re.*`
- `hyperhive.enable` → `services.hyperhive.enable`
- `hyperhive.domain` → `services.hyperhive.domain`
- `hyperhive.forge.*` → `services.hyperhive.forge.*`
- `hyperhive.matrix.*` → `services.hyperhive.matrix.*`
Per mara's "earlier = less breakage", the previous `services.hive-c0re.enable`
deprecation alias is dropped. Operators get a clear eval error on the
old paths pointing at the rename. Single migration moment.
Per-agent options in `nix/templates/harness-base.nix` (`hyperhive.model`,
`hyperhive.allowedRecipients`, etc.) stay at `hyperhive.*` — they're
container-level config, not services in the NixOS sense.
Verified via `nix flake check --no-build` + an end-to-end NixOS eval
exercising every renamed path.
Follow-up needed: rust source comments referencing the old NixOS
option names (`hive-c0re/src/{meta,coordinator,main,dashboard}.rs`)
should be updated in a separate pure-rust PR to keep this one
strictly nix-only.
- Move options.services.hive-c0re → options.hyperhive.c0re
- Add options.hyperhive.enable to auto-enable c0re + subsystems
- Add deprecation alias for services.hive-c0re.enable (backward compat)
- Update doc references in README, flake.nix, docs, harness-base.nix
- Simplifies config: 'hyperhive.enable = true' now enables everything
Existing operator configs using services.hive-c0re.enable will
continue to work but emit a deprecation warning. Aligns the option
namespace with the existing hyperhive.* family (matrix, forge, domain).
fixes#612
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.
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.
Cuts every `include_bytes!`/`include_str!` of a non-rust path in
the workspace over to runtime file loads from `$HIVE_ASSETS_DIR`
(the `hyperhive-assets` derivation introduced in the previous
commit). After this commit the rust derivation has no compile-time
dependency on `branding/*` or `hive-ag3nt/prompts/*` anymore.
Call-site flips:
- `hive-c0re/src/forge.rs::CORE_AVATAR_PNG` /
`CONFIG_ORG_AVATAR_PNG`: were `include_bytes!` of
`branding/hyperhive.png` and `$OUT_DIR/agent-configs.png`. Now
`ensure_core_avatar` / `ensure_config_org_avatar` `tokio::fs::read`
via `hive_sh4re::assets::{core_avatar_png, config_org_avatar_png}`
at startup. The `agent-configs.png` is now rendered by the
`hyperhive-assets` derivation's rsvg-convert step (was
`hive-c0re/build.rs` + librsvg on the rust derivation's
nativeBuildInputs — both gone in the next commit).
- `hive-ag3nt/src/prompt.rs::TEMPLATE`: `render` now takes the
template as an argument; `write_system_prompt` reads it once from
`$HIVE_ASSETS_DIR/prompts/system.md` before calling render. The
test module still `include_str!`s the production template so
`cargo test --workspace` doesn't need `HIVE_ASSETS_DIR` set —
this is the only remaining compile-time reference to the file
from the rust workspace, gated to `#[cfg(test)]`.
- `hive-ag3nt/src/turn.rs::CLAUDE_SETTINGS`: was `include_str!`'d
and written via `tokio::fs::write`; now `tokio::fs::copy` from
`$HIVE_ASSETS_DIR/prompts/claude-settings.json` into the
per-agent socket dir.
- `hive-ag3nt/src/web_ui.rs::DEFAULT_ICON`: was `include_str!`'d;
now read on-demand from `$HIVE_ASSETS_DIR/branding/hyperhive.svg`
inside `serve_icon`. Falls back to an empty body if missing so
the endpoint never panics on a misconfigured container (matches
the existing "per-agent icon.svg override" fallthrough).
`HIVE_ASSETS_DIR` wiring:
- Inside containers: `nix/templates/harness-base.nix`
`environment.variables` sets it to
`${pkgs.hyperhive-assets}/share/hyperhive` (resolved through
the default overlay applied in `mkContainer`). Verified by
building `agent-base-toplevel` and grepping the resulting
`/etc/set-environment`.
- Host-side: `nix/modules/hive-c0re.nix` adds an `assets` option
defaulting to `hyperhive.packages.${system}.assets`, threaded
in from the flake's nixosModules wiring, and sets the same env
var on the `hive-c0re` systemd unit so the daemon's
`forge::ensure_*_avatar` startup hooks find the PNGs.
`hive-c0re/build.rs` deleted entirely; `[package].build` removed
from `hive-c0re/Cargo.toml`; rsvg-convert dependency lives in the
assets derivation only.
Validated: `nix build .#default .#checks.x86_64-linux.clippy
.#agent-base-toplevel .#manager-toplevel --fallback` all succeed.
`/etc/set-environment` in the toplevel shows
`HIVE_ASSETS_DIR="/nix/store/.../hyperhive-assets-0.1.0/share/hyperhive"`.
Hoists the project's branding/* + hive-ag3nt/prompts/* out of the
rust derivation's src set. Lives as `packages.<system>.assets` (also
exported as `pkgs.hyperhive-assets` via the default overlay).
Output layout:
$out/share/hyperhive/branding/{hyperhive,agent-configs}.{svg,png}
$out/share/hyperhive/prompts/{system.md,claude-settings.json}
`agent-configs.png` is rendered at build time from its SVG via
rsvg-convert — same shape as the old `hive-c0re/build.rs` rasteriser,
just hoisted into nix so the librsvg dependency stays *here* instead
of in the rust derivation.
No consumer change yet — the rust binaries still `include_bytes!`
their copies from the in-source paths; later commits in this PR cut
those over to runtime loads from `$HIVE_ASSETS_DIR/share/hyperhive/`.
Why split: `src = ./.;` on the crane derivation invalidates the
cargo cache on every edit to anything in the repo, including
branding tweaks + prompt edits + docs. Splitting these out is the
first step toward dropping the rust src input down to
`craneLib.cleanCargoSource ./.` (the eventual end-state in the
final commit of this PR).
The output-layout block was written before:
- the dashboard's app.js → tabs.js rename (#495)
- the flow.html / flow.js page (#406 / #485)
- the SharedWorker stream-worker.js (#448)
- the build.mjs split-into-static/ subdir convention
Brings the comment in line with what `find dist -type f` actually
prints for both packages. Pure documentation refresh; install phase
and build hashes untouched.
Manager approval 1b1bcca added `pkgs.prefetch-npm-deps` to my
container. Ran `prefetch-npm-deps frontend/package-lock.json` →
`sha256-MHXxkZpe/5LAhpQ76ZK94znG2noTobthjUi6iNY8/K4=`. Replaced
the `lib.fakeHash` placeholder in `nix/frontend.nix` with the real
value; updated the comment to point at the recompute command instead
of the let-it-fail workflow.
This unblocks PR #350 for merge — `nix build .#frontend` will now
succeed without the operator having to compute and patch the hash.
Refs #273.
damocles suggested using lib.types.strMatching for the target option
itself rather than relying solely on the post-hoc assertion. Pattern:
`^[A-Za-z0-9_][A-Za-z0-9_./-]*$` — first char alphanumeric/_, then
alphanumerics + _ + . + / + - allowed (so nested layouts like
"games/bitburner" still work).
This rejects at type-check time:
- leading `/` (absolute paths)
- leading `.` (so `..` as a full string blocked, also `./foo`)
- leading `-` (would parse as flag by some tools)
- spaces, control chars, weird unicode
The existing assertion stays — it catches mid-path `..` segments
(`foo/../bar`) that the regex can't reject without lookahead. POSIX
regex (which nix uses) doesn't support lookahead, so the
type-and-assertion split is the cleanest expression.
Refs #273.
Follow-up to PR #350 review:
1. New assertion: hyperhive.frontend.extraFiles[*].target must be a
relative path inside the static dir — leading '/' and '..'
segments rejected at config eval time. Belt-and-braces against
string-concat-into-paths escapes (the boundary doc flags this
pattern even though agent.nix goes through operator review).
2. Documented overwrite semantics in the option doc: collision with
a default-dist path or with a prior entry's target is a hard-fail
(`refusing to overwrite existing path …`). To override a default
file, fork `hyperhive.frontend.dist` instead — extraFiles is
pure additions.
The collision-hard-fail behaviour was already implemented in
`mergedDist` (in commit a19e156); this commit just makes the
contract explicit in the docstring.
Refs #273, addresses damocles' notes on PR #350.
Phase 3 of #273. Container plumbing for the bundled frontend dist:
- flake.nix overlay: `pkgs.hyperhive-frontend` exposed for the
agent / manager containers (mirrors the existing `pkgs.hyperhive`
pattern); module argument `hyperhiveFrontend = system: self
.packages.${system}.frontend` threads the package into the host
hive-c0re module without forcing operators to apply the overlay
on their host pkgs.
- `services.hive-c0re.frontend` option: pinned to the flake's
frontend package by default, overridable for custom dashboard
SPAs. The hive-c0re systemd service gets `HIVE_STATIC_DIR =
${cfg.frontend}/dashboard` — the Rust binary will pick it up
in Phase 4.
- `hyperhive.frontend.dist` option: per-container, defaults to
`pkgs.hyperhive-frontend`. Override to ship a fully custom
agent SPA (advanced; the default + extraFiles flow handles the
common 'add files' case).
- `hyperhive.frontend.extraFiles` option: attrsOf submodule
(mirroring the `hyperhive.extraMcpServers` shape per damocles'
request so existing #322-style assertions keep their grip).
Each entry has `source` (path relative to agent.nix) and
`target` (URL/disk prefix within the merged static tree,
defaulting to the attribute name). Operator-named example:
the bitburner agent drops `bitburner-dist` into
`/bitburner/` alongside the default agent UI at `/`.
- `hyperhive.frontend.mergedDist` (readOnly): the runCommand
derivation that composes `agent/` from the default dist plus
every `extraFiles` entry. Aborts on overwrite so a filename
collision becomes a build error rather than a silent dist swap.
agent-base.nix + manager.nix set their respective systemd
service `HIVE_STATIC_DIR` to this merged path.
Until Phase 4 lands, the env var is set but unused — the Rust
binaries still serve assets via `include_str!`. The cutover
happens in the next commit on this branch.
Refs #273.
Phase 2 of #273. Adds `packages.${system}.frontend` to the flake —
a `buildNpmPackage` derivation that consumes the lockfile committed
in the previous step and produces two static dist trees under $out:
$out/dashboard/ the hive-c0re dashboard SPA assets
(index.html, app.js, dashboard.css, favicon.svg)
$out/agent/ the per-agent default UI assets
(index.html, app.js, stats.html, stats.js,
agent.css, screen.html)
The dashboard favicon lives outside the frontend src tree
(branding/hyperhive.svg at the repo root). It's passed in as a
callPackage argument so the hermetic build can grab it.
`npmDepsHash` is set to `lib.fakeHash` — the build will fail on
first attempt with the actual sha256 printed; copy that in. Use
`nix run nixpkgs#prefetch-npm-deps -- frontend/package-lock.json`
to recompute locally without a build round-trip (works from
operator's host; iris's container can't recompute it without
prefetch-npm-deps in PATH).
The Rust crates and NixOS modules continue to use the legacy
include_str! routes; cutover happens in Phase 4.
Refs #273.