Align conftest mock herdr and unit test assertions with Claude's simplified session-based isolation and native herdr command updates

This commit is contained in:
2026-07-20 07:42:05 +09:00
parent cccc30a8ac
commit 6df4b03661
13 changed files with 312 additions and 115 deletions
+27 -12
View File
@@ -66,6 +66,8 @@ When running multiple agent sessions alongside other workflows (e.g., cmux, Kanb
To prevent this, you can run this skill inside an **isolated herdr server** using the `HERDR_SERVER_NAME` environment variable or the `--herdr-server <name>` flag (opt-in).
Under the hood this now maps to a real, separate herdr **session** (`herdr --session <name>` — its own socket, its own `agent list`/`workspace list`, completely invisible to the default session and vice versa), not just a workspace label inside the same server. `lib.sh`'s shim bootstraps the named session's server headlessly (`herdr --session <name> server`, backgrounded) the first time it's needed, and scopes every subsequent herdr call to it automatically — this headless bootstrap is what lets it work even when the skill itself is running from inside another herdr-managed pane (a plain interactive `herdr --session <name>` launch is blocked there by herdr's "nested herdr is disabled" guard; headless `server` mode isn't).
### How to use
1. **Via Environment Variable**:
```bash
@@ -95,8 +97,9 @@ tmc ls # Lists only your multi-agent sessions
```
### Safety Rules (Pitfall 29 Summary)
- Never use global server termination commands like `herdr kill-server` or `herdr kill-session -a` as they will destroy all sessions on that server (including your own workspace sessions if they share the server).
- By using an isolated server via `HERDR_SERVER_NAME`, your agent sessions are completely separated from your default user workspace, ensuring 0% interference.
- Never use global server termination commands like `herdr server stop` as they will destroy every workspace/agent on that server (including your own workspace sessions if they share the server). (`kill-server`/`kill-session -a` are tmux-era names that don't exist in herdr's real CLI — see Pitfalls below.)
- By using an isolated server via `HERDR_SERVER_NAME`, your agent sessions are completely separated from your default user workspace, ensuring 0% interference — this is now backed by a genuinely separate `herdr` session/socket, not merely a workspace label.
- To deliberately tear down an *entire* isolated group at once (all its workspaces and agents), use `herdr session stop <HERDR_SERVER_NAME>` followed by `herdr session delete <HERDR_SERVER_NAME>` — this only affects that named session, never the default one.
## Workflow
@@ -137,7 +140,9 @@ sleep 6
PANE_PID=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_pid}')
PANE_CWD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_path}')
PANE_CMD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_command}')
HERDR_EPOCH=$(herdr list-sessions -F '#{session_created}' -t "$SESSION_NAME" 2>/dev/null | head -1)
# `herdr list-sessions` doesn't exist (real or shimmed) — we just spawned this
# session ourselves, so stamp the epoch locally instead of round-tripping herdr.
HERDR_EPOCH=$(date +%s)
```
## Registering the session in agent-sessions.yaml
@@ -162,9 +167,13 @@ After spawn, append a new `herdr_sessions[]` entry to `.mam/agent-sessions.yaml`
plan: <from TUI status>
account: <from TUI status>
version: <from TUI status>
start_command: <the exact herdr new-session command used>
attach_command: "herdr attach -t <SESSION_NAME>"
kill_command: "herdr kill-session -t <SESSION_NAME>"
start_command: "HERDR_SERVER_NAME=<herdr_server> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
attach_command: "HERDR_SERVER_NAME=<herdr_server> herdr agent attach <SESSION_NAME>"
kill_command: "HERDR_SERVER_NAME=<herdr_server> herdr kill-session -t <SESSION_NAME>"
# All three require `source .agents/skills/lib.sh` first — `new-session`/`kill-session`
# are tmux-compat pseudo-commands the shim translates, and `HERDR_SERVER_NAME` is what
# the shim reads to route to the right isolated herdr *session* (real `herdr` has no
# env-var-based scoping of its own; `herdr_server: default` needs no prefix at all).
```
`cmd_full` per agent (this is the actual command line in the pane, not the resume command):
@@ -196,11 +205,15 @@ The script handles the YAML append, pane capture, and the `last_visible_status`
After spawn + YAML append:
```bash
# 1. herdr session is alive
herdr has-session -t "$SESSION_NAME" && echo OK || echo MISSING
# 1. herdr session is alive (real native command — no lib.sh needed)
herdr agent get "$SESSION_NAME" >/dev/null 2>&1 && echo OK || echo MISSING
# 2. pane has the expected cmd + cwd
herdr list-panes -t "$SESSION_NAME" -F 'cmd=#{pane_current_command} cwd=#{pane_current_path}'
herdr agent get "$SESSION_NAME" | python3 -c "
import sys, json
a = json.load(sys.stdin)['result']['agent']
print(f\"cmd={a['agent']} cwd={a['cwd']}\")
"
# 3. agent-sessions.yaml has the new entry
python3 -c "
@@ -211,13 +224,15 @@ assert '$SESSION_NAME' in names, 'session not registered'
print('OK:', names)
"
# 4. Optional: check the TUI status via capture-pane
herdr capture-pane -t "$SESSION_NAME" -p -S -20 # TUI ready = agent banner visible, no dialog text
# 4. Optional: check the TUI status (real native command)
herdr agent read "$SESSION_NAME" --source visible --lines 20 # TUI ready = agent banner visible, no dialog text
```
> `herdr has-session` / `herdr list-panes` / `herdr capture-pane` above are tmux-compat pseudo-commands only understood after `source .agents/skills/lib.sh` (see `Workflow`) — the real `herdr` binary has no such subcommands. The block above uses the real `herdr agent get`/`herdr agent read` equivalents so it also works standalone.
## When NOT to use this skill
- **Resuming an old conversation** → `multi-agent-mux-resume`
- **Killing an existing session** → `multi-agent-mux-stop`
- **Just attaching to an existing session** → `herdr attach -t <name>` (no skill needed)
- **Just attaching to an existing session** → `herdr agent attach <name>` (no skill needed)
- **One-shot print mode (claude -p "...")** → no herdr needed; use `claude-code` skill's print mode