This commit is contained in:
2026-08-24 08:11:59 -07:00
commit 53df0eed10
275 changed files with 133056 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
from __future__ import annotations
import contextlib
import os
import tempfile
from collections.abc import Mapping
from pathlib import Path
from typing import Any
from unittest import mock
ROOT = Path(__file__).resolve().parents[1]
FAKE_CODEX = ROOT / "tests" / "helpers" / "fake_codex.py"
FAKE_SWITCHYARD = ROOT / "tests" / "helpers" / "fake_switchyard.py"
def root_thread_binding(thread_id: str | None) -> dict[str, object]:
"""Return one internally consistent root-thread lineage for state-fixture tests."""
if thread_id is None:
return {
"root_thread_id": None,
"root_thread_generation": 0,
"root_thread_lineage": [],
"root_thread_transition": None,
}
return {
"root_thread_id": thread_id,
"root_thread_generation": 1,
"root_thread_lineage": [
{
"generation": 1,
"thread_id": thread_id,
"codex_session_id": thread_id,
"adopted_at": "2000-01-01T00:00:00+00:00",
"reason": "test_fixture",
}
],
"root_thread_transition": None,
}
def create_access_lab_session(
*, cwd: Path, profile: str | Path = "access-efficient-escalation-lab"
) -> dict[str, Any]:
"""Create the local-first fixture without depending on a host llama.cpp process."""
import mmo_runtime
real_availability = mmo_runtime.route_availability
def available_local_route(snapshot: Mapping[str, Any]) -> dict[str, dict[str, Any]]:
availability = real_availability(snapshot)
availability["llama_cpp_local_openai_chat"] = {
"available": True,
"selected_credential_env": None,
"reason": None,
}
return availability
with mock.patch.object(
mmo_runtime,
"route_availability",
side_effect=available_local_route,
):
return mmo_runtime.create_session(profile=profile, cwd=cwd)
class RuntimeSandbox:
def __init__(self) -> None:
self.temp = tempfile.TemporaryDirectory(prefix="codex-mmo-test-")
self.root = Path(self.temp.name)
self.config = self.root / "config with spaces"
self.state = self.root / "state with spaces"
self.runtime = self.root / "runtime with spaces"
self.workspace = self.root / "workspace with spaces"
self.base_codex_home = self.root / "base codex home"
self.old_env: dict[str, str | None] = {}
def __enter__(self) -> RuntimeSandbox:
for path in (
self.config,
self.state,
self.runtime,
self.workspace,
self.base_codex_home,
):
path.mkdir(parents=True, exist_ok=True)
self.old_env = {
key: os.environ.get(key)
for key in (
"MMO_INSTALL_ROOT",
"MMO_CONFIG_ROOT",
"MMO_STATE_ROOT",
"XDG_RUNTIME_DIR",
"MMO_CODEX_BIN",
"ZAI_CODING_API_KEY",
"OPENCODE_API_KEY",
"OPENROUTER_API_KEY",
"OPENAI_API_KEY",
"FIRECRAWL_API_KEY",
"IDA_MCP_TOKEN",
"CODEX_HOME",
)
}
os.environ.update(
{
"MMO_INSTALL_ROOT": str(ROOT),
"MMO_CONFIG_ROOT": str(self.config),
"MMO_STATE_ROOT": str(self.state),
"XDG_RUNTIME_DIR": str(self.runtime),
"MMO_CODEX_BIN": str(FAKE_CODEX),
"ZAI_CODING_API_KEY": "fake-zai-coding",
"OPENCODE_API_KEY": "fake-opencode",
"OPENROUTER_API_KEY": "fake-openrouter",
"OPENAI_API_KEY": "fake-openai",
}
)
(self.config / "profiles.d").mkdir()
(self.config / "catalog.d").mkdir()
(self.config / "tool-mcp.d").mkdir()
settings = (ROOT / "config" / "settings.toml").read_text(encoding="utf-8")
settings = settings.replace(
'base_codex_home = "~/.codex"', f"base_codex_home = {self.base_codex_home.as_posix()!r}"
)
# TOML accepts JSON-style double quoted paths, not Python repr single quotes.
settings = settings.replace(
f"base_codex_home = '{self.base_codex_home.as_posix()}'",
f'base_codex_home = "{self.base_codex_home.as_posix()}"',
)
settings = settings.replace(
'switchyard_bin = "switchyard-server"',
f'switchyard_bin = "{FAKE_SWITCHYARD.as_posix()}"',
)
settings = settings.replace(
"gateway_start_timeout_seconds = 15", "gateway_start_timeout_seconds = 5"
)
settings = settings.replace(
"gateway_idle_timeout_seconds = 3600", "gateway_idle_timeout_seconds = 1"
)
(self.config / "settings.toml").write_text(settings, encoding="utf-8")
(self.config / "credentials.env").write_text(
"ZAI_CODING_API_KEY=fake-zai-coding\nOPENCODE_API_KEY=fake-opencode\n"
"OPENROUTER_API_KEY=fake-openrouter\nOPENAI_API_KEY=fake-openai\n",
encoding="utf-8",
)
(self.base_codex_home / "auth.json").write_text('{"fake":true}\n', encoding="utf-8")
return self
def __exit__(self, *_exc: object) -> None:
with contextlib.suppress(Exception):
from mmo_runtime import cancel_session, iter_sessions
for session in iter_sessions(strict=False):
with contextlib.suppress(Exception):
cancel_session(str(session["session_id"]))
with contextlib.suppress(Exception):
from mmo_gateway import list_gateways, stop_gateway
for gateway in list_gateways():
stop_gateway(str(gateway["snapshot_hash"]))
for key, value in self.old_env.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
self.temp.cleanup()
def init_git(self) -> None:
import subprocess
subprocess.run(["git", "init", "-q", str(self.workspace)], check=True)
subprocess.run(
["git", "-C", str(self.workspace), "config", "user.email", "test@example.invalid"],
check=True,
)
subprocess.run(
["git", "-C", str(self.workspace), "config", "user.name", "MMO Test"], check=True
)
(self.workspace / "README.md").write_text("fixture\n", encoding="utf-8")
subprocess.run(["git", "-C", str(self.workspace), "add", "."], check=True)
subprocess.run(["git", "-C", str(self.workspace), "commit", "-qm", "fixture"], check=True)
+1426
View File
File diff suppressed because it is too large Load Diff
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
"""Small Switchyard-compatible health/models stand-in for integration tests."""
from __future__ import annotations
import argparse
import json
import signal
import tomllib
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
def route_ids(path: Path) -> list[str]:
with path.open("rb") as handle:
data = tomllib.load(handle)
return [str(value["id"]) for value in data.get("routes", {}).values()]
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--version", action="version", version="switchyard-server 0.2.0")
parser.add_argument("--config", type=Path, required=True)
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=4000)
parser.add_argument("--routing-log-file")
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()
models = route_ids(args.config)
if args.dry_run:
print(json.dumps({"valid": True, "routes": models}))
return 0
class Handler(BaseHTTPRequestHandler):
def log_message(self, _format: str, *_args: object) -> None:
return
def respond(self, status: int, value: object) -> None:
body = json.dumps(value).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self) -> None: # noqa: N802
if self.path == "/health":
self.respond(200, {"status": "ok"})
elif self.path in {"/v1/models", "/models"}:
self.respond(
200,
{
"object": "list",
"data": [{"id": item, "object": "model"} for item in models],
},
)
else:
self.respond(404, {"error": "not found"})
server = ThreadingHTTPServer((args.host, args.port), Handler)
def stop(_signum: int, _frame: object) -> None:
raise KeyboardInterrupt
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGINT, stop)
try:
server.serve_forever(poll_interval=0.1)
except KeyboardInterrupt:
pass
finally:
server.server_close()
return 0
if __name__ == "__main__":
raise SystemExit(main())
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
"""Enter an allocated pseudo-terminal and invoke the real MMO TUI launcher."""
from __future__ import annotations
import fcntl
import json
import os
import sys
import termios
from mmo_runtime import launch_interactive
def main() -> int:
try:
# Popen(start_new_session=True) made this process a session leader. The
# slave PTY descriptors were inherited, so explicitly claim the terminal
# before MMO performs normal foreground process-group handoff.
fcntl.ioctl(sys.stdin.fileno(), termios.TIOCSCTTY, 0)
os.tcsetpgrp(sys.stdin.fileno(), os.getpgrp())
initial = termios.tcgetattr(sys.stdin.fileno())
exit_code = launch_interactive(profile=sys.argv[1], cwd=sys.argv[2])
restored = termios.tcgetattr(sys.stdin.fileno())
print(
json.dumps(
{
"event": "launcher_returned",
"exit_code": exit_code,
"echo_enabled": bool(restored[3] & termios.ECHO),
"attributes_restored": restored == initial,
"pgrp": os.getpgrp(),
"foreground_pgrp": os.tcgetpgrp(sys.stdin.fileno()),
},
sort_keys=True,
),
flush=True,
)
return exit_code
except BaseException as exc:
print(json.dumps({"event": "launcher_error", "error": repr(exc)}), flush=True)
return 97
if __name__ == "__main__":
raise SystemExit(main())
File diff suppressed because it is too large Load Diff
+322
View File
@@ -0,0 +1,322 @@
from __future__ import annotations
import argparse
import io
import json
import os
import unittest
from pathlib import Path
from unittest import mock
import mmo_cli_output
import mmoctl
import scripts.install as install_script
class TTYBuffer(io.StringIO):
def isatty(self) -> bool:
return True
class UnreadableTTY(TTYBuffer):
def read(self, *_args: object, **_kwargs: object) -> str:
raise AssertionError("interactive stdin must not be read implicitly")
def parser_tree(
root: argparse.ArgumentParser,
) -> list[tuple[tuple[str, ...], argparse.ArgumentParser]]:
found: list[tuple[tuple[str, ...], argparse.ArgumentParser]] = []
pending: list[tuple[tuple[str, ...], argparse.ArgumentParser]] = [((), root)]
while pending:
path, parser = pending.pop()
found.append((path, parser))
for action in parser._actions:
if isinstance(action, argparse._SubParsersAction):
pending.extend(((*path, name), child) for name, child in action.choices.items())
return found
class CLIUXTests(unittest.TestCase):
def test_complete_command_surface_has_descriptions_and_option_help(self) -> None:
parsers = parser_tree(mmoctl._parser())
self.assertEqual(len(parsers), 69)
for path, parser in parsers:
with self.subTest(command=" ".join(path) or "root"):
self.assertTrue(parser.description)
help_text = parser.format_help()
self.assertIn("usage:", help_text)
self.assertNotIn("\x1b[", help_text)
for action in parser._actions:
if isinstance(action, (argparse._HelpAction, argparse._SubParsersAction)):
continue
self.assertNotIn(action.help, (None, "", argparse.SUPPRESS))
def test_entrypoint_routing_has_one_source_of_truth(self) -> None:
parser = mmoctl._parser(prog="codex-mmo")
self.assertEqual(mmoctl._route_argv(parser, [], implicit_run=True), ["run"])
self.assertEqual(
mmoctl._route_argv(parser, ["profile", "list"], implicit_run=True),
["profile", "list"],
)
self.assertEqual(
mmoctl._route_argv(parser, ["profile", "list", "--json"], implicit_run=True),
["--json", "profile", "list"],
)
self.assertEqual(
mmoctl._route_argv(parser, ["--quiet", "--", "--search"], implicit_run=True),
["--quiet", "run", "--", "--search"],
)
self.assertEqual(
mmoctl._route_argv(parser, ["run", "--", "--json"], implicit_run=True),
["run", "--", "--json"],
)
def test_usage_errors_are_local_actionable_and_machine_readable(self) -> None:
stdout = io.StringIO()
stderr = io.StringIO()
with mock.patch("sys.stdout", stdout), mock.patch("sys.stderr", stderr):
status = mmoctl.main(["session", "list", "--limt", "1"])
self.assertEqual(status, 2)
self.assertEqual(stdout.getvalue(), "")
self.assertIn("usage: codex-mmoctl session list", stderr.getvalue())
self.assertIn("Did you mean '--limit'?", stderr.getvalue())
stdout = io.StringIO()
stderr = io.StringIO()
with mock.patch("sys.stdout", stdout), mock.patch("sys.stderr", stderr):
status = mmoctl.main(["session", "list", "--limt", "1", "--json"])
self.assertEqual(status, 2)
self.assertEqual(stdout.getvalue(), "")
error = json.loads(stderr.getvalue())
self.assertEqual(error["error_type"], "usage")
self.assertIn("--limit", error["hint"])
def test_cross_option_errors_fail_before_runtime_initialization(self) -> None:
cases = (
(["resume"], "exactly one"),
(["resume", "session-id", "--last"], "exactly one"),
(["resume", "session-id", "--all"], "only with --last"),
(["doctor", "--probe"], "requires --live"),
(["eval", "compare", "one-run"], "at least two"),
(
["catalog", "refresh", "--no-codex", "--install-codex-overlay"],
"cannot be combined",
),
(
[
"catalog",
"refresh",
"--no-remote",
"--openrouter-url",
"https://example.invalid/models",
],
"cannot be combined",
),
(
["catalog", "refresh", "--no-codex", "--codex-bin", "/bin/false"],
"cannot be combined",
),
(["catalog", "discover", "codex", "--timeout", "2"], "not valid"),
(
[
"catalog",
"discover",
"opencode-go",
"--url",
"https://one.invalid/models",
"--opencode-url",
"https://two.invalid/models",
],
"not both",
),
(
["catalog", "discover", "openrouter", "--codex-bin", "/bin/false"],
"not valid",
),
(["run", "--json"], "not supported"),
)
for argv, expected in cases:
with self.subTest(argv=argv):
stderr = io.StringIO()
with mock.patch("sys.stdout", io.StringIO()), mock.patch("sys.stderr", stderr):
status = mmoctl.main(argv)
self.assertEqual(status, 2)
self.assertIn(expected, stderr.getvalue())
def test_exec_never_blocks_for_an_implicit_interactive_prompt(self) -> None:
stderr = io.StringIO()
with (
mock.patch("sys.stdin", UnreadableTTY()),
mock.patch("sys.stdout", io.StringIO()),
mock.patch("sys.stderr", stderr),
):
status = mmoctl.main(["exec"])
self.assertEqual(status, 2)
self.assertIn("requires PROMPT or piped stdin", stderr.getvalue())
stdout = io.StringIO()
with (
mock.patch("sys.stdin", io.StringIO("inspect this\n")),
mock.patch("sys.stdout", stdout),
mock.patch("sys.stderr", io.StringIO()),
mock.patch(
"mmoctl.run_root_exec",
return_value={"exit_code": 0, "result": "complete"},
) as execute,
):
status = mmoctl.main(["exec", "--profile", "fixture"])
self.assertEqual(status, 0)
self.assertEqual(stdout.getvalue(), "complete\n")
self.assertEqual(execute.call_args.kwargs["prompt"], "inspect this\n")
def test_structured_output_is_human_on_tty_and_json_in_pipelines(self) -> None:
session_id = "20260823-120000-reverse-engineering-0123456789"
sessions = [
{
"session_id": session_id,
"status": "paused",
"profile_id": "reverse-engineering",
"session_kind": "interactive",
"last_active_at": "2026-08-23T12:00:00+00:00",
"resumable": True,
}
]
human = TTYBuffer()
with mock.patch("sys.stdout", human), mock.patch.dict(os.environ, {"COLUMNS": "50"}):
mmo_cli_output.emit_structured("session.list", sessions)
self.assertIn(session_id, human.getvalue())
self.assertIn("Status: paused", human.getvalue())
self.assertNotIn("\x1b[", human.getvalue())
machine = io.StringIO()
with mock.patch("sys.stdout", machine):
mmo_cli_output.emit_structured("session.list", sessions)
self.assertEqual(json.loads(machine.getvalue()), sessions)
forced = TTYBuffer()
with mock.patch("sys.stdout", forced):
mmo_cli_output.emit_structured("session.list", sessions, force_json=True)
self.assertEqual(json.loads(forced.getvalue()), sessions)
def test_human_empty_states_are_unambiguous(self) -> None:
output = TTYBuffer()
with mock.patch("sys.stdout", output):
mmo_cli_output.emit_structured("jobs.list", [])
self.assertEqual(output.getvalue(), "No jobs found.\n")
def test_catalog_tables_show_domain_fields_instead_of_empty_generic_columns(self) -> None:
resources = {
"chatgpt_subscription": {
"max_active": 4,
"lock_key": "provider:chatgpt",
"description": "Built-in ChatGPT account concurrency",
}
}
output = TTYBuffer()
with mock.patch("sys.stdout", output), mock.patch.dict(os.environ, {"COLUMNS": "120"}):
mmo_cli_output.emit_structured("catalog.resources", resources)
rendered = output.getvalue()
self.assertIn("CAPACITY", rendered)
self.assertIn("provider:chatgpt", rendered)
self.assertIn("Built-in ChatGPT", rendered)
def test_progress_uses_only_interactive_stderr_and_honors_quiet(self) -> None:
stdout = TTYBuffer()
stderr = TTYBuffer()
with mock.patch("sys.stdout", stdout), mock.patch("sys.stderr", stderr):
mmo_cli_output.progress("Checking profile...")
self.assertEqual(stdout.getvalue(), "")
self.assertEqual(stderr.getvalue(), "Checking profile...\n")
quiet = TTYBuffer()
with mock.patch("sys.stderr", quiet):
mmo_cli_output.progress("Checking profile...", quiet=True)
self.assertEqual(quiet.getvalue(), "")
redirected = io.StringIO()
with mock.patch("sys.stderr", redirected):
mmo_cli_output.progress("Checking profile...")
self.assertEqual(redirected.getvalue(), "")
def test_runtime_errors_never_pollute_structured_stdout(self) -> None:
stdout = io.StringIO()
stderr = io.StringIO()
with (
mock.patch("sys.stdout", stdout),
mock.patch("sys.stderr", stderr),
mock.patch("mmoctl._handle_catalog", side_effect=RuntimeError("provider failed")),
):
status = mmoctl.main(["catalog", "summary", "--json"])
self.assertEqual(status, 1)
self.assertEqual(stdout.getvalue(), "")
error = json.loads(stderr.getvalue())
self.assertEqual(error["error_type"], "runtime")
self.assertEqual(error["error"], "provider failed")
def test_scalar_commands_offer_explicit_json_without_changing_text_mode(self) -> None:
stdout = io.StringIO()
with (
mock.patch("sys.stdout", stdout),
mock.patch("mmoctl.active_profile_id", return_value="reverse-engineering"),
):
self.assertEqual(mmoctl.main(["profile", "current"]), 0)
self.assertEqual(stdout.getvalue(), "reverse-engineering\n")
stdout = io.StringIO()
with (
mock.patch("sys.stdout", stdout),
mock.patch("mmoctl.active_profile_id", return_value="reverse-engineering"),
):
self.assertEqual(mmoctl.main(["profile", "current", "--json"]), 0)
self.assertEqual(json.loads(stdout.getvalue()), {"profile_id": "reverse-engineering"})
def test_clean_reports_scope_and_preserves_dry_run_semantics(self) -> None:
stdout = io.StringIO()
with (
mock.patch("sys.stdout", stdout),
mock.patch(
"mmoctl.load_settings",
return_value={"job_retention_days": 30, "session_retention_days": 90},
),
mock.patch(
"mmoctl.clean_state", return_value={"jobs_removed": 4, "sessions_removed": 2}
) as clean,
):
self.assertEqual(mmoctl.main(["clean", "--dry-run"]), 0)
clean.assert_called_once_with(job_days=30, session_days=90, dry_run=True)
self.assertEqual(
json.loads(stdout.getvalue()),
{
"dry_run": True,
"job_days": 30,
"jobs_removed": 4,
"session_days": 90,
"sessions_removed": 2,
},
)
def test_generated_wrappers_delegate_all_routing_to_the_python_cli(self) -> None:
entrypoint = Path("/tmp/codex mmo/mmoctl.py")
primary = install_script.main_wrapper(Path("/usr/bin/python3"), entrypoint)
control = install_script.wrapper(
Path("/usr/bin/python3"),
entrypoint,
environment={"MMO_CLI_ENTRYPOINT": "codex-mmoctl"},
)
self.assertIn("export MMO_CLI_ENTRYPOINT=codex-mmo", primary)
self.assertIn("export MMO_CLI_ENTRYPOINT=codex-mmoctl", control)
self.assertNotIn("case ", primary)
self.assertIn("'$@'".replace("'", '"'), primary)
def test_installer_help_is_descriptive_and_color_free(self) -> None:
help_text = install_script.parser().format_help()
self.assertIn("atomically replace", help_text)
self.assertIn("--install-root", help_text)
self.assertIn("--debug", help_text)
self.assertNotIn("\x1b[", help_text)
if __name__ == "__main__":
unittest.main()
File diff suppressed because it is too large Load Diff
+428
View File
@@ -0,0 +1,428 @@
from __future__ import annotations
import copy
import json
import os
import stat
import subprocess
import sys
import tarfile
import tempfile
import unittest
import zipfile
from pathlib import Path
from unittest import mock
from common import ROOT as PACKAGE_ROOT
from scripts import build_release
from scripts.verify_release import _strict_json_loads as release_strict_json_loads
VERSION = (PACKAGE_ROOT / "VERSION").read_text(encoding="utf-8").strip()
PACKAGE_NAME = f"codex-multimodel-orchestrator-{VERSION}"
class ReleaseIntegrityTests(unittest.TestCase):
def test_release_manifest_json_rejects_ambiguous_members_and_invalid_unicode(self) -> None:
for payload in (
'{"schema_version": 2, "schema_version": 1}',
'{"path": "\\ud800"}',
'{"size": 1e400}',
):
with self.subTest(payload=payload), self.assertRaises(ValueError):
release_strict_json_loads(payload)
def test_archive_set_publication_rolls_back_as_a_unit(self) -> None:
with tempfile.TemporaryDirectory(prefix="mmo-release-publish-") as temporary_raw:
root = Path(temporary_raw)
source_paths = tuple(root / f"source-{index}" for index in range(4))
final_paths = tuple(root / f"final-{index}" for index in range(4))
for index, path in enumerate(source_paths):
path.write_bytes(f"new {index}".encode())
for index, path in enumerate(final_paths):
path.write_bytes(f"old {index}".encode())
real_replace = os.replace
def fail_metadata_publish(
source: str | os.PathLike[str], destination: str | os.PathLike[str]
) -> None:
source_path = Path(source)
destination_path = Path(destination)
if destination_path == final_paths[2] and ".publish-" in source_path.name:
raise OSError("synthetic metadata publication failure")
real_replace(source, destination)
with mock.patch.object(build_release.os, "replace", side_effect=fail_metadata_publish):
with self.assertRaisesRegex(OSError, "metadata publication"):
build_release._publish_artifacts(
tuple(zip(source_paths, final_paths, strict=True))
)
for index, path in enumerate(final_paths):
self.assertEqual(path.read_bytes(), f"old {index}".encode())
self.assertFalse(any(path.name.startswith(".final") for path in root.iterdir()))
symlink_target = root / "symlink-target"
symlink_target.write_bytes(b"must remain untouched")
symlink_destination = root / "symlink-destination"
symlink_destination.symlink_to(symlink_target)
with self.assertRaisesRegex(RuntimeError, "non-regular release artifact"):
build_release._publish_artifacts(((source_paths[0], symlink_destination),))
self.assertTrue(symlink_destination.is_symlink())
self.assertEqual(symlink_target.read_bytes(), b"must remain untouched")
def interrupt_final_verification() -> None:
raise KeyboardInterrupt
with self.assertRaises(KeyboardInterrupt):
build_release._publish_artifacts(
tuple(zip(source_paths, final_paths, strict=True)),
verify=interrupt_final_verification,
)
for index, path in enumerate(final_paths):
self.assertEqual(path.read_bytes(), f"old {index}".encode())
def fail_publish_and_restore(
source: str | os.PathLike[str], destination: str | os.PathLike[str]
) -> None:
source_path = Path(source)
destination_path = Path(destination)
if destination_path == final_paths[2] and ".publish-" in source_path.name:
raise OSError("synthetic publication failure")
if destination_path == final_paths[0] and ".backup-" in source_path.name:
raise OSError("synthetic restoration failure")
real_replace(source, destination)
with mock.patch.object(
build_release.os,
"replace",
side_effect=fail_publish_and_restore,
):
with self.assertRaisesRegex(RuntimeError, "rollback was incomplete"):
build_release._publish_artifacts(
tuple(zip(source_paths, final_paths, strict=True))
)
retained = list(root.glob(".final-0.backup-*"))
self.assertEqual(len(retained), 1)
self.assertEqual(retained[0].read_bytes(), b"old 0")
final_paths[0].write_bytes(retained[0].read_bytes())
retained[0].unlink()
def fail_final_verification() -> None:
raise RuntimeError("synthetic final verification failure")
with self.assertRaisesRegex(RuntimeError, "final verification"):
build_release._publish_artifacts(
tuple(zip(source_paths, final_paths, strict=True)),
verify=fail_final_verification,
)
for index, path in enumerate(final_paths):
self.assertEqual(path.read_bytes(), f"old {index}".encode())
self.assertFalse(any(path.name.startswith(".final") for path in root.iterdir()))
def test_release_builder_publishes_complete_verified_archives(self) -> None:
with tempfile.TemporaryDirectory(prefix="mmo-release-test-") as temporary_raw:
output = Path(temporary_raw)
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "build_release.py"),
"--output-dir",
str(output),
"--skip-validation",
"--no-reproducibility-check",
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=120,
)
self.assertEqual(result.returncode, 0, result.stderr or result.stdout)
tar_path = output / f"{PACKAGE_NAME}-linux.tar.gz"
zip_path = output / f"{PACKAGE_NAME}-linux.zip"
integrity_path = output / f"{PACKAGE_NAME}-INTEGRITY.json"
for path in (tar_path, zip_path, integrity_path):
self.assertTrue(path.is_file(), path)
self.assertGreater(path.stat().st_size, 1_000)
verify = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "verify_release.py"),
"--source-tree",
str(PACKAGE_ROOT),
str(tar_path),
str(zip_path),
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=120,
)
self.assertEqual(verify.returncode, 0, verify.stderr or verify.stdout)
integrity = json.loads(integrity_path.read_text(encoding="utf-8"))
self.assertGreaterEqual(integrity["source_files"], 100)
self.assertEqual(len(integrity["archives"]), 2)
self.assertEqual(
{item["manifest_files"] for item in integrity["archives"]},
{integrity["source_files"]},
)
def test_builder_rejects_output_inside_source_tree(self) -> None:
output = PACKAGE_ROOT / ".forbidden-release-output"
self.assertFalse(output.exists())
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "build_release.py"),
"--output-dir",
str(output),
"--skip-validation",
"--no-reproducibility-check",
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=60,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("inside the source tree", result.stderr + result.stdout)
self.assertFalse(output.exists())
def test_release_verifier_rejects_tampering_and_wrong_root(self) -> None:
package = PACKAGE_NAME
with tempfile.TemporaryDirectory(prefix="mmo-release-tamper-") as temporary_raw:
output = Path(temporary_raw)
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "build_release.py"),
"--output-dir",
str(output),
"--skip-validation",
"--no-reproducibility-check",
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=120,
)
self.assertEqual(result.returncode, 0, result.stderr or result.stdout)
original = output / f"{package}-linux.zip"
tampered = output / "tampered.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(tampered, "w", compression=zipfile.ZIP_DEFLATED) as destination,
):
for info in source.infolist():
data = source.read(info.filename)
if info.filename == f"{package}/README.md":
data += b"\nTAMPERED\n"
destination.writestr(copy.copy(info), data)
wrong_root = output / "wrong-root.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(wrong_root, "w", compression=zipfile.ZIP_DEFLATED) as destination,
):
for info in source.infolist():
renamed = copy.copy(info)
renamed.filename = info.filename.replace(package, "wrong-package-root", 1)
destination.writestr(renamed, source.read(info.filename))
mode_drift = output / "mode-drift.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(mode_drift, "w", compression=zipfile.ZIP_DEFLATED) as destination,
):
for info in source.infolist():
changed = copy.copy(info)
if info.filename == f"{package}/README.md":
changed.external_attr = (stat.S_IFREG | 0o666) << 16
destination.writestr(changed, source.read(info.filename))
directory_mode_drift = output / "directory-mode-drift.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(
directory_mode_drift, "w", compression=zipfile.ZIP_DEFLATED
) as destination,
):
for info in source.infolist():
changed = copy.copy(info)
if info.filename == f"{package}/docs/":
changed.external_attr = (stat.S_IFDIR | 0o777) << 16
destination.writestr(changed, source.read(info.filename))
missing_directory = output / "missing-directory-entry.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(
missing_directory, "w", compression=zipfile.ZIP_DEFLATED
) as destination,
):
for info in source.infolist():
if info.filename != f"{package}/docs/":
destination.writestr(copy.copy(info), source.read(info.filename))
extra_directory = output / "extra-empty-directory.zip"
with (
zipfile.ZipFile(original) as source,
zipfile.ZipFile(
extra_directory, "w", compression=zipfile.ZIP_DEFLATED
) as destination,
):
for info in source.infolist():
destination.writestr(copy.copy(info), source.read(info.filename))
empty = zipfile.ZipInfo(f"{package}/unexpected-empty/")
empty.create_system = 3
empty.external_attr = (stat.S_IFDIR | 0o755) << 16
destination.writestr(empty, b"")
original_tar = output / f"{package}-linux.tar.gz"
tar_directory_mode_drift = output / "directory-mode-drift.tar.gz"
with (
tarfile.open(original_tar, "r:gz") as source,
tarfile.open(tar_directory_mode_drift, "w:gz") as destination,
):
for tar_info in source:
changed_tar = copy.copy(tar_info)
if tar_info.name == f"{package}/docs":
changed_tar.mode = 0o777
payload = source.extractfile(tar_info) if tar_info.isfile() else None
if payload is None:
destination.addfile(changed_tar)
else:
with payload:
destination.addfile(changed_tar, payload)
verify = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "verify_release.py"),
str(tampered),
str(wrong_root),
str(mode_drift),
str(directory_mode_drift),
str(missing_directory),
str(extra_directory),
str(tar_directory_mode_drift),
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=120,
)
self.assertNotEqual(verify.returncode, 0)
report = json.loads(verify.stdout)
self.assertEqual(len(report["errors"]), 7)
self.assertTrue(any("sha256" in item for item in report["errors"]))
self.assertTrue(any("top-level directory" in item for item in report["errors"]))
self.assertTrue(any("mode" in item for item in report["errors"]))
self.assertEqual(sum("invalid permission mode" in item for item in report["errors"]), 3)
self.assertEqual(sum("directory set differs" in item for item in report["errors"]), 2)
def test_release_verifier_rejects_path_traversal(self) -> None:
with tempfile.TemporaryDirectory(prefix="mmo-release-traversal-") as temporary_raw:
archive = Path(temporary_raw) / "traversal.zip"
with zipfile.ZipFile(archive, "w") as handle:
handle.writestr("../escape.txt", "bad")
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "verify_release.py"),
str(archive),
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=60,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("unsafe archive member path", result.stdout)
def test_release_verifier_rejects_canonical_path_aliases(self) -> None:
with tempfile.TemporaryDirectory(prefix="mmo-release-alias-") as temporary_raw:
archive = Path(temporary_raw) / "alias.zip"
with zipfile.ZipFile(archive, "w") as handle:
handle.writestr(f"{PACKAGE_NAME}/nested/file.txt", "first")
handle.writestr(f"{PACKAGE_NAME}/nested/./file.txt", "second")
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "verify_release.py"),
str(archive),
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=60,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("unsafe archive member path", result.stdout)
def test_builder_rejects_invalid_source_epoch(self) -> None:
with tempfile.TemporaryDirectory(prefix="mmo-release-epoch-") as temporary_raw:
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "build_release.py"),
"--output-dir",
temporary_raw,
"--source-date-epoch",
"-1",
"--skip-validation",
"--no-reproducibility-check",
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=60,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("source-date-epoch", result.stderr + result.stdout)
def test_one_file_archives_are_rejected(self) -> None:
package = PACKAGE_NAME
with tempfile.TemporaryDirectory(prefix="mmo-release-corrupt-") as temporary_raw:
temporary = Path(temporary_raw)
zip_path = temporary / "incomplete.zip"
tar_path = temporary / "incomplete.tar.gz"
payload = temporary / "PLAN-COVERAGE.md"
payload.write_text("incomplete\n", encoding="utf-8")
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as archive:
archive.write(payload, f"{package}/docs/PLAN-COVERAGE.md")
with tarfile.open(tar_path, "w:gz") as archive:
archive.add(payload, arcname=f"{package}/docs/PLAN-COVERAGE.md")
result = subprocess.run(
[
sys.executable,
str(PACKAGE_ROOT / "scripts" / "verify_release.py"),
str(zip_path),
str(tar_path),
],
cwd=PACKAGE_ROOT,
text=True,
capture_output=True,
check=False,
timeout=60,
)
self.assertNotEqual(result.returncode, 0)
report = json.loads(result.stdout)
self.assertFalse(report["passed"])
self.assertEqual(len(report["errors"]), 2)
self.assertTrue(
all("archive directory set differs" in item for item in report["errors"])
)
if __name__ == "__main__":
unittest.main()
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+306
View File
@@ -0,0 +1,306 @@
from __future__ import annotations
import fcntl
import json
import os
import pty
import select
import shutil
import struct
import subprocess
import sys
import termios
import time
import tomllib
import unittest
from pathlib import Path
from typing import Any
from unittest import mock
import mmo_codex_home
import mmo_runtime
from common import ROOT, RuntimeSandbox
from mmo_runtime import create_session, finish_session
from mmo_util import read_toml, toml_dumps
from mmo_version import MMO_SCHEMA_VERSION
class TuiAndModelMetadataTests(unittest.TestCase):
def _config(self, home: str) -> dict[str, Any]:
with (Path(home) / "config.toml").open("rb") as handle:
return tomllib.load(handle)
def _catalog(self, config: dict[str, Any]) -> dict[str, dict[str, Any]]:
path = Path(config["model_catalog_json"])
payload = json.loads(path.read_text(encoding="utf-8"))
return {item["slug"]: item for item in payload["models"]}
def test_switchyard_bindings_have_exact_codex_model_metadata(self) -> None:
expected: dict[str, dict[str, Any]] = {
"routine_engineer": {
"context_window": 1000000,
"default_reasoning_level": "high",
"apply_patch_tool_type": "freeform",
},
"literal_scout": {
"context_window": 32768,
"default_reasoning_level": None,
"apply_patch_tool_type": "freeform",
},
}
with RuntimeSandbox() as box:
session = create_session(profile="access-efficient-escalation-lab", cwd=box.workspace)
try:
for agent_id, required in expected.items():
home_record = session["homes"][agent_id]
config = self._config(home_record["home"])
self.assertIn("model_catalog_json", config)
self.assertEqual(
config["model_catalog_json"], home_record["model_catalog_json"]
)
entries = self._catalog(config)
selected = config["model"]
self.assertIn(selected, entries)
metadata = entries[selected]
self.assertEqual(metadata["slug"], selected)
self.assertEqual(metadata["context_window"], required["context_window"])
self.assertEqual(metadata["max_context_window"], required["context_window"])
self.assertEqual(
metadata["default_reasoning_level"],
required["default_reasoning_level"],
)
self.assertEqual(
metadata["apply_patch_tool_type"],
required["apply_patch_tool_type"],
)
self.assertEqual(metadata["shell_type"], "shell_command")
self.assertTrue(metadata["supported_in_api"])
self.assertIn("text", metadata["input_modalities"])
self.assertEqual(metadata["default_reasoning_summary"], "none")
self.assertNotIn("base_instructions", metadata)
self.assertTrue(metadata["model_messages"]["instructions_template"])
self.assertEqual(
set(metadata["model_messages"]),
{
"instructions_template",
"instructions_variables",
"approvals",
"collaboration_modes",
"auto_review",
"permissions",
"token_budget",
},
)
self.assertNotIn("node_repl_auto_review_required", metadata)
self.assertNotIn("node_repl_disabled", metadata)
self.assertEqual(
metadata["supports_reasoning_summary_parameter"],
required["default_reasoning_level"] is not None
and agent_id != "routine_engineer",
)
self.assertNotIn("used_fallback_model_metadata", metadata)
self.assertIn("truncation_policy", metadata)
finally:
finish_session(session["session_id"], exit_code=0)
def test_function_only_model_omits_custom_patch_but_keeps_shell(self) -> None:
with RuntimeSandbox() as box:
profile = box.root / "function-only-model"
shutil.copytree(ROOT / "profiles" / "access-efficient-escalation-lab", profile)
profile_path = profile / "profile.toml"
profile_data = read_toml(profile_path)
profile_data["id"] = "function-only-model"
profile_data["catalog"] = "catalog.toml"
profile_path.write_text(toml_dumps(profile_data), encoding="utf-8")
(profile / "catalog.toml").write_text(
toml_dumps(
{
"schema_version": MMO_SCHEMA_VERSION,
"models": {
"opencode_go_openai_chat__deepseek_v4_flash": {
"supports_custom_tools": False,
}
},
}
),
encoding="utf-8",
)
session = create_session(profile=profile, cwd=box.workspace)
try:
home = session["homes"]["routine_engineer"]["home"]
config = self._config(home)
metadata = self._catalog(config)[config["model"]]
self.assertEqual(metadata["shell_type"], "shell_command")
self.assertIsNone(metadata["apply_patch_tool_type"])
finally:
finish_session(session["session_id"], exit_code=0)
def test_hybrid_catalog_preserves_bundled_models_and_adds_external_bindings(self) -> None:
with RuntimeSandbox() as box:
mmo_codex_home._BUNDLED_CODEX_CATALOGS.clear()
profile = box.root / "hybrid-native-external"
shutil.copytree(ROOT / "profiles" / "adaptive-engineering", profile)
profile_path = profile / "profile.toml"
profile_data = read_toml(profile_path)
profile_data["id"] = "hybrid-native-external"
profile_data["agents"]["implementation_specialist"]["backends"] = [
"mcp",
"native",
]
specialist = profile_data["agents"]["implementation_specialist"]
specialist["permissions"] = "read-only"
specialist["execution_mode"] = "turn"
specialist.pop("goal_token_budget")
specialist.pop("max_goal_token_budget")
profile_data["coordination"]["max_active_writers"] = 0
profile_path.write_text(toml_dumps(profile_data), encoding="utf-8")
original = mmo_runtime.bundled_codex_catalog_for_profile
with mock.patch(
"mmo_runtime.bundled_codex_catalog_for_profile", wraps=original
) as load_catalog:
session = create_session(profile=profile, cwd=box.workspace)
try:
# The active Codex catalog is queried once per session, not once
# for every generated agent home.
load_catalog.assert_called_once()
self.assertEqual(load_catalog.call_args.args[1], Path(session["codex_binary"]))
root_home = session["homes"][session["root_agent"]]["home"]
config = self._config(root_home)
self.assertIn("model_catalog_json", config)
entries = self._catalog(config)
# model_catalog_json is a startup replacement, so MMO preserves
# the exact bundled rows before adding external route bindings.
self.assertIn("gpt-5.6-terra", entries)
self.assertIn(config["model"], entries)
native_dir = Path(root_home) / "agents"
native_configs = [
tomllib.loads(path.read_text(encoding="utf-8"))
for path in native_dir.glob("*.toml")
]
external = [
item["model"] for item in native_configs if item["model"].startswith("mmo-")
]
self.assertTrue(external)
self.assertTrue(all(slug in entries for slug in external))
patch_types = {entries[slug]["apply_patch_tool_type"] for slug in external}
self.assertEqual(patch_types, {"freeform"})
finally:
finish_session(session["session_id"], exit_code=0)
def test_builtin_only_process_uses_codex_native_catalog(self) -> None:
with RuntimeSandbox() as box:
session = create_session(profile="codex-harness-team", cwd=box.workspace)
try:
config = self._config(session["homes"][session["root_agent"]]["home"])
self.assertNotIn("model_catalog_json", config)
finally:
finish_session(session["session_id"], exit_code=0)
def test_interactive_launch_preserves_tty_with_redirected_stderr(self) -> None:
with RuntimeSandbox() as box:
old = {key: os.environ.get(key) for key in ("NO_COLOR", "TERM", "FAKE_TUI_PROBE")}
os.environ.pop("NO_COLOR", None)
os.environ["TERM"] = "xterm-256color"
os.environ["FAKE_TUI_PROBE"] = "1"
try:
master, slave = pty.openpty()
fcntl.ioctl(slave, termios.TIOCSWINSZ, struct.pack("HHHH", 24, 80, 0, 0))
environment = {
**os.environ,
"PYTHONPATH": os.pathsep.join([str(ROOT / "libexec"), str(ROOT / "tests")]),
}
process = subprocess.Popen(
[
sys.executable,
str(ROOT / "tests" / "helpers" / "tui_probe_launcher.py"),
"access-efficient-escalation-lab",
str(box.workspace),
],
stdin=slave,
stdout=slave,
stderr=subprocess.PIPE,
env=environment,
start_new_session=True,
close_fds=True,
)
os.close(slave)
buffer = b""
all_output = b""
records: list[dict] = []
resized = False
deadline = time.monotonic() + 30
while time.monotonic() < deadline:
readable, _, _ = select.select([master], [], [], 0.25)
if readable:
try:
chunk = os.read(master, 65536)
except OSError:
break
if not chunk:
break
all_output += chunk
buffer += chunk
while b"\n" in buffer:
raw, buffer = buffer.split(b"\n", 1)
text = raw.decode("utf-8", errors="replace").strip().strip("\r")
if not text.startswith("{"):
continue
try:
record = json.loads(text)
except json.JSONDecodeError:
continue
records.append(record)
if record.get("event") == "ready" and not resized:
fcntl.ioctl(
master,
termios.TIOCSWINSZ,
struct.pack("HHHH", 42, 132, 0, 0),
)
resized = True
if any(
item.get("event") in {"launcher_returned", "launcher_error"}
for item in records
):
break
_unused_stdout, stderr_output = process.communicate(timeout=10)
exit_code = int(process.returncode or 0)
os.close(master)
diagnostic = {
"records": records,
"output": all_output.decode("utf-8", errors="replace"),
"stderr": stderr_output.decode("utf-8", errors="replace"),
}
self.assertEqual(exit_code, 0, diagnostic)
self.assertIn(b"\x1b[32mFAKE_TUI_COLOR\x1b[0m", all_output, diagnostic)
ready = next((item for item in records if item.get("event") == "ready"), None)
resize = next((item for item in records if item.get("event") == "resized"), None)
returned = next(
(item for item in records if item.get("event") == "launcher_returned"),
None,
)
self.assertIsNotNone(ready, diagnostic)
self.assertIsNotNone(resize, diagnostic)
self.assertIsNotNone(returned, diagnostic)
assert ready is not None and resize is not None and returned is not None
self.assertTrue(ready["stdin_isatty"])
self.assertTrue(ready["stdout_isatty"])
self.assertFalse(ready["stderr_isatty"])
self.assertIsNone(ready["no_color"])
self.assertEqual(ready["term"], "xterm-256color")
self.assertEqual(ready["pgrp"], ready["foreground_pgrp"])
self.assertEqual((resize["columns"], resize["lines"]), (132, 42))
self.assertEqual(resize["pgrp"], resize["foreground_pgrp"])
self.assertEqual(returned["exit_code"], 0)
self.assertTrue(returned["echo_enabled"], diagnostic)
self.assertTrue(returned["attributes_restored"], diagnostic)
self.assertEqual(returned["pgrp"], returned["foreground_pgrp"])
finally:
for key, value in old.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
if __name__ == "__main__":
unittest.main()