fix(issue-45): MAM herdr servers start with restore-on-restart off; resume closes its own restored empty shell (v4.8.5) #48
No files matched your search
+15
-1
@@ -230,6 +230,18 @@ except Exception:
|
|||||||
# identity to its sub-agents. Drop only per-session runtime markers - user
|
# identity to its sub-agents. Drop only per-session runtime markers - user
|
||||||
# configuration such as CLAUDE_PROJECT_DIR or CLAUDE_CONFIG_DIR still
|
# configuration such as CLAUDE_PROJECT_DIR or CLAUDE_CONFIG_DIR still
|
||||||
# inherits. The family ids mirror what orc_onboard.sh auto-detects.
|
# inherits. The family ids mirror what orc_onboard.sh auto-detects.
|
||||||
|
#
|
||||||
|
# ISSUE-45: the server restores its saved layout on start and would
|
||||||
|
# relaunch every saved agent with herdr's own resume command (no permission
|
||||||
|
# flags, deleted agents included). It gets HERDR_CONFIG_PATH = the user's
|
||||||
|
# herdr config with [session] resume_agents_on_restore = false, rebuilt on
|
||||||
|
# every start (lib_py/herdr_config.py). Without that file the server still
|
||||||
|
# starts - with restore on, as before.
|
||||||
|
MAM_SERVER_CFG=$(python3 -m lib_py.herdr_config server-config --fallback-dir "$_SHIM_DIR/.." || true)
|
||||||
|
export MAM_SERVER_CFG
|
||||||
|
if [ -z "$MAM_SERVER_CFG" ]; then
|
||||||
|
echo "WARNING: restore-on-restart stays enabled for herdr session $_MAM_SESSION (no server config)" >&2
|
||||||
|
fi
|
||||||
_mam_server_pid=$(python3 -c '
|
_mam_server_pid=$(python3 -c '
|
||||||
import os, subprocess, sys
|
import os, subprocess, sys
|
||||||
deny = ("CLAUDECODE", "CLAUDE_CODE_CHILD_SESSION", "CLAUDE_CODE_SESSION_ID",
|
deny = ("CLAUDECODE", "CLAUDE_CODE_CHILD_SESSION", "CLAUDE_CODE_SESSION_ID",
|
||||||
@@ -237,8 +249,10 @@ deny = ("CLAUDECODE", "CLAUDE_CODE_CHILD_SESSION", "CLAUDE_CODE_SESSION_ID",
|
|||||||
"CLAUDE_CODE_MESSAGING_TOKEN", "CLAUDE_CODE_MESSAGING_SOCKET",
|
"CLAUDE_CODE_MESSAGING_TOKEN", "CLAUDE_CODE_MESSAGING_SOCKET",
|
||||||
"CLAUDE_CODE_BRIDGE_SESSION_ID",
|
"CLAUDE_CODE_BRIDGE_SESSION_ID",
|
||||||
"ANTIGRAVITY_CONVERSATION_ID", "HERMES_SESSION_ID", "GROK_SESSION_ID",
|
"ANTIGRAVITY_CONVERSATION_ID", "HERMES_SESSION_ID", "GROK_SESSION_ID",
|
||||||
"OPENCODE_SESSION_ID")
|
"OPENCODE_SESSION_ID", "MAM_SERVER_CFG")
|
||||||
env = {k: v for k, v in os.environ.items() if k not in deny}
|
env = {k: v for k, v in os.environ.items() if k not in deny}
|
||||||
|
if os.environ.get("MAM_SERVER_CFG"):
|
||||||
|
env["HERDR_CONFIG_PATH"] = os.environ["MAM_SERVER_CFG"]
|
||||||
p = subprocess.Popen(sys.argv[1:], start_new_session=True, env=env,
|
p = subprocess.Popen(sys.argv[1:], start_new_session=True, env=env,
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||||
stdin=subprocess.DEVNULL)
|
stdin=subprocess.DEVNULL)
|
||||||
|
|||||||
@@ -236,6 +236,11 @@ def mam_sandbox(tmp_path, monkeypatch, request):
|
|||||||
monkeypatch.delenv("HERDR_SESSION_NAME", raising=False)
|
monkeypatch.delenv("HERDR_SESSION_NAME", raising=False)
|
||||||
monkeypatch.delenv("HERDR_SERVER_NAME", raising=False)
|
monkeypatch.delenv("HERDR_SERVER_NAME", raising=False)
|
||||||
monkeypatch.delenv("HERDR_WORKSPACE_ID", raising=False)
|
monkeypatch.delenv("HERDR_WORKSPACE_ID", raising=False)
|
||||||
|
# Issue #45: the shim bootstrap writes a herdr server config next to the
|
||||||
|
# user's; with these unset that is $HOME/.config/herdr, inside the sandbox.
|
||||||
|
# Every pane of a MAM server inherits HERDR_CONFIG_PATH.
|
||||||
|
monkeypatch.delenv("HERDR_CONFIG_PATH", raising=False)
|
||||||
|
monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
|
||||||
import sys
|
import sys
|
||||||
monkeypatch.setenv("AGENT_PYTHON_BIN", sys.executable)
|
monkeypatch.setenv("AGENT_PYTHON_BIN", sys.executable)
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,27 @@ def test_bootstrap_strips_agent_runtime_markers(mam_sandbox):
|
|||||||
assert key in server_env
|
assert key in server_env
|
||||||
|
|
||||||
|
|
||||||
|
def test_bootstrap_hands_the_server_a_no_restore_config(mam_sandbox):
|
||||||
|
"""Issue #45: the server starts with HERDR_CONFIG_PATH = the user's herdr
|
||||||
|
config plus [session] resume_agents_on_restore = false (that herdr obeys it
|
||||||
|
is test_issue45_restore.py, on a real server)."""
|
||||||
|
import tomllib
|
||||||
|
env = _install_fake_herdr(mam_sandbox)
|
||||||
|
user_cfg = mam_sandbox / ".config" / "herdr" / "config.toml"
|
||||||
|
user_cfg.parent.mkdir(parents=True)
|
||||||
|
user_cfg.write_text("[ui]\nconfirm_close = false\n")
|
||||||
|
|
||||||
|
res = _run_through_shim(mam_sandbox, env, "issue45-probe")
|
||||||
|
assert res.returncode == 0, res.stderr
|
||||||
|
assert "restore-on-restart stays enabled" not in res.stderr, res.stderr
|
||||||
|
|
||||||
|
server_env = json.loads(Path(env["FAKE_HERDR_ENV_DUMP"]).read_text())
|
||||||
|
assert server_env.get("HERDR_CONFIG_PATH") == str(user_cfg.parent / "mam-server-config.toml")
|
||||||
|
assert "MAM_SERVER_CFG" not in server_env
|
||||||
|
cfg = tomllib.loads(Path(server_env["HERDR_CONFIG_PATH"]).read_text())
|
||||||
|
assert cfg == {"ui": {"confirm_close": False}, "session": {"resume_agents_on_restore": False}}
|
||||||
|
|
||||||
|
|
||||||
def test_no_autostart_skips_bootstrap_but_still_routes_the_call(mam_sandbox):
|
def test_no_autostart_skips_bootstrap_but_still_routes_the_call(mam_sandbox):
|
||||||
env = _install_fake_herdr(mam_sandbox)
|
env = _install_fake_herdr(mam_sandbox)
|
||||||
env["MAM_NO_AUTOSTART"] = "1"
|
env["MAM_NO_AUTOSTART"] = "1"
|
||||||
|
|||||||
Reference in new issue
Block a user