The nixpkgs bump to clippy 0.1.95 / cargo 1.95.0 added + strengthened a
large batch of lints. CI denied ALL warnings (`-D warnings`) against the
`pedantic = warn` workspace lint, so the bump hard-failed `nix flake
check` workspace-wide with zero code changes — and would recur on every
future clippy bump.
Posture fix (the durable part): CI now runs
`-D warnings -A clippy::pedantic`, so the default/correctness/style lints
stay a hard gate while the "extra, opinionated" pedantic group is
advisory only (still `warn` for local `cargo clippy` via the workspace
lints table, just non-blocking in CI). `-A` rather than `-W` so the
group drop doesn't re-enable the specific pedantic lints the workspace
allows (e.g. `must_use_candidate`).
Also fixes the genuine DEFAULT/STYLE lints the bump surfaced across the
workspace (doc_lazy_continuation, collapsible_if, ptr_arg,
match_like_matches_macro, …) via `cargo clippy --fix` + manual stragglers
(`too_many_arguments` #[allow] on the host-config constructors), and
three tests that had rotted while the CI runner was offline (#1221):
- topology::top_level_agents_in_multi_root — hardcoded unsorted expected
- rebuild_queue::depends_on_evicted_dep_counts_as_resolved — needs
MAX_HISTORY_PER_KIND newer terminals to evict, not one
- coordinator::agent_paths doctest — illustrative pseudo-code, now `ignore`
Validated: clippy + formatting + cargo-test checks all pass.
Per mara's direction: both nixpkgs and nixpkgs-unstable are now
top-level meta flake inputs with explicit store-path URLs. Hyperhive
follows them rather than the other way around:
inputs.nixpkgs.url = "path:${pkgs.path}";
inputs.nixpkgs-unstable.url = "path:${nixpkgs-unstable}";
inputs.hyperhive.url = "...";
inputs.hyperhive.inputs.nixpkgs.follows = "nixpkgs";
inputs.hyperhive.inputs.nixpkgs-unstable.follows = "nixpkgs-unstable";
New NixOS host options (auto-set at build time, overridable):
services.hyperhive.c0re.nixpkgsFlake
default: "path:${pkgs.path}" — host's evaluated nixpkgs.
services.hyperhive.c0re.nixpkgsUnstableFlake
default: "path:${nixpkgs-unstable}" from hyperhive's flake.nix —
the channel that carries claude-code. Operators can override to
track a different unstable snapshot.
Legacy fallback (both args empty) preserved for backward compat.
Two new Rust tests cover the full-URL and fallback paths.
Replaces the earlier PAM+binary approach with nginx's built-in
`auth_basic` module. No new binary, no new systemd service, no PAM.
New option `services.hyperhive.gateway.auth`:
- `enable` — off by default
- `htpasswdFile` — host path to an htpasswd file (required when enable)
- `realm` — WWW-Authenticate realm string (default "hyperhive");
restricted to `strMatching "[^\"$]*"` to prevent nginx config injection
When enabled:
- the parent directory of `htpasswdFile` is bind-mounted read-only
into the gateway container at `/run/gateway-auth/`
- the `"/"` proxy location gets `auth_basic` + `auth_basic_user_file`
Create credentials: `htpasswd -Bc /path/to/file alice` (BCrypt).
See `docs/gateway.md` ("HTTP Basic auth") for the full setup guide.
Adds opt-in HTTP Basic auth to the hive-gateway backed by the host PAM
stack + group membership check.
New binary `hive-gateway-auth` (hive-c0re workspace):
- Axum HTTP service on 127.0.0.1:7002 (host loopback)
- Decodes Basic credentials, authenticates via pam_unix.so
- Checks membership in `hyperhive-operator` group (or custom)
- Returns 200 / 401 / 403; nginx `auth_request` consumes these
New options under `services.hyperhive.gateway.auth`:
- `enable` — off by default
- `port` — auth service port (default 7002)
- `realm` — WWW-Authenticate realm string (default "hyperhive")
- `group` — required host group (default "hyperhive-operator")
- `pamService` — PAM service name (default "hive-gateway")
Host-side NixOS wiring:
- `users.groups.hyperhive-operator` declared when default group used
- `/etc/pam.d/hive-gateway` emitted via `security.pam.services`
- `systemd.services.hive-gateway-auth` runs the auth binary as root
(needs /etc/shadow access for pam_unix.so)
Gateway container nginx wiring:
- `location = /__hive_gateway_auth` — internal proxy to auth service
- `auth_request /__hive_gateway_auth` on the `"/"` proxy location
- `@hive_auth_required` named location adds WWW-Authenticate: Basic
header on 401 so browsers display a login prompt
Workspace deps: pam = "0.8"; flake.nix: linux-pam added to
nativeBuildInputs so pkg-config can find libpam at build time.
Adds `services.hyperhive.ci` NixOS module that spins up a `hive-ci`
nixos-container running `gitea-actions-runner` against the hive-forge
Forgejo instance. Off by default; opt in with `ci.enable = true` after
generating a runner registration token in Forgejo.
Also adds `.forgejo/workflows/ci.yml` with four jobs: nix flake check,
formatting (nix fmt + cargo fmt), cargo test, and cargo clippy. Jobs
target the `hive-ci` runner label.
Container design mirrors hive-forge (shared host netns, non-ephemeral
state, loopback reach to forge). sandbox-fallback = true since nspawn
containers can't create user-namespaces for nix sandbox.
Closes#175.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Per mara on #622 comment 7442:
> follow up moving scripts and css and stuff out of the nix file.
> can live in the same dir.
Layout:
nix/docs/
default.nix ← what was nix/docs.nix
style.css ← extracted from inline `styleCSS = '' ... ''`
`builtins.readFile ./style.css` loads the stylesheet at evaluation
time, so the rendered HTML stays byte-identical (CSS inlined into
each page's `<style>` block — verified). Future client-side scripts
can land at `nix/docs/script.js` with the same `builtins.readFile`
pattern.
Bonus: the docs.nix stub NixOS eval was still force-disabling
`hyperhive.{forge,matrix}.enable` on the pre-#615 namespace; updated
to `services.hyperhive.{forge,matrix}.enable` so `nix flake check`
passes against current main. (Same fix lives on PRs #619 + #620;
whichever lands first wins, the others rebase to a no-op.)
`flake.nix` references updated: `./nix/docs.nix` → `./nix/docs`.
Verified:
- `nix flake check --no-build` passes clean
- `nix build .#docs` produces 5-file bundle identical to pre-PR shape
- inline CSS still appears 3× per HTML page (one per index/host/agent)
Drops the hardcoded `nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"`
from the meta flake renderer. meta now declares:
nixpkgs.follows = "hyperhive/nixpkgs";
nixpkgs-unstable.follows = "hyperhive/nixpkgs-unstable";
so every agent-level `inputs.<X>.inputs.nixpkgs.follows = "nixpkgs"`
resolves transitively to hyperhive's own pin. One channel decision
in the whole tree (hyperhive/flake.nix line 5), no second source
to drift.
`closes #317` invariant still holds: `nixpkgs` is a single canonical
name in the meta tree, it just resolves through hyperhive instead
of being its own root input.
Also:
- bump hyperhive/flake.nix line 5: `nixos-25.11` → `nixos-26.05`,
flake.lock relocked
- flake_check.rs fixtures bumped cosmetically (synthetic data, not
shape-affecting)
- rename + rewrite `render_flake_declares_canonical_nixpkgs` →
`render_flake_aliases_nixpkgs_to_hyperhive`; asserts the new
follows-form AND the absence of any literal `nixpkgs.url`
- drop the now-redundant `render_flake_collapses_hyperhive_nixpkgs_via_follows`
test (the old indirection it covered no longer exists)
Closes#526.
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.
Per mara's review on PR #561: the previous commit kept
`./hive-ag3nt/prompts` in `cleanSrc` because
`hive-ag3nt::prompt::tests` had a compile-time
`include_str!("../prompts/system.md")`. That meant a prompt edit
still busted the cargo cache.
This change:
- Replaces the test-side `include_str!` with a runtime read from
`$HIVE_ASSETS_DIR/prompts/system.md` (with a CARGO_MANIFEST_DIR
fallback for plain `cargo test` from a checked-out repo).
- Drops `./hive-ag3nt/prompts` from `cleanSrc` — it's now
`craneLib.cleanCargoSource ./.` (Cargo.* + *.rs only).
- Sets `doCheck = false` on `packages.default` and lifts
`cargo test` into a separate `checks.cargo-test` derivation
that carries the `hyperhive-assets` build input. That scopes the
asset rebuild blast radius to the test check — `nix flake check`
still exercises the suite, but the binary derivation no longer
carries the assets dep.
Verified cache-invariance matrix (via `echo '' >> <f>; nix eval
.#default.outPath`):
| edit | default | cargo-test | clippy |
|-------------------------|---------|------------|--------|
| README.md | stable | stable | stable |
| branding/hyperhive.svg | stable | CHANGED | stable |
| nix/modules/* | stable | stable | stable |
| prompts/system.md | stable | CHANGED | stable |
| hive-c0re/src/main.rs | CHANGED | CHANGED | CHANGED |
(`cargo-test` CHANGED on prompts/branding is correct — tests
read the production template + need the assets output.)
After the asset-split in the previous commit the rust derivations
have no compile-time dependency on `branding/*` and the only
remaining reference to `hive-ag3nt/prompts/` is a `#[cfg(test)]`
`include_str!` of `system.md` for the prompt-renderer tests. So we
can finally narrow the src input down from `./.` (the post-naersk-
port shape) to a fileset:
fileset = lib.fileset.unions [
(craneLib.fileset.commonCargoSources ./.) # *.rs + Cargo.{toml,lock}
./hive-ag3nt/prompts # cfg(test) include_str!
];
Same `cleanSrc` is fed into all three derivations
(`buildDepsOnly`, `buildPackage`, `cargoClippy`) so the input hash
stays consistent across the chain (no surprise cache misses
between stages of the same nix build).
Verified the cache-invalidation contract by `echo '' >> <file>`
and re-evaluating `.#default.outPath`:
README.md → unchanged ✓
branding/hyperhive.{svg,png} → unchanged ✓
hive-c0re/src/main.rs → invalidates ✓
hive-ag3nt/prompts/system.md → invalidates ✓ (cfg(test))
branding/agent-configs.svg → unchanged ✓
(assets derivation rebuilds
independently)
End state: a tweak to nix modules, frontend JS, docs, README, or
any branding asset rebuilds nothing rust-side. Only Rust source
changes and prompt edits invalidate the cargo cache — and the
prompt edit is gated to tests, so the production binary derivation
is invariant to it (a follow-up could move the `include_str!` into
its own test-only fixture if even that residual coupling matters,
but the operator-visible cost today is zero).
Closes#555.
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).
Framework swap, no public API change.
- naersk input → crane (`github:ipetkov/crane`); crane is stateless, no
nixpkgs.follows needed.
- `forAllSystems` exposes `craneLib = crane.mkLib pkgs`,
`cargoArtifacts = craneLib.buildDepsOnly` (built once, reused), and
a shared `nativeBuildInputs = [ pkgs.librsvg pkgs.git ]` consumed by
buildDepsOnly + buildPackage + cargoClippy so the three derivations
see the same toolchain shape.
- `packages.default = craneLib.buildPackage` (was naersk-lib.buildPackage)
with explicit `pname = "hyperhive-workspace"; version = "0.1.0";` —
the virtual workspace Cargo.toml has no [package].name so crane
needs the hint.
- `checks.clippy = craneLib.cargoClippy` (was naersk + overrideAttrs
hack). Crane parses `cargoClippyExtraArgs = "--workspace --all-targets
-- -D warnings"` correctly; naersk's `mode = "clippy"` used to mangle
the `--` separator which is why the old wiring went through
overrideAttrs. The whole hack — including `doCheck = false`,
`copyTarget = false`, and the swapped buildPhase/installPhase — is
now gone.
- librsvg native dep (#424) preserved on all three derivations. Added
pkgs.git too — naersk auto-included it; crane is more minimal, so
hive-c0re's `lifecycle::tests::setup_proposed_*` (which shell out to
`git init`+commit) need it explicit to pass under `cargo test` in
the sandbox.
- build.rs + hive-c0re/Cargo.toml comments updated from "naersk
derivation" to "crane derivation".
- 3 doc-list-indentation lints in hive-sh4re/src/lib.rs cleaned up
(replaced `+`-at-line-start with `and`/`/` so doc continuations
don't trigger `clippy::doc_lazy_continuation`).
Validated locally: `nix build .#default --fallback` succeeds, all
117 tests pass, all four bins in `result/bin/`.
Sibling to ensure_core_avatar (#320). Same one-shot marker-guarded
upload pattern, this time aimed at the Forgejo per-org avatar
endpoint (`POST /api/v1/orgs/{org}/avatar`).
## SVG-to-PNG at build time
Mara: *don't check in the png. instead generate png on the fly or
in build.*
`hive-c0re/build.rs` renders `branding/agent-configs.svg` →
`$OUT_DIR/agent-configs.png` via `rsvg-convert` (librsvg) on every
compile; `forge.rs` then `include_bytes!`s the OUT_DIR PNG. The
raster never gets checked into git — SVG stays source of truth,
the PNG is a build artifact.
- `hive-c0re/Cargo.toml`: declares `build = "build.rs"`
- `flake.nix`: adds `librsvg` to `naersk-lib.buildPackage`
`nativeBuildInputs` (covers both the runtime package and the
clippy check derivation) and to the dev shell so local
`cargo build` finds `rsvg-convert` on PATH.
- For dev builds outside Nix, install librsvg (Debian:
`librsvg2-bin`, macOS: `brew install librsvg`).
## Icon design
Sibling visual to the main hyperhive mark — same dark base + outer
ring + corner-bracket frame so the family reads at a glance. Centre
swaps the hexagonal hive for a stacked-config-files motif: three
offset sheets, folded-corner affordance, curly-brace `{ }` glyph
telegraphing "config file."
Brace font-size dropped 78→56 + letter-spacing -3 (#424 mara:
"braces cross the boundaries of the page") so the glyphs sit
comfortably inside the 120-wide front sheet with clear breathing
room on the left/right edges. The stack is shifted so the front
sheet centres on canvas-(150, 150); brace text anchors there with
`dominant-baseline=central` for true vertical centring.
## Validation
- `cargo check` clean (only pre-existing warnings).
- One-shot marker honoured: re-runs of `ensure_all` skip after the
first success; `rm /var/lib/hyperhive/forge-agent-configs-avatar-set`
forces re-upload (useful for icon revisions).
- Behaviour mirrors the existing `ensure_core_avatar` pattern.
Browser smoke test isn't possible from inside iris's container.
Worth eyeballing post-deploy: `http://localhost:3000/agent-configs`
should show the new avatar where the default identicon used to be.
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.
new `services.hive-forge.enable` (off by default) wraps
`services.forgejo` with hyperhive-friendly defaults: sqlite (no
extra db service), built-in ssh on 2222 so it doesn't fight the
host's openssh, http on 3000 (outside hyperhive's 7000/8000/8100-8999
ranges), registration off (operator seeds agent users), private
repos by default. exported as `nixosModules.hive-forge` — operator
imports it on the host alongside hive-c0re. container-side wiring
(MCP tools or a bind-mounted token) is deferred; containers already
share the host netns so they can reach http://localhost:3000 today.
revert the earlier 'operator must set allowUnfree' move:
per-agent containers evaluate their own nixpkgs and the operator's
host-level allowUnfree doesn't propagate in. restoring the scoped
allowUnfreePredicate inside both the claude-unstable overlay and
harness-base.nix; documented in README + gotchas as 'nothing to
set on the operator side'.
docs:
- claude.md file map adds crash_watch.rs, kick_agent on coordinator,
/api/model + journald viewer + bind-with-retry references.
- scratchpad rewritten to reflect the recent run.
- web-ui.md: notification row + browser notifications section,
state row (badge + model chip + last-turn chip + cancel button),
per-agent inbox, /model slash, /cancel-question + journald
endpoints, focus-preservation on refresh.
- turn-loop.md: --model is read from Bus::model() per turn (runtime
override via /model); recv(wait_seconds) up to 180s with the
rationale; ask_operator gains ttl_seconds; new TurnState section;
kick_agent inbox-on-startup hint.
- approvals.md: ttl/cancel resolution paths for operator questions.
- persistence.md: /state/hyperhive-model file.
- gotchas.md: web UI port collision policy (rename, don't probe);
bind retry + SO_REUSEADDR shape; auto-unfree restored.
- todo.md: cleaned up empty sections and stale entries; /model
shipped, dropped from the list.
model persistence: /model <name> now writes to /state/hyperhive-model
(in-container), Bus::new reads it on init. operator override survives
harness restart and container rebuild; gone on --purge like every
other piece of agent state. path overridable via HYPERHIVE_MODEL_FILE
for tests. failure to persist is a warn, not fatal — runtime override
still applies, just won't survive a restart.
unfree opt-in: drop the auto-allowUnfreePredicate from
harness-base.nix and the claude-unstable overlay. operator now has to
set nixpkgs.config.allowUnfree (or a predicate listing claude-code)
in their own host config. silent unfree bypass was sketchy; this is
honest. readme + gotchas updated to spell out the snippet.
todo: drops model-persistence + container-crash + journald (all
shipped); adds per-agent send allow-list (constrain who an agent can
message).