diff --git a/hive-c0re/src/lifecycle.rs b/hive-c0re/src/lifecycle.rs index 1f59dcc9..2a9d8822 100644 --- a/hive-c0re/src/lifecycle.rs +++ b/hive-c0re/src/lifecycle.rs @@ -478,11 +478,38 @@ pub async fn rebuild_no_meta( /// cache hit when nothing changed (handful of seconds for the /// eval), expensive only on the rebuild that actually has work. /// +/// Attr path is `#nixosConfigurations..config. +/// system.build.toplevel` — `nix build` won't auto-resolve the bare +/// `` against `nixosConfigurations` like `nixos-container` does +/// internally, so we have to spell the path out explicitly. Falling +/// back to `meta#` (the shape `nixos-container update --flake +/// meta#` uses) makes nix look for `packages..`, +/// `legacyPackages..`, or `` at the flake root — +/// none of which exist in the rendered meta flake (closes #735, the +/// argus-prebuild regression after the first cold rebuild post-#721). +/// /// Returns the same error shape as the other nixos-container /// helpers so callers can use `?` without translation. async fn prebuild_toplevel(name: &str, flake_ref: &str) -> Result<()> { use tokio::io::{AsyncBufReadExt, BufReader}; - let attr = format!("{flake_ref}.config.system.build.toplevel"); + // Split `#` so we can re-emit with the explicit + // `nixosConfigurations.` segment. The flake_ref shape is + // constructed by `rebuild_no_meta` and always contains exactly one + // `#`; `split_once` returning None here would be a programmer + // error we'd want to surface loudly rather than paper over. + let (flake_root, fragment) = flake_ref + .split_once('#') + .with_context(|| format!("flake_ref {flake_ref:?} missing '#' fragment"))?; + // Sanity-check the fragment matches the agent name we were + // passed — guards against future calls that pass a divergent + // pair (no current callsite does, but the pair is redundant + // and worth checking once). + if fragment != name { + anyhow::bail!( + "prebuild_toplevel: flake_ref fragment '{fragment}' ≠ agent name '{name}'" + ); + } + let attr = format!("{flake_root}#nixosConfigurations.{name}.config.system.build.toplevel"); let args = vec![ "--extra-experimental-features", "nix-command flakes",