Review loop (--review-only, --all-reviewer): round 1 (@325b056) 4/4 PASS,
round 2 (@db7f4ca, HERDR_SESSION) 4/4 PASS. Full suite at 325b056 on
macOS / Python 3.9 / bash 3.2 / herdr 0.9.3 from an agent pane:
1845 passed / 0 failed / 56 skipped (18 test_deploy_freshness skips: no
nats-docker submodule in the fresh worktree); the panes of the real
servers (default, multi-agent-mux) and ~/.claude/projects were unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
4.0 KiB
Review 9cd9b3f0 — the sandbox also drops HERDR_SESSION
Head db7f4cab9c60ff5db009cf3fc625e9a86a465ef6 (tree f32cabd3a6c8d775c9223509967f1a810f0cf827) is the one commit db7f4ca test(sandbox): mam_sandbox also drops HERDR_SESSION on base 325b056057fcdd717d2c81017fc5ef57183cb4d0. Two files, +5/−1. git diff --check is clean. Snapshot porcelain empty. Control-plane main is still 8b0b4a07dc76a4915895bdde6170dc8eed9b5f74, porcelain empty.
mam_sandbox deletes HERDR_SESSION next to HERDR_SOCKET_PATH (tests/conftest.py:298-299). L2's pane model now includes HERDR_SESSION=real (tests/test_herdr_real_server_leak.py:73-76) and asserts that name is gone with the others (:86-88).
What the variable does inside a sandbox
The herdr binary treats HERDR_SESSION as a session name: the string beside it is session name cannot be empty. A named session's socket is $HOME/.config/herdr/sessions/<name>/herdr.sock. mam_sandbox sets HOME to the sandbox, so that name resolves inside the sandbox. The route that reached the caller's real server was HERDR_SOCKET_PATH, which the previous commit already deletes.
_herdr_caller_server (lib.sh:1424-1427), pane_lock.caller_server (lib_py/pane_lock.py:44-50), and watcher.caller_server (lib_py/loop/watcher.py:50-66) return HERDR_SESSION whenever it is set, ahead of the socket. A test run inside a pane therefore took the in-pane branch, and the same test outside a pane took the other. Dropping the variable makes those helpers see a process outside a pane unless the test supplies the name itself.
Tests that supply the name
No test calls monkeypatch.setenv("HERDR_SESSION"). The tests that need a value build the child environment themselves:
tests/test_issue23_24_startup_path.py_run_lib(:36-40) popsHERDR_SESSIONfrom the inherited environment and then applies the dict the test passes.test_s1gpassesHERDR_SESSION=from-herdrand expectscaller=from-herdr.tests/test_issue34_job_tree.py_run_lib(:590-591) drops everyHERDR_*name and then appliesSAME_SERVER_PANE, which containsHERDR_SESSION=multi-agent-mux.tests/test_issue50_pane_lock.pypasses an explicit mapping intolock_pathand into thepane_lock pathsubprocess.test_p1bbuilds that subprocess environment from the keys that do not start withHERDR_, then adds the socket it wants.
A direct call of mam_sandbox with HERDR_SESSION=probe-session left the name unset. A setenv after that call left HERDR_SESSION=set-by-test. The fixture setup runs before the test body, so a test that sets the name for itself keeps it. The one setenv of a HERDR_ name in a test body is HERDR_SERVER_NAME in tests/test_tier3_integration.py:31, and that line runs after the fixture.
What the sandbox still leaves
HERDR_ENV stays. In this pane its value is 1. The binary's text says Requires HERDR_ENV=1 beside the inception check, so this is a feature flag. HERDR_BIN_PATH stays, and its value names the herdr binary. HERDR_CLIENT_SOCKET_PATH sits beside HERDR_SOCKET_PATH in the binary's pane-export cluster. This process does not have that name, and the sandbox does not delete it.
What was run
Control-plane venv, Python 3.9.6, pytest 8.4.2, PYTHONDONTWRITEBYTECODE=1, -p no:cacheprovider, --basetemp=/tmp/m9cdbt. Inherited HERDR_SOCKET_PATH, HERDR_PANE_ID, HERDR_TAB_ID, HERDR_WORKSPACE_ID, HERDR_SESSION_NAME, HERDR_SESSION, HERDR_SERVER_NAME, HERDR_CONFIG_PATH, HERDR_ENV, HERDR_BIN_PATH, WORKSPACE_ROOT, MAM_ENV_FILE, HOME_DIR, CLAUDE_PROJECT_DIR, and CODEX_HOME were unset. The real herdr binary was not run.
tests/test_herdr_real_server_leak.py, tests/test_issue23_24_startup_path.py, and tests/test_issue50_pane_lock.py: 84 passed in 195.84s. That is the same 84 the orchestrator reported. The session guards on that run completed. The #55 agent-home guard did not fire.
User ~/.config/herdr/config.toml mtime stayed 1784456394. Snapshot porcelain stayed empty after the run.
[VERDICT: PASS]