Watch
0
0
Fork
You've already forked hyperhive
0

docs: the agent config meta-flake input is the local applied mirror, not forge git+http

config-changes.md § Meta flake, hive-c0re nix comments and the meta.rs/exec.rs
doc comments still described the declared agent-<n> input as a forge-hosted
git+http repo; meta.rs renders git+file://<applied>.
This commit is contained in:
atlas 2026-10-10 00:42:10 +02:00 • committed by mara
commit 295e8af43a
5 changed files with 33 additions and 36 deletions

View file

@ -114,27 +114,26 @@ transient.
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
declares one flake input per agent (`agent-<n>.url =
"git+http://<forge>/agent-configs/<n>.git"`) and one
"git+file://<applied>"`, the agent's local `applied` mirror) and one
`nixosConfigurations.<n>` output per agent. Each output wraps
`inputs.agent-<n>.nixosModules.default` with the identity +
`HIVE_PORT` / `HIVE_LABEL` / `HIVE_DASHBOARD_PORT` injection module.
Containers run against `--flake /var/lib/hyperhive/meta#<n>`.
The declared input url is the agent's **forge config repo** (the
same `agent-configs/<n>` config PRs merge into), so the meta flake
references a reviewable, reproducible source rather than a local
checkout. hive-c0re authenticates that `git+http` fetch via a git
credential helper that reads the live forge-core token — no token in
the url or the lock. The rebuild paths, however, do **not** re-lock
from the forge: they `--override-input agent-<n>
git+file:///var/lib/hyperhive/applied/<n>`, locking the exact config
`applied/<n>/main` was fast-forwarded to. That keeps a rebuild
reproducible and independent of forge reachability — rebuilds fire on
crash-restart and meta bumps, not just config merges — while the
declared url stays the forge. `sync_agents` re-renders + re-locks the
persistent input; a plain `nix flake lock` leaves an existing applied
override in place (it only re-locks when the declared url itself
changes), so the forge-declared / applied-deployed split is stable.
The declared input url is the agent's **local `applied` mirror**
(`/var/lib/hyperhive/applied/<n>`) of its forge config repo
(`agent-configs/<n>`, the one config PRs merge into). The meta flake
therefore resolves entirely from on-disk state: building, and booting,
never depend on the forge being reachable. hive-c0re fills the mirror
by fast-forwarding `applied/<n>/main` to the merged config commit,
reading the forge with the hive's read token
(`forge::reader_token()`); the forge repo is the review and audit
surface, not a flake input. The rebuild paths re-lock the input with
`--override-input agent-<n> git+file:///var/lib/hyperhive/applied/<n>`,
locking the exact config `applied/<n>/main` was fast-forwarded to.
Rebuilds fire on crash-restart and meta bumps, not just config
merges, so the lock stays on that head. `sync_agents` re-renders and
re-locks the persistent input.
Lock updates are single-phase and commit when the lock changed:
`meta::lock_update_for_rebuild(name)` relocks one agent's input for a

View file

