#!/usr/bin/env python3
"""Profile discovery, composition validation, and safe profile packs."""

from __future__ import annotations

import contextlib
import hashlib
import json
import os
import re
import shutil
import stat
import tarfile
import tempfile
import uuid
import zipfile
from collections.abc import Mapping
from ipaddress import IPv6Address, ip_address
from pathlib import Path
from typing import Any

from mmo_catalog_data import load_catalog, validate_catalog_data
from mmo_schema import validate_schema_definition
from mmo_tool_mcp import (
    load_tool_mcp_registry,
    tool_mcp_environment_names,
    validate_tool_mcp_grants,
)
from mmo_util import (
    atomic_write_text,
    config_root,
    copy_tree_static,
    deep_merge,
    install_root,
    package_version,
    read_toml,
    stable_hash,
    strict_json_loads,
    validate_id,
)
from mmo_version import MMO_SCHEMA_VERSION, PACKAGE_VERSION

ALLOWED_PERMISSIONS = {"read-only", "workspace-write"}
ALLOWED_TRUST = {"low", "normal", "high", "adversarial_reviewer"}
ALLOWED_VERIFICATION = {"always", "material_changes", "risk_based", "root_adjudication"}
ALLOWED_WAIT_POLICIES = {"dependency_only"}
ALLOWED_RESULT_VISIBILITY = {"ancestors", "session"}
ALLOWED_CONTRADICTION_POLICIES = {"primary_evidence", "designated_judge", "root_adjudication"}
ALLOWED_WEB_SEARCH = {"disabled", "cached", "indexed", "live"}
ALLOWED_APPROVAL_POLICIES = {"untrusted", "on-request", "never"}
ALLOWED_CONTRACT_ENFORCEMENT = {"warn", "strict"}
ALLOWED_ORCHESTRATION = {"mcp", "native", "hybrid"}
ALLOWED_AGENT_BACKENDS = {"mcp", "native"}
ALLOWED_MODALITIES = {"text", "image", "audio", "video", "file"}
ALLOWED_REASONING = {"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"}
ALLOWED_EXECUTION_MODES = {"turn", "goal"}
ALLOWED_CONTROL_ACTIONS = {
    "inspect",
    "trace",
    "steer",
    "interrupt",
    "pause",
    "continue",
    "detach",
    "stop",
    "finalize",
    "compact",
    "respond",
    "set_effort",
    "fork",
}
LOW_TRUST_TASK_KINDS = {"locate", "references", "extract", "summarize_supplied"}
ALLOWED_PROFILE_MATURITY = {"featured", "lab"}
AGENT_MCP_MANAGEMENT_TOOLS = (
    "agent_spawn",
    "agents_spawn",
    "agent_status",
    "agents_wait",
    "agent_result",
    "agent_result_accept",
    "agent_result_reject",
    "agent_patch_integrate",
    "agent_cancel",
)
AGENT_MCP_CONTROL_TOOLS = (
    "agent_list",
    "agent_inspect",
    "agent_trace",
    "agent_trace_record",
    "agent_steer",
    "agent_interrupt",
    "agent_pause",
    "agent_continue",
    "agent_detach",
    "agent_stop",
    "agent_finalize",
    "agent_compact",
    "agent_respond",
    "agent_set_effort",
    "agent_fork",
)
ALLOWED_PROFILE_FILES = {
    "profile.toml",
    "catalog.toml",
    "smoke.toml",
    "README.md",
    "LICENSE",
}
ALLOWED_PROFILE_SUFFIXES = {
    "agents": {".md"},
    "contracts": {".json"},
}
MAX_PROFILE_ARCHIVE_BYTES = 32 * 1024 * 1024
MAX_PROFILE_ARCHIVE_FILES = 256
MAX_PROFILE_MEMBER_BYTES = 1024 * 1024
MAX_PROFILE_UNCOMPRESSED_BYTES = 16 * 1024 * 1024
MAX_ZIP_COMPRESSION_RATIO = 200

COORDINATION_DEFAULTS: dict[str, Any] = {
    "mode": "rooted_team",
    "orchestration": "mcp",
    "max_active_agents": 5,
    "max_depth": 1,
    "max_children_per_agent": 4,
    "max_active_writers": 2,
    "reject_ancestor_role": True,
    "wait_policy": "dependency_only",
    "write_conflict_policy": "reject",
    "contradiction_policy": "primary_evidence",
    "result_visibility": "ancestors",
    "default_result_chars": 12000,
    "max_result_chars": 30000,
    "native_max_concurrent_threads": None,
    "native_interrupt_message": True,
    "native_nested_delegation": False,
}


def agent_mcp_tool_names(
    agents: Mapping[str, Mapping[str, Any]],
    *,
    root_agent: str,
    agent_id: str,
) -> set[str]:
    """Return the exact runtime-owned Agent MCP tools exposed to one role."""

    agent = agents[agent_id]
    has_mcp_children = any(
        "mcp" in agents[child].get("backends", []) for child in agent.get("can_spawn", [])
    )
    controls = agent.get("controls", {})
    granted_actions = {
        action
        for grant in controls.values()
        if isinstance(grant, Mapping)
        for action in grant.get("actions", [])
    }
    tools: set[str] = set(AGENT_MCP_MANAGEMENT_TOOLS if has_mcp_children else ())
    action_tools = {
        "inspect": {"agent_list", "agent_inspect", "agent_status"},
        "trace": {"agent_list", "agent_trace", "agent_trace_record"},
        "steer": {"agent_list", "agent_steer"},
        "interrupt": {"agent_list", "agent_interrupt"},
        "pause": {"agent_list", "agent_pause"},
        "continue": {"agent_list", "agent_continue"},
        "detach": {"agent_list", "agent_detach"},
        "stop": {"agent_list", "agent_stop"},
        "finalize": {"agent_list", "agent_finalize"},
        "compact": {"agent_list", "agent_compact"},
        "respond": {"agent_list", "agent_respond"},
        "set_effort": {"agent_list", "agent_set_effort"},
        "fork": {"agent_list", "agent_fork"},
    }
    for action in granted_actions:
        tools.update(action_tools[action])
    if granted_actions:
        # Controllers may inspect terminal output, but only normal lineage
        # authorities may cancel, accept, reject, or integrate jobs at runtime.
        tools.update({"agent_status", "agents_wait", "agent_result"})
    return tools


def control_targets(agent: Mapping[str, Any]) -> list[str]:
    """Return stable configured control targets for one resolved agent."""

    controls = agent.get("controls", {})
    return sorted(controls) if isinstance(controls, Mapping) else []


def control_actions(agent: Mapping[str, Any], target: str) -> frozenset[str]:
    """Return the exact actions one resolved agent may apply to a target role."""

    controls = agent.get("controls", {})
    grant = controls.get(target) if isinstance(controls, Mapping) else None
    actions = grant.get("actions", []) if isinstance(grant, Mapping) else []
    return frozenset(str(action) for action in actions)


def native_agent_ids(resolved: Mapping[str, Any]) -> list[str]:
    return [
        key
        for key, agent in resolved["agents"].items()
        if agent["kind"] != "root" and "native" in agent.get("backends", [])
    ]


def native_children(resolved: Mapping[str, Any], agent_id: str) -> list[str]:
    return [
        child
        for child in resolved["agents"][agent_id]["can_spawn"]
        if "native" in resolved["agents"][child].get("backends", [])
    ]


def mcp_children(resolved: Mapping[str, Any], agent_id: str) -> list[str]:
    return [
        child
        for child in resolved["agents"][agent_id]["can_spawn"]
        if "mcp" in resolved["agents"][child].get("backends", [])
    ]


def reachable_native_agent_ids(resolved: Mapping[str, Any], start_agent: str) -> list[str]:
    """Return native descendants reachable from an agent in stable BFS order."""

    result: list[str] = []
    seen = {start_agent}
    pending = [start_agent]
    while pending:
        current = pending.pop(0)
        for child in native_children(resolved, current):
            if child in seen:
                continue
            seen.add(child)
            result.append(child)
            pending.append(child)
    return result


