cleanup(#1177): unify manager socket path, remove dead manager-name branches, rename ensure_manager

This commit is contained in:
damocles 2026-06-03 20:32:43 +02:00 committed by mara
commit eb3c6cd0c4
8 changed files with 36 additions and 41 deletions

View file

@ -66,7 +66,7 @@ pub fn agent_config_pending(name: &str, deployed_sha: Option<&str>) -> bool {
/// `queue_entry_id` is `Some(id)` when the rebuild was dispatched from
/// the `rebuild_queue` worker (lets the function annotate its phase via
/// `coord.set_queue_step`) and `None` when called directly (e.g. the
/// manager-migration nudge in `ensure_manager`).
/// root-agent migration nudge in `ensure_root_agent`).
pub async fn rebuild_agent(
coord: &Arc<Coordinator>,
name: &str,
@ -156,10 +156,13 @@ pub async fn rebuild_agent(
}
/// Auto-create the manager container on startup if it isn't already there.
/// hive-c0re manages `ruth` end-to-end: operators no
/// longer declare `containers.h-ruth` in their host NixOS config. Bypasses
/// the approval queue — manager is required infrastructure. Idempotent.
pub async fn ensure_manager(coord: &Arc<Coordinator>) -> Result<()> {
/// hive-c0re manages the manager end-to-end: operators no longer declare
/// `containers.h-ruth` in their host NixOS config. Bypasses the approval
/// queue — manager is required infrastructure. Idempotent.
///
/// (Renamed from `ensure_manager` to align with the "root agent" terminology
/// used in docs and issues; behaviour is identical.)
pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
let existing = lifecycle::list().await.unwrap_or_default();
let current_rev = current_flake_rev(&coord.hyperhive_flake);
if existing

View file

@ -23,7 +23,6 @@ use crate::operator_questions::OperatorQuestions;
const DASHBOARD_CHANNEL: usize = 256;
const AGENT_RUNTIME_ROOT: &str = "/run/hyperhive/agents";
const MANAGER_RUNTIME_ROOT: &str = "/run/hyperhive/manager";
/// Manager-editable per-agent config repos. Bind-mounted RW into the manager
/// container as `/agents/<name>/`. Hive-c0re only writes to these on first
/// spawn (initial commit); after that it's manager-only.
@ -857,12 +856,15 @@ impl Coordinator {
Self::agent_dir(name).join("mcp.sock")
}
/// Runtime dir for the manager. Uses the same per-agent subdir layout as
/// sub-agents — the manager is just another agent under
/// `AGENT_RUNTIME_ROOT` with its own subdirectory.
pub fn manager_dir() -> PathBuf {
PathBuf::from(MANAGER_RUNTIME_ROOT)
Self::agent_dir(crate::lifecycle::MANAGER_NAME)
}
pub fn manager_socket_path() -> PathBuf {
Self::manager_dir().join("mcp.sock")
Self::socket_path(crate::lifecycle::MANAGER_NAME)
}
/// Ensure a runtime dir + (for sub-agents) per-agent socket exists. For
@ -872,7 +874,7 @@ impl Coordinator {
/// `/run/hive/mcp.sock` bind that ends up in `set_nspawn_flags`.
pub fn ensure_runtime(self: &Arc<Self>, name: &str) -> Result<PathBuf> {
if name == crate::lifecycle::MANAGER_NAME {
let dir = Self::manager_dir();
let dir = Self::agent_dir(name);
std::fs::create_dir_all(&dir)
.with_context(|| format!("create manager dir {}", dir.display()))?;
return Ok(dir);

View file

@ -33,13 +33,10 @@ pub fn spawn(coord: Arc<Coordinator>) {
let mut current_logged_in = HashSet::new();
let mut sub_agents: Vec<String> = Vec::new();
for c in &raw {
let logical = if c == MANAGER_NAME {
MANAGER_NAME.to_owned()
} else if let Some(n) = c.strip_prefix(AGENT_PREFIX) {
n.to_owned()
} else {
let Some(logical) = c.strip_prefix(AGENT_PREFIX) else {
continue;
};
let logical = logical.to_owned();
if logical != MANAGER_NAME {
sub_agents.push(logical.clone());
}

View file

@ -222,12 +222,12 @@ async fn cmd_serve(
if let Err(e) = migrate::run(&coord).await {
tracing::warn!(error = ?e, "startup migration failed");
}
// Auto-create the manager container if it isn't there yet. Block
// Auto-create the root agent container if it isn't there yet. Block
// on this — without root the system has no manager harness.
// Failures are logged but allowed: a broken auto-spawn shouldn't
// make the dashboard unreachable for debugging.
if let Err(e) = auto_update::ensure_manager(&coord).await {
tracing::warn!(error = ?e, "auto-spawn manager failed");
if let Err(e) = auto_update::ensure_root_agent(&coord).await {
tracing::warn!(error = ?e, "auto-spawn root agent failed");
}
// Auto-update in the background — don't block service start.
// Sub-agent rebuilds can take tens of seconds; we want the admin

View file

@ -189,7 +189,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
let id = match coord
.approvals
.submit_kind(
hive_sh4re::MANAGER_AGENT,
MANAGER_AGENT,
hive_sh4re::ApprovalKind::UpdateMetaInputs,
&commit_ref,
description.as_deref(),
@ -206,7 +206,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
tracing::info!(%id, %label, "update_meta_inputs approval queued");
coord.emit_approval_added(
id,
hive_sh4re::MANAGER_AGENT,
MANAGER_AGENT,
"update_meta_inputs",
None,
None,
@ -215,10 +215,10 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
ManagerResponse::Ok
}
ManagerRequest::RequestSchedulePrompt(payload) => {
handle_request_schedule_prompt(coord, hive_sh4re::MANAGER_AGENT, payload)
handle_request_schedule_prompt(coord, MANAGER_AGENT, payload)
}
ManagerRequest::CancelSchedule { id, targets } => {
handle_cancel_schedule(coord, hive_sh4re::MANAGER_AGENT, *id, targets.as_deref())
handle_cancel_schedule(coord, MANAGER_AGENT, *id, targets.as_deref())
}
ManagerRequest::EditSchedule {
id,
@ -230,7 +230,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
targets_remove,
} => handle_edit_schedule(
coord,
hive_sh4re::MANAGER_AGENT,
MANAGER_AGENT,
*id,
body.clone(),
description.clone(),
@ -248,7 +248,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
},
},
ManagerRequest::FireScheduleNow { id } => {
handle_fire_schedule_now(coord, hive_sh4re::MANAGER_AGENT, *id).await
handle_fire_schedule_now(coord, MANAGER_AGENT, *id).await
}
ManagerRequest::GetLogs { agent, lines } => {
let n = lines.unwrap_or(50);

View file

@ -781,12 +781,8 @@ pub async fn meta_update_cascade_agents(inputs: &[String]) -> Vec<String> {
.unwrap_or_default()
.into_iter()
.filter_map(|c| {
if c == crate::lifecycle::MANAGER_NAME {
Some(crate::lifecycle::MANAGER_NAME.to_owned())
} else {
c.strip_prefix(crate::lifecycle::AGENT_PREFIX)
.map(str::to_owned)
}
c.strip_prefix(crate::lifecycle::AGENT_PREFIX)
.map(str::to_owned)
})
.collect()
} else {

View file

@ -168,17 +168,12 @@ pub fn write_payload(agent: &str, host_path: &Path, message: &str) -> Result<(),
}
/// Container-visible state prefix the caller's `file_path` must live
/// under. Every agent sees its state at `/agents/<container>/state/`
/// under. Every agent sees its state at `/agents/<name>/state/`
/// (see `lifecycle::set_nspawn_flags`). Auto-file paths use the same
/// prefix so the round-trip is symmetric. The manager logical name
/// maps to its container name (`root`) per `lifecycle::MANAGER_NAME`.
/// prefix so the round-trip is symmetric.
#[must_use]
pub fn container_state_prefix(agent: &str) -> String {
if agent == hive_sh4re::MANAGER_AGENT {
format!("/agents/{}/state/", crate::lifecycle::MANAGER_NAME)
} else {
format!("/agents/{agent}/state/")
}
format!("/agents/{agent}/state/")
}
/// Map an agent-visible container path to the matching host path,

View file

@ -190,6 +190,8 @@ fn known_agents(_coord: &Coordinator) -> std::collections::HashSet<String> {
// safe (we're not in a `current_thread` runtime).
use std::collections::HashSet;
let mut out: HashSet<String> = HashSet::new();
// Manager is always a scheduled-prompt target (fail-safe: include
// it even if `list()` fails so prompts to the manager never silently drop).
out.insert(hive_sh4re::MANAGER_AGENT.to_owned());
let containers = tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(crate::lifecycle::list())
@ -199,9 +201,9 @@ fn known_agents(_coord: &Coordinator) -> std::collections::HashSet<String> {
for raw in list {
if let Some(name) = raw.strip_prefix(crate::lifecycle::AGENT_PREFIX) {
out.insert(name.to_owned());
} else if raw == crate::lifecycle::MANAGER_NAME {
out.insert(hive_sh4re::MANAGER_AGENT.to_owned());
}
// Note: the old `else if raw == MANAGER_NAME` branch was dead code;
// the manager container uses the h- prefix like all other agents.
}
}
Err(e) => {
@ -376,9 +378,9 @@ async fn known_agents_async() -> std::collections::HashSet<String> {
for raw in list {
if let Some(name) = raw.strip_prefix(crate::lifecycle::AGENT_PREFIX) {
out.insert(name.to_owned());
} else if raw == crate::lifecycle::MANAGER_NAME {
out.insert(hive_sh4re::MANAGER_AGENT.to_owned());
}
// Note: the old `else if raw == MANAGER_NAME` branch was dead code;
// the manager container uses the h- prefix like all other agents.
}
}
Err(e) => {