From 0df52806f9e3a16ce009662c63499987fd16e123 Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 21 Jun 2026 23:19:03 +0200 Subject: [PATCH] hive-c0re: drop the dead manager exclusion from the agent web-port map --- docs/gateway.md | 10 +++++----- hive-c0re/src/agent_ports.rs | 25 ++++++++++++------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/gateway.md b/docs/gateway.md index d790f9e2..6315b961 100644 --- a/docs/gateway.md +++ b/docs/gateway.md @@ -131,11 +131,11 @@ logical agent name → TCP web port: Written alongside `agents.conf` on every topology change. Ports come from `lifecycle::agent_web_port(name)` — a pure FNV-1a hash of the name, -reproducible from the name alone. The manager is excluded: it always -uses a unix socket (`HIVE_WEB_SOCKET` is unconditionally set for the -manager role), so its TCP port never appears in the fallback map. -The gateway routes `/agent/root/` to the manager's unix socket via -`agents.conf` alongside sub-agents. +reproducible from the name alone. Every agent gets an entry — no name is +special-cased. Note this TCP map is now a fallback the gateway no longer +reaches: all agents bind a unix-socket web UI (`HIVE_WEB_SOCKET`) and the +gateway routes via `agent-sockets.json`, picking the socket upstream +whenever one exists. The root agent's UI is routed at `/agent/root/`. The file doubles as a human-readable audit artifact — `cat agent-ports.json` shows every registered sub-agent and its deterministic port assignment. TCP diff --git a/hive-c0re/src/agent_ports.rs b/hive-c0re/src/agent_ports.rs index 9b879c38..3d73ae50 100644 --- a/hive-c0re/src/agent_ports.rs +++ b/hive-c0re/src/agent_ports.rs @@ -1,23 +1,24 @@ //! `/var/lib/hyperhive/run/agent-ports.json` writer — flat map of //! agent name → TCP web port. Written alongside `agents.conf` on //! every topology change. JSON shape, port derivation (FNV-1a hash), -//! atomicity, and manager exclusion: `docs/gateway.md::Agent port map`. +//! and atomicity: `docs/gateway.md::Agent port map`. use std::collections::BTreeMap; use std::path::PathBuf; use anyhow::{Context, Result}; -use crate::lifecycle::{self, MANAGER_NAME}; +use crate::lifecycle; #[must_use] pub fn host_ports_path() -> PathBuf { crate::paths::agent_ports_file() } -/// Compute the agent-port map for the given logical agent names. -/// Sub-agents only — manager is filtered out at the call boundary -/// because the gateway doesn't surface per-agent routing for it. +/// Compute the agent-port map for the given logical agent names. Every +/// agent gets an entry — no name is special-cased. (All agents now bind +/// a unix-socket web UI via `HIVE_WEB_SOCKET`, so this TCP map is a +/// fallback the gateway no longer reaches; tracked for removal.) /// /// `BTreeMap` keeps the JSON output sorted by key so a re-emit /// without churn produces byte-identical output (helpful when the @@ -26,7 +27,6 @@ pub fn host_ports_path() -> PathBuf { pub fn build_map(names: &[String]) -> BTreeMap { names .iter() - .filter(|n| n.as_str() != MANAGER_NAME) .map(|n| (n.clone(), lifecycle::agent_web_port(n))) .collect() } @@ -77,17 +77,16 @@ mod tests { use super::*; #[test] - fn build_map_filters_manager() { - // Use MANAGER_NAME in the input so the assert below actually - // exercises the filter path — a literal `"root"` would pass - // trivially if the constant ever changed and the filter - // silently became a no-op. - let names: Vec = ["iris", MANAGER_NAME, "argus"] + fn build_map_includes_every_agent() { + // No name is special-cased: the bootstrap/root container gets a + // port entry like any other agent. Use the bootstrap name in the + // input so this guards against re-introducing an exclusion. + let names: Vec = ["iris", lifecycle::MANAGER_NAME, "argus"] .iter() .map(|s| (*s).to_owned()) .collect(); let map = build_map(&names); - assert!(!map.contains_key(MANAGER_NAME)); + assert!(map.contains_key(lifecycle::MANAGER_NAME)); assert!(map.contains_key("iris")); assert!(map.contains_key("argus")); }