AGENT_DEFAULTS: dict[str, Any] = {
    "kind": "participant",
    "description": "",
    "reasoning": "high",
    "plan_reasoning": None,
    "permissions": "read-only",
    "can_spawn": [],
    "controls": {},
    "max_active": 1,
    "max_children": None,
    "write_scope_required": True,
    "trust": "normal",
    "verification": "material_changes",
    "allowed_task_kinds": ["analysis", "other"],
    "max_task_chars": 12000,
    "min_task_chars": 12,
    "execution_mode": "turn",
    "goal_token_budget": None,
    "max_goal_token_budget": None,
    "stall_warning_seconds": 1800,
    "finalization_grace_seconds": 900,
    "allowed_reasoning_efforts": None,
    "requires_modalities": ["text"],
    "requires_output_modalities": ["text"],
    "requires_tool_images": False,
    "requires_documents": False,
    "attachments_allowed": False,
    "network_access": False,
    "web_search": "disabled",
    "output_contract": None,
    "contract_enforcement": "warn",
    "resource_group": None,
    "resource_units": 1,
    "instructions": None,
    "approval_policy": "never",
    "backends": None,
    "native_name": None,
    "tool_mcp_servers": {},
}

SETTINGS_FIELDS = {
    "schema_version",
    "default_profile",
    "base_codex_home",
    "auth_link_mode",
    "gateway_host",
    "gateway_port_min",
    "gateway_port_max",
    "gateway_start_timeout_seconds",
    "gateway_idle_timeout_seconds",
    "job_retention_days",
    "session_retention_days",
    "codex_bin",
    "switchyard_bin",
}
PROFILE_FIELDS = {
    "schema_version",
    "id",
    "version",
    "display_name",
    "description",
    "tags",
    "maturity",
    "root",
    "catalog",
    "smoke",
    "coordination",
    "agents",
}
SMOKE_FIELDS = {"schema_version", "tasks"}
SMOKE_TASK_FIELDS = {
    "agent",
    "task",
    "task_kind",
    "literal_task",
    "mode",
    "backend",
    "wall_timeout_seconds",
    "wait_seconds",
    "write_scope",
    "attachments",
    "required_mcp_tools",
}


def _reject_unknown_fields(value: Mapping[str, Any], allowed: set[str], label: str) -> None:
    unknown = sorted(set(value) - allowed)
    if unknown:
        raise ValueError(f"{label} has unknown fields: {', '.join(unknown)}")


def _schema_version(value: Any, expected: int, label: str) -> int:
    if not isinstance(value, int) or isinstance(value, bool) or value != expected:
        raise ValueError(f"unsupported {label} schema_version")
    return value


def _nonempty_string(value: Any, label: str) -> str:
    if not isinstance(value, str) or not value.strip():
        raise ValueError(f"{label} must be a non-empty string")
    return value


def _optional_nonempty_string(value: Any, label: str) -> str | None:
    if value is None:
        return None
    return _nonempty_string(value, label)


def _enum_string(value: Any, allowed: set[str], label: str) -> str:
    if not isinstance(value, str) or value not in allowed:
        raise ValueError(f"{label} must be one of {sorted(allowed)}")
    return value


def _required_id(value: Any, label: str) -> str:
    return validate_id(_nonempty_string(value, label), label)


def builtin_profiles_root() -> Path:
    return install_root() / "profiles"


def user_profiles_root() -> Path:
    return config_root() / "profiles.d"


def load_settings() -> dict[str, Any]:
    defaults_path = install_root() / "config" / "settings.toml"
    settings = read_toml(defaults_path)
    user_path = config_root() / "settings.toml"
    if user_path.is_file():
        settings = deep_merge(settings, read_toml(user_path))
    _reject_unknown_fields(settings, SETTINGS_FIELDS, "settings")
    _schema_version(settings.get("schema_version"), MMO_SCHEMA_VERSION, "settings")
    for field in (
        "default_profile",
        "base_codex_home",
        "codex_bin",
        "switchyard_bin",
    ):
        settings[field] = _nonempty_string(settings.get(field), f"settings.{field}")
    validate_id(settings["default_profile"], "settings.default_profile")
    try:
        base_codex_home = Path(settings["base_codex_home"]).expanduser()
    except RuntimeError as exc:
        raise ValueError("settings.base_codex_home has an unknown home-directory user") from exc
    if not base_codex_home.is_absolute():
        raise ValueError("settings.base_codex_home must expand to an absolute path")
    settings["base_codex_home"] = str(base_codex_home.resolve())
    gateway_host = settings.get("gateway_host")
    if not isinstance(gateway_host, str) or not gateway_host:
        raise ValueError("settings.gateway_host must be a non-empty string")
    try:
        parsed_gateway_host = ip_address(gateway_host)
    except ValueError as exc:
        raise ValueError(
            "settings.gateway_host must be an unbracketed IPv4 or IPv6 literal"
        ) from exc
    if isinstance(parsed_gateway_host, IPv6Address) and parsed_gateway_host.scope_id is not None:
        raise ValueError("settings.gateway_host must not contain an IPv6 scope identifier")
    if not parsed_gateway_host.is_loopback:
        raise ValueError("settings.gateway_host must be a loopback address")
    settings["gateway_host"] = str(parsed_gateway_host)
    _enum_string(
        settings.get("auth_link_mode"),
        {"shared", "copy", "none"},
        "settings.auth_link_mode",
    )
    for field, minimum, maximum in (
        ("gateway_port_min", 1024, 65535),
        ("gateway_port_max", 1024, 65535),
        ("gateway_start_timeout_seconds", 1, 3600),
        ("gateway_idle_timeout_seconds", 0, 31_536_000),
        ("job_retention_days", 0, 36_500),
        ("session_retention_days", 0, 36_500),
    ):
        settings[field] = _positive_int(settings.get(field), f"settings.{field}", minimum, maximum)
    if settings["gateway_port_min"] > settings["gateway_port_max"]:
        raise ValueError("settings.gateway_port_min exceeds gateway_port_max")
    return settings


def builtin_auth_link_mode(
    provider: Mapping[str, Any], settings: Mapping[str, Any] | None = None
) -> str:
    """Resolve how a generated Codex home receives file-backed built-in auth.

    A provider may explicitly override the operator default. Bundled providers
    intentionally omit the field so ``settings.toml`` remains effective.
    """

    effective_settings = settings if settings is not None else load_settings()
    value = provider.get("auth_link_mode")
    if value is None:
        value = effective_settings.get("auth_link_mode", "shared")
    return _enum_string(value, {"shared", "copy", "none"}, "auth_link_mode")


def discover_profiles() -> dict[str, dict[str, Any]]:
    results: dict[str, dict[str, Any]] = {}
    for source, root in (("builtin", builtin_profiles_root()), ("user", user_profiles_root())):
        if not root.is_dir():
            continue
        for directory in sorted(path for path in root.iterdir() if path.is_dir()):
            manifest = directory / "profile.toml"
            if not manifest.is_file():
                continue
            try:
                data = read_toml(manifest)
                profile_id = _required_id(data.get("id"), "profile id")
            except (OSError, ValueError):
                continue
            # User profiles intentionally override a bundled profile with the same id.
            results[profile_id] = {
                "id": profile_id,
                "source": source,
                "path": str(directory),
                "display_name": data.get("display_name", profile_id),
                "description": data.get("description", ""),
                "version": data.get("version", "0"),
                "maturity": data.get("maturity"),
                "root": data.get("root"),
                "tags": data.get("tags", []),
            }
    return results


def resolve_profile_dir(value: str | Path) -> tuple[Path, str]:
    candidate = Path(value).expanduser()
    if candidate.exists():
        directory = candidate.resolve()
        if directory.is_file():
            directory = directory.parent
        if not (directory / "profile.toml").is_file():
            raise ValueError(f"profile.toml not found in {directory}")
        return directory, "path"
    profile_id = validate_id(str(value), "profile id")
    profiles = discover_profiles()
    if profile_id not in profiles:
        raise FileNotFoundError(f"unknown profile {profile_id!r}")
    item = profiles[profile_id]
    return Path(item["path"]), item["source"]


def validate_profile_pack_tree(directory: Path) -> list[str]:
    errors: list[str] = []
    if not directory.is_dir():
        return [f"profile pack is not a directory: {directory}"]
    for path in sorted(directory.rglob("*")):
        relative = path.relative_to(directory)
        if path.is_symlink():
            errors.append(f"symbolic links are not allowed: {relative}")
            continue
        if path.is_dir():
            if relative.parts[0] not in {"agents", "contracts"}:
                errors.append(f"unknown profile directory: {relative}")
            continue
        if not path.is_file():
            errors.append(f"special files are not allowed: {relative}")
            continue
        if len(relative.parts) == 1:
            if relative.name not in ALLOWED_PROFILE_FILES:
                errors.append(f"unknown top-level profile file: {relative}")
        elif len(relative.parts) == 2:
            parent, name = relative.parts
            suffixes = ALLOWED_PROFILE_SUFFIXES.get(parent)
            if suffixes is None or Path(name).suffix not in suffixes:
                errors.append(f"unsupported profile file: {relative}")
        else:
            errors.append(f"nested profile paths are not allowed: {relative}")
        if path.stat().st_size > 1024 * 1024:
            errors.append(f"profile file exceeds 1 MiB: {relative}")
    if not (directory / "profile.toml").is_file():
        errors.append("profile.toml is required")
    return errors


