test(issue-20): record and drop the ambient control-plane binding before collection; per-test default registry and audit-log roots

pytest_configure records WORKSPACE_ROOT, AGENT_SESSIONS_YAML, MAM_JOBS_DIR and DELEGATE_JOB_LOGS_DIR and drops the last three, plus WORKSPACE_ROOT when it names another checkout: a worktree creator's pane carries all four at the live main checkout, and each wins over a test's own WORKSPACE_ROOT. It runs before collection because test_orc_onboard copies os.environ at import. Every test then defaults MAM_JOBS_DIR and DELEGATE_JOB_LOGS_DIR to tmp_path/.mam-test-state; mam_sandbox and a test's own monkeypatch still override.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sdga4A8i1iSc8DaaW9iKU2
This commit is contained in:
GodopuandClaude Opus 5 committed 2026-09-15 02:02:51 +00:00
1 parent b1e313be04
commit 3433ffdc41
1 file changed
+59
+59
View File
@@ -109,6 +109,65 @@ def _pid_alive(pid):
return bool(state) and not state.startswith("Z") return bool(state) and not state.startswith("Z")
# ==============================================================================
# Issue #20: test state stays out of every real control plane.
#
# An agent pane can carry a control-plane binding: a worktree creator's pane
# gets WORKSPACE_ROOT, AGENT_SESSIONS_YAML, MAM_JOBS_DIR and
# DELEGATE_JOB_LOGS_DIR pointing at the live main checkout (create/resume
# forward the row's control_plane), and each of them wins over a test's own
# WORKSPACE_ROOT (mqtt_common.default_registry_dir/get_logs_dir, lib.sh's
# AGENT_SESSIONS_YAML). pytest_configure records the binding and drops it
# before collection - a session fixture is too late for a module that copies
# os.environ at import (test_orc_onboard.SCRUBBED_ENV). WORKSPACE_ROOT is
# dropped only when it names another checkout; naming this one, it is what
# lib.sh derives anyway. Every test then defaults to a registry and an
# audit-log root under its own tmp_path, and a session guard (next to the #19
# one) reports new entries in the recorded control planes.
# ==============================================================================
_REPO_ROOT = Path(__file__).resolve().parent.parent
_BINDING_VARS = ("WORKSPACE_ROOT", "AGENT_SESSIONS_YAML", "MAM_JOBS_DIR", "DELEGATE_JOB_LOGS_DIR")
_RECORDED_BINDING = {}
_DROPPED_BINDING = pytest.StashKey[dict]()
def pytest_configure(config):
_RECORDED_BINDING.clear()
_RECORDED_BINDING.update({k: os.environ[k] for k in _BINDING_VARS if os.environ.get(k)})
dropped = {k: os.environ.pop(k) for k in ("AGENT_SESSIONS_YAML", "MAM_JOBS_DIR", "DELEGATE_JOB_LOGS_DIR")
if k in os.environ}
ws = os.environ.get("WORKSPACE_ROOT")
if ws and os.path.realpath(ws) != str(_REPO_ROOT):
dropped["WORKSPACE_ROOT"] = os.environ.pop("WORKSPACE_ROOT")
config.stash[_DROPPED_BINDING] = dropped
def pytest_unconfigure(config):
# Back for callers that run pytest.main() in-process.
os.environ.update(config.stash.get(_DROPPED_BINDING, {}))
@pytest.fixture(scope="session")
def _ambient_control_plane():
"""The binding pytest_configure recorded (and dropped), as a copy."""
return dict(_RECORDED_BINDING)
@pytest.fixture(autouse=True)
def _isolate_mam_state_dirs(_ambient_control_plane, tmp_path, monkeypatch):
"""Default registry and audit-log roots under this test's tmp_path; only
the env is set, nothing is created. mam_sandbox and a test's own
setenv/delenv run after this autouse fixture and win, and the shared
function-scope monkeypatch undoes them in LIFO order. A hidden directory,
so tests that use tmp_path/"jobs" as their own registry or list tmp_path
are unaffected. Takes _ambient_control_plane to state the order, not to
rely on it."""
state = tmp_path / ".mam-test-state"
monkeypatch.setenv("MAM_JOBS_DIR", str(state / "jobs"))
monkeypatch.setenv("DELEGATE_JOB_LOGS_DIR", str(state / "delegate_job_logs"))
@pytest.fixture @pytest.fixture
def mam_sandbox(tmp_path, monkeypatch, request): def mam_sandbox(tmp_path, monkeypatch, request):
""" """