README: drop the PATH note — the fix belongs in the host config, not the docs

Operator: rather than documenting the workaround, notplants-nix should put the system profile on
the agent PATH. It already does (two orchestrator units export it); the gap is that the change is
committed and not yet deployed. The /proc rewrite in agents.py stands on its own — harness code
should not depend on an external tool for something the kernel exposes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3LdmEL7CvCYTNpoBq1kce
This commit is contained in:
2026-08-21 03:52:39 +00:00
co-authored by Claude Fable 5
parent e185cec88c
commit fe9d98fad3
-49
View File
@@ -480,55 +480,6 @@ The agent CLIs themselves (`claude`, `opencode`) are **external, non-Nix tools**
per their own docs and make sure they are on `PATH` before launching live agents. The devShell
documents this in its banner.
### PATH on a NixOS host: why a tool that IS installed says "command not found"
**An agent's `PATH` does not include the system profile.** On `notplants-orchestrator` the agent
shell gets a pinned list of individual store paths (bash, git, python, coreutils, findutils, grep,
sed, systemd, tmux, openssh, net-tools) and **not** `/run/current-system/sw/bin`. Everything the
host declares in `environment.systemPackages` therefore exists and is unreachable.
Measured 2026-08-21: `ps`, `pgrep`, `free`, `cmp`, `awk`, `curl`, `diff`, `strings`, `nm`, `getent`
and `ping` were ALL installed (notplants-nix `hosts/notplants-orchestrator/configuration.nix`,
"give agents a real toolbox") and all reported `command not found`.
**Why this is worse than an inconvenience.** A missing binary run through `shell=True` returns
**rc=127 with empty stdout**, and empty stdout is indistinguishable from a real answer of "none":
- `agents.py` shelled out to `pgrep -P` to find a pane's child processes. With `pgrep` unreachable
it returned *no children*, so `_build_running` was **always False** and the stall detector could
reboot an agent in the middle of a build. It shipped that way and no test caught it, because the
unit tests **mocked `pgrep`** — the fake stood in for the broken dependency.
- The same session read an empty `ps` as "0 agent processes running", and an empty `strings` as
proof that a binary had its features stripped.
**Check before concluding a tool is absent:**
```bash
ls /run/current-system/sw/bin/<tool> # installed but unreachable?
command -v <tool> # reachable?
```
**Put the system profile on PATH** (appended, so the sandbox's pinned store paths keep priority):
```bash
case ":$PATH:" in *":/run/current-system/sw/bin:"*) ;;
*) export PATH="$PATH:/run/current-system/sw/bin" ;; esac
```
For something genuinely not installed, fetch it without changing the host:
```bash
nix shell nixpkgs#tcpdump -c tcpdump ... # one command, nothing persisted
nix run nixpkgs#git-filter-repo -- --help
```
`nix` itself may also be off `PATH`; it lives at `/nix/var/nix/profiles/default/bin/nix`.
**Rule for harness code: do not shell out for something the kernel already exposes.** `agents.py`
now reads `/proc/<pid>/stat` and `/proc/<pid>/comm` directly instead of calling `pgrep` and `ps`.
That has no PATH dependency and cannot fail silently in the direction that matters. If you must
call an external tool, check the return code — never treat empty output as an answer.
---
## Testing