Compare commits

..

No commits in common. "3e949145694e69c6b094842be12e2f0adc6984ee" and "2f1b846bafcf90103f9082c0cbeb904935e46b8a" have entirely different histories.

2 changed files with 27 additions and 49 deletions

View file

@ -101,13 +101,6 @@ pub async fn rebuild_agent(coord: &Arc<Coordinator>, name: &str, current_rev: &s
sha: None, sha: None,
tag: None, tag: None,
}); });
// Run the full forge sync on every successful rebuild so
// the rebuild path is equivalent to the hive-c0re startup
// sweep: token, config-repo mirror, meta read access, and
// meta remote are all kept in sync. Recovers missing tokens
// (e.g. first-spawn seeding failed transiently) without
// requiring a full hive-c0re restart.
crate::forge::sync_agent(name, crate::forge::core_token().as_deref()).await;
// Wake the agent on its next turn so claude sees a // Wake the agent on its next turn so claude sees a
// "you were rebuilt — check /state/ for notes, --continue // "you were rebuilt — check /state/ for notes, --continue
// session intact" hint. Covers dashboard rebuild, admin // session intact" hint. Covers dashboard rebuild, admin

View file

@ -519,47 +519,6 @@ async fn ensure_org(name: &str, admin_token: &str) -> Result<()> {
} }
} }
/// Per-agent forge sync: ensure the agent has a forgejo user + token,
/// a mirrored config repo, read access to `core/meta`, and the `meta`
/// remote in its proposed repo. All operations are idempotent; failures
/// are logged as warnings but don't abort the caller.
///
/// `core_token` is `core_token()` — passed in so callers that already
/// fetched it don't re-read the file. Pass `None` to skip the
/// `meta_read_access` step (safe: the access grant is best-effort).
///
/// Called by both `ensure_all()` (startup sweep) and `rebuild_agent`
/// (per-rebuild) so the two paths stay equivalent.
pub async fn sync_agent(name: &str, core_token: Option<&str>) {
if let Err(e) = ensure_user_for(name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_user failed");
}
// Align email to match the git user.email set by meta::render_flake
// so commits link to the agent's Forgejo profile. Best-effort;
// also patches up agents created before this fix (old @hive.local).
ensure_user_email(name).await;
// Mirror the agent's applied config repo into agent-configs.
// ensure_config_repo is idempotent; push_config catches any
// drift since the last run — e.g. the startup migration just
// relocated `deployed/0`, or a deploy landed while the forge
// was down.
if let Err(e) = ensure_config_repo(name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_config_repo failed");
}
if let Err(e) = push_config(name).await {
tracing::warn!(%name, error = ?e, "forge: push_config failed");
}
// Grant read-only access to core/meta and wire the `meta` remote
// into the proposed repo so agents can fetch their deployment context.
if let Some(token) = core_token
&& let Err(e) = meta_read_access(name, token).await {
tracing::warn!(%name, error = ?e, "forge: ensure_meta_read_access failed");
}
if let Err(e) = ensure_meta_remote(name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_meta_remote failed");
}
}
/// Sweep every existing container (manager + sub-agents) and ensure /// Sweep every existing container (manager + sub-agents) and ensure
/// each has a forgejo user + token, plus an `agent-configs/<name>` /// each has a forgejo user + token, plus an `agent-configs/<name>`
/// repo mirroring its applied config. Also seeds the `core` admin /// repo mirroring its applied config. Also seeds the `core` admin
@ -604,6 +563,32 @@ pub async fn ensure_all() {
} else { } else {
continue; continue;
}; };
sync_agent(&name, core_token.as_deref()).await; if let Err(e) = ensure_user_for(&name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_user failed");
}
// Align email to match the git user.email set by meta::render_flake
// so commits link to the agent's Forgejo profile. Best-effort;
// also patches up agents created before this fix (old @hive.local).
ensure_user_email(&name).await;
// Mirror the agent's applied config repo into agent-configs.
// ensure_config_repo is idempotent; push_config catches any
// drift since the last run — e.g. the startup migration just
// relocated `deployed/0`, or a deploy landed while the forge
// was down.
if let Err(e) = ensure_config_repo(&name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_config_repo failed");
}
if let Err(e) = push_config(&name).await {
tracing::warn!(%name, error = ?e, "forge: push_config failed");
}
// Grant read-only access to core/meta and wire the `meta` remote
// into the proposed repo so agents can fetch their deployment context.
if let Some(token) = core_token.as_deref()
&& let Err(e) = meta_read_access(&name, token).await {
tracing::warn!(%name, error = ?e, "forge: ensure_meta_read_access failed");
}
if let Err(e) = ensure_meta_remote(&name).await {
tracing::warn!(%name, error = ?e, "forge: ensure_meta_remote failed");
}
} }
} }