From e8d39ecb8b147d69a3fef7a24d1c1f0e0d9dd7ce Mon Sep 17 00:00:00 2001 From: damocles Date: Tue, 16 Jun 2026 12:36:48 +0200 Subject: [PATCH] hive-sh4re: make harness_dir the single resolver; hive-ag3nt delegates (#1450) --- hive-ag3nt/src/paths.rs | 13 ++++++------- hive-sh4re/src/paths.rs | 21 ++++++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/hive-ag3nt/src/paths.rs b/hive-ag3nt/src/paths.rs index 62c466f9..9535c7a5 100644 --- a/hive-ag3nt/src/paths.rs +++ b/hive-ag3nt/src/paths.rs @@ -30,15 +30,14 @@ pub fn state_dir() -> PathBuf { /// Harness-internal state directory. Holds files the harness owns /// (`hyperhive-events.sqlite`, `hyperhive-turn-stats.sqlite`, /// `hyperhive-model`) so they do not appear inside the agent-visible -/// `/agents/{label}/state` tree. Reads `HYPERHIVE_HARNESS_DIR` first; -/// falls back to `/agents/{label}/harness` derived from `HIVE_LABEL`. +/// `/agents/{label}/state` tree. Delegates to the shared canonical +/// resolver in `hive_sh4re::paths` so the harness + every out-of-process +/// MCP daemon resolve this identically (reads `HYPERHIVE_HARNESS_DIR`, +/// then a `harness/` sibling of `HYPERHIVE_STATE_DIR`, then +/// `/agents/{HIVE_LABEL}/harness`). #[must_use] pub fn harness_dir() -> PathBuf { - if let Some(p) = std::env::var_os("HYPERHIVE_HARNESS_DIR") { - return PathBuf::from(p); - } - let label = std::env::var("HIVE_LABEL").unwrap_or_default(); - PathBuf::from(format!("/agents/{label}/harness")) + hive_sh4re::paths::harness_dir() } /// Per-turn config dir for the regenerated claude-{mcp-config,settings, diff --git a/hive-sh4re/src/paths.rs b/hive-sh4re/src/paths.rs index f19b3ef4..1da656d1 100644 --- a/hive-sh4re/src/paths.rs +++ b/hive-sh4re/src/paths.rs @@ -11,18 +11,25 @@ use std::path::PathBuf; /// Base harness directory for the current agent. Uses `HYPERHIVE_HARNESS_DIR` /// if set (injected by the hive-c0re meta flake after the harness/state -/// split); falls back to a `harness/` sibling of `HYPERHIVE_STATE_DIR` for -/// pre-split / dev deployments. +/// split). For pre-split / dev deployments where it isn't set, falls back to +/// a `harness/` sibling of `HYPERHIVE_STATE_DIR`, and finally to +/// `/agents/{HIVE_LABEL}/harness` when neither dir env var is present — the +/// shape the harness derives from its label alone. The label tier subsumes +/// the resolver `hive-ag3nt` previously kept as its own copy, so the +/// resolution now genuinely lives here exactly once. #[must_use] pub fn harness_dir() -> PathBuf { if let Some(p) = std::env::var_os("HYPERHIVE_HARNESS_DIR") { return PathBuf::from(p); } - let state = std::env::var("HYPERHIVE_STATE_DIR").unwrap_or_default(); - let state_path = PathBuf::from(&state); - state_path - .parent() - .map_or_else(|| PathBuf::from(state), |p| p.join("harness")) + if let Some(state) = std::env::var_os("HYPERHIVE_STATE_DIR") { + let state_path = PathBuf::from(&state); + if let Some(parent) = state_path.parent() { + return parent.join("harness"); + } + } + let label = std::env::var("HIVE_LABEL").unwrap_or_default(); + PathBuf::from(format!("/agents/{label}/harness")) } /// Directory where out-of-process MCP daemons write loose-end summary