From c8472966e9c65cd55b4f3ec8532f26f09ae72689 Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 7 Oct 2026 20:04:07 +0200 Subject: [PATCH] hive-c0re: drop the remaining "mirror" wording for the removed push The reseed bail text, the `ensure_all` doc, the forge module doc and a rebuild comment still described hive-c0re mirroring the applied config to `agent-configs/`. State what the code does now; scope the config-changes doc to swarm-created agents and say what a legacy agent whose repo has no `main` gets. Refs #4851 --- docs/agent-lifecycle/config-changes.md | 22 ++++++++++++++-------- hive-c0re/src/forge/mod.rs | 14 +++++++------- hive-c0re/src/job_queue/exec.rs | 6 +++--- hive-c0re/src/lifecycle/mod.rs | 4 ++-- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/docs/agent-lifecycle/config-changes.md b/docs/agent-lifecycle/config-changes.md index 4f7551a7..1800f17d 100644 --- a/docs/agent-lifecycle/config-changes.md +++ b/docs/agent-lifecycle/config-changes.md @@ -29,7 +29,7 @@ No MCP tool exists for config changes: opening the PR IS the request. (it's currently mounted read-write, which is a defect tracked separately, not an authoring path.) Branch protection (the agent isn't on the `main` push allowlist; - merge and approvals allowlist = `operators` team; see "Forge mirror" + merge and approvals allowlist = `operators` team; see "Forge config repos" below) makes the agent a write collaborator that **can't merge its own config PR**. 2. An operator reviews the PR **on the forge** (native diff, threaded @@ -204,16 +204,22 @@ forge and meta's lock commits record it. A config PR nobody merges carries no extra state on the forge side: the PR stays open, and the submitter pushes again (or closes it) to retry. -### Forge mirror +### Forge config repos The bundled `hive-forge` container runs on the swarm's forge host (`deploy.forgejo.enable`, see [`../swarm/services.md`](../swarm/services.md)). -Every agent has a repo in the private `agent-configs` Forgejo org, created -and seeded by swarm-controller. hive-c0re pushes nothing to it: the -applied repo's tags (`deployed/0`) exist only locally, and forge `main` -advances only by an operator's merge. hive-c0re -reads from it — reseeding a purged `applied`, catching `applied` up, and -seeding `proposed` at first spawn. +Every agent created through the swarm has a repo in the private +`agent-configs` Forgejo org, created and seeded by swarm-controller. +hive-c0re pushes nothing to it: the applied repo's tags (`deployed/0`) +exist only locally, and forge `main` advances only by an operator's merge. +hive-c0re reads from it — reseeding a purged `applied` +(`forge::fetch_config_main_into_applied`), catching `applied` up, and +seeding `proposed` at first spawn (`forge::clone_config_into_proposed`). + +A legacy agent spawned by the hive alone has no swarm-seeded repo; if its +`agent-configs/` has no `main`, a first spawn falls back to the local +template, and reseeding a purged `applied` fails with a `destroy --purge` +and re-spawn instruction. Each agent is a **write collaborator on its own** `agent-configs/` repo — so it can push a branch and open a config PR — but not a member diff --git a/hive-c0re/src/forge/mod.rs b/hive-c0re/src/forge/mod.rs index ab181ce9..a59d7b5e 100644 --- a/hive-c0re/src/forge/mod.rs +++ b/hive-c0re/src/forge/mod.rs @@ -1,4 +1,4 @@ -//! Optional Forgejo wiring — config-repo mirroring, meta read-access +//! Optional Forgejo wiring — the `core/meta` repo, meta read-access //! grants, and each agent's read-only grant on `internal/docs` (the //! swarm-controller creates that repo, with the other swarm-wide orgs, //! teams and repos). @@ -360,12 +360,12 @@ async fn wait_until_ready() -> bool { } } -/// Sweep every existing container (manager + sub-agents) and ensure -/// each has a forgejo user + token, plus an `agent-configs/` -/// repo mirroring its applied config. Also seeds the `core` admin -/// user (hive-c0re's own identity for pushing the meta repo + driving -/// the API) and the `core/meta` repo. The `agent-configs` org itself is -/// the swarm-controller's to ensure. +/// Sweep the forge at startup: seed the `core` admin user (hive-c0re's own +/// identity for pushing the meta repo + driving the API) and its token, the +/// `core/meta` repo and the local knowledge clone, then run [`sync_agent`] +/// over every existing container (manager + sub-agents). Agent accounts, +/// tokens and `agent-configs/` repos are the swarm-controller's, as is +/// the `agent-configs` org; this sweep pushes nothing to them. /// Called once at hive-c0re startup. Per-step failures are logged /// but don't abort the sweep. pub async fn ensure_all() { diff --git a/hive-c0re/src/job_queue/exec.rs b/hive-c0re/src/job_queue/exec.rs index 1d406eb1..652f6d45 100644 --- a/hive-c0re/src/job_queue/exec.rs +++ b/hive-c0re/src/job_queue/exec.rs @@ -469,9 +469,9 @@ async fn run_rebuild_bookkeeping(coord: &Arc, name: &str) -> Result // `EmitRebuilt` tail — emitting ok here and letting a failed tail `Reconcile` // add a contradictory !ok would double-report the same rebuild. // Full forge sync on every successful rebuild so the rebuild path is - // equivalent to the startup sweep: tokens, config-repo mirror, meta - // access all recover without a hive-c0re restart. (No matrix step: the - // swarm mints an agent's matrix account, not this hive.) + // equivalent to the startup sweep: meta access, the `meta` remote and the + // `internal/docs` grant all recover without a hive-c0re restart. (No + // matrix step: the swarm mints an agent's matrix account, not this hive.) crate::forge::sync_agent(name, crate::forge::core_token().as_deref()).await; // No `kick_agent` here any more — reporting from `hive-agent`'s own // boot instead avoids the duplicate-restart-message problem this used diff --git a/hive-c0re/src/lifecycle/mod.rs b/hive-c0re/src/lifecycle/mod.rs index e0ea9409..3ecc815a 100644 --- a/hive-c0re/src/lifecycle/mod.rs +++ b/hive-c0re/src/lifecycle/mod.rs @@ -295,8 +295,8 @@ pub async fn prepare_rebuild_dirs(name: &str, paths: &AgentPaths) -> Result<()> { bail!( "applied repo at {} is missing its .git directory and could not be reseeded from \ - the forge (agent-configs/{name} unreachable, not yet mirrored, or absent); \ - destroy --purge and re-spawn this agent.", + the forge (agent-configs/{name} unreachable, has no `main` — never merged or \ + never seeded — or absent); destroy --purge and re-spawn this agent.", paths.applied.display() ); }