refactor(#2285): drop coordinator 1:1 path accessors, callers use paths:: directly
This commit is contained in:
parent
187c364feb
commit
cfb84b420a
13 changed files with 38 additions and 56 deletions
|
|
@ -161,8 +161,8 @@ pub async fn run_approval_apply_commit(
|
|||
let approval = fetch_approval_for_worker(coord, approval_id, ApprovalKind::ApplyCommit)?;
|
||||
// Runtime dir creation is handled inside lifecycle::rebuild_no_meta's
|
||||
// spawn path (first-spawn) or is already present for rebuilds.
|
||||
let agent_dir = Coordinator::agent_dir(&approval.agent);
|
||||
let applied_dir = Coordinator::agent_applied_dir(&approval.agent);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(&approval.agent);
|
||||
let applied_dir = crate::paths::applied_dir(&approval.agent);
|
||||
coord.set_queue_step(queue_entry_id, "apply commit");
|
||||
let (result, terminal_tag, is_first_spawn) =
|
||||
run_apply_commit(coord, &approval, &agent_dir, &applied_dir, queue_entry_id).await;
|
||||
|
|
@ -194,8 +194,8 @@ pub async fn run_approval_merge_config_pr(
|
|||
approval_id: i64,
|
||||
) -> Result<()> {
|
||||
let approval = fetch_approval_for_worker(coord, approval_id, ApprovalKind::MergeConfigPr)?;
|
||||
let agent_dir = Coordinator::agent_dir(&approval.agent);
|
||||
let applied_dir = Coordinator::agent_applied_dir(&approval.agent);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(&approval.agent);
|
||||
let applied_dir = crate::paths::applied_dir(&approval.agent);
|
||||
coord.set_queue_step(queue_entry_id, "merge config pr");
|
||||
let (result, terminal_tag) =
|
||||
run_merge_config_pr(coord, &approval, &agent_dir, &applied_dir, queue_entry_id).await;
|
||||
|
|
@ -911,7 +911,7 @@ pub async fn destroy(coord: &Arc<Coordinator>, name: &str, purge: bool) -> Resul
|
|||
let guard = coord.transient_guard(name, TransientKind::Destroying);
|
||||
lifecycle::destroy(name).await?;
|
||||
coord.unregister_agent(name);
|
||||
let runtime = Coordinator::agent_dir(name);
|
||||
let runtime = crate::paths::agent_runtime_dir(name);
|
||||
if runtime.exists() {
|
||||
let _ = std::fs::remove_dir_all(&runtime);
|
||||
}
|
||||
|
|
@ -924,8 +924,8 @@ pub async fn destroy(coord: &Arc<Coordinator>, name: &str, purge: bool) -> Resul
|
|||
tracing::warn!(error = ?e, %name, "purge: delete state subvolume failed");
|
||||
}
|
||||
for dir in [
|
||||
Coordinator::agent_state_root(name),
|
||||
Coordinator::agent_applied_dir(name),
|
||||
crate::paths::agent_state_dir(name),
|
||||
crate::paths::applied_dir(name),
|
||||
] {
|
||||
if dir.exists()
|
||||
&& let Err(e) = std::fs::remove_dir_all(&dir)
|
||||
|
|
@ -997,7 +997,7 @@ pub async fn deny(coord: &Coordinator, id: i64, note: Option<&str>) -> Result<()
|
|||
// the annotated body) the reason. Spawn approvals have no
|
||||
// commit to tag, so they fall through unannotated.
|
||||
if matches!(a.kind, ApprovalKind::ApplyCommit) {
|
||||
let applied_dir = Coordinator::agent_applied_dir(&a.agent);
|
||||
let applied_dir = crate::paths::applied_dir(&a.agent);
|
||||
let proposal_ref = format!("refs/tags/proposal/{id}");
|
||||
if lifecycle::git_rev_parse(&applied_dir, &proposal_ref)
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -1048,7 +1048,7 @@ fn human_bytes(n: u64) -> String {
|
|||
/// "needs root" error fixes that first-run footgun, where running a
|
||||
/// privileged verb without sudo reported as a missing agent.
|
||||
fn agent_exists(name: &str) -> Result<bool> {
|
||||
let root = Coordinator::agent_state_root(name);
|
||||
let root = hive_c0re::paths::agent_state_dir(name);
|
||||
match root.try_exists() {
|
||||
Ok(found) => Ok(found),
|
||||
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => bail!(
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ impl Coordinator {
|
|||
|
||||
/// Assemble the per-agent filesystem paths for `name`. `agent_dir`
|
||||
/// is the runtime directory (`/run/hyperhive/agents/<name>`), obtained
|
||||
/// from `Coordinator::agent_dir(name)` (pure path) or from
|
||||
/// from `crate::paths::agent_runtime_dir(name)` (pure path) or from
|
||||
/// `lifecycle::ensure_agent_runtime_dir(name)` when the dir must be
|
||||
/// created. All other paths are derived statically from `name`.
|
||||
#[must_use]
|
||||
|
|
@ -545,7 +545,7 @@ impl Coordinator {
|
|||
AgentPaths {
|
||||
agent_dir,
|
||||
proposed_dir: Self::agent_proposed_dir(name),
|
||||
applied_dir: Self::agent_applied_dir(name),
|
||||
applied_dir: crate::paths::applied_dir(name),
|
||||
claude_dir: Self::agent_claude_dir(name),
|
||||
notes_dir: Self::agent_notes_dir(name),
|
||||
}
|
||||
|
|
@ -1124,7 +1124,7 @@ impl Coordinator {
|
|||
// Idempotent: drop any existing listener so re-registration (e.g. on rebuild,
|
||||
// or after a hive-c0re restart cleared /run/hyperhive) gets a fresh socket.
|
||||
self.unregister_agent(name);
|
||||
let agent_dir = Self::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
std::fs::create_dir_all(&agent_dir)
|
||||
.with_context(|| format!("create agent dir {}", agent_dir.display()))?;
|
||||
let socket_path = Self::socket_path(name);
|
||||
|
|
@ -1432,25 +1432,14 @@ impl Coordinator {
|
|||
errors
|
||||
}
|
||||
|
||||
pub fn agent_dir(name: &str) -> PathBuf {
|
||||
crate::paths::agent_runtime_dir(name)
|
||||
}
|
||||
|
||||
pub fn socket_path(name: &str) -> PathBuf {
|
||||
Self::agent_dir(name).join("mcp.sock")
|
||||
}
|
||||
|
||||
/// Ensure a runtime dir + (for sub-agents) per-agent socket exists.
|
||||
///
|
||||
/// Per-agent state root (parent of `config/`, future `prompts/`, etc.).
|
||||
pub fn agent_state_root(name: &str) -> PathBuf {
|
||||
crate::paths::agent_state_dir(name)
|
||||
crate::paths::agent_runtime_dir(name).join("mcp.sock")
|
||||
}
|
||||
|
||||
/// Manager-editable proposed config repo. Bind-mounted into the manager
|
||||
/// container as `/agents/<name>/config/`.
|
||||
pub fn agent_proposed_dir(name: &str) -> PathBuf {
|
||||
Self::agent_state_root(name).join("config")
|
||||
crate::paths::agent_state_dir(name).join("config")
|
||||
}
|
||||
|
||||
/// Per-agent Claude credentials dir. Bind-mounted RW into the agent
|
||||
|
|
@ -1458,14 +1447,14 @@ impl Coordinator {
|
|||
/// destroy/recreate. Each agent owns its own token lineage — sharing
|
||||
/// would break on the first refresh-token rotation.
|
||||
pub fn agent_claude_dir(name: &str) -> PathBuf {
|
||||
Self::agent_state_root(name).join("claude")
|
||||
crate::paths::agent_state_dir(name).join("claude")
|
||||
}
|
||||
|
||||
/// Per-agent durable knowledge dir. Bind-mounted RW into the agent
|
||||
/// container at `/agents/{name}/state`. Survives destroy/recreate.
|
||||
/// Agent-visible — claude is told to write long-lived notes here.
|
||||
pub fn agent_notes_dir(name: &str) -> PathBuf {
|
||||
Self::agent_state_root(name).join("state")
|
||||
crate::paths::agent_state_dir(name).join("state")
|
||||
}
|
||||
|
||||
/// Per-agent harness-internal state dir. Bind-mounted RW into the
|
||||
|
|
@ -1475,12 +1464,7 @@ impl Coordinator {
|
|||
/// from the agent-visible `state/` so claude's "my notes" view is
|
||||
/// uncluttered and the host vacuum has a clean sweep root.
|
||||
pub fn agent_harness_dir(name: &str) -> PathBuf {
|
||||
Self::agent_state_root(name).join("harness")
|
||||
}
|
||||
|
||||
/// Authoritative applied config repo. Hive-c0re-only.
|
||||
pub fn agent_applied_dir(name: &str) -> PathBuf {
|
||||
crate::paths::applied_dir(name)
|
||||
crate::paths::agent_state_dir(name).join("harness")
|
||||
}
|
||||
|
||||
/// Enumerate names that have a persistent state dir under
|
||||
|
|
@ -1514,7 +1498,7 @@ impl Coordinator {
|
|||
.into_iter()
|
||||
.filter(|n| {
|
||||
Self::agent_proposed_dir(n).join(".git").exists()
|
||||
&& !Self::agent_applied_dir(n).join(".git").exists()
|
||||
&& !crate::paths::applied_dir(n).join(".git").exists()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ pub(super) fn gc_orphans(coord: &Coordinator, approvals: Vec<Approval>) -> Vec<A
|
|||
/// dashboard event (instead of forcing the dashboard to wait a
|
||||
/// `/api/state` cycle to see the diff for newly-queued approvals).
|
||||
pub(crate) async fn approval_diff(agent: &str, approval_id: i64) -> String {
|
||||
let applied = Coordinator::agent_applied_dir(agent);
|
||||
let applied = crate::paths::applied_dir(agent);
|
||||
if !applied.join(".git").exists() {
|
||||
return format!("(no applied git repo at {})", applied.display());
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ pub(super) async fn get_approval_diff(
|
|||
if !matches!(approval.kind, hive_sh4re::ApprovalKind::ApplyCommit) {
|
||||
return Err(error_problem("spawn approvals carry no commit to diff"));
|
||||
}
|
||||
let applied = Coordinator::agent_applied_dir(&approval.agent);
|
||||
let applied = crate::paths::applied_dir(&approval.agent);
|
||||
if !applied.join(".git").exists() {
|
||||
return Ok(plain_text(format!(
|
||||
"(no applied git repo at {})",
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub(super) fn build_tombstone_views(
|
|||
.into_iter()
|
||||
.filter(|name| !live.contains(name.as_str()))
|
||||
.map(|name| {
|
||||
let root = Coordinator::agent_state_root(&name);
|
||||
let root = crate::paths::agent_state_dir(&name);
|
||||
let state_bytes = dir_size_bytes(&root);
|
||||
let last_seen = std::fs::metadata(&root)
|
||||
.and_then(|m| m.modified())
|
||||
|
|
@ -133,8 +133,8 @@ pub(super) async fn post_purge_tombstone(
|
|||
}
|
||||
let mut errors = Vec::new();
|
||||
for dir in [
|
||||
Coordinator::agent_state_root(&name),
|
||||
Coordinator::agent_applied_dir(&name),
|
||||
crate::paths::agent_state_dir(&name),
|
||||
crate::paths::applied_dir(&name),
|
||||
] {
|
||||
if dir.exists()
|
||||
&& let Err(e) = std::fs::remove_dir_all(&dir)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ use anyhow::Context;
|
|||
use forgejo_api::ForgejoError;
|
||||
use forgejo_api::structs::{MergePullRequestOption, MergePullRequestOptionDo};
|
||||
|
||||
use crate::coordinator::Coordinator;
|
||||
|
||||
use super::{CONFIG_ORG, api, core_token, forge_git_url};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -133,7 +131,7 @@ pub async fn fetch_pr_head_into_applied(repo: &str, pr: u64) -> Result<(), Forge
|
|||
let token = core_token()
|
||||
.ok_or_else(|| ForgeMergeError::Other(anyhow::anyhow!("forge core token absent")))?;
|
||||
let url = forge_git_url(&token, repo);
|
||||
let applied = Coordinator::agent_applied_dir(repo_agent_name(repo));
|
||||
let applied = crate::paths::applied_dir(repo_agent_name(repo));
|
||||
let refspec = format!("refs/pull/{pr}/head");
|
||||
let out = crate::lifecycle::git_command()
|
||||
.current_dir(&applied)
|
||||
|
|
@ -165,7 +163,7 @@ pub async fn ff_push_to_main(repo: &str, sha: &str) -> Result<(), ForgeMergeErro
|
|||
let token = core_token()
|
||||
.ok_or_else(|| ForgeMergeError::Other(anyhow::anyhow!("forge core token absent")))?;
|
||||
let url = forge_git_url(&token, repo);
|
||||
let applied = Coordinator::agent_applied_dir(repo_agent_name(repo));
|
||||
let applied = crate::paths::applied_dir(repo_agent_name(repo));
|
||||
|
||||
// Current `main` on the forge repo.
|
||||
let ls = crate::lifecycle::git_command()
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ pub async fn push_config(name: &str) -> Result<()> {
|
|||
let Some(token) = core_token() else {
|
||||
return Ok(());
|
||||
};
|
||||
let dir = Coordinator::agent_applied_dir(name);
|
||||
let dir = crate::paths::applied_dir(name);
|
||||
if !dir.join(".git").exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ async fn run_prebuild(
|
|||
// Prebuild runs while the agent is still up — the runtime dir and
|
||||
// MCP listener already exist. Use the pure path accessor; no need
|
||||
// to re-register the listener (event-driven: registered at start/create).
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
crate::lifecycle::prepare_rebuild_dirs(name, &paths).await?;
|
||||
|
|
@ -134,7 +134,7 @@ async fn run_swap(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Res
|
|||
let name = &claim.agent;
|
||||
// Swap runs on an already-existing (stopped) container — runtime dir
|
||||
// and listener were created earlier. Pure path accessor suffices.
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
let result =
|
||||
|
|
@ -181,7 +181,7 @@ async fn run_swap(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Res
|
|||
/// build+create — no prebuild needed).
|
||||
async fn run_create(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Result<NodeOutput> {
|
||||
let name = &claim.agent;
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
ctx.step("nixos-container create");
|
||||
|
|
@ -255,7 +255,7 @@ async fn run_reconcile(
|
|||
// exists and writes the nspawn/resource-limits drop-ins.
|
||||
// The returned StartableAgent token is the only way to call
|
||||
// start_with_fallback — omitting this becomes a compile error.
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
let token = crate::lifecycle::converge_start_preamble(name, &hive, &paths).await?;
|
||||
|
|
@ -346,7 +346,7 @@ async fn run_write_dropin(coord: &Arc<Coordinator>, claim: &Claim) -> Result<Nod
|
|||
// write_dropins only needs the path value to build AgentPaths; the
|
||||
// dir doesn't need to exist at this point (created by ensure_agent_runtime_dir
|
||||
// on the upstream Prebuild/Start node).
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
crate::lifecycle::write_dropins(name, &hive, &paths).await?;
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ async fn enumerate_agents() -> Vec<String> {
|
|||
}
|
||||
|
||||
async fn migrate_applied_repo(name: &str) -> Result<()> {
|
||||
let dir = Coordinator::agent_applied_dir(name);
|
||||
let dir = crate::paths::applied_dir(name);
|
||||
if !dir.join(".git").exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ async fn dispatch(req: &HostRequest, coord: Arc<Coordinator>) -> HostResponse {
|
|||
/// registration and notifying the manager on failure.
|
||||
async fn handle_spawn(coord: &Arc<Coordinator>, name: &str) -> Result<HostResponse> {
|
||||
tracing::info!(%name, "spawn");
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let agent_dir = crate::paths::agent_runtime_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
// lifecycle::spawn creates the runtime dir internally before start.
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ pub(crate) async fn submit_apply_commit(
|
|||
) -> anyhow::Result<(i64, String)> {
|
||||
validate_commit_ref(commit_ref)?;
|
||||
let proposed_dir = crate::coordinator::Coordinator::agent_proposed_dir(agent);
|
||||
let applied_dir = crate::coordinator::Coordinator::agent_applied_dir(agent);
|
||||
let applied_dir = crate::paths::applied_dir(agent);
|
||||
if !proposed_dir.exists() {
|
||||
anyhow::bail!(
|
||||
"proposed repo missing for agent '{agent}' (expected at {})",
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ pub fn start(agent: &str, socket_path: &Path, coord: Arc<Coordinator>) -> Result
|
|||
/// standard per-agent runtime dir + socket, with no dedicated helpers.
|
||||
pub fn start_manager(coord: Arc<Coordinator>) -> Result<()> {
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
let dir = Coordinator::agent_dir(crate::lifecycle::MANAGER_NAME);
|
||||
let dir = crate::paths::agent_runtime_dir(crate::lifecycle::MANAGER_NAME);
|
||||
std::fs::create_dir_all(&dir)
|
||||
.with_context(|| format!("create manager dir {}", dir.display()))?;
|
||||
let socket = Coordinator::socket_path(crate::lifecycle::MANAGER_NAME);
|
||||
|
|
@ -1026,7 +1026,7 @@ pub(crate) fn handle_send(
|
|||
};
|
||||
}
|
||||
if resolved != hive_sh4re::OPERATOR_RECIPIENT {
|
||||
let state_root = crate::coordinator::Coordinator::agent_state_root(&resolved);
|
||||
let state_root = crate::paths::agent_state_dir(&resolved);
|
||||
if !state_root.exists() {
|
||||
return AgentResponse::Err {
|
||||
message: format!(
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
|
|||
// (no applied flake on disk) we must rebuild — otherwise it's
|
||||
// running whatever the host-declarative config was at create
|
||||
// time, with a wrong systemd unit and port.
|
||||
let applied_flake = Coordinator::agent_applied_dir(MANAGER_NAME).join("flake.nix");
|
||||
let applied_flake = crate::paths::applied_dir(MANAGER_NAME).join("flake.nix");
|
||||
if !applied_flake.exists() && current_rev.is_some() {
|
||||
tracing::warn!(
|
||||
"manager container exists but no applied flake — forcing rebuild to migrate"
|
||||
|
|
@ -151,7 +151,7 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
|
|||
tracing::info!("manager container missing — spawning");
|
||||
// lifecycle::spawn creates the runtime dir internally; no manual
|
||||
// ensure_agent_runtime_dir needed here.
|
||||
let runtime = Coordinator::agent_dir(MANAGER_NAME);
|
||||
let runtime = crate::paths::agent_runtime_dir(MANAGER_NAME);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(MANAGER_NAME, runtime);
|
||||
lifecycle::spawn(MANAGER_NAME, &hive, &paths).await?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue