docs: fix stale wake caveat, add <parent> sentinel + systemd path gotcha

turn-loop.md:
- remove stale "Agent-only today" note from hive wake (fixed by #698)
- add <parent> sentinel to send tool description (added by #703)

gotchas.md:
- add systemd.services.*.path /bin auto-append gotcha (hit by #672/#705)
This commit is contained in:
lexis 2026-05-31 11:42:38 +02:00 committed by Mara
commit 31288ae760
2 changed files with 27 additions and 3 deletions

View file

@ -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.<unit>.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

View file

@ -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: "<parent>"` 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