revive: reseed applied from forge main, no proposed fallback

This commit is contained in:
damocles 2026-08-18 00:02:48 +02:00 committed by mara
commit 07d3d3060e
3 changed files with 96 additions and 8 deletions

View file

@ -18,7 +18,8 @@ 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, meta_read_access, push_config, push_meta, shared_docs_access,
ensure_shared_docs_repo, fetch_config_main_into_applied, meta_read_access, push_config,
push_meta, shared_docs_access,
};
pub use users::{core_token, ensure_user_for, provision_user_token};

View file

@ -519,6 +519,80 @@ 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/<name>`'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 <url> <refspec>` 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.