def _profile_pack_content_hash(directory: Path) -> str:
    """Hash every validated pack-owned file by relative name and exact bytes."""

    digest = hashlib.sha256(b"codex-mmo-profile-pack-v1\0")
    for path in sorted(item for item in directory.rglob("*") if item.is_file()):
        relative = path.relative_to(directory).as_posix().encode("utf-8")
        payload = path.read_bytes()
        digest.update(len(relative).to_bytes(8, "big"))
        digest.update(relative)
        digest.update(len(payload).to_bytes(8, "big"))
        digest.update(payload)
    return digest.hexdigest()


def _string_list(value: Any, label: str, *, allow_empty: bool = True) -> list[str]:
    if value is None and allow_empty:
        return []
    if not isinstance(value, list) or not all(isinstance(item, str) for item in value):
        raise ValueError(f"{label} must be an array of strings")
    if any(not item.strip() for item in value):
        raise ValueError(f"{label} cannot contain empty strings")
    if not allow_empty and not value:
        raise ValueError(f"{label} cannot be empty")
    if len(value) != len(set(value)):
        raise ValueError(f"{label} cannot contain duplicates")
    return list(value)


def _positive_int(value: Any, label: str, minimum: int = 1, maximum: int = 1_000_000) -> int:
    if not isinstance(value, int) or isinstance(value, bool) or not minimum <= value <= maximum:
        raise ValueError(f"{label} must be an integer between {minimum} and {maximum}")
    return value


def _validate_controls(value: Any, label: str) -> dict[str, dict[str, list[str]]]:
    if not isinstance(value, Mapping):
        raise ValueError(f"{label} must be a table keyed by target agent")
    result: dict[str, dict[str, list[str]]] = {}
    for target, raw_grant in value.items():
        validate_id(target, f"{label} target")
        if not isinstance(raw_grant, Mapping):
            raise ValueError(f"{label}.{target} must be a table")
        _reject_unknown_fields(raw_grant, {"actions"}, f"{label}.{target}")
        actions = _string_list(
            raw_grant.get("actions"),
            f"{label}.{target}.actions",
            allow_empty=False,
        )
        unknown = sorted(set(actions) - ALLOWED_CONTROL_ACTIONS)
        if unknown:
            raise ValueError(f"{label}.{target}.actions contains unsupported actions: {unknown}")
        result[target] = {"actions": actions}
    return result


_HEADER_NAME = re.compile(r"[!#$%&'*+.^_`|~0-9A-Za-z-]+")
_ENVIRONMENT_NAME = re.compile(r"[A-Za-z_][A-Za-z0-9_]*")


def _validate_coordination(profile: Mapping[str, Any]) -> dict[str, Any]:
    raw_coordination = profile.get("coordination", {})
    if not isinstance(raw_coordination, Mapping):
        raise ValueError("profile.coordination must be a table")
    _reject_unknown_fields(raw_coordination, set(COORDINATION_DEFAULTS), "profile.coordination")
    coordination = deep_merge(COORDINATION_DEFAULTS, raw_coordination)
    coordination["orchestration"] = _enum_string(
        coordination["orchestration"],
        ALLOWED_ORCHESTRATION,
        "coordination.orchestration",
    )
    for field, minimum, maximum in (
        ("max_active_agents", 1, 64),
        ("max_depth", 0, 8),
        ("max_children_per_agent", 1, 64),
        ("max_active_writers", 0, 32),
        ("default_result_chars", 500, 100_000),
        ("max_result_chars", 500, 500_000),
    ):
        coordination[field] = _positive_int(
            coordination[field], f"coordination.{field}", minimum, maximum
        )
    native_limit = coordination.get("native_max_concurrent_threads")
    if native_limit is None:
        native_limit = max(1, coordination["max_active_agents"] - 1)
    coordination["native_max_concurrent_threads"] = _positive_int(
        native_limit,
        "coordination.native_max_concurrent_threads",
        1,
        64,
    )
    if not isinstance(coordination.get("native_interrupt_message"), bool):
        raise ValueError("coordination.native_interrupt_message must be boolean")
    if not isinstance(coordination.get("native_nested_delegation"), bool):
        raise ValueError("coordination.native_nested_delegation must be boolean")
    if not isinstance(coordination.get("reject_ancestor_role"), bool):
        raise ValueError("coordination.reject_ancestor_role must be boolean")
    if not isinstance(coordination.get("mode"), str) or not coordination["mode"]:
        raise ValueError("coordination.mode must be a non-empty string")
    if coordination["default_result_chars"] > coordination["max_result_chars"]:
        raise ValueError("coordination.default_result_chars exceeds max_result_chars")
    coordination["wait_policy"] = _enum_string(
        coordination["wait_policy"], ALLOWED_WAIT_POLICIES, "coordination.wait_policy"
    )
    coordination["result_visibility"] = _enum_string(
        coordination["result_visibility"],
        ALLOWED_RESULT_VISIBILITY,
        "coordination.result_visibility",
    )
    coordination["contradiction_policy"] = _enum_string(
        coordination["contradiction_policy"],
        ALLOWED_CONTRADICTION_POLICIES,
        "coordination.contradiction_policy",
    )
    if (
        not isinstance(coordination["write_conflict_policy"], str)
        or coordination["write_conflict_policy"] != "reject"
    ):
        raise ValueError("only write_conflict_policy='reject' is supported")
    return coordination


def _default_agent_backends(orchestration: str) -> list[str]:
    if orchestration == "mcp":
        return ["mcp"]
    if orchestration == "native":
        return ["native"]
    return ["mcp", "native"]


def _load_relative_text(
    profile_dir: Path,
    relative: str,
    label: str,
    *,
    parent: str,
    suffix: str,
) -> str:
    relative_path = Path(relative)
    if (
        relative_path.is_absolute()
        or len(relative_path.parts) != 2
        or relative_path.parts[0] != parent
        or relative_path.suffix != suffix
    ):
        raise ValueError(f"{label} must be a relative {parent}/*{suffix} path")
    path = (profile_dir / relative).resolve()
    if profile_dir not in path.parents:
        raise ValueError(f"{label} path escapes the profile pack: {relative}")
    if not path.is_file():
        raise ValueError(f"{label} file is missing: {relative}")
    return path.read_text(encoding="utf-8")


