flake: narrow crane src to cleanCargoSource + prompts (closes #555)

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.
This commit is contained in:
iris 2026-05-29 02:46:56 +02:00 committed by Mara
commit 0058ed1e59

View file

@ -46,16 +46,33 @@
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
treefmt-eval = treefmt-nix.lib.evalModule pkgs treefmt-config; treefmt-eval = treefmt-nix.lib.evalModule pkgs treefmt-config;
craneLib = crane.mkLib pkgs; craneLib = crane.mkLib pkgs;
# Narrowed source tree the rust derivations consume.
# `commonCargoSources` is crane's standard "everything cargo
# cares about" filter (Cargo.toml/Cargo.lock + *.rs); we
# union it with the one non-rust path the workspace still
# references — `hive-ag3nt/prompts/` — which is read at
# compile time by `hive-ag3nt::prompt::tests` via
# `include_str!`. Branding assets + claude prompts at
# runtime live in the `hyperhive-assets` derivation
# (#555), so a tweak to e.g. `branding/hyperhive.svg`,
# `README.md`, the `nix/` modules, or the frontend tree
# does NOT bust this src hash and the rust derivations
# stay cached.
cleanSrc = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
(craneLib.fileset.commonCargoSources ./.)
./hive-ag3nt/prompts
];
};
# Build the workspace's dependency tree once, cached as # Build the workspace's dependency tree once, cached as
# its own derivation. `buildPackage` and `cargoClippy` # its own derivation. `buildPackage` and `cargoClippy`
# both reuse this via `inherit cargoArtifacts;` so a # both reuse this via `inherit cargoArtifacts;` so a
# workspace-only edit doesn't rebuild deps. Same # workspace-only edit doesn't rebuild deps. All three
# `nativeBuildInputs` as the workspace build itself — # derivations consume the same `cleanSrc` so the input
# build.rs runs during dep-build too (any deps with a # hash stays consistent across the chain.
# build.rs need rsvg too if they transitively pull it
# in; harmless if they don't).
cargoArtifacts = craneLib.buildDepsOnly { cargoArtifacts = craneLib.buildDepsOnly {
src = ./.; src = cleanSrc;
# Workspace Cargo.toml is virtual (no `[package].name`), # Workspace Cargo.toml is virtual (no `[package].name`),
# so crane can't auto-derive a name. Spell it out # so crane can't auto-derive a name. Spell it out
# explicitly here and below — keeps the derivation name # explicitly here and below — keeps the derivation name
@ -88,13 +105,14 @@
{ {
pkgs, pkgs,
craneLib, craneLib,
cleanSrc,
cargoArtifacts, cargoArtifacts,
nativeBuildInputs, nativeBuildInputs,
... ...
}: }:
{ {
default = craneLib.buildPackage { default = craneLib.buildPackage {
src = ./.; src = cleanSrc;
inherit cargoArtifacts nativeBuildInputs; inherit cargoArtifacts nativeBuildInputs;
pname = "hyperhive-workspace"; pname = "hyperhive-workspace";
version = "0.1.0"; version = "0.1.0";
@ -250,6 +268,7 @@
{ {
treefmt-eval, treefmt-eval,
craneLib, craneLib,
cleanSrc,
cargoArtifacts, cargoArtifacts,
nativeBuildInputs, nativeBuildInputs,
... ...
@ -265,7 +284,7 @@
# separator, which is why the old wiring went through # separator, which is why the old wiring went through
# overrideAttrs). # overrideAttrs).
clippy = craneLib.cargoClippy { clippy = craneLib.cargoClippy {
src = ./.; src = cleanSrc;
inherit cargoArtifacts nativeBuildInputs; inherit cargoArtifacts nativeBuildInputs;
pname = "hyperhive-workspace"; pname = "hyperhive-workspace";
version = "0.1.0"; version = "0.1.0";