From 3433ffdc419aa87190ffe06a45cb48ac9051276b Mon Sep 17 00:00:00 2001 From: Godopu Date: Tue, 15 Sep 2026 02:02:51 +0000 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_01Sdga4A8i1iSc8DaaW9iKU2 --- tests/conftest.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 32587ad..25e6531 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -109,6 +109,65 @@ def _pid_alive(pid): 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 def mam_sandbox(tmp_path, monkeypatch, request): """