def _validate_agent(
    key: str,
    agent: Mapping[str, Any],
    *,
    profile_dir: Path,
    models: Mapping[str, Any],
    routes: Mapping[str, Any],
    resources: Mapping[str, Any],
    tool_mcp_registry: Mapping[str, Mapping[str, Any]],
    binding: str | None,
    orchestration: str,
) -> dict[str, Any]:
    validate_id(key, "agent id")
    _reject_unknown_fields(
        agent,
        set(AGENT_DEFAULTS) | {"model"},
        f"agent {key}",
    )
    result = deep_merge(AGENT_DEFAULTS, agent)
    if binding:
        result["model"] = binding
    model_key = result.get("model")
    if not isinstance(model_key, str) or model_key not in models:
        raise ValueError(f"agent {key}: unknown model {model_key!r}")
    model = models[model_key]
    route = routes[model["route"]]
    if not model.get("agent_compatible", False):
        raise ValueError(
            f"agent {key}: model {model_key!r} is catalogued but is not Codex-agent compatible"
        )
    result["model"] = model_key
    result["route"] = model["route"]
    result["driver"] = route["driver"]
    result["kind"] = _enum_string(result["kind"], {"root", "participant"}, f"agent {key}.kind")
    if not isinstance(result["description"], str):
        raise ValueError(f"agent {key}.description must be a string")
    raw_backends = result.get("backends")
    if result["kind"] == "root":
        if raw_backends not in (None, []):
            raise ValueError(f"agent {key}: root agents cannot declare execution backends")
        result["backends"] = []
    else:
        result["backends"] = (
            _default_agent_backends(orchestration)
            if raw_backends is None
            else _string_list(raw_backends, f"agent {key}.backends", allow_empty=False)
        )
        if len(result["backends"]) != len(set(result["backends"])):
            raise ValueError(f"agent {key}.backends contains duplicates")
        unknown_backends = sorted(set(result["backends"]) - ALLOWED_AGENT_BACKENDS)
        if unknown_backends:
            raise ValueError(f"agent {key}: unsupported backends {unknown_backends}")
        allowed_for_mode = {
            "mcp": {"mcp"},
            "native": {"native"},
            "hybrid": {"mcp", "native"},
        }[orchestration]
        invalid_backends = sorted(set(result["backends"]) - allowed_for_mode)
        if invalid_backends:
            raise ValueError(
                f"agent {key}: backends {invalid_backends} are incompatible with "
                f"coordination.orchestration={orchestration!r}"
            )
    configured_native_name = result.get("native_name")
    native_name = (
        key
        if configured_native_name is None
        else _nonempty_string(configured_native_name, f"agent {key}.native_name")
    )
    result["native_name"] = validate_id(native_name, f"agent {key} native_name")
    result["tool_mcp_servers"] = validate_tool_mcp_grants(
        result.get("tool_mcp_servers"),
        tool_mcp_registry,
        label=f"agent {key}.tool_mcp_servers",
    )
    for field, allowed in (
        ("permissions", ALLOWED_PERMISSIONS),
        ("trust", ALLOWED_TRUST),
        ("verification", ALLOWED_VERIFICATION),
        ("web_search", ALLOWED_WEB_SEARCH),
        ("contract_enforcement", ALLOWED_CONTRACT_ENFORCEMENT),
    ):
        result[field] = _enum_string(result[field], allowed, f"agent {key}.{field}")
    result["can_spawn"] = _string_list(result["can_spawn"], f"agent {key}.can_spawn")
    result["controls"] = _validate_controls(result["controls"], f"agent {key}.controls")
    result["allowed_task_kinds"] = _string_list(
        result["allowed_task_kinds"],
        f"agent {key}.allowed_task_kinds",
        allow_empty=result["kind"] == "root",
    )
    for task_kind in result["allowed_task_kinds"]:
        validate_id(task_kind, f"agent {key} task kind")
    result["requires_modalities"] = _string_list(
        result["requires_modalities"], f"agent {key}.requires_modalities", allow_empty=False
    )
    result["requires_output_modalities"] = _string_list(
        result["requires_output_modalities"],
        f"agent {key}.requires_output_modalities",
        allow_empty=False,
    )
    for boolean_field in (
        "write_scope_required",
        "requires_tool_images",
        "requires_documents",
        "attachments_allowed",
        "network_access",
    ):
        if not isinstance(result[boolean_field], bool):
            raise ValueError(f"agent {key}.{boolean_field} must be boolean")
    result["approval_policy"] = _enum_string(
        result.get("approval_policy"),
        ALLOWED_APPROVAL_POLICIES,
        f"agent {key}.approval_policy",
    )
    if not isinstance(result.get("reasoning"), str):
        raise ValueError(f"agent {key}.reasoning must be a string")
    missing_model = sorted(set(result["requires_modalities"]) - set(model["modalities"]))
    missing_transport = sorted(
        set(result["requires_modalities"]) - set(route["transport_modalities"])
    )
    missing_model_output = sorted(
        set(result["requires_output_modalities"]) - set(model["output_modalities"])
    )
    missing_transport_output = sorted(
        set(result["requires_output_modalities"]) - set(route["transport_output_modalities"])
    )
    if missing_model:
        raise ValueError(f"agent {key}: model lacks required modalities {missing_model}")
    if missing_transport:
        raise ValueError(
            f"agent {key}: route transport loses required modalities {missing_transport}"
        )
    if missing_model_output:
        raise ValueError(
            f"agent {key}: model lacks required output modalities {missing_model_output}"
        )
    if missing_transport_output:
        raise ValueError(
            f"agent {key}: route transport loses required output modalities "
            f"{missing_transport_output}"
        )
    if result["requires_tool_images"]:
        if not model.get("supports_tool_images", False):
            raise ValueError(f"agent {key}: model cannot consume image-bearing tool results")
        if not route.get("preserves_tool_media", False) or "image" not in route.get(
            "tool_result_modalities", []
        ):
            raise ValueError(f"agent {key}: route does not preserve image-bearing tool results")
    if result["requires_documents"]:
        if not model.get("supports_documents", False):
            raise ValueError(f"agent {key}: model does not support document/file input")
        if not route.get("supports_documents", False):
            raise ValueError(f"agent {key}: route does not preserve documents")
    if not model.get("tool_calling", False):
        raise ValueError(f"agent {key}: model must support tool calling for Codex execution")
    if result["reasoning"] == "auto":
        result["reasoning"] = model["default_reasoning"]
    if result["reasoning"] not in model["reasoning_levels"]:
        raise ValueError(
            f"agent {key}: reasoning {result['reasoning']!r} is not supported by model {model_key}"
        )
    configured_efforts = result.get("allowed_reasoning_efforts")
    if configured_efforts is None:
        configured_efforts = [result["reasoning"]]
    result["allowed_reasoning_efforts"] = _string_list(
        configured_efforts,
        f"agent {key}.allowed_reasoning_efforts",
        allow_empty=False,
    )
    if len(result["allowed_reasoning_efforts"]) != len(set(result["allowed_reasoning_efforts"])):
        raise ValueError(f"agent {key}.allowed_reasoning_efforts contains duplicates")
    unsupported_efforts = sorted(
        set(result["allowed_reasoning_efforts"]) - set(model["reasoning_levels"])
    )
    if unsupported_efforts:
        raise ValueError(
            f"agent {key}: unsupported allowed reasoning efforts for {model_key}: "
            + ", ".join(unsupported_efforts)
        )
    if result["reasoning"] not in result["allowed_reasoning_efforts"]:
        raise ValueError(
            f"agent {key}: initial reasoning must be present in allowed_reasoning_efforts"
        )
    if result.get("plan_reasoning") == "auto":
        result["plan_reasoning"] = model["default_reasoning"]
    if result.get("plan_reasoning") is not None and not isinstance(result["plan_reasoning"], str):
        raise ValueError(f"agent {key}: plan_reasoning must be a string")
    if (
        result.get("plan_reasoning") is not None
        and result["plan_reasoning"] not in model["reasoning_levels"]
    ):
        raise ValueError(
            f"agent {key}: plan_reasoning {result['plan_reasoning']!r} is not supported by model {model_key}"
        )
    result["max_active"] = _positive_int(result["max_active"], f"agent {key}.max_active", 1, 64)
    result["resource_units"] = _positive_int(
        result["resource_units"], f"agent {key}.resource_units", 1, 64
    )
    for field, minimum, maximum in (
        ("max_task_chars", 64, 100_000),
        ("min_task_chars", 1, 10_000),
        ("finalization_grace_seconds", 30, 3600),
        ("stall_warning_seconds", 60, 86_400),
    ):
        result[field] = _positive_int(result[field], f"agent {key}.{field}", minimum, maximum)
    if result["min_task_chars"] > result["max_task_chars"]:
        raise ValueError(f"agent {key}: min_task_chars exceeds max_task_chars")
    result["execution_mode"] = _enum_string(
        result["execution_mode"],
        ALLOWED_EXECUTION_MODES,
        f"agent {key}.execution_mode",
    )
    if result["execution_mode"] == "goal":
        if "native" in result["backends"]:
            raise ValueError(
                f"agent {key}: native participants must use turn execution; "
                "Codex native delegation does not expose a mechanically owned goal lifecycle"
            )
        result["goal_token_budget"] = _positive_int(
            result.get("goal_token_budget"),
            f"agent {key}.goal_token_budget",
            10_000,
            100_000_000,
        )
        result["max_goal_token_budget"] = _positive_int(
            result.get("max_goal_token_budget"),
            f"agent {key}.max_goal_token_budget",
            10_000,
            100_000_000,
        )
        if result["goal_token_budget"] > result["max_goal_token_budget"]:
            raise ValueError(f"agent {key}: goal_token_budget exceeds max_goal_token_budget")
    else:
        if (
            result.get("goal_token_budget") is not None
            or result.get("max_goal_token_budget") is not None
        ):
            raise ValueError(f"agent {key}: turn execution cannot declare goal token budgets")
    if result.get("max_children") is not None:
        result["max_children"] = _positive_int(
            result["max_children"], f"agent {key}.max_children", 1, 64
        )
    configured_resource = _optional_nonempty_string(
        result.get("resource_group"), f"agent {key}.resource_group"
    )
    resource_key = configured_resource or model.get("resource_group")
    if resource_key is not None and resource_key not in resources:
        raise ValueError(f"agent {key}: unknown resource group {resource_key!r}")
    result["resource_group"] = resource_key
    instructions_path = result.get("instructions")
    if instructions_path is not None:
        instructions_path = _nonempty_string(instructions_path, f"agent {key}.instructions")
    result["instructions_text"] = (
        _load_relative_text(
            profile_dir,
            instructions_path,
            f"agent {key} instructions",
            parent="agents",
            suffix=".md",
        )
        if instructions_path
        else ""
    )
    contract_path = result.get("output_contract")
    if contract_path is not None:
        contract_path = _nonempty_string(contract_path, f"agent {key}.output_contract")
    if contract_path:
        contract_text = _load_relative_text(
            profile_dir,
            contract_path,
            f"agent {key} contract",
            parent="contracts",
            suffix=".json",
        )
        try:
            contract = strict_json_loads(contract_text)
        except json.JSONDecodeError as exc:
            raise ValueError(f"agent {key}: invalid JSON output contract: {exc}") from exc
        schema_errors = validate_schema_definition(contract)
        if schema_errors:
            raise ValueError(f"agent {key}: invalid output contract: {'; '.join(schema_errors)}")
        result["output_contract_schema"] = contract
    else:
        result["output_contract_schema"] = None
    if result["contract_enforcement"] == "strict" and result["output_contract_schema"] is None:
        raise ValueError(f"agent {key}: strict contract enforcement requires output_contract")
    if result["contract_enforcement"] == "strict" and result["backends"] == ["native"]:
        raise ValueError(
            f"agent {key}: native-only agents cannot claim strict contract enforcement"
        )
    if result["trust"] == "low":
        # Low-trust roles are mechanically contained. These are runtime
        # invariants, not advisory prompt text.
        if result["kind"] == "root":
            raise ValueError(f"agent {key}: low-trust agents cannot be profile roots")
        if result["backends"] != ["mcp"]:
            raise ValueError(
                f"agent {key}: low-trust agents must use only the supervised MCP backend"
            )
        if result["permissions"] != "read-only":
            raise ValueError(f"agent {key}: low-trust agents must be read-only")
        if result["verification"] != "always":
            raise ValueError(f"agent {key}: low-trust agents require verification='always'")
        if result["output_contract_schema"] is None:
            raise ValueError(f"agent {key}: low-trust agents require an output contract")
        if result["contract_enforcement"] != "strict":
            raise ValueError(f"agent {key}: low-trust agents require strict contract enforcement")
        if result["can_spawn"]:
            raise ValueError(f"agent {key}: low-trust agents cannot spawn descendants")
        if result["controls"]:
            raise ValueError(f"agent {key}: low-trust agents cannot control other workers")
        if result["max_active"] != 1:
            raise ValueError(f"agent {key}: low-trust agents require max_active=1")
        if result["network_access"] or result["web_search"] != "disabled":
            raise ValueError(f"agent {key}: low-trust agents cannot use network or web search")
        if result["attachments_allowed"]:
            raise ValueError(f"agent {key}: low-trust agents cannot receive attachments")
        unknown_low_trust_tasks = sorted(set(result["allowed_task_kinds"]) - LOW_TRUST_TASK_KINDS)
        if unknown_low_trust_tasks:
            raise ValueError(
                f"agent {key}: low-trust task kinds are limited to literal evidence work; "
                f"invalid values: {unknown_low_trust_tasks}"
            )
        if result["max_task_chars"] > 2500:
            raise ValueError(f"agent {key}: low-trust task briefs are limited to 2500 characters")
        if resource_key is None:
            raise ValueError(f"agent {key}: low-trust agents require a single-slot resource group")
        if resources[resource_key]["max_active"] != 1:
            raise ValueError(
                f"agent {key}: low-trust resource group {resource_key!r} must have max_active=1"
            )
        if result["resource_units"] != 1:
            raise ValueError(f"agent {key}: low-trust agents require resource_units=1")
    result["model_config"] = model
    result["route_config"] = route
    return result


