diff --git a/hive-c0re/src/forge/mod.rs b/hive-c0re/src/forge/mod.rs index 5d5bb182..51d44dc2 100644 --- a/hive-c0re/src/forge/mod.rs +++ b/hive-c0re/src/forge/mod.rs @@ -18,8 +18,7 @@ pub use pr_merge::{ pub use reconcile::{reconcile_config_apply, reconcile_config_status}; pub use repos::{ create_agent_repo, ensure_config_repo, ensure_knowledge_repo, ensure_meta_remote, ensure_repo, - ensure_shared_docs_repo, fetch_config_main_into_applied, meta_read_access, push_config, - push_meta, shared_docs_access, + ensure_shared_docs_repo, meta_read_access, push_config, push_meta, shared_docs_access, }; pub use users::{core_token, ensure_user_for, provision_user_token}; diff --git a/hive-c0re/src/forge/repos.rs b/hive-c0re/src/forge/repos.rs index ed80387c..a65f1bc0 100644 --- a/hive-c0re/src/forge/repos.rs +++ b/hive-c0re/src/forge/repos.rs @@ -519,80 +519,6 @@ pub async fn push_config(name: &str) -> Result<()> { Ok(()) } -/// Reseed a revived agent's `applied` repo — missing its `.git` entirely, -/// e.g. after `destroy --purge` — by fetching `agent-configs/`'s -/// `main` from the forge, [`push_config`]'s mirror target. Unlike -/// `proposed` (seeded once at first spawn and never touched again — see -/// `lifecycle::setup_proposed`'s own doc comment), the forge mirror is -/// kept current after every deploy, so this reflects the agent's actual -/// last-deployed state rather than a stale creation-time snapshot. -/// -/// Best-effort, mirroring [`push_config`]'s own shape: returns `false` -/// (not an error) rather than bailing when the forge is absent, the core -/// token isn't minted yet, `applied` already has a `.git` (nothing to -/// do), or any git step fails — callers fall back to a less-current -/// source or the original hard error. Only `true` once `applied` is -/// actually seeded and tagged `deployed/0`, mirroring first-spawn's own -/// `setup_applied` seed shape exactly. -pub async fn fetch_config_main_into_applied(name: &str) -> bool { - if !is_present().await { - return false; - } - let Some(token) = core_token() else { - return false; - }; - let applied = crate::paths::applied_dir(name); - if applied.join(".git").exists() { - return false; - } - if let Err(e) = std::fs::create_dir_all(&applied) { - tracing::warn!(%name, error = ?e, "forge: applied reseed mkdir failed"); - return false; - } - if let Err(e) = crate::lifecycle::git(&applied, &["init", "--initial-branch=main"]).await { - tracing::warn!(%name, error = ?e, "forge: applied reseed init failed"); - return false; - } - let url = forge_git_url(&format!("{CONFIG_ORG}/{name}")); - let auth = core_auth_header(&token); - let out = crate::lifecycle::git_command_authed(&auth) - .current_dir(&applied) - .args([ - "fetch", - "--no-tags", - "--update-head-ok", - &url, - "refs/heads/main:refs/heads/main", - ]) - .output() - .await; - match out { - Ok(o) if o.status.success() => {} - Ok(o) => { - tracing::warn!( - %name, - stderr = %String::from_utf8_lossy(&o.stderr).trim(), - "forge: applied reseed fetch failed" - ); - return false; - } - Err(e) => { - tracing::warn!(%name, error = ?e, "forge: applied reseed fetch failed"); - return false; - } - } - if let Err(e) = crate::lifecycle::git_read_tree_reset(&applied, "refs/heads/main").await { - tracing::warn!(%name, error = ?e, "forge: applied reseed read-tree failed"); - return false; - } - if let Err(e) = crate::lifecycle::git_tag(&applied, "deployed/0", "refs/heads/main").await { - tracing::warn!(%name, error = ?e, "forge: applied reseed tag failed"); - return false; - } - tracing::info!(%name, "forge: reseeded applied repo from agent-configs main"); - true -} - /// Run a single `git push ` in the applied repo `dir` and /// return the raw output for the caller to classify. Split out so /// [`push_config`] can push tags and `main` as independent pushes. diff --git a/hive-c0re/src/lifecycle/mod.rs b/hive-c0re/src/lifecycle/mod.rs index 36cd6cc1..a93edadd 100644 --- a/hive-c0re/src/lifecycle/mod.rs +++ b/hive-c0re/src/lifecycle/mod.rs @@ -250,20 +250,6 @@ pub async fn create_container(name: &str, hive: &HiveEnv, paths: &AgentPaths) -> /// Rebuild-path preamble, run by the job queue's `Prebuild` node: fail fast on /// a port collision, then make sure the applied repo + state dirs exist. /// Container untouched. -/// -/// `applied` is normally already the right shape here (this runs against a -/// previously-provisioned agent), but a `destroy --purge` removes it -/// (`job_queue::exec::run_purge_state`) — a later revive of the *same* -/// agent name is still a rebuild, not a first-spawn, so it lands here, not -/// in `provision_container`. Recover from `agent-configs/` on the -/// forge when that's the case (kept current after every deploy by -/// `forge::push_config` — see `forge::fetch_config_main_into_applied`'s own -/// doc comment) rather than bailing outright. Deliberately **no fallback to -/// `proposed`**: that repo is seeded once at first spawn and never touched -/// again (`setup_proposed`'s own doc comment), so it can be arbitrarily -/// stale for a long-lived agent — restoring from it would silently revive -/// the *wrong* config rather than recovering the right one, which is worse -/// than the clear bail this replaces. pub async fn prepare_rebuild_dirs(name: &str, paths: &AgentPaths) -> Result<()> { validate(name)?; if let Some(other) = port_collision(name).await { @@ -272,16 +258,6 @@ pub async fn prepare_rebuild_dirs(name: &str, paths: &AgentPaths) -> Result<()> agent_web_port(name) ); } - if !paths.applied.join(".git").exists() - && !crate::forge::fetch_config_main_into_applied(name).await - { - 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.", - paths.applied.display() - ); - } setup_applied(&paths.applied, None, name).await?; ensure_agent_state_subvolume(name).await?; ensure_claude_dir(&paths.claude)?;