From 31288ae76079dbc0f640c9a938baa1c056cbca0b Mon Sep 17 00:00:00 2001 From: lexis Date: Sun, 31 May 2026 11:42:38 +0200 Subject: [PATCH] docs: fix stale wake caveat, add sentinel + systemd path gotcha turn-loop.md: - remove stale "Agent-only today" note from hive wake (fixed by #698) - add sentinel to send tool description (added by #703) gotchas.md: - add systemd.services.*.path /bin auto-append gotcha (hit by #672/#705) --- docs/gotchas.md | 22 ++++++++++++++++++++++ docs/turn-loop.md | 8 +++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/gotchas.md b/docs/gotchas.md index 5f13dce6..b7b2442e 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -39,6 +39,28 @@ claude's Bash tool without editing the service definition. `environment.HYPERHIVE_GIT` bakes git's absolute path in (read by `lifecycle::git_command()`) for the host. +## `systemd.services.*.path` appends `/bin` to every entry + +NixOS's `systemd.services..path` list feeds every entry through +`lib.makeBinPath`, which **appends `/bin` unconditionally**. That's +the right thing for Nix packages (their `outPath` is the store root, +not the `bin/` subdir), but it bites when you pass a string that +already ends with `/bin`: + +```nix +# ❌ /run/wrappers/bin → /run/wrappers/bin/bin (does not exist) +path = [ "/run/wrappers/bin" "/run/current-system/sw" ]; + +# ✅ /run/wrappers → /run/wrappers/bin (the real wrappers dir) +path = [ "/run/wrappers" "/run/current-system/sw" ]; +``` + +The bug is silent: `nix eval` succeeds, the unit starts, but PATH +contains a non-existent directory. The first symptom is usually +`sudo: must be owned by uid 0 and have the setuid bit set` because +the setuid sudo wrapper lives at `/run/wrappers/bin/sudo` and +the path entry resolves to `/run/wrappers/bin/bin` instead. + ## `RuntimeDirectoryPreserve = "yes"` …keeps `/run/hyperhive/` (and the per-agent sub-dirs) across diff --git a/docs/turn-loop.md b/docs/turn-loop.md index 6bfea1c1..3ad1ab2a 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -198,7 +198,10 @@ it as a stdio child via `--mcp-config`. The hyperhive socket name is - `send(to, body, in_reply_to?)` — message a peer (logical agent name), another agent, or the operator (recipient `operator`, - surfaces in the dashboard inbox). Optional `in_reply_to: i64` + surfaces in the dashboard inbox). Use `to: ""` to + address the agent's topology parent without knowing its label; + the broker resolves the sentinel at delivery time (falls back + to `operator` for root agents). Optional `in_reply_to: i64` links this message to a prior message id for thread rendering in the dashboard message flow and the per-agent inbox. - `recv(wait_seconds?, max?)` — drain inbox messages. Without @@ -269,8 +272,7 @@ socket at `/run/hive/mcp.sock`. Two equivalent paths: (use `--body -` to read body from stdin). Already on the container's `PATH` since the harness binary is in `systemPackages`. Convenient for shell-script integrations. - Agent-only today (refused when `HIVE_ROLE=manager`); see - [#693](http://localhost:3000/hyperhive/hyperhive/issues/693). + Works for both `agent` and `manager` roles. - **Speak the wire protocol directly** — JSON-line over the unix socket: `{"cmd":"wake","from":"matrix","body":"new dm