def derive_coordination_capacities(
    agents: Mapping[str, Mapping[str, Any]],
    resources: Mapping[str, Mapping[str, Any]],
    *,
    root_agent: str,
    max_depth: int,
) -> dict[str, Any]:
    """Derive reachable active, writer, and weighted-resource ceilings."""

    reachable = {root_agent}
    frontier = {root_agent}
    for _depth in range(max_depth):
        frontier = {
            child
            for parent in frontier
            for child in agents[parent]["can_spawn"]
            if child not in reachable
        }
        reachable.update(frontier)
    reachable_workers = sorted(reachable - {root_agent})
    active_slots = {key: int(agents[key]["max_active"]) for key in reachable_workers}
    grouped: dict[str, list[str]] = {}
    ungrouped = 0
    for key, slots in active_slots.items():
        resource_key = agents[key].get("resource_group")
        if resource_key is None:
            ungrouped += slots
            continue
        lock_key = str(resources[str(resource_key)]["lock_key"])
        grouped.setdefault(lock_key, []).append(key)

    resource_feasible_workers = ungrouped
    root_resource = agents[root_agent].get("resource_group")
    root_lock = (
        str(resources[str(root_resource)]["lock_key"]) if root_resource is not None else None
    )
    for lock_key, keys in grouped.items():
        resource = resources[str(agents[keys[0]]["resource_group"])]
        available_units = int(resource["max_active"])
        if lock_key == root_lock:
            available_units -= int(agents[root_agent]["resource_units"])
        weights = sorted(
            int(agents[key]["resource_units"]) for key in keys for _slot in range(active_slots[key])
        )
        used_units = 0
        admitted_slots = 0
        for weight in weights:
            if used_units + weight > max(0, available_units):
                break
            used_units += weight
            admitted_slots += 1
        resource_feasible_workers += admitted_slots

    feasible_workers = resource_feasible_workers
    writable_slots = sum(
        active_slots[key]
        for key in reachable_workers
        if agents[key]["permissions"] == "workspace-write" and "mcp" in agents[key]["backends"]
    )
    return {
        "reachable_workers": reachable_workers,
        "feasible_max_active_agents": 1 + feasible_workers,
        "writable_slots": writable_slots,
    }


