import os import sys import json import sqlite3 import subprocess import shutil import pytest from pathlib import Path REPO_ROOT = Path(__file__).parent.parent LIB_SH = REPO_ROOT / ".agents" / "skills" / "lib.sh" ONBOARD_SH = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-orc-onboard" / "scripts" / "orc_onboard.sh" RECONCILE_SH = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-monitor" / "scripts" / "reconcile.sh" SCRUBBED_ENV = dict(os.environ) for k in ["CLAUDE_CODE_SESSION_ID", "ANTIGRAVITY_CONVERSATION_ID", "HERMES_SESSION_ID", "CLINE_SESSION_ID", "MAM_ORCHESTRATOR_UUIDS"]: SCRUBBED_ENV.pop(k, None) SCRUBBED_ENV["PYTHONPATH"] = f"{LIB_SH.parent}:{SCRUBBED_ENV.get('PYTHONPATH', '')}" def run_onboard(args, env=None, cwd=None): run_env = dict(SCRUBBED_ENV) if cwd: run_env["AGENT_SESSIONS_YAML"] = f"{cwd}/.mam/agent-sessions.yaml" run_env["YAML_PATH"] = f"{cwd}/.mam/agent-sessions.yaml" run_env["HOME_DIR"] = cwd if env: run_env.update(env) cmd = ["bash", str(ONBOARD_SH)] + list(args) return subprocess.run(cmd, capture_output=True, text=True, env=run_env, cwd=cwd) def run_find_uuid(ws, agent, target="", env=None): run_env = dict(SCRUBBED_ENV) run_env["AGENT_SESSIONS_YAML"] = f"{ws}/.mam/agent-sessions.yaml" run_env["YAML_PATH"] = f"{ws}/.mam/agent-sessions.yaml" run_env["HOME_DIR"] = ws run_env["CLAUDE_PROJECT_DIR"] = f"{ws}/.claude/projects" if env: run_env.update(env) cmd = ["bash", "-c", f"source '{LIB_SH}' && find_workspace_uuid '{ws}' '{agent}' '{target}'"] res = subprocess.run(cmd, capture_output=True, text=True, env=run_env) return res.stdout.strip() def run_verify_uuid(ws, agent, uuid, row=None, mode="discover", env=None): run_env = dict(SCRUBBED_ENV) run_env["AGENT_SESSIONS_YAML"] = f"{ws}/.mam/agent-sessions.yaml" run_env["YAML_PATH"] = f"{ws}/.mam/agent-sessions.yaml" run_env["HOME_DIR"] = ws run_env["CLAUDE_PROJECT_DIR"] = f"{ws}/.claude/projects" if env: run_env.update(env) row_json = json.dumps(row) if row else "{}" cmd = ["bash", "-c", f"source '{LIB_SH}' && verify_session_uuid '{ws}' '{agent}' '{uuid}' '{row_json}' '{mode}'"] res = subprocess.run(cmd, capture_output=True, text=True, env=run_env) return res.returncode == 0 def dump_state(mam_sandbox, state): yaml_path = str(mam_sandbox / ".mam" / "agent-sessions.yaml") env = {"AGENT_SESSIONS_YAML": yaml_path, "YAML_PATH": yaml_path, "HOME_DIR": str(mam_sandbox)} state_str = json.dumps(state) cmd = f"source '{LIB_SH}' && atomic_dump_yaml '{yaml_path}' <<'PYEOF'\nd.update({state_str})\nPYEOF" subprocess.run(["bash", "-c", cmd], env={**SCRUBBED_ENV, **env}, check=True) return env def make_claude_transcript(mam_sandbox, uuid, target_dir=None): key = str(mam_sandbox.resolve()).replace("/", "-").replace("_", "-") if target_dir: c_dir = target_dir / "projects" / key else: c_dir = mam_sandbox / ".claude" / "projects" / key c_dir.mkdir(parents=True, exist_ok=True) t_file = c_dir / f"{uuid}.jsonl" t_file.write_text(f'{{"sessionId": "{uuid}", "cwd": "{mam_sandbox}"}}\n') return t_file # O-1: find_workspace_uuid excludes orchestrator UUID in discover mode def test_o1_find_workspace_uuid_excludes_orchestrator(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) state = { "orchestrator_uuids": [orc_uuid], "herdr_sessions": [] } env = dump_state(mam_sandbox, state) found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found != orc_uuid # O-2: find_workspace_uuid preserves target row own ID even if in orchestrator_uuids def test_o2_find_workspace_uuid_preserves_own_id(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) state = { "orchestrator_uuids": [orc_uuid], "herdr_sessions": [{ "name": "my-orc-session", "status": "running", "claude_session_id_own": orc_uuid, "pane": {"cwd": str(mam_sandbox)} }] } env = dump_state(mam_sandbox, state) found = run_find_uuid(str(mam_sandbox), "claude", target="my-orc-session", env=env) assert found == orc_uuid # O-3: Baseline non-orchestrator transcript is found def test_o3_find_workspace_uuid_finds_normal_subagent(mam_sandbox): sub_uuid = "02222222-2222-2222-2222-222222222222" make_claude_transcript(mam_sandbox, sub_uuid) env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found == sub_uuid # O-4: find_workspace_uuid without target excludes orchestrator_uuids def test_o4_find_workspace_uuid_without_target_excludes_orc(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) state = {"orchestrator_uuids": [orc_uuid], "herdr_sessions": []} env = dump_state(mam_sandbox, state) found = run_find_uuid(str(mam_sandbox), "claude", target="", env=env) assert found == "" # O-5: MAM_ORCHESTRATOR_UUIDS env var override def test_o5_env_override_orchestrator_uuids(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_ORCHESTRATOR_UUIDS": orc_uuid } found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found == "" # O-6: Empty MAM_ORCHESTRATOR_UUIDS disables gate def test_o6_empty_env_override_disables_gate(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) state = {"orchestrator_uuids": [orc_uuid], "herdr_sessions": []} env = dump_state(mam_sandbox, state) env["MAM_ORCHESTRATOR_UUIDS"] = "" found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found == orc_uuid # O-7: JSON array format in MAM_ORCHESTRATOR_UUIDS def test_o7_json_array_env_override(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_ORCHESTRATOR_UUIDS": f'["{orc_uuid}"]' } found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found == "" # O-8: verify_session_uuid in revalidate mode permits orchestrator_uuids for own row def test_o8_revalidate_mode_permits_orchestrator_uuid(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) row = { "name": "my-orc", "claude_session_id_own": orc_uuid, "pane": {"cwd": str(mam_sandbox)} } env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_ORCHESTRATOR_UUIDS": orc_uuid } assert run_verify_uuid(str(mam_sandbox), "claude", orc_uuid, row=row, mode="revalidate", env=env) # O-9: verify_session_uuid in discover mode blocks orchestrator_uuids for unowned row def test_o9_discover_mode_blocks_orchestrator_uuid(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" make_claude_transcript(mam_sandbox, orc_uuid) row = { "name": "subagent-session", "claude_session_id_own": None, "pane": {"cwd": str(mam_sandbox)} } env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_ORCHESTRATOR_UUIDS": orc_uuid } assert not run_verify_uuid(str(mam_sandbox), "claude", orc_uuid, row=row, mode="discover", env=env) # O-10: Baseline revalidate mode passes for non-orchestrator def test_o10_revalidate_normal_subagent(mam_sandbox): sub_uuid = "02222222-2222-2222-2222-222222222222" make_claude_transcript(mam_sandbox, sub_uuid) row = {"name": "subagent", "claude_session_id_own": sub_uuid, "pane": {"cwd": str(mam_sandbox)}} env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} assert run_verify_uuid(str(mam_sandbox), "claude", sub_uuid, row=row, mode="revalidate", env=env) # O-11: verify_session_uuid respects isolation root def test_o11_isolation_root_respected(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" iso_root = mam_sandbox / "iso" make_claude_transcript(mam_sandbox, orc_uuid, target_dir=iso_root) row = { "name": "my-orc", "claude_session_id_own": orc_uuid, "isolation": {"root": str(iso_root), "uuid": "iso-1"}, "pane": {"cwd": str(mam_sandbox)} } env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} assert run_verify_uuid(str(mam_sandbox), "claude", orc_uuid, row=row, mode="revalidate", env=env) # O-12: orc_onboard.sh --uuid explicitly adds UUID def test_o12_onboard_add_uuid(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} res = run_onboard(["--uuid", orc_uuid], env=env, cwd=str(mam_sandbox)) assert res.returncode == 0 assert "Successfully added" in res.stdout or "Successfully" in res.stdout # Verify list res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid in res_list.stdout # O-13: orc_onboard.sh --remove removes UUID def test_o13_onboard_remove_uuid(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} run_onboard(["--uuid", orc_uuid], env=env, cwd=str(mam_sandbox)) res = run_onboard(["--remove", orc_uuid], env=env, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid not in res_list.stdout # O-14: orc_onboard.sh --dry-run does not mutate state def test_o14_onboard_dry_run(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} res = run_onboard(["--uuid", orc_uuid, "--dry-run"], env=env, cwd=str(mam_sandbox)) assert res.returncode == 0 assert "[dry-run]" in res.stdout res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid not in res_list.stdout # O-15: orc_onboard.sh duplicate add is idempotent def test_o15_onboard_duplicate_add(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} run_onboard(["--uuid", orc_uuid], env=env, cwd=str(mam_sandbox)) res = run_onboard(["--uuid", orc_uuid], env=env, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert res_list.stdout.count(orc_uuid) == 1 # O-16: orc_onboard.sh rejects invalid UUID format (exit 2) def test_o16_onboard_invalid_uuid_rejected(mam_sandbox): env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} res = run_onboard(["--uuid", "not-a-valid-uuid"], env=env, cwd=str(mam_sandbox)) assert res.returncode == 2 # O-17: orc_onboard.sh rejects adding ID owned by a running session (exit 1) def test_o17_onboard_conflict_running_session(mam_sandbox): sub_uuid = "02222222-2222-2222-2222-222222222222" state = { "orchestrator_uuids": [], "herdr_sessions": [{ "name": "active-subagent", "status": "running", "claude_session_id_own": sub_uuid, "pane": {"cwd": str(mam_sandbox)} }] } env = dump_state(mam_sandbox, state) res = run_onboard(["--uuid", sub_uuid], env=env, cwd=str(mam_sandbox)) assert res.returncode == 1 # O-18: orc_onboard.sh autodetects via environment variable (CLAUDE_CODE_SESSION_ID) def test_o18_autodetect_via_env(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "CLAUDE_CODE_SESSION_ID": orc_uuid } # Run inside subshell where command line matches claude cmd = f"export CLAUDE_CODE_SESSION_ID='{orc_uuid}' && exec -a claude bash '{ONBOARD_SH}'" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid in res_list.stdout # O-19: orc_onboard.sh exit 3 when autodetect fails def test_o19_autodetect_failure_exits_3(mam_sandbox): env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_AUTODETECT_FORCE_FAIL": "1"} res = run_onboard([], env=env, cwd=str(mam_sandbox)) assert res.returncode == 3 # O-20: _validate fails on malformed orchestrator_uuids (not a list) def test_o20_validate_fails_on_non_list_orchestrator_uuids(mam_sandbox): state = {"orchestrator_uuids": "not-a-list", "herdr_sessions": []} env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "YAML_PATH": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} state_str = json.dumps(state) cmd = f"source '{LIB_SH}' && atomic_dump_yaml '{env['YAML_PATH']}' <<'PYEOF'\nd.update({state_str})\nPYEOF" res = subprocess.run(["bash", "-c", cmd], env={**SCRUBBED_ENV, **env}, capture_output=True, text=True) assert res.returncode != 0 assert "VALIDATE" in res.stderr or "VALIDATE" in res.stdout # O-21: _validate fails on duplicate orchestrator_uuids def test_o21_validate_fails_on_duplicate_orchestrator_uuids(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" state = {"orchestrator_uuids": [orc_uuid, orc_uuid], "herdr_sessions": []} env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "YAML_PATH": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} state_str = json.dumps(state) cmd = f"source '{LIB_SH}' && atomic_dump_yaml '{env['YAML_PATH']}' <<'PYEOF'\nd.update({state_str})\nPYEOF" res = subprocess.run(["bash", "-c", cmd], env={**SCRUBBED_ENV, **env}, capture_output=True, text=True) assert res.returncode != 0 # O-22: _validate fails on empty string in orchestrator_uuids def test_o22_validate_fails_on_empty_string_orchestrator_uuid(mam_sandbox): state = {"orchestrator_uuids": [""], "herdr_sessions": []} env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "YAML_PATH": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} state_str = json.dumps(state) cmd = f"source '{LIB_SH}' && atomic_dump_yaml '{env['YAML_PATH']}' <<'PYEOF'\nd.update({state_str})\nPYEOF" res = subprocess.run(["bash", "-c", cmd], env={**SCRUBBED_ENV, **env}, capture_output=True, text=True) assert res.returncode != 0 # O-23: get_all_sessions_status folds orchestrator_uuids into hash def test_o23_status_hash_includes_orchestrator_uuids(mam_sandbox): state1 = {"orchestrator_uuids": ["01eae7cf-1db6-4395-ba48-5fb02f4b6b1f"], "herdr_sessions": []} state2 = {"orchestrator_uuids": ["02222222-2222-2222-2222-222222222222"], "herdr_sessions": []} yaml_path = str(mam_sandbox / ".mam" / "agent-sessions.yaml") cmd = f"""source '{LIB_SH}' && atomic_dump_yaml '{yaml_path}' <<'PYEOF' import json, sys h1 = get_all_sessions_status({json.dumps(state1)}) h2 = get_all_sessions_status({json.dumps(state2)}) if h1 == h2: sys.exit(1) PYEOF """ res = subprocess.run(["bash", "-c", cmd], env={**SCRUBBED_ENV, "AGENT_SESSIONS_YAML": yaml_path, "YAML_PATH": yaml_path}, capture_output=True, text=True) assert res.returncode == 0 # O-24: Substring matching prevented in verify_session_uuid def test_o24_substring_matching_prevented(mam_sandbox): full_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" sub_str = "01eae7cf" make_claude_transcript(mam_sandbox, sub_str) row = {"name": "subagent", "claude_session_id_own": None, "pane": {"cwd": str(mam_sandbox)}} env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_ORCHESTRATOR_UUIDS": full_uuid } # sub_str is not full_uuid -> discover mode should NOT block sub_str assert run_verify_uuid(str(mam_sandbox), "claude", sub_str, row=row, mode="discover", env=env) # O-25: agy agent family orchestrator exclusion def test_o25_agy_orchestrator_exclusion(mam_sandbox): orc_uuid = "72d2d251-5a06-486b-92e5-7e46a7a80d2e" db_dir = mam_sandbox / ".gemini" / "antigravity-cli" / "conversations" db_dir.mkdir(parents=True, exist_ok=True) db_path = db_dir / f"{orc_uuid}.db" conn = sqlite3.connect(db_path) conn.execute("CREATE TABLE steps (id INT)") conn.execute("INSERT INTO steps VALUES (1)") conn.commit() conn.close() lc_path = mam_sandbox / ".gemini" / "antigravity-cli" / "cache" / "last_conversations.json" lc_path.parent.mkdir(parents=True, exist_ok=True) lc_path.write_text(json.dumps({str(mam_sandbox): orc_uuid})) state = {"orchestrator_uuids": [orc_uuid], "herdr_sessions": []} env = dump_state(mam_sandbox, state) found = run_find_uuid(str(mam_sandbox), "agy", env=env) assert found != orc_uuid # O-26: hermes agent family orchestrator exclusion def test_o26_hermes_orchestrator_exclusion(mam_sandbox): orc_uuid = "03333333-3333-3333-3333-333333333333" hdb_dir = mam_sandbox / ".hermes" hdb_dir.mkdir(parents=True, exist_ok=True) hdb_path = hdb_dir / "state.db" conn = sqlite3.connect(hdb_path) conn.execute("CREATE TABLE sessions (id TEXT, cwd TEXT, started_at TEXT)") conn.execute("INSERT INTO sessions VALUES (?, ?, ?)", (orc_uuid, str(mam_sandbox), "2026-08-12T00:00:00Z")) conn.commit() conn.close() state = {"orchestrator_uuids": [orc_uuid], "herdr_sessions": []} env = dump_state(mam_sandbox, state) row = {"name": "subagent", "hermes_conversation_id_own": None, "pane": {"cwd": str(mam_sandbox)}} assert not run_verify_uuid(str(mam_sandbox), "hermes", orc_uuid, row=row, mode="discover", env=env) # O-27: Ignore env variable belonging to a different agent family (Challenge fix) def test_o27_ignore_different_family_env_variable(mam_sandbox): # Under claude process ancestor, ANTIGRAVITY_CONVERSATION_ID should be ignored env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "ANTIGRAVITY_CONVERSATION_ID": "72d2d251-5a06-486b-92e5-7e46a7a80d2e" } cmd = f"export ANTIGRAVITY_CONVERSATION_ID='72d2d251-5a06-486b-92e5-7e46a7a80d2e' && exec -a claude bash '{ONBOARD_SH}'" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 3 # O-28: Use env variable when agent family matches def test_o28_use_family_matched_env_variable(mam_sandbox): orc_uuid = "72d2d251-5a06-486b-92e5-7e46a7a80d2e" env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "ANTIGRAVITY_CONVERSATION_ID": orc_uuid } cmd = f"export ANTIGRAVITY_CONVERSATION_ID='{orc_uuid}' && exec -a agy bash '{ONBOARD_SH}'" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid in res_list.stdout # O-29: Fresh claude session detected via CLAUDE_CODE_SESSION_ID def test_o29_fresh_claude_session_detection(mam_sandbox): orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "CLAUDE_CODE_SESSION_ID": orc_uuid } cmd = f"export CLAUDE_CODE_SESSION_ID='{orc_uuid}' && exec -a claude bash '{ONBOARD_SH}'" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert orc_uuid in res_list.stdout # O-30: argv takes precedence over env variable def test_o30_argv_precedes_env(mam_sandbox): argv_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" env_uuid = "02222222-2222-2222-2222-222222222222" env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "CLAUDE_CODE_SESSION_ID": env_uuid } cmd = f"export CLAUDE_CODE_SESSION_ID='{env_uuid}' && exec -a claude bash '{ONBOARD_SH}' --uuid {argv_uuid}" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert argv_uuid in res_list.stdout assert env_uuid not in res_list.stdout # O-31: cline node launcher & non-UUID ID format (1785635248957_fajon) def test_o31_cline_node_launcher_id_format(mam_sandbox): cline_id = "1785635248957_fajon" env = { "AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox) } cmd = f"exec -a 'cline --id {cline_id}' bash '{ONBOARD_SH}'" res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True, env={**SCRUBBED_ENV, **env}, cwd=str(mam_sandbox)) assert res.returncode == 0 res_list = run_onboard(["--list"], env=env, cwd=str(mam_sandbox)) assert cline_id in res_list.stdout # O-32: ID format strictness rejects invalid strings def test_o32_id_format_strictness(mam_sandbox): env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} for bad in ["../../etc/passwd", "a b", "fajon", "1785635248957"]: res = run_onboard(["--uuid", bad], env=env, cwd=str(mam_sandbox)) assert res.returncode == 2 # O-33: No workspace cache fallback (last_conversations.json excluded) def test_o33_no_workspace_cache_fallback(mam_sandbox): lc_path = mam_sandbox / ".gemini" / "antigravity-cli" / "cache" / "last_conversations.json" lc_path.parent.mkdir(parents=True, exist_ok=True) cached_uuid = "0f84dbf7-5ddf-4619-a813-7e1ae35be009" lc_path.write_text(json.dumps({str(mam_sandbox): cached_uuid})) env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox), "MAM_AUTODETECT_FORCE_FAIL": "1"} res = run_onboard([], env=env, cwd=str(mam_sandbox)) assert res.returncode == 3 # O-34: deploy/remove.sh fallback_assets contains multi-agent-mux-orc-onboard def test_o34_remove_sh_fallback_assets(): remove_sh = REPO_ROOT / "deploy" / "remove.sh" content = remove_sh.read_text() assert ".agents/skills/multi-agent-mux-orc-onboard" in content # O-35: deploy/gitea-ci.yml contains shellcheck line for orc_onboard.sh def test_o35_gitea_ci_shellcheck(): ci_file = REPO_ROOT / "deploy" / "gitea-ci.yml" content = ci_file.read_text() assert "shellcheck .agents/skills/multi-agent-mux-orc-onboard/scripts/orc_onboard.sh" in content # O-36: bash syntax check clean on orc_onboard.sh def test_o36_bash_syntax_clean(): res = subprocess.run(["bash", "-n", str(ONBOARD_SH)], capture_output=True) assert res.returncode == 0, res.stderr # O-37: SKILL.md file exists and has valid frontmatter def test_o37_skill_md_valid(): skill_md = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-orc-onboard" / "SKILL.md" assert skill_md.is_file() content = skill_md.read_text() assert "name: multi-agent-mux-orc-onboard" in content # O-38: atomic_dump_yaml handles empty orchestrator_uuids initialization def test_o38_atomic_dump_yaml_initialization(mam_sandbox): env = {"AGENT_SESSIONS_YAML": str(mam_sandbox / ".mam" / "agent-sessions.yaml"), "HOME_DIR": str(mam_sandbox)} orc_uuid = "01eae7cf-1db6-4395-ba48-5fb02f4b6b1f" res = run_onboard(["--uuid", orc_uuid], env=env, cwd=str(mam_sandbox)) assert res.returncode == 0 yaml_path = mam_sandbox / ".mam" / "agent-sessions.yaml" assert yaml_path.is_file() assert orc_uuid in yaml_path.read_text() # O-39: cline agent family discovery exclusion in verify_session_uuid def test_o39_cline_orchestrator_exclusion(mam_sandbox): cline_id = "1785635248957_fajon" c_dir = mam_sandbox / ".cline" / "data" / "sessions" / cline_id c_dir.mkdir(parents=True, exist_ok=True) (c_dir / f"{cline_id}.json").write_text(json.dumps({"session_id": cline_id})) state = {"orchestrator_uuids": [cline_id], "herdr_sessions": []} env = dump_state(mam_sandbox, state) row = {"name": "subagent", "cline_conversation_id_own": None, "pane": {"cwd": str(mam_sandbox)}} assert not run_verify_uuid(str(mam_sandbox), "cline", cline_id, row=row, mode="discover", env=env) # O-40: Malformed orchestrator_uuids logs warning to stderr and degrades gracefully def test_o40_malformed_orchestrator_uuids_degrades_open(mam_sandbox): sub_uuid = "02222222-2222-2222-2222-222222222222" make_claude_transcript(mam_sandbox, sub_uuid) yaml_path = mam_sandbox / ".mam" / "agent-sessions.yaml" yaml_path.parent.mkdir(parents=True, exist_ok=True) yaml_path.write_text("orchestrator_uuids: 12345\nherdr_sessions: []\n") env = {"AGENT_SESSIONS_YAML": str(yaml_path), "HOME_DIR": str(mam_sandbox)} found = run_find_uuid(str(mam_sandbox), "claude", env=env) assert found == sub_uuid