@ -884,7 +884,7 @@ fn parse_agent_input_names(inputs: &[String]) -> Vec<String> {
/// validating parser every other agent-name wire field in this codebase
/// goes through, so a name that reaches
/// [`fast_forward_applied_main`](crate::forge::fast_forward_applied_main) or
/// a `git+http://.../agent-configs/<name>.git` URL built off it has already
/// an `agent-configs/<name>` forge URL built off it has already
/// passed the same bar as one that arrived over a socket. Not just a
/// helper for [`parse_agent_input_names`]: `run_meta_lock`'s `fanout`
/// parameter carries pre-computed agent names too, and while today's only

View file

@ -235,9 +235,8 @@ pub async fn lock_update_for_rebuild(name: &str) -> Result<()> {
let _guard = META_LOCK.lock().await;
let dir = crate::paths::meta_root();
let input = format!("agent-{name}");
// Re-lock from the local applied mirror, not the persistent forge URL:
// build exactly `applied/<n>/main` and stay reproducible when the forge
// is unreachable.
// Re-lock against `applied/<n>/main` explicitly, so the lock is the
// exact applied head whatever the declared input url says.
let applied = applied_override_url(&crate::paths::applied_dir(name));
nix(
&dir,
@ -264,12 +263,12 @@ pub async fn lock_update_for_rebuild(name: &str) -> Result<()> {
}
/// `--override-input` URL re-locking an agent's config input against its
/// LOCAL applied mirror (`git+file://<applied_dir>`, current `main` head)
/// instead of the persistent forge URL declared in the meta flake. The
/// deploy + rebuild paths re-lock from here: the applied tree was already
/// fast-forwarded to the reviewed head, so this builds exactly that config
/// and stays reproducible when the forge is unreachable. No `?rev` — `main`
/// head is the reviewed head at deploy time. Pure so it's unit-testable.
/// LOCAL applied mirror (`git+file://<applied_dir>`, current `main` head),
/// the same url the meta flake declares. The deploy + rebuild paths re-lock
/// from here: the applied tree was already fast-forwarded to the reviewed
/// head, so this builds exactly that config with no forge access. No
/// `?rev` — `main` head is the reviewed head at deploy time. Pure so it's
/// unit-testable.
fn applied_override_url(applied_dir: &Path) -> String {
format!("git+file://{}", applied_dir.display())
}
@ -1456,8 +1455,8 @@ mod tests {
#[test]
fn applied_override_url_targets_local_mirror_main_head() {
// Deploy + rebuild re-lock against the local applied mirror's `main`
// head (no `?rev`), never the persistent forge URL — so a rebuild
// survives forge unreachability and builds the fast-forwarded config.
// head (no `?rev`) — so a rebuild survives forge unreachability and
// builds the fast-forwarded config.
let p = Path::new("/var/lib/hyperhive/agents/iris/applied");
let url = applied_override_url(p);
assert_eq!(url, "git+file:///var/lib/hyperhive/agents/iris/applied");

View file

@ -56,9 +56,9 @@ let
username = core
[http]
# Abort a stalled fetch instead of blocking startup indefinitely. If a
# git+http transfer (e.g. `nix flake lock` of the forge-hosted config
# inputs) drops below 1 KiB/s for 30s -- forge unreachable / not ready
# on cold boot -- git fails fast rather than hanging the whole daemon.
# git http transfer from the forge (e.g. filling an applied mirror)
# drops below 1 KiB/s for 30s -- forge unreachable / not ready on cold
# boot -- git fails fast rather than hanging the whole daemon.
# Pairs with GIT_TERMINAL_PROMPT=0 (no credential-prompt hang) and the
# migration shellout timeout in migrate.rs.
lowSpeedLimit = 1024
@ -265,8 +265,8 @@ in
after = [ "hive-c0re.socket" ];
path = [
pkgs.git
# `git-credential-hive-forge` on PATH so git finds it when nix fetches
# the forge-hosted agent-config inputs (helper = hive-forge).
# `git-credential-hive-forge` on PATH so git finds it for git+http
# fetches from the forge (helper = hive-forge).
forgeCredHelper
"/run/current-system/sw"
];

View file

@ -28,9 +28,8 @@ in
# Never let git block on an interactive credential prompt. hive-core is a
# TTY-less system user, so a prompt (e.g. the forge credential helper
# returns nothing because the forge isn't reachable yet on cold boot)
# would hang forever — this is what froze the whole daemon during startup
# migration's `nix flake lock` of the forge-hosted config inputs. With
# this set, git fails fast instead of prompting. Paired with the git http
# would hang forever and freeze the daemon during startup. With this set,
# git fails fast instead of prompting. Paired with the git http
# low-speed abort in `safeDirGitconfig` (bounds a stalled transfer) and
# the 120s migration shellout timeout in migrate.rs.
GIT_TERMINAL_PROMPT = "0";