def resolve_profile(
    value: str | Path,
    *,
    bindings: Mapping[str, str] | None = None,
) -> dict[str, Any]:
    directory, source = resolve_profile_dir(value)
    pack_errors = validate_profile_pack_tree(directory)
    if pack_errors:
        raise ValueError("invalid profile pack: " + "; ".join(pack_errors))
    profile = read_toml(directory / "profile.toml")
    _reject_unknown_fields(profile, PROFILE_FIELDS, f"profile {directory}")
    try:
        _schema_version(profile.get("schema_version"), MMO_SCHEMA_VERSION, "profile")
    except ValueError as exc:
        raise ValueError(f"unsupported profile schema_version in {directory}") from exc
    profile_id = _required_id(profile.get("id"), "profile id")
    root_agent = _required_id(profile.get("root"), "root agent id")
    for field in ("version", "display_name", "description"):
        if not isinstance(profile.get(field), str) or not profile[field].strip():
            raise ValueError(f"profile.{field} must be a non-empty string")
    if profile["version"] != PACKAGE_VERSION:
        raise ValueError(
            f"profile version must exactly match the active package version {PACKAGE_VERSION}"
        )
    catalog = validate_catalog_data(
        load_catalog(directory, profile), label=f"profile {profile_id} catalog"
    )
    tool_mcp_registry = load_tool_mcp_registry()
    maturity = _enum_string(profile.get("maturity"), ALLOWED_PROFILE_MATURITY, "profile.maturity")
    routes = catalog["routes"]
    resources = catalog["resources"]
    models = catalog["models"]
    coordination = _validate_coordination(profile)
    agent_tables = profile.get("agents")
    if not isinstance(agent_tables, Mapping) or not agent_tables:
        raise ValueError(f"profile {profile_id}: [agents] must define at least one agent")
    if not all(isinstance(item, Mapping) for item in agent_tables.values()):
        raise ValueError(f"profile {profile_id}: every agent must be a table")
    supplied_bindings = dict(bindings or {})
    unknown_bindings = sorted(set(supplied_bindings) - set(agent_tables))
    if unknown_bindings:
        raise ValueError(f"unknown agent bindings: {', '.join(unknown_bindings)}")
    agents = {
        key: _validate_agent(
            key,
            value,
            profile_dir=directory,
            models=models,
            routes=routes,
            resources=resources,
            tool_mcp_registry=tool_mcp_registry,
            binding=supplied_bindings.get(key),
            orchestration=coordination["orchestration"],
        )
        for key, value in agent_tables.items()
    }
    if root_agent not in agents:
        raise ValueError(f"profile {profile_id}: root agent {root_agent!r} is not defined")
    roots = [key for key, agent in agents.items() if agent["kind"] == "root"]
    if roots != [root_agent]:
        raise ValueError(
            f"profile {profile_id}: exactly the configured root must have kind='root'; found {roots}"
        )
    for key, agent in agents.items():
        for child in agent["can_spawn"]:
            if child not in agents:
                raise ValueError(f"agent {key}: unknown spawn target {child!r}")
            if child == root_agent:
                raise ValueError(f"agent {key}: the root agent cannot be spawned")
            if not agents[child]["backends"]:
                raise ValueError(f"agent {key}: child {child!r} has no execution backend")
        for target, grant in agent["controls"].items():
            if target not in agents:
                raise ValueError(f"agent {key}: unknown control target {target!r}")
            if target == key:
                raise ValueError(f"agent {key}: an agent cannot grant itself controls")
            if not set(grant["actions"]).issubset(ALLOWED_CONTROL_ACTIONS):
                raise ValueError(f"agent {key}: control target {target!r} has invalid actions")
            if target == root_agent and "fork" in grant["actions"]:
                raise ValueError(
                    f"agent {key}: the immutable root run cannot be a fork control target"
                )
    # Native root -> participant spawning is supported directly by Codex. By
    # default, nested participant delegation is forced through Agent MCP so the
    # MMO kernel can authenticate the caller and enforce graph, depth, budget,
    # resource, scope, and result policies. Pure native nesting is available
    # only as an explicit advisory opt-in because Codex exposes no supervisor
    # hook that can mechanically validate each native edge.
    if not coordination["native_nested_delegation"]:
        for key, agent in agents.items():
            if key == root_agent or "native" not in agent["backends"]:
                continue
            for child in agent["can_spawn"]:
                if "mcp" not in agents[child]["backends"]:
                    raise ValueError(
                        f"agent {key}: child {child!r} must support MCP when "
                        "coordination.native_nested_delegation=false"
                    )

    native_names: dict[str, str] = {}
    for key, agent in agents.items():
        if "native" not in agent["backends"]:
            continue
        name = agent["native_name"]
        if name in native_names:
            raise ValueError(
                f"agents {native_names[name]!r} and {key!r} share native_name {name!r}"
            )
        native_names[name] = key
    if coordination["max_depth"] == 0 and any(agent["can_spawn"] for agent in agents.values()):
        raise ValueError("max_depth=0 is incompatible with configured spawn edges")
    if coordination["max_active_agents"] < 2 and agents[root_agent]["can_spawn"]:
        raise ValueError("a spawning profile requires max_active_agents >= 2")
    for key, agent in agents.items():
        resource_key = agent.get("resource_group")
        if resource_key is None:
            continue
        units = int(agent["resource_units"])
        capacity = int(resources[resource_key]["max_active"])
        if units > capacity:
            raise ValueError(
                f"agent {key}.resource_units ({units}) exceeds resource group "
                f"{resource_key!r} capacity ({capacity})"
            )
    capacities = derive_coordination_capacities(
        agents,
        resources,
        root_agent=root_agent,
        max_depth=int(coordination["max_depth"]),
    )
    reachable_workers = capacities["reachable_workers"]
    feasible_active_agents = int(capacities["feasible_max_active_agents"])
    if coordination["max_active_agents"] > feasible_active_agents:
        raise ValueError(
            "coordination.max_active_agents exceeds compiler-derived feasible concurrency "
            f"({feasible_active_agents})"
        )
    writable_slots = int(capacities["writable_slots"])
    if coordination["max_active_writers"] > writable_slots:
        raise ValueError(
            "coordination.max_active_writers exceeds reachable writable MCP capacity "
            f"({writable_slots})"
        )
    if maturity == "featured":
        native_writers = [
            key
            for key in reachable_workers
            if "native" in agents[key]["backends"]
            and agents[key]["permissions"] == "workspace-write"
        ]
        if native_writers:
            raise ValueError(
                "featured profiles require native participants to be read-only: "
                + ", ".join(native_writers)
            )
    coordination["feasible_max_active_agents"] = feasible_active_agents

    used_model_keys = sorted({agent["model"] for agent in agents.values()})
    used_route_keys = sorted({models[key]["route"] for key in used_model_keys})
    used_resource_keys = sorted(
        {agent["resource_group"] for agent in agents.values() if agent["resource_group"]}
    )
    used_tool_mcp_server_ids = sorted(
        {server_id for agent in agents.values() for server_id in agent["tool_mcp_servers"]}
    )
    smoke_data: dict[str, Any] | None = None
    smoke_name = profile.get("smoke", "smoke.toml")
    if not isinstance(smoke_name, str) or not smoke_name:
        raise ValueError("profile.smoke must be a non-empty relative path string")
    if Path(smoke_name).is_absolute():
        raise ValueError("profile.smoke must be a non-empty relative path string")
    smoke_path = (directory / smoke_name).resolve()
    if directory not in smoke_path.parents:
        raise ValueError("profile smoke path escapes the profile pack")
    if smoke_path.is_file():
        smoke_data = read_toml(smoke_path)
        _reject_unknown_fields(smoke_data, SMOKE_FIELDS, f"profile {profile_id} smoke")
        try:
            _schema_version(smoke_data.get("schema_version"), MMO_SCHEMA_VERSION, "smoke")
        except ValueError as exc:
            raise ValueError(f"profile {profile_id}: unsupported smoke schema") from exc
        tasks = smoke_data.get("tasks", [])
        if not isinstance(tasks, list):
            raise ValueError(f"profile {profile_id}: smoke.tasks must be an array of tables")
        for index, task in enumerate(tasks):
            if not isinstance(task, Mapping):
                raise ValueError(f"profile {profile_id}: smoke task {index} must be a table")
            _reject_unknown_fields(
                task,
                SMOKE_TASK_FIELDS,
                f"profile {profile_id} smoke task {index}",
            )
            task_agent = task.get("agent")
            if not isinstance(task_agent, str) or task_agent not in agents:
                raise ValueError(f"profile {profile_id}: smoke task {index} uses unknown agent")
            smoke_agent = agents[task_agent]
            if smoke_agent["trust"] == "low":
                if "task" in task or "task_kind" in task:
                    raise ValueError(
                        f"profile {profile_id}: low-trust smoke task {index} must use "
                        "literal_task instead of free-form task/task_kind"
                    )
                literal_task = task.get("literal_task")
                if not isinstance(literal_task, Mapping):
                    raise ValueError(
                        f"profile {profile_id}: low-trust smoke task {index} requires literal_task"
                    )
                operation = literal_task.get("operation")
                if operation not in LOW_TRUST_TASK_KINDS:
                    raise ValueError(
                        f"profile {profile_id}: low-trust smoke task {index} has invalid "
                        "literal operation"
                    )
                task_text = ""
                task_kind = str(operation)
            else:
                if "literal_task" in task:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} reserves literal_task "
                        "for low-trust agents"
                    )
                if not isinstance(task.get("task"), str) or not task["task"].strip():
                    raise ValueError(f"profile {profile_id}: smoke task {index} has no task text")
                task_text = task["task"].strip()
                task_kind = _required_id(
                    task.get("task_kind"), f"profile {profile_id} smoke task kind"
                )
                if task_agent != root_agent and task_kind not in smoke_agent["allowed_task_kinds"]:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} has invalid task_kind"
                    )
            mode = task.get("mode", "read-only")
            mode = _enum_string(
                mode,
                ALLOWED_PERMISSIONS,
                f"profile {profile_id} smoke task {index}.mode",
            )
            if mode == "workspace-write" and smoke_agent["permissions"] != "workspace-write":
                raise ValueError(
                    f"profile {profile_id}: smoke task {index} exceeds agent permissions"
                )
            for field in ("write_scope", "attachments"):
                _string_list(
                    task.get(field, []),
                    f"profile {profile_id} smoke task {index}.{field}",
                )
            required_mcp_tools = _string_list(
                task.get("required_mcp_tools", []),
                f"profile {profile_id} smoke task {index}.required_mcp_tools",
            )
            grants = smoke_agent["tool_mcp_servers"]
            agent_mcp_tools = agent_mcp_tool_names(
                agents,
                root_agent=root_agent,
                agent_id=task_agent,
            )
            for qualified_tool in required_mcp_tools:
                if "." not in qualified_tool:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} required MCP tool "
                        f"{qualified_tool!r} must use server.tool form"
                    )
                matches = [
                    (server_id, qualified_tool[len(server_id) + 1 :])
                    for server_id, grant in grants.items()
                    if qualified_tool.startswith(server_id + ".")
                    and qualified_tool[len(server_id) + 1 :] in grant["enabled_tools"]
                ]
                if qualified_tool.startswith("mmo_mesh."):
                    tool_name = qualified_tool.removeprefix("mmo_mesh.")
                    if tool_name in agent_mcp_tools:
                        matches.append(("mmo_mesh", tool_name))
                if not matches:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} requires ungranted "
                        f"MCP tool {qualified_tool!r}"
                    )
                if len(matches) > 1:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} required MCP tool "
                        f"{qualified_tool!r} is ambiguous across granted servers"
                    )
            if mode == "read-only" and task.get("write_scope"):
                raise ValueError(
                    f"profile {profile_id}: read-only smoke task {index} has write_scope"
                )
            if "wall_timeout_seconds" in task:
                _positive_int(
                    task["wall_timeout_seconds"],
                    f"profile {profile_id} smoke task {index}.wall_timeout_seconds",
                    1,
                    172_800,
                )
            if "wait_seconds" in task:
                _positive_int(
                    task["wait_seconds"],
                    f"profile {profile_id} smoke task {index}.wait_seconds",
                    0,
                    120,
                )
            backend = task.get("backend")
            if task_agent == root_agent and backend is not None:
                raise ValueError(
                    f"profile {profile_id}: root smoke task {index} cannot select a backend"
                )
            if backend is not None and backend not in smoke_agent["backends"]:
                raise ValueError(
                    f"profile {profile_id}: smoke task {index} requests unsupported backend {backend!r}"
                )
            selected_backend = backend
            if task_agent != root_agent and selected_backend is None:
                available_backends = list(smoke_agent["backends"])
                selected_backend = (
                    "mcp"
                    if "mcp" in available_backends
                    else (available_backends[0] if len(available_backends) == 1 else None)
                )
                if selected_backend is None:
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} has no executable backend"
                    )
            if task_agent != root_agent and selected_backend == "mcp":
                if smoke_agent["trust"] != "low" and not (
                    int(smoke_agent["min_task_chars"])
                    <= len(task_text)
                    <= int(smoke_agent["max_task_chars"])
                ):
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} length is outside "
                        f"agent {task_agent}'s MCP task bounds"
                    )
                if (
                    mode == "workspace-write"
                    and smoke_agent.get("write_scope_required", True)
                    and not task.get("write_scope")
                ):
                    raise ValueError(
                        f"profile {profile_id}: MCP workspace-write smoke task {index} "
                        "requires write_scope"
                    )
                if task.get("attachments") and not smoke_agent.get("attachments_allowed"):
                    raise ValueError(
                        f"profile {profile_id}: smoke task {index} supplies attachments to "
                        f"agent {task_agent}, which does not permit them"
                    )
    elif "smoke" in profile:
        raise ValueError(f"explicit profile smoke file is missing: {smoke_name}")

    warnings: list[str] = []
    native_agents = [key for key, agent in agents.items() if "native" in agent["backends"]]
    mcp_agents = [key for key, agent in agents.items() if "mcp" in agent["backends"]]
    for key in native_agents:
        agent = agents[key]
        if agent["permissions"] == "workspace-write":
            warnings.append(
                f"native agent {key}: MMO write-scope leasing/audit is unavailable; "
                "Codex sandboxing and integration review remain required"
            )
        if agent["contract_enforcement"] == "strict":
            warnings.append(
                f"native agent {key}: output contract is prompt-enforced only on the native backend"
            )
        credential_servers = [
            server_id
            for server_id in agent["tool_mcp_servers"]
            if tool_mcp_environment_names(tool_mcp_registry[server_id])
        ]
        if credential_servers:
            warnings.append(
                f"native agent {key}: tool MCP credentials for {credential_servers} share the "
                "parent Codex process environment; use the Agent MCP backend for strict "
                "credential isolation"
            )
    if native_agents and coordination["native_nested_delegation"]:
        warnings.append(
            "native nested delegation is advisory: Codex does not expose a supervisor hook "
            "for MMO to mechanically enforce every native edge, depth, resource, or scope limit"
        )

    public_agents: dict[str, Any] = {}
    for key, agent in agents.items():
        item = dict(agent)
        item.pop("model_config", None)
        item.pop("route_config", None)
        public_agents[key] = item
    resolved: dict[str, Any] = {
        "schema_version": MMO_SCHEMA_VERSION,
        "package_version": package_version(),
        "profile": {
            "id": profile_id,
            "version": profile["version"],
            "display_name": profile["display_name"],
            "description": profile["description"],
            "tags": _string_list(profile.get("tags", []), "profile.tags"),
            "maturity": maturity,
            "source": source,
            "root": root_agent,
        },
        "coordination": coordination,
        "routes": {key: routes[key] for key in used_route_keys},
        "models": {key: models[key] for key in used_model_keys},
        "resources": {key: resources[key] for key in used_resource_keys},
        "tool_mcp_servers": {key: tool_mcp_registry[key] for key in used_tool_mcp_server_ids},
        "agents": public_agents,
        "smoke": smoke_data,
        "bindings": supplied_bindings,
        "capabilities": {
            "native_agents": native_agents,
            "mcp_agents": mcp_agents,
            "tool_mcp_servers": used_tool_mcp_server_ids,
            "orchestration": coordination["orchestration"],
        },
        "warnings": warnings,
    }
    # Profile location is discovery metadata, not execution semantics. The same
    # static profile must compile to the same logical identity whether bundled,
    # installed by a user, or addressed directly by path.
    hash_payload = dict(resolved)
    hash_payload["profile"] = dict(resolved["profile"])
    hash_payload["profile"].pop("source", None)
    resolved["logical_hash"] = stable_hash(hash_payload)
    return resolved


