test(issue-21): h25 pins the revised env contract - with env flags the idle pane is skipped and the env rides on the pane-creation call

Review N1 (planner-reviewer-claude-01 50ae9fb0, planner-reviewer-codex-01
8779f4b4): af8a54c (R1) stopped reusing an idle pane when env flags are
present, because the old path put `env K=V ...` after `herdr agent start ...
--`, where herdr passes it to the agent executable as arguments. h25 still
required that old behaviour (idle pane reused, env in the agent command) and
failed. It now asserts the new contract instead: a pane split / workspace
create carries MY_TEST_FLAG=active and HERDR_WORKSPACE_ID as --env, the agent
does not land on the idle pane, and nothing env-like follows `--` in agent
start. Finding A's intent (env must not be silently lost) is kept; reuse
without env flags stays pinned by h24. No product code changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017R3Eg7MEpSWnm1oB9ZPP6G
This commit is contained in:
GodopuandClaude Opus 5 committed 2026-09-14 05:45:12 +00:00
1 parent af8a54c028
commit 13259edb06
1 file changed
+22 -14
+22 -14
View File
@@ -516,10 +516,13 @@ def test_h24_new_session_reuses_idle_pane_without_split(mam_sandbox, mock_herdr,
assert not split_calls, f"Expected no pane split call when an idle pane was available: {split_calls}" assert not split_calls, f"Expected no pane split call when an idle pane was available: {split_calls}"
def test_h25_new_session_idle_pane_preserves_env_and_ws_id(mam_sandbox, mock_herdr, mock_agents): def test_h25_new_session_with_env_flags_skips_the_idle_pane_and_uses_env_on_split(mam_sandbox, mock_herdr, mock_agents):
"""Finding A: when an idle pane is reused, caller-provided KEY=VAL environment """Finding A, revised for Issue #21 R1: caller-provided KEY=VAL environment
flags (and HERDR_WORKSPACE_ID) must be prepended via env to final_cmd so they flags (and HERDR_WORKSPACE_ID) must not be silently lost - and must not be
are not silently lost when pane split / workspace create is bypassed.""" put after `agent start --` either, because herdr passes those tokens to the
agent executable (--kind) as arguments. With env flags an idle pane is not
reused; the env rides on the pane-creation call (pane split / workspace
create --env). Reuse without env flags stays covered by h24."""
tmp_path = mam_sandbox tmp_path = mam_sandbox
state = _load_mock_state(mock_herdr) state = _load_mock_state(mock_herdr)
state["panes"] = [{ state["panes"] = [{
@@ -538,17 +541,22 @@ def test_h25_new_session_idle_pane_preserves_env_and_ws_id(mam_sandbox, mock_her
assert res.returncode == 0, f"Stderr: {res.stderr}\nStdout: {res.stdout}" assert res.returncode == 0, f"Stderr: {res.stderr}\nStdout: {res.stdout}"
final_state = _load_mock_state(mock_herdr) final_state = _load_mock_state(mock_herdr)
agents = final_state.get("agents", {}) # the shim may prefix `--session <name>`; compare the subcommands themselves
matched = [d for n, d in agents.items() if "test-creator-claude" in n] new_calls = [c[2:] if c[:1] == ["--session"] else c for c in final_state.get("calls", [])[n_calls:]]
assert matched, agents creates = [c for c in new_calls if c[:2] in (["pane", "split"], ["workspace", "create"])]
assert matched[0].get("pane_id") == "w1:p_idle" assert creates, f"expected a pane split / workspace create carrying the env: {new_calls}"
cmd = matched[0].get("command", "") env_vals = [c[i + 1] for c in creates for i, t in enumerate(c[:-1]) if t == "--env"]
assert "MY_TEST_FLAG=active" in cmd, f"Expected MY_TEST_FLAG=active in agent command: {cmd}" assert "MY_TEST_FLAG=active" in env_vals and "HERDR_WORKSPACE_ID=w1" in env_vals, env_vals
assert "HERDR_WORKSPACE_ID=w1" in cmd, f"Expected HERDR_WORKSPACE_ID=w1 in agent command: {cmd}"
new_calls = final_state.get("calls", [])[n_calls:] matched = [d for n, d in final_state.get("agents", {}).items() if "test-creator-claude" in n]
split_calls = [c for c in new_calls if len(c) >= 2 and c[0] == "pane" and c[1] == "split"] assert matched and matched[0].get("pane_id") != "w1:p_idle", matched
assert not split_calls, f"Expected no pane split call when an idle pane was available: {split_calls}"
starts = [c for c in new_calls if c[:2] == ["agent", "start"]]
assert starts, new_calls
for c in starts:
args = c[c.index("--") + 1:] if "--" in c else []
assert "env" not in args, args
assert not any(a.startswith(("MY_TEST_FLAG=", "HERDR_WORKSPACE_ID=")) for a in args), args
def test_h26_daemon_spawn_uses_process_group_detachment(mam_sandbox, mock_herdr, mock_agents): def test_h26_daemon_spawn_uses_process_group_detachment(mam_sandbox, mock_herdr, mock_agents):