def profile_summary(
    value: str | Path, *, bindings: Mapping[str, str] | None = None
) -> dict[str, Any]:
    resolved = resolve_profile(value, bindings=bindings)
    return {
        "id": resolved["profile"]["id"],
        "version": resolved["profile"]["version"],
        "display_name": resolved["profile"]["display_name"],
        "description": resolved["profile"]["description"],
        "maturity": resolved["profile"]["maturity"],
        "root": resolved["profile"]["root"],
        "agents": {
            key: {
                "kind": agent["kind"],
                "model": agent["model"],
                "route": agent["route"],
                "permissions": agent["permissions"],
                "trust": agent["trust"],
                "can_spawn": agent["can_spawn"],
                "backends": agent["backends"],
                "tool_mcp_servers": agent["tool_mcp_servers"],
            }
            for key, agent in resolved["agents"].items()
        },
        "coordination": resolved["coordination"],
        "logical_hash": resolved["logical_hash"],
    }


def active_profile_id() -> str:
    path = config_root() / "active-profile"
    if path.is_file():
        value = path.read_text(encoding="utf-8").strip()
        if value:
            return validate_id(value, "active profile id")
    settings = load_settings()
    configured = settings.get("default_profile")
    if configured:
        return validate_id(configured, "default profile")
    profiles = discover_profiles()
    if not profiles:
        raise RuntimeError("no composition profiles are installed")
    return sorted(profiles)[0]


def set_active_profile(profile_id: str) -> None:
    validate_id(profile_id, "profile id")
    resolve_profile(profile_id)
    atomic_write_text(config_root() / "active-profile", profile_id + "\n", 0o600)


def _safe_archive_target(destination: Path, raw_name: str) -> Path:
    if not raw_name or "\x00" in raw_name or "\\" in raw_name or raw_name.startswith("/"):
        raise ValueError("archive member has an invalid name")
    normalized = raw_name[:-1] if raw_name.endswith("/") else raw_name
    parts = normalized.split("/")
    if not normalized or any(part in {"", ".", ".."} for part in parts):
        raise ValueError(f"unsafe archive member: {raw_name}")
    target = destination.joinpath(*parts).resolve()
    root = destination.resolve()
    if target != root and root not in target.parents:
        raise ValueError(f"unsafe archive member: {raw_name}")
    return target


def _copy_limited(source: Any, output: Any, *, maximum: int, label: str) -> int:
    copied = 0
    while True:
        block = source.read(min(1024 * 1024, maximum - copied + 1))
        if not block:
            return copied
        copied += len(block)
        if copied > maximum:
            raise ValueError(f"profile archive member exceeds {maximum} bytes: {label}")
        output.write(block)


def _safe_extract_archive(archive: Path, destination: Path) -> None:
    if archive.stat().st_size > MAX_PROFILE_ARCHIVE_BYTES:
        raise ValueError(f"profile archive exceeds {MAX_PROFILE_ARCHIVE_BYTES} compressed bytes")
    file_count = 0
    total_bytes = 0
    seen_targets: set[str] = set()
    if archive.suffix.lower() == ".zip":
        with zipfile.ZipFile(archive) as handle:
            infos = handle.infolist()
            if len(infos) > MAX_PROFILE_ARCHIVE_FILES * 2:
                raise ValueError("profile archive contains too many members")
            for info in infos:
                target = _safe_archive_target(destination, info.filename)
                target_key = target.relative_to(destination.resolve()).as_posix()
                if target_key in seen_targets:
                    raise ValueError(f"duplicate profile archive member: {info.filename}")
                seen_targets.add(target_key)
                unix_mode = (info.external_attr >> 16) & 0xFFFF
                file_type = stat.S_IFMT(unix_mode)
                if file_type not in {0, stat.S_IFREG, stat.S_IFDIR}:
                    raise ValueError(f"links and special files are not allowed: {info.filename}")
                if info.flag_bits & 0x1:
                    raise ValueError(
                        f"encrypted profile archive member is not allowed: {info.filename}"
                    )
                if info.is_dir() or file_type == stat.S_IFDIR:
                    target.mkdir(parents=True, exist_ok=True)
                    continue
                file_count += 1
                if file_count > MAX_PROFILE_ARCHIVE_FILES:
                    raise ValueError("profile archive contains too many files")
                if info.file_size > MAX_PROFILE_MEMBER_BYTES:
                    raise ValueError(f"profile archive member exceeds 1 MiB: {info.filename}")
                total_bytes += int(info.file_size)
                if total_bytes > MAX_PROFILE_UNCOMPRESSED_BYTES:
                    raise ValueError("profile archive expands beyond the allowed size")
                if info.file_size and info.compress_size == 0:
                    raise ValueError(f"invalid compressed size for archive member: {info.filename}")
                if (
                    info.compress_size > 0
                    and info.file_size / info.compress_size > MAX_ZIP_COMPRESSION_RATIO
                ):
                    raise ValueError(f"suspicious compression ratio: {info.filename}")
                target.parent.mkdir(parents=True, exist_ok=True)
                with handle.open(info) as source, target.open("wb") as output:
                    copied = _copy_limited(
                        source, output, maximum=MAX_PROFILE_MEMBER_BYTES, label=info.filename
                    )
                if copied != info.file_size:
                    raise ValueError(f"archive member size mismatch: {info.filename}")
    else:
        with tarfile.open(archive, "r|*") as handle:
            member_count = 0
            for member in handle:
                member_count += 1
                if member_count > MAX_PROFILE_ARCHIVE_FILES * 2:
                    raise ValueError("profile archive contains too many members")
                if member.size < 0:
                    raise ValueError(f"archive member has a negative size: {member.name}")
                target = _safe_archive_target(destination, member.name)
                target_key = target.relative_to(destination.resolve()).as_posix()
                if target_key in seen_targets:
                    raise ValueError(f"duplicate profile archive member: {member.name}")
                seen_targets.add(target_key)
                if member.issym() or member.islnk() or member.isdev():
                    raise ValueError(f"links and special files are not allowed: {member.name}")
                if not (member.isdir() or member.isfile()):
                    raise ValueError(f"unsupported archive member: {member.name}")
                if member.isdir():
                    target.mkdir(parents=True, exist_ok=True)
                    continue
                file_count += 1
                if file_count > MAX_PROFILE_ARCHIVE_FILES:
                    raise ValueError("profile archive contains too many files")
                if member.size > MAX_PROFILE_MEMBER_BYTES:
                    raise ValueError(f"profile archive member exceeds 1 MiB: {member.name}")
                total_bytes += int(member.size)
                if total_bytes > MAX_PROFILE_UNCOMPRESSED_BYTES:
                    raise ValueError("profile archive expands beyond the allowed size")
                target.parent.mkdir(parents=True, exist_ok=True)
                tar_source = handle.extractfile(member)
                if tar_source is None:
                    raise ValueError(f"unable to read archive member: {member.name}")
                with tar_source, target.open("wb") as output:
                    copied = _copy_limited(
                        tar_source,
                        output,
                        maximum=MAX_PROFILE_MEMBER_BYTES,
                        label=member.name,
                    )
                if copied != member.size:
                    raise ValueError(f"archive member size mismatch: {member.name}")


def _find_profile_root(extracted: Path) -> Path:
    candidates = [path.parent for path in extracted.rglob("profile.toml")]
    if len(candidates) != 1:
        raise ValueError("profile archive must contain exactly one profile.toml")
    return candidates[0]


def install_profile_pack(source: Path, *, replace: bool = False) -> str:
    source = source.expanduser().resolve()
    with tempfile.TemporaryDirectory(prefix="mmo-profile-") as temporary:
        stage_root = Path(temporary)
        if source.is_dir():
            profile_root = source
        elif source.is_file():
            _safe_extract_archive(source, stage_root)
            profile_root = _find_profile_root(stage_root)
        else:
            raise FileNotFoundError(source)
        errors = validate_profile_pack_tree(profile_root)
        if errors:
            raise ValueError("invalid profile pack: " + "; ".join(errors))
        data = read_toml(profile_root / "profile.toml")
        profile_id = _required_id(data.get("id"), "profile id")
        destination = user_profiles_root() / profile_id
        profiles_root = user_profiles_root()
        profiles_root.mkdir(parents=True, exist_ok=True, mode=0o700)
        staged = Path(tempfile.mkdtemp(prefix=f".{profile_id}.staging-", dir=profiles_root))
        try:
            copy_tree_static(profile_root, staged)
            # Validation reads the path directly, so user profile discovery is irrelevant.
            incoming = resolve_profile(staged)
            if destination.exists():
                try:
                    installed = resolve_profile(destination)
                except (OSError, UnicodeError, ValueError):
                    if not replace:
                        raise FileExistsError(
                            f"profile {profile_id} already exists but is not valid for the active "
                            "generation; use --replace to replace it atomically"
                        ) from None
                else:
                    incoming_content_hash = _profile_pack_content_hash(staged)
                    installed_content_hash = _profile_pack_content_hash(destination)
                    if (
                        incoming["logical_hash"] == installed["logical_hash"]
                        and incoming_content_hash == installed_content_hash
                    ):
                        return profile_id
                    if not replace:
                        raise FileExistsError(
                            f"profile {profile_id} already exists with different "
                            "current-generation content; use --replace to replace it atomically"
                        )
                backup = destination.with_name(f".{profile_id}.backup-{uuid.uuid4().hex}")
                os.replace(destination, backup)
                try:
                    os.replace(staged, destination)
                except Exception:
                    os.replace(backup, destination)
                    raise
                with contextlib.suppress(OSError):
                    shutil.rmtree(backup)
            else:
                os.replace(staged, destination)
        finally:
            if staged.exists():
                shutil.rmtree(staged, ignore_errors=True)
        return profile_id


def remove_profile(profile_id: str) -> None:
    profile_id = validate_id(profile_id, "profile id")
    path = user_profiles_root() / profile_id
    if not path.is_dir():
        if (builtin_profiles_root() / profile_id).is_dir():
            raise ValueError("bundled profiles cannot be removed")
        raise FileNotFoundError(f"user profile not found: {profile_id}")
    if active_profile_id() == profile_id:
        raise ValueError("cannot remove the active profile; select another profile first")
    shutil.rmtree(path)


def clone_profile(source_id: str, destination_id: str, *, replace: bool = False) -> Path:
    source_dir, _ = resolve_profile_dir(source_id)
    destination_id = validate_id(destination_id, "destination profile id")
    destination = user_profiles_root() / destination_id
    if destination.exists() and not replace:
        raise FileExistsError(destination)
    with tempfile.TemporaryDirectory(prefix="mmo-clone-") as temporary:
        staged = Path(temporary) / destination_id
        staged.mkdir(parents=True)
        copy_tree_static(source_dir, staged)
        manifest = staged / "profile.toml"
        text = manifest.read_text(encoding="utf-8")
        replaced, count = re.subn(
            r"""(?m)^(?P<indent>[ \t]*)(?:id|"id"|'id')[ \t]*=[ \t]*"""
            r"""(?:"[^"\r\n]*"|'[^'\r\n]*')(?P<suffix>[ \t]*(?:#[^\r\n]*)?)$""",
            lambda match: f'{match.group("indent")}id = "{destination_id}"{match.group("suffix")}',
            text,
            count=1,
        )
        if count != 1:
            raise ValueError("unable to rewrite profile id")
        manifest.write_text(replaced, encoding="utf-8")
        install_profile_pack(staged, replace=replace)
    return destination
