{"repo": "amd-agi/hyperloom", "files": {"src/hyperloom/inference_optimizer/cli/backends.py": {"4d4df25ca9f7b6e932a8a09163e5337a9f6be65a": {"t": 1785745456.397582, "n": 17878, "h": "b5d80ab34c02dfd4", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and (\n _official_openai_only()\n or os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\"\n )\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "4c05092144e9740f44780d3e9ae6041aa9fdb1a9": {"t": 1785746714.434084, "n": 17878, "h": "b5d80ab34c02dfd4", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and (\n _official_openai_only()\n or os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\"\n )\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "f106d359c05759e3c969c9c7a5833937a6655b6f": {"t": 1785753437.862435, "n": 17878, "h": "b5d80ab34c02dfd4", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and (\n _official_openai_only()\n or os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\"\n )\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "256fa94c4379045fc0ab8946eb09f66b98a9648e": {"t": 1785753439.2502642, "n": 18115, "h": "e9cbd798846be5a2", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and (\n _official_openai_only()\n or os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\"\n )\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "480c02121b240221154b9a7385f88a1df475e99c": {"t": 1785753442.505469, "n": 18022, "h": "a34f5c51d2780ef1", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "0b0b505777041410a4d087e562645dbb6eec7807": {"t": 1785753445.1239462, "n": 18022, "h": "e4228cce83ad5a0f", "c": "# SPDX-FileCopyrightText: 2025 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "caed4dd8e55ab8451be83347b0a33016e9232da0": {"t": 1785753446.54486, "n": 18063, "h": "9da8b247c0dc2223", "c": "# SPDX-FileCopyrightText: 2025 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "db6374f25758ecb8748963ca879fbff6b00a93c6": {"t": 1785753448.0991726, "n": 18034, "h": "d3a048a980705ccf", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "45cf1dd79edab2541c0658a33737c7dae59a2df0": {"t": 1785753450.247721, "n": 20969, "h": "e2081f84b5c1bbeb", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint rather than the native Anthropic Messages path.\n An explicit Anthropic key takes precedence (official Anthropic wins).\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's existing OpenAI review path works unchanged once the client\n base URL / key are set to DeepSeek — without mutating the process env (which\n would flip the provider-only routing decision for the other roles).\n\n The OpenAI SDK appends the route to ``base_url`` verbatim (it does not\n insert ``/v1``), so the default carries the conventional ``/v1`` suffix. An\n explicit ``DEEPSEEK_BASE_URL`` is respected as-is (custom gateways may not\n use ``/v1``).\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only (no OpenAI-compatible gateway): keep the FULL KB+tools\n # critic-agent instead of degrading to plain Claude tool-use. The\n # review inference is driven over the native provider endpoint:\n # - DeepSeek-only -> DeepSeek's OpenAI-compatible /chat/completions\n # - Anthropic-only -> native Anthropic /v1/messages\n # prepare-review / commit-review KB machinery is protocol-independent.\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback only: the critic-agent runtime could not be resolved, so\n # degrade to Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed (``--no-proposal-scoring`` is the explicit off form and the\n default). Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n The flag is not persisted across ``--resume``: a resumed session must\n re-pass ``--proposal-scoring`` to keep scoring on. This is intentional --\n scoring is advisory (it never gates or alters the search), so a resume\n that omits it simply drops the reference signal without affecting\n optimization correctness.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "b82da9c3eaf165c098a7af151d770e03f8d9b934": {"t": 1785753451.7154799, "n": 20874, "h": "335617cdf605bb80", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint rather than the native Anthropic Messages path.\n An explicit Anthropic key takes precedence (official Anthropic wins).\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's existing OpenAI review path works unchanged once the client\n base URL / key are set to DeepSeek — without mutating the process env (which\n would flip the provider-only routing decision for the other roles).\n\n The OpenAI SDK appends the route to ``base_url`` verbatim (it does not\n insert ``/v1``), so the default carries the conventional ``/v1`` suffix. An\n explicit ``DEEPSEEK_BASE_URL`` is respected as-is (custom gateways may not\n use ``/v1``).\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only (no OpenAI-compatible gateway): keep the FULL KB+tools\n # critic-agent instead of degrading to plain Claude tool-use. The\n # review inference is driven over the native provider endpoint:\n # - DeepSeek-only -> DeepSeek's OpenAI-compatible /chat/completions\n # - Anthropic-only -> native Anthropic /v1/messages\n # prepare-review / commit-review KB machinery is protocol-independent.\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback only: the critic-agent runtime could not be resolved, so\n # degrade to Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed (``--no-proposal-scoring`` is the explicit off form and the\n default). Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n The flag is not persisted across ``--resume``: a resumed session must\n re-pass ``--proposal-scoring`` to keep scoring on. This is intentional --\n scoring is advisory (it never gates or alters the search), so a resume\n that omits it simply drops the reference signal without affecting\n optimization correctness.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "50763ddc803db5ec36bc58523c50ed94e8e7b568": {"t": 1785753454.569026, "n": 20327, "h": "570bf60bb62a6e58", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint rather than the native Anthropic Messages path.\n An explicit Anthropic key takes precedence (official Anthropic wins).\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's existing OpenAI review path works unchanged once the client\n base URL / key are set to DeepSeek — without mutating the process env (which\n would flip the provider-only routing decision for the other roles).\n\n The OpenAI SDK appends the route to ``base_url`` verbatim (it does not\n insert ``/v1``), so the default carries the conventional ``/v1`` suffix. An\n explicit ``DEEPSEEK_BASE_URL`` is respected as-is (custom gateways may not\n use ``/v1``).\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only (no OpenAI-compatible gateway): keep the FULL KB+tools\n # critic-agent instead of degrading to plain Claude tool-use. The\n # review inference is driven over the native provider endpoint:\n # - DeepSeek-only -> DeepSeek's OpenAI-compatible /chat/completions\n # - Anthropic-only -> native Anthropic /v1/messages\n # prepare-review / commit-review KB machinery is protocol-independent.\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback only: the critic-agent runtime could not be resolved, so\n # degrade to Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "864ac55b84e5de5391cd0cfb79549165a9a6f5a7": {"t": 1785753455.8848865, "n": 17472, "h": "69e1524d4e862b2b", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only:\n # No OpenAI-compatible endpoint exists, so run the critic role through\n # Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed (``--no-proposal-scoring`` is the explicit off form and the\n default). Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n The flag is not persisted across ``--resume``: a resumed session must\n re-pass ``--proposal-scoring`` to keep scoring on. This is intentional --\n scoring is advisory (it never gates or alters the search), so a resume\n that omits it simply drops the reference signal without affecting\n optimization correctness.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "14f3f77675fffa6625e89efd14be1bef8782ca80": {"t": 1785753457.5367644, "n": 17569, "h": "edf935762a1df0bf", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only:\n # No OpenAI-compatible endpoint exists, so run the critic role through\n # Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--enable-proposal-scoring``\n is passed. Even when enabled, still returns ``None`` when\n ``--no-proposal-scoring`` is set, in Anthropic-only deployments (the\n scorer is OpenAI-compatible only), or when the resolved model list is\n empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The scorer is purely\n advisory and never gates anything.\n\n The flag is not persisted across ``--resume``: a resumed session must\n re-pass ``--enable-proposal-scoring`` to keep scoring on. This is\n intentional -- scoring is advisory (it never gates or alters the search),\n so a resume that omits it simply drops the reference signal without\n affecting optimization correctness.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``enable_proposal_scoring`` /\n ``no_proposal_scoring`` / ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n if not getattr(args, \"enable_proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "5ba52dd103984a8f4c042c21a068d8d0deb847f9": {"t": 1785753458.882005, "n": 20071, "h": "7ca82a639c19561e", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint rather than the native Anthropic Messages path.\n An explicit Anthropic key takes precedence (official Anthropic wins).\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's existing OpenAI review path works unchanged once the client\n base URL / key are set to DeepSeek — without mutating the process env (which\n would flip the provider-only routing decision for the other roles).\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only (no OpenAI-compatible gateway): keep the FULL KB+tools\n # critic-agent instead of degrading to plain Claude tool-use. The\n # review inference is driven over the native provider endpoint:\n # - DeepSeek-only -> DeepSeek's OpenAI-compatible /chat/completions\n # - Anthropic-only -> native Anthropic /v1/messages\n # prepare-review / commit-review KB machinery is protocol-independent.\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback only: the critic-agent runtime could not be resolved, so\n # degrade to Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "b0c37797278ee931c4613065af21e2e5f015b0c2": {"t": 1785753460.0858185, "n": 16925, "h": "38b90440cdaf2cf3", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only:\n # No OpenAI-compatible endpoint exists, so run the critic role through\n # Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "edd199c938a39fec0397ccdd4bfbf01acd2575b2": {"t": 1785753461.2922647, "n": 16145, "h": "2a5d0f8ee9998f80", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n return bool((os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()) and not bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n )\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n return bool((os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()) and not bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n )\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = _official_anthropic_only()\n provider_openai_only = _official_openai_only()\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only:\n # No OpenAI-compatible endpoint exists, so run the critic role through\n # Claude tool-use. The critic system prompt still gates it to\n # review_verdict / advice intents.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Anthropic/Claude-Code endpoint. Use the\n # JSON-intent Codex backend for Orchestration so an OpenAI-only config\n # can still drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the model's plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only; avoid calling official\n # OpenAI with an Anthropic key in Anthropic-only deployments.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "02464f032152b6a88fb5b357c6c93e404fb4a82e": {"t": 1785753463.13639, "n": 14696, "h": "3c08d1cdc95024ad", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n backends: dict[str, Any] = {\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the\n # model's plan / chain-of-thought persists instead of being\n # re-derived from a full state dump each turn. The conversational\n # floors (max_turns / call_timeout) are applied inside\n # ClaudeBackend.__post_init__. kernel / critic / robustness keep\n # the stateless per-tick reactor mode.\n \"orchestration\": ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n ),\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity. Prompt composition is unchanged\n # (still full state per turn) — this is resume-only, no delta.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "46e173e686de1e75413340686d14529c225f2ec2": {"t": 1785753486.7203991, "n": 14318, "h": "3fe378ba2985adc3", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n backends: dict[str, Any] = {\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the\n # model's plan / chain-of-thought persists instead of being\n # re-derived from a full state dump each turn. The conversational\n # floors (max_turns / call_timeout) are applied inside\n # ClaudeBackend.__post_init__. kernel / critic / robustness keep\n # the stateless per-tick reactor mode.\n \"orchestration\": ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n ),\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "1fbca8970e984df3b7c3c7677b8e3285c595f8a8": {"t": 1785753490.0992877, "n": 13447, "h": "6591a68658054f9b", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n backends: dict[str, Any] = {\n # Orchestration runs as a persistent ReAct conversation: the same\n # Claude session is resumed across ticks so the\n # model's plan / chain-of-thought persists instead of being\n # re-derived from a full state dump each turn. The conversational\n # floors (max_turns / call_timeout) are applied inside\n # ClaudeBackend.__post_init__. kernel / critic / robustness keep\n # the stateless per-tick reactor mode.\n \"orchestration\": ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n ),\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n backends[\"kernel_agent\"] = ClaudeBackend(model=claude_model, max_turns_default=5)\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "328c2d0151ca686072eeb34819de93450d446a1b": {"t": 1785753493.458317, "n": 14332, "h": "c628ebcaf0816562", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` (5, unchanged default)\n on unset/invalid/<=0. Lets an operator raise the budget to avoid a\n \"Reached maximum number of turns\" failure on complex kernel tasks\n without editing the reactor logic.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n backends: dict[str, Any] = {\n # Orchestration runs as a persistent ReAct conversation (plan\n # Step 1): the same Claude session is resumed across ticks so the\n # model's plan / chain-of-thought persists instead of being\n # re-derived from a full state dump each turn. The conversational\n # floors (max_turns / call_timeout) are applied inside\n # ClaudeBackend.__post_init__. kernel / critic / robustness keep\n # the stateless per-tick reactor mode.\n \"orchestration\": ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n ),\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "14bc9cdd44c72fb23b3f22a8853d185a7a7a7e21": {"t": 1785753495.045411, "n": 13461, "h": "c5f15af55c5fa1b1", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n cortex_kb_url: str | None = None,\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n cortex_kb_url: Optional Cortex KB URL for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n # Feed the registry-derived per-action verdict policy so the\n # critic-agent runtime sees\n # ``review_constraints.action_verdict_policy[]`` and\n # approves exploration / archival actions without demanding the\n # before/after evidence they themselves produce.\n try:\n from hyperloom.orchestrator.actions.registry import (\n ActionRegistry,\n )\n\n _reg = ActionRegistry().load()\n _policy = {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n _policy = {}\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n cortex_kb_url=cortex_kb_url,\n action_verdict_policy=_policy,\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n backends: dict[str, Any] = {\n # Orchestration runs as a persistent ReAct conversation (plan\n # Step 1): the same Claude session is resumed across ticks so the\n # model's plan / chain-of-thought persists instead of being\n # re-derived from a full state dump each turn. The conversational\n # floors (max_turns / call_timeout) are applied inside\n # ClaudeBackend.__post_init__. kernel / critic / robustness keep\n # the stateless per-tick reactor mode.\n \"orchestration\": ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n ),\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n backends[\"kernel_agent\"] = ClaudeBackend(model=claude_model, max_turns_default=5)\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Returns ``None`` when ``--no-proposal-scoring`` is set or the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger (component=proposal_scorer); when\n omitted the scorer simply skips trace writes.\n\n Args:\n args: Parsed CLI args (``no_proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if getattr(args, \"no_proposal_scoring\", False):\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node policy (``--nodes >= 2``): the agent must source signals\n from the cluster (robustness-server) rather than the local sandbox,\n else the per-pod LocalProbe trips false ``ray_head_dead`` /\n ``local_server_unreachable`` symptoms. We therefore default\n ``disable_local_probe`` + ``enable_cluster_pod_metrics`` to True,\n forward a workload_uid hint, disable the 127.0.0.1:8888 auto-probe,\n and lift the ``no_levers_found`` floor to 60 min.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` so the 127.0.0.1:8888 /health\n probe is silenced (the optimizer's per-benchmark server restarts\n otherwise trip the same false ``local_server_unreachable``), while the\n rest of LocalProbe keeps running. All other single-node semantics stay\n untouched. Scriptable (server-less) frameworks (e.g. xDiT) default the\n same probe OFF since they never run an inference server.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health\n # auto-probe inside LocalProbe.\n # * Multi-node: the inference server lives in the head pod, so the probe\n # can never succeed and would flood the bus with false-positive\n # ``local_server_unreachable`` symptoms — default it OFF.\n # * Single-node: the optimizer restarts the inference server between\n # benchmarks; those restart windows trip the SAME false positive (and\n # can escalate to a premature skip_to_close / robustness_escalated stop).\n # Operators opt in via ``--robustness-disable-server-probe``. Unlike\n # ``--robustness-disable-local-probe`` this is surgical: only the\n # 127.0.0.1:8888 probe is silenced; the rest of LocalProbe (gpu-leak,\n # gateway 401, coordinator-zombie, aiter-JIT, disk/fd) keeps running.\n # * Scriptable (server-less) frameworks (e.g. xDiT diffusion): there is\n # never an inference server, so the 127.0.0.1:8888 probe can never\n # succeed and would false-fire local_server_unreachable every tick —\n # default it OFF (like multi-node). FRAMEWORK is exported before this\n # call; --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # B3 no_levers_found floor — multi-node large-model spends\n # 35-50 min on sglang cold start + baseline + profile +\n # turnaround alone before the first explore family runs, so lift\n # the elapsed-time floor from 45 to 60 minutes (single-node\n # default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}, "2c3802738a7d93ec2447c0bb2d894b0aa8a4871e": {"t": 1786067721.1373978, "n": 17878, "h": "b5d80ab34c02dfd4", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Per-role backend construction + robustness option wiring for the CLI.\n\nBuilds the orchestration / critic / robustness / kernel backends, the\nadvisory proposal scorer, and robustness ``request.options`` overrides from\nparsed CLI args. Imports orchestrator packages only (must not import ``cli``).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Any\n\nfrom .. import framework_registry\nfrom hyperloom.common.env import env_bool\nfrom hyperloom.orchestrator.roles import (\n ClaudeBackend,\n CodexBackend,\n CriticAgentBackend,\n MockCriticBackend,\n MockRobustnessBackend,\n RobustnessAgentBackend,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS, ProposalScorer\n\n\n_KERNEL_AGENT_DEFAULT_MAX_TURNS = 5\n\n\ndef _official_anthropic_only() -> bool:\n \"\"\"True when only the Anthropic-side endpoint is available.\"\"\"\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_anthropic and not has_openai\n\n\ndef _official_openai_only() -> bool:\n \"\"\"True when only the OpenAI-side endpoint is available.\"\"\"\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n has_anthropic = bool(\n (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip()\n or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n return has_openai and not has_anthropic\n\n\ndef _deepseek_only() -> bool:\n \"\"\"True for a DeepSeek-keyed provider-only config with no Anthropic key.\n\n DeepSeek is natively OpenAI-compatible, so its critic review runs over the\n DeepSeek OpenAI endpoint. An explicit Anthropic key takes precedence.\n \"\"\"\n has_deepseek = bool(\n (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n )\n has_anthropic_key = bool(\n (os.environ.get(\"ANTHROPIC_API_KEY\") or \"\").strip() or (os.environ.get(\"ANTHROPIC_AUTH_TOKEN\") or \"\").strip()\n )\n has_openai = bool(\n (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip() or (os.environ.get(\"OPENAI_API_KEY\") or \"\").strip()\n )\n return has_deepseek and not has_anthropic_key and not has_openai\n\n\ndef _deepseek_openai_client_factory() -> Any:\n \"\"\"Build a factory that points the critic's OpenAI client at DeepSeek.\n\n DeepSeek exposes an OpenAI-compatible ``/chat/completions`` API, so the\n critic-agent's OpenAI review path works once the client base URL / key are\n set to DeepSeek, without mutating the process env. The OpenAI SDK appends\n the route to ``base_url`` verbatim, so the default carries the ``/v1``\n suffix; an explicit ``DEEPSEEK_BASE_URL`` is respected as-is.\n \"\"\"\n base_url = (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"https://api.deepseek.com/v1\").strip().rstrip(\"/\")\n api_key = (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n\n def _factory() -> Any:\n from openai import AsyncOpenAI # local import: keep module import-light\n\n return AsyncOpenAI(base_url=base_url, api_key=api_key)\n\n return _factory\n\n\ndef _load_action_verdict_policy() -> dict[str, str]:\n \"\"\"Return the registry-derived per-action verdict policy (or empty on error).\n\n Feeds ``review_constraints.action_verdict_policy[]`` so the\n critic-agent approves exploration / archival actions without demanding the\n before/after evidence they themselves produce.\n \"\"\"\n try:\n from hyperloom.orchestrator.actions.registry import ActionRegistry\n\n _reg = ActionRegistry().load()\n return {a.name: a.verdict_class for a in _reg.all()}\n except Exception: # noqa: BLE001 — degrade to empty policy\n return {}\n\n\ndef _resolve_kernel_agent_max_turns() -> int:\n \"\"\"Resolve the kernel_agent Claude turn budget.\n\n Reads ``INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS`` (a positive int);\n falls back to ``_KERNEL_AGENT_DEFAULT_MAX_TURNS`` on unset/invalid/<=0.\n \"\"\"\n raw = os.environ.get(\"INFERENCE_OPTIMIZER_KERNEL_AGENT_MAX_TURNS\", \"\").strip()\n if not raw:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n try:\n val = int(raw)\n except ValueError:\n return _KERNEL_AGENT_DEFAULT_MAX_TURNS\n return val if val >= 1 else _KERNEL_AGENT_DEFAULT_MAX_TURNS\n\n\ndef _build_backends(\n *,\n claude_model: str,\n codex_model: str,\n kernel_codex: bool,\n critic_choice: str,\n session_dir: Path,\n critic_agent_root: Path | None = None,\n critic_kb_mode: str = \"inmemory\",\n robustness_choice: str = \"mock\",\n robustness_agent_root: Path | None = None,\n robustness_options: dict[str, Any] | None = None,\n no_kernel: bool = False,\n codex_follows_claude: bool = False,\n) -> dict[str, Any]:\n \"\"\"Construct all per-role backends.\n\n ``critic_choice`` ∈ {``mock``, ``agent``}: mock is the always-approve\n adapter; ``agent`` is :class:`CriticAgentBackend` (requires\n ``critic_agent_root``). ``robustness_choice`` ∈ {``mock``, ``agent``}:\n mock is the heartbeat-only backend; ``agent`` is\n :class:`RobustnessAgentBackend` (requires ``robustness_agent_root``).\n\n Args:\n claude_model: Claude model id for the orchestration / kernel backends.\n codex_model: Codex model id for the kernel / critic backends.\n kernel_codex: Use a Codex backend for the kernel_agent role when ``True``.\n critic_choice: Critic backend selector (``mock`` or ``agent``).\n session_dir: Session directory passed to agent backends.\n critic_agent_root: Critic-agent root, required when\n ``critic_choice='agent'``.\n critic_kb_mode: Knowledge-base mode for the critic agent.\n robustness_choice: Robustness backend selector (``mock`` or ``agent``).\n robustness_agent_root: Robustness-agent root, required when\n ``robustness_choice='agent'``.\n robustness_options: Optional ``request.options`` overrides for the\n robustness agent.\n no_kernel: Skip building the kernel backend when ``True``.\n\n Returns:\n A mapping of role name to its constructed backend.\n\n Raises:\n ValueError: If ``critic_choice`` / ``robustness_choice`` is invalid, or\n an ``agent`` choice is missing its required agent root.\n \"\"\"\n if critic_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: critic_choice={critic_choice!r} not in {{'mock','agent'}}\")\n\n provider_anthropic_only = codex_follows_claude or _official_anthropic_only()\n provider_openai_only = (not codex_follows_claude) and (\n _official_openai_only()\n or os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\"\n )\n\n if critic_choice == \"mock\":\n critic_backend: Any = MockCriticBackend()\n elif provider_anthropic_only and critic_agent_root is not None:\n # Provider-only: keep the full KB+tools critic-agent, driving review\n # inference over the native provider endpoint (DeepSeek OpenAI-compatible\n # or Anthropic /v1/messages).\n _policy = _load_action_verdict_policy()\n if _deepseek_only():\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"openai\",\n codex_model=claude_model,\n codex_client_factory=_deepseek_openai_client_factory(),\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n else:\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n protocol=\"anthropic\",\n claude_model=claude_model,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_policy,\n )\n elif provider_anthropic_only:\n # Fallback: critic-agent runtime unresolved, degrade to Claude tool-use.\n critic_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n )\n else: # \"agent\"\n if critic_agent_root is None:\n raise ValueError(\"_build_backends: critic_choice='agent' requires critic_agent_root\")\n critic_backend = CriticAgentBackend(\n critic_agent_root=critic_agent_root,\n session_dir=session_dir,\n codex_model=codex_model,\n kb_mode=critic_kb_mode,\n action_verdict_policy=_load_action_verdict_policy(),\n )\n\n if robustness_choice not in (\"mock\", \"agent\"):\n raise ValueError(f\"_build_backends: robustness_choice={robustness_choice!r} not in {{'mock','agent'}}\")\n if robustness_choice == \"mock\":\n robustness_backend: Any = MockRobustnessBackend()\n else: # \"agent\"\n if robustness_agent_root is None:\n raise ValueError(\"_build_backends: robustness_choice='agent' requires robustness_agent_root\")\n robustness_backend = RobustnessAgentBackend(\n robustness_agent_root=robustness_agent_root,\n session_dir=session_dir,\n options=robustness_options,\n )\n\n if provider_openai_only:\n # Official OpenAI has no Claude endpoint; use the Codex backend for\n # Orchestration so an OpenAI-only config can drive the coordinator.\n orchestration_backend: Any = CodexBackend(model=codex_model)\n else:\n # Orchestration runs as a persistent ReAct conversation: the Claude\n # session is resumed across ticks so the plan persists.\n orchestration_backend = ClaudeBackend(\n model=claude_model,\n max_turns_default=4,\n conversational=True,\n )\n\n backends: dict[str, Any] = {\n \"orchestration\": orchestration_backend,\n \"critic\": critic_backend,\n \"robustness\": robustness_backend,\n }\n if not no_kernel:\n if provider_anthropic_only:\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n )\n elif provider_openai_only or kernel_codex:\n backends[\"kernel_agent\"] = CodexBackend(model=codex_model)\n else:\n # Opt-in (default off): resume the kernel Claude session across LLM\n # turns for prompt-cache continuity.\n backends[\"kernel_agent\"] = ClaudeBackend(\n model=claude_model,\n max_turns_default=_resolve_kernel_agent_max_turns(),\n conversational=env_bool(\"INFERENCE_OPTIMIZER_KERNEL_CLAUDE_CONVERSATIONAL\", False),\n )\n return backends\n\n\ndef _build_proposal_scorer(\n args: argparse.Namespace,\n session_dir: Path | None = None,\n) -> ProposalScorer | None:\n \"\"\"Construct the advisory specialist-proposal scorer, or ``None``.\n\n Disabled by default: returns ``None`` unless ``--proposal-scoring`` is\n passed. Even when enabled, still returns ``None`` in Anthropic-only\n deployments (the scorer is OpenAI-compatible only) or when the resolved\n model list is empty (defaults to :data:`DEFAULT_SCORER_MODELS`). The\n scorer is purely advisory and never gates anything. The flag is not\n persisted across ``--resume``.\n\n ``session_dir`` is forwarded so the scorer can append its per-model\n token usage to the full-trace ledger; when omitted trace writes are skipped.\n\n Args:\n args: Parsed CLI args (``proposal_scoring`` /\n ``proposal_scorer_models``).\n session_dir: Optional session directory for token-usage trace writes.\n\n Returns:\n A configured :class:`ProposalScorer`, or ``None`` when scoring is\n disabled or no models resolve.\n \"\"\"\n if not getattr(args, \"proposal_scoring\", False):\n return None\n if _official_anthropic_only():\n # ProposalScorer is OpenAI-compatible only.\n return None\n raw = getattr(args, \"proposal_scorer_models\", None)\n if raw is None:\n models = tuple(DEFAULT_SCORER_MODELS)\n else:\n models = tuple(m for m in (s.strip() for s in str(raw).split(\",\")) if m)\n if not models:\n return None\n return ProposalScorer(models=models, session_dir=session_dir)\n\n\ndef _robustness_server_configured(args: argparse.Namespace) -> bool:\n \"\"\"Return True when a robustness-server endpoint is configured.\n\n The server is the only cluster-wide signal source on multi-node; when\n wired the agent runs with ``disable_local_probe`` /\n ``enable_cluster_pod_metrics`` and the sandbox-local LocalProbe false\n positives are silenced. Configured = ``--robustness-server-url`` or\n ``ROBUSTNESS_SERVER_URL`` is set.\n\n Args:\n args: Parsed CLI args carrying ``robustness_server_url``.\n\n Returns:\n ``True`` when a robustness-server endpoint is configured via flag or\n environment.\n \"\"\"\n url = (getattr(args, \"robustness_server_url\", None) or \"\").strip()\n if url:\n return True\n return bool((os.environ.get(\"ROBUSTNESS_SERVER_URL\") or \"\").strip())\n\n\n_MULTI_NODE_WORKLOAD_UID_ENV_KEYS: tuple[str, ...] = (\n \"ROBUSTNESS_WORKLOAD_UID\",\n \"CLAW_WORKLOAD_UID\",\n \"WORKLOAD_UID\",\n \"KUBE_WORKLOAD_UID\",\n \"RAY_JOB_ID\",\n)\n\n\ndef _build_robustness_options(args: argparse.Namespace) -> dict[str, Any]:\n \"\"\"Collect non-default ``request.options`` overrides from CLI flags.\n\n Only emits keys the operator actually passed so the runtime CLI falls\n back to its own defaults / env-discovery for the rest.\n\n Multi-node (``--nodes >= 2``): defaults ``disable_local_probe`` +\n ``enable_cluster_pod_metrics`` to True, forwards a workload_uid hint,\n disables the 127.0.0.1:8888 auto-probe, and lifts the ``no_levers_found``\n floor to 60 min so cluster-sourced signals replace the local sandbox.\n\n Single-node opt-in: ``--robustness-disable-server-probe`` sets\n ``auto_probe_inference_server=False`` to silence the 127.0.0.1:8888 /health\n probe while the rest of LocalProbe keeps running. Scriptable (server-less)\n frameworks (e.g. xDiT) default the same probe OFF.\n\n Args:\n args: Parsed CLI args carrying the robustness-related flags.\n\n Returns:\n The non-default ``request.options`` overrides derived from the flags\n (and multi-node policy); keys the operator did not set are omitted.\n \"\"\"\n options: dict[str, Any] = {}\n server_url = getattr(args, \"robustness_server_url\", None)\n if server_url is not None:\n options[\"robustness_server_url\"] = server_url\n llm_rca = getattr(args, \"robustness_llm_rca\", None)\n if llm_rca is not None:\n options[\"llm_rca_enabled\"] = bool(llm_rca)\n\n nodes = int(getattr(args, \"nodes\", 1) or 1)\n multi_node = nodes >= 2\n if nodes > 1:\n options[\"nodes\"] = nodes\n\n workload_uid = (getattr(args, \"robustness_workload_uid\", None) or \"\").strip()\n if not workload_uid:\n for key in _MULTI_NODE_WORKLOAD_UID_ENV_KEYS:\n candidate = (os.environ.get(key) or \"\").strip()\n if candidate:\n workload_uid = candidate\n break\n if workload_uid:\n options[\"workload_uid\"] = workload_uid\n\n disable_local = getattr(args, \"robustness_disable_local_probe\", None)\n if disable_local is None and multi_node:\n disable_local = True\n if disable_local is not None:\n options[\"disable_local_probe\"] = bool(disable_local)\n\n enable_pod_metrics = getattr(args, \"robustness_enable_cluster_pod_metrics\", None)\n if enable_pod_metrics is None and multi_node:\n enable_pod_metrics = True\n if enable_pod_metrics is not None:\n options[\"enable_cluster_pod_metrics\"] = bool(enable_pod_metrics)\n\n categories_raw = getattr(args, \"robustness_pod_metrics_categories\", None)\n if categories_raw:\n if isinstance(categories_raw, (list, tuple)):\n cat_iter = categories_raw\n else:\n cat_iter = str(categories_raw).split(\",\")\n cat_list = [c.strip() for c in cat_iter if str(c).strip()]\n if cat_list:\n options[\"pod_metrics_categories\"] = cat_list\n\n # ``auto_probe_inference_server`` controls the 127.0.0.1:8888 /health probe\n # in LocalProbe. Default it OFF for multi-node (server lives in the head pod)\n # and scriptable server-less frameworks; single-node operators opt in via\n # ``--robustness-disable-server-probe``. --framework wins, then $FRAMEWORK.\n fw = (getattr(args, \"framework\", None) or os.environ.get(\"FRAMEWORK\", \"\")).strip()\n scriptable_fw = framework_registry.is_scriptable(fw) if fw else False\n disable_server_probe = getattr(args, \"robustness_disable_server_probe\", None)\n if disable_server_probe is None and (multi_node or scriptable_fw):\n disable_server_probe = True\n if disable_server_probe is not None:\n options[\"auto_probe_inference_server\"] = not bool(disable_server_probe)\n\n if multi_node:\n # Lift the no_levers_found elapsed-time floor to 60 min for multi-node\n # (single-node default 45.0 stays untouched).\n options[\"progress_no_levers_min_minutes\"] = 60.0\n\n return options\n"}}, "src/hyperloom/inference_optimizer/tests/test_model_config_compat_preflight.py": {"4c05092144e9740f44780d3e9ae6041aa9fdb1a9": {"t": 1785747159.7366834, "n": 50706, "h": "077cf6db1a1fdd4a", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4, \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\", \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"adapter_model.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"model-00001.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd)))\n monkeypatch.setattr(bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd)))\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\": \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"org/repo\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(cli_model_gate, \"resolve_local_model_dir\", lambda mp: None)\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"/raw/model/path\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "480c02121b240221154b9a7385f88a1df475e99c": {"t": 1785753439.1241376, "n": 50706, "h": "077cf6db1a1fdd4a", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4, \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\", \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"adapter_model.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"model-00001.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd)))\n monkeypatch.setattr(bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd)))\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\": \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"org/repo\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(cli_model_gate, \"resolve_local_model_dir\", lambda mp: None)\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"/raw/model/path\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "0b0b505777041410a4d087e562645dbb6eec7807": {"t": 1785753440.910954, "n": 50706, "h": "a731a28ed6a81775", "c": "# SPDX-FileCopyrightText: 2025 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4, \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\", \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"adapter_model.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"model-00001.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd)))\n monkeypatch.setattr(bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd)))\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\": \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"org/repo\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(cli_model_gate, \"resolve_local_model_dir\", lambda mp: None)\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"/raw/model/path\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "caed4dd8e55ab8451be83347b0a33016e9232da0": {"t": 1785753443.7964716, "n": 50450, "h": "889d1c5fd2db3f3b", "c": "# SPDX-FileCopyrightText: 2025 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(\n spec, model_path=\"org/repo\", data={}, gpu_type=None\n )\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(\n cli_model_gate, \"resolve_local_model_dir\", lambda mp: None\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(\n spec, model_path=\"/raw/model/path\", data={}, gpu_type=None\n )\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "1fca6a8fbedfdf59ab18878eff6de109a581539c": {"t": 1785753445.275247, "n": 50421, "h": "a22009a730e9fd61", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(\n spec, model_path=\"org/repo\", data={}, gpu_type=None\n )\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(\n cli_model_gate, \"resolve_local_model_dir\", lambda mp: None\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(\n spec, model_path=\"/raw/model/path\", data={}, gpu_type=None\n )\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "db6374f25758ecb8748963ca879fbff6b00a93c6": {"t": 1785753446.8116772, "n": 48789, "h": "b6d589eb5a5299ac", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "f5e85e8820958e50bb8a3f1eafda4e148fb7bb0e": {"t": 1785753448.6691394, "n": 50413, "h": "7e545ce421705604", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4: the current runtime (transformers 5.8.1 + vLLM 0.21.0 rocm722)\n # resolves DeepseekV4Config via AutoConfig and vLLM get_config, so it was\n # removed from the unrecognized blocklist and is no longer fail-fasted by the\n # model-config gate.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "670e1985368d0a3da32c5f293610dbcbf708194d": {"t": 1785753450.1267483, "n": 48917, "h": "35c3154ff49a193e", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4: the current runtime (transformers 5.8.1 + vLLM 0.21.0 rocm722)\n # resolves DeepseekV4Config via AutoConfig and vLLM get_config, so it was\n # removed from the unrecognized blocklist and is no longer fail-fasted by the\n # model-config gate.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "0172aac076e5c2882b9e51cfb33e83ef3e4d8355": {"t": 1785753453.2906585, "n": 48899, "h": "7ddcc42329a7f01a", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer import cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4: the current runtime (transformers 5.8.1 + vLLM 0.21.0 rocm722)\n # resolves DeepseekV4Config via AutoConfig and vLLM get_config, so it was\n # removed from the unrecognized blocklist and is no longer fail-fasted by the\n # model-config gate.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "02a1fa7361e5418e691d50b4f923d390c16d942a": {"t": 1785753454.7146447, "n": 48775, "h": "0c3d8eda99986910", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_unrecognized_blocked(tmp_path):\n # DeepSeek-V4 currently fails sglang ModelConfig validation during server init.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "49cfd818f9736416984e50bb9ccf79d820d735a9": {"t": 1785753456.254062, "n": 48757, "h": "b6aa452b9cf17ded", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer import cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_unrecognized_blocked(tmp_path):\n # DeepSeek-V4 currently fails sglang ModelConfig validation during server init.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "14bc9cdd44c72fb23b3f22a8853d185a7a7a7e21": {"t": 1785753457.6753895, "n": 48766, "h": "11bf9e80b58c1610", "c": "# Copyright Advanced Micro Devices, Inc. All rights reserved.\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present\nbut statically known to crash vLLM/transformers at load — a corrupt config, or\na RoPE block without any max-position field (the DeepSeek-V3.2-Exp shape that\ndies with \"'PreTrainedConfig' object has no attribute 'max_position_embeddings'\"\ndeep in engine init). A fully absent config is NOT blocked (soft-degrade).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer import cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # _detect_incompatible_model_config -> _resolve_amd_gpu_type ->\n # _autodetect_gpu_type all live in cli_model_gate after the phase-6D fold;\n # patch the real call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert (\n cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n )\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_unrecognized_blocked(tmp_path):\n # DeepSeek-V4 currently fails sglang ModelConfig validation during server init.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # zai-org GLM-5.x (glm_moe_dsa): the current stack (transformers 5.12.1 +\n # vLLM 0.24.0) registers it (AutoConfig resolves GlmMoeDsaConfig, vLLM\n # ModelRegistry registers GlmMoeDsaForCausalLM; gfx942 sparse-MLA falls back\n # to Triton via vllm-project/vllm#45782). It was removed from the\n # unrecognized blocklist, so it is no longer fail-fasted by the gate.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # google-gemma-4-26B-A4B-it: the current pinned stack (transformers 5.5.0 +\n # vLLM 0.18.2rc1) registers gemma4 (CONFIG_MAPPING has \"gemma4\", AutoConfig\n # resolves Gemma4Config, vLLM ModelConfig resolves Gemma4ForCausalLM). It was\n # removed from the unrecognized blocklist, so a plain text Gemma4 config is no\n # longer fail-fasted by the model-config gate.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # #649 does not add Bailing filters; keep these out of the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # #649 does not add Ovis filters; keep this out of the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # The Qwen3.5-MoE wrapper exposes text_config.model_type=qwen3_5_moe_text.\n # The current runtime registers Qwen3_5MoeConfig/Qwen3_5MoeTextConfig and\n # vLLM ModelRegistry knows Qwen3_5MoeForConditionalGeneration, so the nested\n # type is no longer gated and falls through to the text_coercible degraded\n # path.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope rope_scaling: even a canonical 3-key rope_scaling crashes,\n# because transformers folds the top-level rope_theta into it at load so the\n# Phi3Config validator sees 4 keys and raises before any override can apply.\n# This mirrors the real failing checkpoints (Seacom/anakin87/ReDiX/SciPhi).\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# Gemma2 missing hidden_act: sglang's gemma2 runtime reads config.hidden_act\n# unconditionally; some checkpoints ship only hidden_activation (the HF name)\n# and crash with AttributeError in engine init. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4,\n \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m, model_type=\"qwen3_5\", max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m, model_type=\"llama\", max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\",\n \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"adapter_model.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\n \"model-00001.safetensors\"\n ),\n }}),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — the pre-flight gates exit before\n# coordinator.run()'s finally (the normal Langfuse flush point), so each must\n# push the breakdown to Langfuse itself or early-aborted sessions land on disk\n# (collector) but never in Langfuse.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(\n lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd))\n )\n monkeypatch.setattr(\n bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd))\n )\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m, model_type=\"qwen3\", max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps({\"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\":\n \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\":\n \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }}), encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n"}, "2c3802738a7d93ec2447c0bb2d894b0aa8a4871e": {"t": 1786068089.5850646, "n": 50706, "h": "077cf6db1a1fdd4a", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4, \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\", \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"adapter_model.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"model-00001.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd)))\n monkeypatch.setattr(bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd)))\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\": \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"org/repo\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(cli_model_gate, \"resolve_local_model_dir\", lambda mp: None)\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"/raw/model/path\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}, "43b48fa732ad3f48df30f529fb8847286f110a59": {"t": 1786068551.6477392, "n": 50706, "h": "077cf6db1a1fdd4a", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"Tests for the model-config compatibility preflight.\n\nPolicy: fail fast (with a persisted stop reason) when config.json is present but\nstatically known to crash vLLM/transformers at load (corrupt config, or a RoPE\nblock without any max-position field). A fully absent config is NOT blocked.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport struct\nfrom pathlib import Path\n\nimport pytest\n\nfrom hyperloom.inference_optimizer.cli import model_gate as cli\nfrom hyperloom.inference_optimizer.cli import model_gate as cli_model_gate\n\n\ndef _write_config(model_dir: Path, *, with_tokenizer: bool = True, **fields) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"config.json\").write_text(json.dumps(fields), encoding=\"utf-8\")\n # Most config-compat tests are unrelated to the tokenizer-artifact check;\n # ship a tokenizer by default so they exercise only the field they target.\n if with_tokenizer:\n (model_dir / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n\ndef _args(model: str, *, gpu_type: str | None = None) -> argparse.Namespace:\n return argparse.Namespace(model=model, isl=1024, osl=1024, gpu_type=gpu_type)\n\n\ndef _seed_state(session_dir: Path, monkeypatch):\n monkeypatch.setenv(\n \"INFERENCE_OPTIMIZER_CURRENT_SESSION_DIR\",\n str(session_dir),\n )\n from hyperloom.orchestrator.state.shared_state import SharedState\n\n session_dir.mkdir(parents=True, exist_ok=True)\n (session_dir / \"reports\").mkdir(parents=True, exist_ok=True)\n SharedState(session_id=\"t\", model_name=\"m\", model_path=\"m\").save(session_dir)\n\n\n@pytest.fixture(autouse=True)\ndef _default_non_amd_gpu(monkeypatch):\n \"\"\"Keep config checks hermetic unless a test passes gpu_type explicitly.\"\"\"\n monkeypatch.delenv(\"GPU_TYPE\", raising=False)\n # Patch the real GPU autodetect call site (cli re-exports the same object).\n monkeypatch.setattr(cli_model_gate, \"_autodetect_gpu_type\", lambda: None)\n\n\n# ---------------------------------------------------------------------------\n# _detect_incompatible_model_config\n# ---------------------------------------------------------------------------\ndef test_compat_detector_registry_order_is_pinned():\n \"\"\"The waterfall order is a behavioral contract (first match wins).\n\n Steps 1 (diffusers) and 2 (config absent/corrupt) are the inline prologue in\n ``_detect_incompatible_model_config``; this registry is steps 3-15. Pin the\n exact order + the amd_only / skip_when_scriptable flags so an accidental\n reorder (which would silently change which reason wins) is caught.\n \"\"\"\n specs = cli_model_gate._COMPAT_DETECTORS\n assert [s.name for s in specs] == [\n \"amd_unsupported_quant\", # 3\n \"amd_unsupported_architecture\", # 4\n \"null_strict_bool\", # 5\n \"rope_without_max_position\", # 6\n \"phi3_rope_scaling\", # 7\n \"gemma2_hidden_act\", # 8\n \"unrecognized_architecture\", # 9\n \"private_quant\", # 10\n \"peft_adapter_only\", # 11\n \"vocab_weight_shape\", # 12\n \"tokenizer_artifacts\", # 13\n \"unregistered_custom_autoconfig\", # 14\n \"amd_dual_chunk_attention\", # 15\n ]\n assert {s.name for s in specs if s.amd_only} == {\n \"amd_unsupported_quant\",\n \"amd_unsupported_architecture\",\n \"amd_dual_chunk_attention\",\n }\n assert {s.name for s in specs if s.skip_when_scriptable} == {\n \"tokenizer_artifacts\",\n }\n # Step 13 is a 3-detector short-circuiting sub-chain.\n tok = next(s for s in specs if s.name == \"tokenizer_artifacts\")\n assert isinstance(tok.fn, tuple)\n assert len(tok.fn) == 3\n\n\ndef test_detect_healthy_config_returns_none(tmp_path):\n m = tmp_path / \"ok\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=4096)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_diffusers_pipeline_blocks_without_config_json(tmp_path):\n m = tmp_path / \"flux\"\n m.mkdir()\n (m / \"model_index.json\").write_text(\n json.dumps({\"_class_name\": \"FluxPipeline\"}),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"Diffusers pipeline\" in reason\n assert \"causal LM\" in reason\n\n\ndef test_detect_null_use_cache_blocks_strict_config_validation(tmp_path):\n m = tmp_path / \"null_use_cache\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=4096,\n use_cache=None,\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"use_cache\" in reason\n assert \"StrictDataclassFieldValidationError\" in reason\n\n\ndef test_detect_null_use_cache_in_text_config_blocks(tmp_path):\n m = tmp_path / \"nested_null_use_cache\"\n _write_config(\n m,\n model_type=\"wrapper\",\n max_position_embeddings=4096,\n text_config={\"model_type\": \"qwen2\", \"use_cache\": None},\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"text_config.use_cache\" in reason\n\n\ndef test_detect_rope_with_maxpos_ok(tmp_path):\n m = tmp_path / \"rope_ok\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_blocks(tmp_path):\n # Gensyn-Swarm fine-tune class: weights + config, no tokenizer artifacts.\n m = tmp_path / \"no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_missing_tokenizer_skipped_for_scriptable_xdit(tmp_path):\n \"\"\"xDiT (scriptable) is a server-less image workload that never loads a HF\n tokenizer, so a missing-tokenizer config.json must NOT block it.\"\"\"\n m = tmp_path / \"xdit_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n assert cli._detect_incompatible_model_config(str(m), framework=\"xdit\") is None\n\n\ndef test_detect_missing_tokenizer_still_blocks_serving_framework(tmp_path):\n \"\"\"Regression guard: the skip is scoped to scriptable — an explicit serving\n framework (sglang) must still block a missing-tokenizer checkpoint.\"\"\"\n m = tmp_path / \"sglang_no_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m), framework=\"sglang\")\n assert reason is not None\n assert \"tokenizer\" in reason.lower()\n\n\ndef test_detect_with_tokenizer_ok(tmp_path):\n m = tmp_path / \"with_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"qwen2\",\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_mistral_tokenizer_json_without_common_files_blocks(tmp_path):\n m = tmp_path / \"mistral_json_only\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"MistralCommonBackend\" in reason\n assert \"No tokenizer file found\" in reason\n\n\ndef test_detect_mistral_tokenizer_model_file_ok(tmp_path):\n m = tmp_path / \"mistral_tokenizer_model\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"mistral\",\n architectures=[\"MistralForCausalLM\"],\n max_position_embeddings=32768,\n )\n (m / \"tokenizer.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_missing_tokenizer_but_auto_map_ok(tmp_path):\n # A custom AutoTokenizer in auto_map can supply the tokenizer at load time.\n m = tmp_path / \"auto_tok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"custom\",\n max_position_embeddings=4096,\n auto_map={\"AutoTokenizer\": [\"x.TokClass\", None]},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_minimax_m1_blocked_on_amd(tmp_path):\n # minimax_m1 lightning-attention kernel needs 128KB LDS > MI300X 64KB.\n m = tmp_path / \"minimax\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_minimax_m1_not_blocked_off_amd(tmp_path):\n # AMD-specific LDS limit; do not block on non-AMD hardware.\n m = tmp_path / \"minimax_non_amd\"\n _write_config(\n m,\n model_type=\"minimax_m1\",\n architectures=[\"MiniMaxM1ForCausalLM\"],\n max_position_embeddings=80000,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_unrecognized_arch_blocked_hardware_agnostic(tmp_path):\n # glm4_moe_lite: Transformers does not recognize → ValidationError on any GPU.\n m = tmp_path / \"glm47flash\"\n _write_config(\n m,\n model_type=\"glm4_moe_lite\",\n architectures=[\"Glm4MoeLiteForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason_amd = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n reason_off = cli._detect_incompatible_model_config(str(m))\n assert reason_amd is not None and \"not recognized\" in reason_amd\n assert reason_off is not None and \"not recognized\" in reason_off\n\n\ndef test_detect_mimo_v2_flash_unrecognized_blocked(tmp_path):\n # mimo_v2_flash: unrecognized arch + Unknown attention backend TRITON.\n m = tmp_path / \"mimo\"\n _write_config(\n m,\n model_type=\"mimo_v2_flash\",\n architectures=[\"MiMoV2FlashForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"not recognized\" in reason\n\n\ndef test_detect_deepseek_v4_now_recognized(tmp_path):\n # DeepSeek-V4 resolves via AutoConfig/vLLM get_config; not fail-fasted.\n m = tmp_path / \"deepseek_v4\"\n _write_config(\n m,\n model_type=\"deepseek_v4\",\n architectures=[\"DeepseekV4ForCausalLM\"],\n max_position_embeddings=1048576,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_glm_moe_dsa_now_recognized(tmp_path):\n # glm_moe_dsa is registered by AutoConfig/vLLM ModelRegistry; not fail-fasted.\n m = tmp_path / \"glm_moe_dsa\"\n _write_config(\n m,\n model_type=\"glm_moe_dsa\",\n architectures=[\"GlmMoeDsaForCausalLM\"],\n max_position_embeddings=131072,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_gemma4_now_recognized(tmp_path):\n # gemma4 is registered by AutoConfig/vLLM ModelConfig; not fail-fasted.\n m = tmp_path / \"gemma4\"\n _write_config(\n m,\n model_type=\"gemma4\",\n architectures=[\"Gemma4ForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_bailing_ling_left_to_runtime_scope(tmp_path):\n # Bailing filters are out of scope for the fail-fast gate.\n for model_type, arch in (\n (\"bailing_moe\", \"BailingMoeV2ForCausalLM\"),\n (\"bailing_hybrid\", \"BailingMoeV2_5ForCausalLM\"),\n ):\n m = tmp_path / model_type\n _write_config(\n m,\n model_type=model_type,\n architectures=[arch],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_ovis_next_left_to_runtime_scope(tmp_path):\n # Ovis filters are out of scope for the fail-fast gate.\n m = tmp_path / \"ovis\"\n _write_config(\n m,\n model_type=\"ovis2_6_next\",\n architectures=[\"Ovis2_6_NextForCausalLM\"],\n max_position_embeddings=32768,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is None\n\n\ndef test_detect_nested_ministral3_unrecognized_blocked(tmp_path):\n # Mistral3 wrapper exposes text_config.model_type=ministral3; vLLM raises KeyError.\n m = tmp_path / \"mistral3\"\n _write_config(\n m,\n model_type=\"mistral3\",\n architectures=[\"Mistral3ForConditionalGeneration\"],\n image_token_index=10,\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 393216,\n \"vocab_size\": 131072,\n \"hidden_size\": 5120,\n \"num_hidden_layers\": 40,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_pure_nested_ministral3_blocked(tmp_path):\n # Parent model_type is NOT ministral3 (a generic wrapper); only the nested\n # text_config carries ministral3. Verifies the nested-only gate in isolation\n # from the parent scope.\n m = tmp_path / \"wrapper_nested_ministral3\"\n _write_config(\n m,\n model_type=\"some_wrapper\",\n architectures=[\"SomeWrapperForConditionalGeneration\"],\n text_config={\n \"model_type\": \"ministral3\",\n \"max_position_embeddings\": 32768,\n \"vocab_size\": 131072,\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"ministral3\" in reason\n\n\ndef test_detect_nested_qwen3_5_moe_text_not_blocked(tmp_path):\n # Nested qwen3_5_moe_text is registered by the runtime and falls through to\n # the text_coercible degraded path; not gated.\n m = tmp_path / \"wrapper_nested_qwen3_5_moe_text\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n text_config={\n \"model_type\": \"qwen3_5_moe_text\",\n \"max_position_embeddings\": 262144,\n \"vocab_size\": 151936,\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_qwen3_5_moe_not_blocked(tmp_path):\n # Bare top-level qwen3_5_moe remains in the text-coercible runtime path; only\n # the nested text_config subtype has a confirmed registry failure.\n m = tmp_path / \"bare_qwen3_5_moe\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n architectures=[\"Qwen3_5MoeForConditionalGeneration\"],\n max_position_embeddings=262144,\n vocab_size=151936,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_top_level_ministral3_not_blocked(tmp_path):\n # A bare top-level model_type=ministral3 (no Mistral3 wrapper) is left to the\n # framework; only the nested text_config form is a confirmed failure.\n m = tmp_path / \"bare_ministral3\"\n _write_config(\n m,\n model_type=\"ministral3\",\n architectures=[\"Ministral3ForCausalLM\"],\n max_position_embeddings=32768,\n vocab_size=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_glm4_moe_not_blocked(tmp_path):\n # glm4_moe (GLM-4.5/4.6 mainline) is a supported arch; must NOT be blocked\n # by the unrecognized-arch rule (only glm4_moe_lite is unrecognized).\n m = tmp_path / \"glm4moe\"\n _write_config(\n m,\n model_type=\"glm4_moe\",\n architectures=[\"Glm4MoeForCausalLM\"],\n max_position_embeddings=131072,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_unsupported_arch_with_maxpos_blocks(tmp_path):\n m = tmp_path / \"deepseek_v32_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"AMD/ROCm\" in reason\n\n\ndef test_detect_amd_unsupported_arch_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"deepseek_v32_non_amd\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_without_maxpos_blocks(tmp_path):\n m = tmp_path / \"rope_no_maxpos\"\n _write_config(\n m,\n model_type=\"deepseek_v32\",\n rope_scaling={\"factor\": 4.0},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"RoPE\" in reason\n\n\n# Phi-3 su/longrope: transformers folds top-level rope_theta into rope_scaling,\n# so Phi3Config sees 4 keys and raises before any override can apply.\ndef test_detect_phi3_su_canonical_three_fields_blocks(tmp_path):\n m = tmp_path / \"phi3_su\"\n _write_config(\n m,\n model_type=\"phi3\",\n architectures=[\"Phi3ForCausalLM\"],\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"su\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n assert \"rope_scaling\" in reason\n\n\ndef test_detect_phi3_longrope_blocks(tmp_path):\n m = tmp_path / \"phi3_longrope\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_theta=10000.0,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Phi-3\" in reason\n\n\ndef test_detect_phi3_yarn_rope_not_blocked(tmp_path):\n # yarn is the non-longrope path and validates differently; do not block it.\n m = tmp_path / \"phi3_yarn\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\"type\": \"yarn\", \"factor\": 4.0},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_phi3_longrope_without_rope_theta_not_blocked(tmp_path):\n # Without a top-level rope_theta, transformers does not fold an extra key\n # into rope_scaling, so the 3-key dict passes Phi3Config validation fine.\n m = tmp_path / \"phi3_longrope_no_theta\"\n _write_config(\n m,\n model_type=\"phi3\",\n max_position_embeddings=131072,\n rope_scaling={\n \"type\": \"longrope\",\n \"short_factor\": [1.05, 1.1],\n \"long_factor\": [1.03, 1.05],\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_phi3_su_rope_not_blocked(tmp_path):\n # The Phi-3 validator is Phi3Config-specific; a non-phi3 model with a\n # su/longrope-typed rope_scaling must not be caught by this gate.\n m = tmp_path / \"llama_su\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n rope_scaling={\"type\": \"su\", \"short_factor\": [1.05], \"extra\": 1},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# sglang's gemma2 runtime reads config.hidden_act unconditionally; checkpoints\n# shipping only hidden_activation crash with AttributeError. Hardware-agnostic.\ndef test_detect_gemma2_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_bad\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_activation=\"gelu_pytorch_tanh\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n assert \"hidden_act\" in reason\n\n\ndef test_detect_gemma2_arch_only_missing_hidden_act_blocks(tmp_path):\n m = tmp_path / \"gemma2_arch_only\"\n _write_config(\n m,\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"Gemma2\" in reason\n\n\ndef test_detect_gemma2_with_hidden_act_ok(tmp_path):\n m = tmp_path / \"gemma2_ok\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n hidden_act=\"gelu_pytorch_tanh\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_gemma2_hidden_act_in_text_config_ok(tmp_path):\n m = tmp_path / \"gemma2_text_cfg\"\n _write_config(\n m,\n model_type=\"gemma2\",\n architectures=[\"Gemma2ForCausalLM\"],\n max_position_embeddings=8192,\n text_config={\"hidden_act\": \"gelu_pytorch_tanh\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_non_gemma2_missing_hidden_act_not_blocked(tmp_path):\n # Only gemma2 reads config.hidden_act unconditionally in sglang; other\n # model types that omit hidden_act must not be caught by this gate.\n m = tmp_path / \"llama_no_act\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_corrupt_config_blocks(tmp_path):\n m = tmp_path / \"corrupt\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\"{not valid json\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"unparseable\" in reason\n\n\ndef test_detect_absent_config_not_blocked(tmp_path):\n m = tmp_path / \"no_config\"\n m.mkdir(parents=True, exist_ok=True)\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_rope_in_nested_text_config(tmp_path):\n m = tmp_path / \"nested\"\n m.mkdir(parents=True, exist_ok=True)\n (m / \"config.json\").write_text(\n json.dumps({\"text_config\": {\"rope_theta\": 10000.0}}),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n\n\ndef test_detect_dual_chunk_blocks_on_amd(tmp_path):\n m = tmp_path / \"dual_chunk_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"dual_chunk\" in reason\n\n\ndef test_detect_dual_chunk_not_blocked_off_amd(tmp_path):\n m = tmp_path / \"dual_chunk_non_amd\"\n _write_config(\n m,\n model_type=\"qwen2\",\n max_position_embeddings=1010000,\n dual_chunk_attention_config={\"chunk_size\": 262144},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef _write_quant_config(model_dir: Path, payload: dict) -> None:\n model_dir.mkdir(parents=True, exist_ok=True)\n (model_dir / \"hf_quant_config.json\").write_text(\n json.dumps(payload),\n encoding=\"utf-8\",\n )\n\n\ndef test_detect_modelopt_fp8_blocks_on_amd(tmp_path):\n \"\"\"ModelOpt FP8 (declared in hf_quant_config.json) has no ROCm loader.\"\"\"\n m = tmp_path / \"modelopt_fp8\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\", \"kv_cache_quant_algo\": \"FP8\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"modelopt\" in reason.lower() or \"FP8\" in reason\n\n\ndef test_detect_nvfp4_blocks_on_amd(tmp_path):\n m = tmp_path / \"nvfp4\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"NVFP4\"},\n },\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"NVFP4\" in reason or \"nvfp4\" in reason.lower()\n\n\ndef test_detect_bitsandbytes_blocks_on_amd(tmp_path):\n \"\"\"bitsandbytes declared in config.json.quantization_config; CUDA-only kernels.\"\"\"\n m = tmp_path / \"bnb\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"bitsandbytes\"},\n )\n reason = cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\")\n assert reason is not None\n assert \"bitsandbytes\" in reason.lower()\n\n\ndef test_detect_modelopt_fp8_not_blocked_off_amd(tmp_path):\n \"\"\"The same checkpoint can still run on a vendor (NVIDIA) engine.\"\"\"\n m = tmp_path / \"modelopt_fp8_nv\"\n _write_config(m, model_type=\"llama\", max_position_embeddings=8192)\n _write_quant_config(\n m,\n {\n \"producer\": {\"name\": \"modelopt\"},\n \"quantization\": {\"quant_algo\": \"FP8\"},\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_amd_native_fp8_not_blocked(tmp_path):\n \"\"\"AMD Quark / compressed-tensors FP8 is ROCm-native; must NOT be blocked.\"\"\"\n m = tmp_path / \"quark_fp8\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m), gpu_type=\"mi300x\") is None\n\n\ndef _write_safetensors_header(model_dir: Path, tensors: dict) -> None:\n header = json.dumps(tensors).encode(\"utf-8\")\n with (model_dir / \"model.safetensors\").open(\"wb\") as f:\n f.write(struct.pack(\" must NOT block.\n m = tmp_path / \"qwen_vocab_ok\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_detect_vocab_shape_padded_not_blocked(tmp_path):\n # actual > config vocab_size -> commonly a padded embedding (rounded up to\n # an alignment / TP boundary while config keeps the unpadded value). The\n # framework handles padding, so preflight must NOT skip such a checkpoint.\n m = tmp_path / \"qwen_vocab_padded\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=151936,\n )\n _write_safetensors_header(\n m,\n {\n \"model.embed_tokens.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536], # padded up from 151936\n \"data_offsets\": [0, 0],\n },\n \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [152064, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_read_safetensors_header_parses_and_rejects(tmp_path):\n # Valid header round-trips; truncated / oversized headers return None.\n good = tmp_path / \"model.safetensors\"\n _write_safetensors_header(tmp_path, {\"x.weight\": {\"shape\": [4, 4]}})\n assert cli._read_safetensors_header(good) == {\"x.weight\": {\"shape\": [4, 4]}}\n\n truncated = tmp_path / \"trunc.safetensors\"\n truncated.write_bytes(struct.pack(\" the path\n # heuristic decides; a gemma-2 path is still detected.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"google-gemma-2-9b-it\"\n m.mkdir()\n (m / \"config.json\").write_text(\"{}\", encoding=\"utf-8\")\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_model_is_gemma2_trusts_identified_non_gemma_config(tmp_path):\n # config clearly identifies llama; even a gemma-2 path must NOT override it.\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"gemma-2-distill-llama\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"llama\",\n \"architectures\": [\"LlamaForCausalLM\"],\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is False\n\n\ndef test_model_is_gemma2_detects_nested_text_config(tmp_path):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n m = tmp_path / \"wrapper\"\n m.mkdir()\n (m / \"config.json\").write_text(\n json.dumps(\n {\n \"model_type\": \"wrapper\",\n \"text_config\": {\"model_type\": \"gemma2\"},\n }\n ),\n encoding=\"utf-8\",\n )\n assert mcu._model_is_gemma2(str(m)) is True\n\n\ndef test_detect_unregistered_custom_config_blocks(tmp_path):\n m = tmp_path / \"kimi_k2\"\n _write_config(\n m,\n model_type=\"kimi_k2\",\n max_position_embeddings=131072,\n auto_map={\"AutoConfig\": \"configuration_deepseek.DeepseekV3Config\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"kimi_k2\" in reason\n\n\ndef test_detect_custom_automap_known_type_not_blocked(tmp_path):\n m = tmp_path / \"known_automap\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=8192,\n auto_map={\"AutoConfig\": \"configuration_custom.CustomConfig\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# _preflight_model_config_compat — persistence + return contract\n# ---------------------------------------------------------------------------\ndef test_preflight_blocks_and_persists(tmp_path, monkeypatch):\n model = tmp_path / \"bad\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n breakdown = json.loads((sd / \"session_breakdown.json\").read_text())\n assert breakdown[\"session\"][\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_preflight_passes_for_healthy_model(tmp_path, monkeypatch):\n model = tmp_path / \"good\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_ok\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert not (sd / \"reports\" / \"final.json\").exists()\n\n\ndef test_preflight_blocks_amd_unsupported_arch_from_args_gpu_type(\n tmp_path,\n monkeypatch,\n):\n model = tmp_path / \"deepseek_v32\"\n _write_config(\n model,\n model_type=\"deepseek_v32\",\n architectures=[\"DeepseekV32ForCausalLM\"],\n max_position_embeddings=163840,\n rope_scaling={\"type\": \"yarn\", \"factor\": 40.0},\n )\n sd = tmp_path / \"session_amd_arch\"\n _seed_state(sd, monkeypatch)\n\n assert (\n cli._preflight_model_config_compat(\n _args(str(model), gpu_type=\"mi300x\"),\n sd,\n )\n is True\n )\n final = json.loads((sd / \"reports\" / \"final.json\").read_text())\n assert final[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_stop_reason_is_canonical_vocab():\n from hyperloom.orchestrator.phases.machine_state import (\n STOP_REASON_VOCAB,\n is_valid_stop_reason,\n )\n\n assert \"model_config_incompatible\" in STOP_REASON_VOCAB\n assert is_valid_stop_reason(\"model_config_incompatible\")\n\n\ndef test_preflight_persists_under_strict_env(tmp_path, monkeypatch):\n monkeypatch.setenv(\"INFERENCE_OPTIMIZER_STRICT_STOP_REASON\", \"1\")\n model = tmp_path / \"bad_strict\"\n _write_config(model, model_type=\"x\", rope_parameters={\"factor\": 2.0})\n sd = tmp_path / \"session_strict\"\n _seed_state(sd, monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\n# ---------------------------------------------------------------------------\n# Private / third-party quantization formats (paroquant, MLX, mxtq, GGUF)\n# ---------------------------------------------------------------------------\ndef test_private_quant_paroquant_blocks(tmp_path):\n m = tmp_path / \"paro\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"paroquant\", \"bits\": 4, \"group_size\": 128, \"krot\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"paroquant\" in reason\n\n\ndef test_private_quant_mlx_affine_blocks(tmp_path):\n # MTPLX / MLX 8-bit affine: mode set, no quant_method.\n m = tmp_path / \"mlx_affine\"\n _write_config(\n m,\n model_type=\"qwen3_5\",\n max_position_embeddings=32768,\n quantization_config={\"bits\": 8, \"group_size\": 64, \"mode\": \"affine\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_no_method_blocks(tmp_path):\n # quantization_config carries bits/group_size but no quant_method/mode;\n # sglang raises \"Unknown quantization method: ''\" in engine init.\n m = tmp_path / \"no_method\"\n _write_config(\n m,\n model_type=\"llama\",\n max_position_embeddings=32768,\n quantization_config={\"group_size\": 64, \"bits\": 8},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method\" in reason\n\n\ndef test_private_quant_mxtq_blocks(tmp_path):\n m = tmp_path / \"mxtq\"\n _write_config(\n m,\n model_type=\"qwen3_5_moe\",\n max_position_embeddings=32768,\n quantization_config={\"weight_format\": \"mxtq\", \"method\": \"affine\", \"group_size\": 64},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"mxtq\" in reason\n\n\ndef test_private_quant_empty_method_blocks(tmp_path):\n m = tmp_path / \"empty_quant_method\"\n _write_config(\n m,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n quantization_config={\"quant_method\": \"\"},\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"quant_method is empty\" in reason\n\n\ndef test_private_quant_mlx_weights_index_blocks(tmp_path):\n # JANG/MLX often declares no quant config; the tell is '.biases'/'.scales'.\n m = tmp_path / \"mlx_weights\"\n _write_config(m, model_type=\"qwen3_5\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"lm_head.biases\": \"model-00001.safetensors\",\n \"lm_head.scales\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"MLX\" in reason\n\n\ndef test_private_quant_gguf_only_blocks(tmp_path):\n m = tmp_path / \"gguf_only\"\n _write_config(m, model_type=\"qwen3_5_moe\", max_position_embeddings=32768)\n (m / \"model-TQ3_4S.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_peft_adapter_only_checkpoint_blocks(tmp_path):\n m = tmp_path / \"adapter_only\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"adapter_config.json\").write_text(\n json.dumps({\"peft_type\": \"LORA\", \"base_model_name_or_path\": \"Qwen/Qwen2-7B\"}),\n encoding=\"utf-8\",\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"base_model.model.lm_head.lora_A.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.lm_head.lora_B.default.weight\": \"adapter_model.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"adapter_model.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n reason = cli._detect_incompatible_model_config(str(m))\n\n assert reason is not None\n assert \"PEFT/LoRA adapter\" in reason\n assert \"base_model.model.lm_head.base_layer.weight\" in reason\n\n\ndef test_merged_peft_like_checkpoint_with_base_weights_not_blocked(tmp_path):\n m = tmp_path / \"merged_adapter\"\n _write_config(m, model_type=\"qwen2\", max_position_embeddings=32768)\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n \"lm_head.weight\": \"model-00001.safetensors\",\n \"base_model.model.layers.0.self_attn.q_proj.lora_A.default.weight\": (\"model-00001.safetensors\"),\n }\n }\n ),\n encoding=\"utf-8\",\n )\n\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_fp8_not_blocked(tmp_path):\n m = tmp_path / \"fp8\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": \"fp8\"},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_standard_quant_awq_gptq_not_blocked(tmp_path):\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_gguf_with_safetensors_not_blocked(tmp_path):\n # A normal safetensors model that merely also ships a .gguf must still pass.\n m = tmp_path / \"gguf_plus_st\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"model.safetensors\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_gguf_with_auxiliary_bin_still_blocks(tmp_path):\n # An arbitrary .bin next to GGUF is not an HF-loadable weight file.\n m = tmp_path / \"gguf_plus_aux_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_cache.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None and \"GGUF\" in reason\n\n\ndef test_gguf_with_pytorch_model_bin_not_blocked(tmp_path):\n # HF PyTorch weights are loadable by the default framework loaders.\n m = tmp_path / \"gguf_plus_hf_bin\"\n _write_config(m, model_type=\"qwen3\", max_position_embeddings=32768)\n (m / \"model.gguf\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\ndef test_llama_sentencepiece_without_metadata_blocks(tmp_path):\n m = tmp_path / \"llama_sentencepiece_gap\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"tokenizer_config.json\" in reason\n assert \"HFValidationError\" in reason\n\n\ndef test_llama_sentencepiece_with_tokenizer_config_ok(tmp_path):\n m = tmp_path / \"llama_sentencepiece_ok\"\n _write_config(\n m,\n with_tokenizer=False,\n model_type=\"llama\",\n architectures=[\"LlamaForCausalLM\"],\n max_position_embeddings=4096,\n )\n (m / \"tokenizer.model\").write_text(\"dummy\", encoding=\"utf-8\")\n (m / \"tokenizer_config.json\").write_text(\"{}\", encoding=\"utf-8\")\n (m / \"pytorch_model.bin\").write_text(\"dummy\", encoding=\"utf-8\")\n assert cli._detect_incompatible_model_config(str(m)) is None\n\n\n# ---------------------------------------------------------------------------\n# Langfuse parity on fail-fast — pre-flight gates exit before the normal\n# Langfuse flush point, so each must push the breakdown to Langfuse itself.\n# ---------------------------------------------------------------------------\ndef _spy_langfuse_emit(monkeypatch) -> dict[str, list]:\n calls: dict[str, list] = {\"flush\": [], \"patch\": [], \"record\": []}\n from hyperloom.inference_optimizer import breakdown as bd\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n monkeypatch.setattr(lfe, \"flush_session\", lambda sd: calls[\"flush\"].append(Path(sd)))\n monkeypatch.setattr(bd, \"patch_breakdown_langfuse\", lambda sd: calls[\"patch\"].append(Path(sd)))\n monkeypatch.setattr(\n lfe,\n \"record_session_breakdown\",\n lambda sd, *a, **k: calls[\"record\"].append(Path(sd)),\n )\n return calls\n\n\ndef test_model_config_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"bad_lf\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n # written to disk AND pushed to Langfuse in flush -> patch -> record order.\n assert (sd / \"session_breakdown.json\").exists()\n assert calls[\"flush\"] == [sd]\n assert calls[\"patch\"] == [sd]\n assert calls[\"record\"] == [sd]\n\n\ndef test_unsupported_model_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"vlm_lf\"\n _write_config(\n model,\n model_type=\"llava\",\n architectures=[\"LlavaForConditionalGeneration\"],\n max_position_embeddings=4096,\n )\n sd = tmp_path / \"session_vlm_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_unsupported_model_arch(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_context_window_fail_fast_emits_to_langfuse(tmp_path, monkeypatch):\n model = tmp_path / \"ctx_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=128)\n sd = tmp_path / \"session_ctx_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n # ISL+OSL (1024+1024) + headroom >> 128 -> fail fast.\n assert cli._preflight_context_window(_args(str(model)), sd) is True\n assert calls[\"record\"] == [sd]\n\n\ndef test_emit_to_langfuse_is_best_effort(tmp_path, monkeypatch):\n # A Langfuse outage must never turn a clean fail-fast into a crash, nor\n # mask the persisted stop reason.\n model = tmp_path / \"bad_raise\"\n _write_config(model, model_type=\"x\", rope_scaling={\"factor\": 2.0})\n sd = tmp_path / \"session_raise\"\n _seed_state(sd, monkeypatch)\n\n from hyperloom.orchestrator.trace import langfuse_emitter as lfe\n\n def _boom(*a, **k):\n raise RuntimeError(\"langfuse down\")\n\n monkeypatch.setattr(lfe, \"flush_session\", _boom)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is True\n state = json.loads((sd / \"state.json\").read_text())\n assert state[\"stop_reason\"] == \"model_config_incompatible\"\n\n\ndef test_healthy_model_does_not_emit_to_langfuse(tmp_path, monkeypatch):\n # A passing pre-flight must not touch Langfuse — the normal end-of-session\n # path owns that for runs that actually start.\n model = tmp_path / \"good_lf\"\n _write_config(model, model_type=\"llama\", max_position_embeddings=8192)\n sd = tmp_path / \"session_good_lf\"\n _seed_state(sd, monkeypatch)\n calls = _spy_langfuse_emit(monkeypatch)\n\n assert cli._preflight_model_config_compat(_args(str(model)), sd) is False\n assert calls[\"record\"] == []\n\n\ndef test_declared_standard_quant_with_scales_index_not_blocked(tmp_path):\n # AWQ/GPTQ/compressed-tensors legitimately ship '.scales'/'.biases' tensors;\n # a declared supported quant_method must NOT be misread as MLX (the weight-\n # index tell only applies to checkpoints with NO quant_method declared).\n for method in (\"awq\", \"gptq\", \"compressed-tensors\"):\n m = tmp_path / f\"std_scales_{method.replace('-', '_')}\"\n _write_config(\n m,\n model_type=\"qwen3\",\n max_position_embeddings=32768,\n quantization_config={\"quant_method\": method},\n )\n (m / \"model.safetensors.index.json\").write_text(\n json.dumps(\n {\n \"weight_map\": {\n \"model.layers.0.self_attn.q_proj.scales\": \"model-00001.safetensors\",\n \"model.layers.0.self_attn.q_proj.biases\": \"model-00001.safetensors\",\n \"model.embed_tokens.weight\": \"model-00001.safetensors\",\n }\n }\n ),\n encoding=\"utf-8\",\n )\n assert cli._detect_incompatible_model_config(str(m)) is None, method\n\n\ndef test_run_compat_detector_resolves_repo_id_before_dispatch(tmp_path, monkeypatch):\n \"\"\"A repo-id must be resolved to its local cache dir before the waterfall so\n disk-reading detectors receive a real directory instead of the bare repo-id\n (which Path().is_dir() would reject, silently skipping the check).\"\"\"\n local_dir = tmp_path / \"cache\" / \"models--org--repo\"\n local_dir.mkdir(parents=True)\n monkeypatch.setattr(\n cli_model_gate,\n \"resolve_local_model_dir\",\n lambda mp: local_dir if mp == \"org/repo\" else None,\n )\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"org/repo\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == str(local_dir)\n\n\ndef test_run_compat_detector_falls_back_to_raw_when_unresolvable(monkeypatch):\n \"\"\"An unresolvable model path (e.g. an uncached repo-id) falls back to the\n raw string so behaviour is unchanged from before the resolver.\"\"\"\n monkeypatch.setattr(cli_model_gate, \"resolve_local_model_dir\", lambda mp: None)\n seen: dict[str, str] = {}\n\n def _fake_detector(model_path):\n seen[\"model_path\"] = model_path\n return None\n\n spec = cli_model_gate.DetectorSpec(\"t\", _fake_detector, args=(\"model_path\",))\n cli_model_gate._run_compat_detector(spec, model_path=\"/raw/model/path\", data={}, gpu_type=None)\n assert seen[\"model_path\"] == \"/raw/model/path\"\n"}}, "src/hyperloom/inference_optimizer/cli/parser.py": {"2c3802738a7d93ec2447c0bb2d894b0aa8a4871e": {"t": 1786067526.1782193, "n": 59198, "h": "29b49889ee705048", "c": "# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n\"\"\"CLI argument parser — ``_build_parser`` and its purely-computational helpers.\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport os\nfrom pathlib import Path\n\nfrom .. import framework_registry\nfrom hyperloom.common.llm_config import DEFAULT_DEEPSEEK_MODEL\nfrom hyperloom.orchestrator.roles.agent_role import (\n DEFAULT_CLAUDE_MODEL,\n DEFAULT_CODEX_MODEL,\n)\nfrom hyperloom.orchestrator.scoring.proposal_scorer import DEFAULT_SCORER_MODELS\n\n# Workload knob fallbacks applied when the operator passes neither the CLI flag\n# nor an inherited value. Flags default to ``None`` so \"omitted\" is\n# distinguishable from \"typed the default\"; the resolver in ``cli`` applies\n# these constants only for genuinely-unset knobs (issue #903).\nDEFAULT_ISL = 1024\nDEFAULT_OSL = 1024\nDEFAULT_CONC = 64\nDEFAULT_TP = 1\nDEFAULT_EP = 1\nDEFAULT_PRECISION = \"bf16\"\n\n\ndef _default_pr_monitor_mcp_url() -> str | None:\n \"\"\"Derive the PR Monitor MCP URL from ``$PRIMUS_CORTEX_PR_API``.\n\n Follows the same ``/mcp`` convention the gbrain ``cortex_kb`` server\n uses, so one env var wires both the REST client and the specialist MCP\n server instead of silently leaving the MCP half disabled. The trailing\n slash is kept because the bare ``/mcp`` form answers 307 and MCP clients do\n not re-POST across the redirect.\n\n Returns:\n The derived URL, or ``None`` when the env var is unset.\n \"\"\"\n base = (os.environ.get(\"PRIMUS_CORTEX_PR_API\") or \"\").strip().rstrip(\"/\")\n return f\"{base}/mcp/\" if base else None\n\n\ndef _positive_int_arg(value: str) -> int:\n \"\"\"argparse type for positive integer knobs.\"\"\"\n try:\n parsed = int(str(value).strip())\n except (TypeError, ValueError) as exc:\n raise argparse.ArgumentTypeError(f\"expected a positive integer, got {value!r}\") from exc\n if parsed <= 0:\n raise argparse.ArgumentTypeError(f\"expected a positive integer, got {value!r}\")\n return parsed\n\n\ndef _default_claude_model_env() -> str:\n \"\"\"Resolve the default Claude model from env.\"\"\"\n explicit = (os.environ.get(\"CLAUDE_MODEL\") or \"\").strip()\n if explicit:\n return explicit\n if (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip() or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip():\n return (os.environ.get(\"DEEPSEEK_MODEL\") or \"\").strip() or DEFAULT_DEEPSEEK_MODEL\n if os.environ.get(\"INFERENCE_OPTIMIZER_CLAUDE_FOLLOWS_CODEX\") == \"1\":\n return (os.environ.get(\"CODEX_MODEL\") or \"\").strip() or DEFAULT_CODEX_MODEL\n openai_url = (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n anthropic_url = (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n if openai_url and not anthropic_url:\n return (os.environ.get(\"CODEX_MODEL\") or \"\").strip() or DEFAULT_CODEX_MODEL\n return DEFAULT_CLAUDE_MODEL\n\n\ndef _default_codex_model_env() -> str:\n \"\"\"Resolve the default Codex-style model from env.\n\n When the operator only configured the Anthropic side, Codex-style JSON\n roles run through the unified gateway with the same Claude model as\n orchestration. This also overrides generated default ``CODEX_MODEL`` values\n from setup env files. Explicit ``CODEX_MODEL`` keeps the historical\n OpenAI-compatible behavior when an OpenAI base URL is configured.\n \"\"\"\n anthropic_url = (os.environ.get(\"ANTHROPIC_BASE_URL\") or \"\").strip()\n openai_url = (os.environ.get(\"OPENAI_BASE_URL\") or \"\").strip()\n if (\n (os.environ.get(\"DEEPSEEK_API_KEY\") or \"\").strip()\n or (os.environ.get(\"DEEPSEEK_BASE_URL\") or \"\").strip()\n or anthropic_url == \"https://api.deepseek.com/anthropic\"\n ) and not openai_url:\n return (\n os.environ.get(\"CLAUDE_MODEL\") or os.environ.get(\"DEEPSEEK_MODEL\") or \"\"\n ).strip() or DEFAULT_DEEPSEEK_MODEL\n if anthropic_url and not openai_url:\n return (os.environ.get(\"CLAUDE_MODEL\") or \"\").strip() or DEFAULT_CLAUDE_MODEL\n explicit = (os.environ.get(\"CODEX_MODEL\") or \"\").strip()\n if explicit:\n return explicit\n return DEFAULT_CODEX_MODEL\n\n\ndef _default_research_lane_capacity() -> int:\n \"\"\"Default ``--research-lane-capacity`` to the GPU ceiling (2×GPU).\n\n Returns:\n int: The policy GPU ceiling.\n \"\"\"\n from hyperloom.orchestrator.policy.gate import research_lane_ceiling\n\n return research_lane_ceiling()\n\n\ndef _default_gpu_specialist_capacity() -> int:\n \"\"\"Default ``--gpu-specialist-capacity`` to the whole visible machine.\n\n WS2 turns GPU specialists on by default at whole-machine capacity. When the\n operator needs a different value, pass ``--gpu-specialist-capacity``.\n\n Returns:\n int: The detected whole-machine GPU count, or ``0`` when nothing can be probed.\n \"\"\"\n from hyperloom.orchestrator.policy.gate import detect_gpu_count\n\n return detect_gpu_count()\n\n\ndef _build_parser() -> argparse.ArgumentParser:\n \"\"\"Build the top-level CLI argument parser and subcommands.\n\n Returns:\n The configured :class:`argparse.ArgumentParser`.\n \"\"\"\n from hyperloom.orchestrator.specialists.domains import (\n DEFAULT_SPECIALIST_MAX_TURNS as _DEFAULT_SPECIALIST_MAX_TURNS,\n )\n\n p = argparse.ArgumentParser(\n prog=\"inference_optimizer\",\n description=\"Inference Optimizer — multi-agent inference optimization (SGLang/vLLM/Atom/xDiT)\",\n )\n p.add_argument(\"--verbose\", \"-v\", action=\"count\", default=0, help=\"Verbose logging (-v INFO, -vv DEBUG)\")\n sub = p.add_subparsers(dest=\"command\", required=True)\n\n opt = sub.add_parser(\"optimize\", help=\"Drive a multi-agent optimization run on a model\")\n opt.add_argument(\n \"--model\",\n \"-m\",\n type=Path,\n default=None,\n help=\"Model path (required for new runs; ignored when \"\n \"--resume is set — model is read from manifest.json/\"\n \"state.json)\",\n )\n opt.add_argument(\n \"--quantize\",\n type=str,\n default=None,\n metavar=\"PROMPT\",\n help=\"Optional natural-language quantization request. When set, the \"\n \"quantization-agent runs ONCE as a prelude before the \"\n \"optimization loop: it drives AMD Quark PTQ from this prompt, \"\n \"then rewrites --model to the exported quantized model so the \"\n \"rest of the run optimizes the quantized model. Ignored on \"\n \"--resume.\",\n )\n from hyperloom.orchestrator.phases.quantization_schemes import QUANT_SCHEME_CHOICES\n\n opt.add_argument(\n \"--quantize-scheme\",\n choices=QUANT_SCHEME_CHOICES,\n default=None,\n metavar=\"SCHEME\",\n help=\"Structured alternative to --quantize for UI/backends: pick a \"\n \"curated quantization scheme (resolved to a prompt internally). \"\n f\"Choices: {', '.join(QUANT_SCHEME_CHOICES)}. 'none' or omit = no \"\n \"quantization. Ignored if --quantize (free text) is also given.\",\n )\n opt.add_argument(\n \"--gpu-type\",\n type=str.lower,\n choices=[\"mi300x\", \"mi308x\", \"mi325x\", \"mi355x\"],\n default=None,\n help=\"Hint for the real target GPU. The rocm-smi probe always \"\n \"wins when both are present and disagree; a WARN is \"\n \"emitted to stderr so the operator sees the typo. Used \"\n \"verbatim only when the probe fails (CPU sandbox / no \"\n \"rocm-smi). Magpie runner_type is derived separately; \"\n \"mi308x and mi325x currently run with mi300x runner scripts because \"\n \"Magpie does not yet ship MI308X/MI325X-specific SGLang/vLLM scripts.\",\n )\n opt.add_argument(\n \"--framework\",\n choices=list(framework_registry.names()),\n default=None,\n help=\"Inference framework to benchmark / optimize. Resolution order: \"\n \"--framework > sglang (default). Selection is \"\n \"session-wide; mixing frameworks in a single session is not \"\n \"supported. NOTE: --framework atom is single-node-only \"\n \"(``--nodes>=2`` fails fast); profile / roofline, \"\n \"kernel-agent, and framework-agent are all enabled on atom. \"\n \"The auto-tighten guard only enforces ``--nodes 1``. \"\n \"--framework xdit is a server-less (scriptable) diffusion \"\n \"workload (xDiT): no serving server, throughput is img/s, and \"\n \"the accuracy gate is an image-quality gate (LPIPS/SSIM/MSE).\",\n )\n opt.add_argument(\n \"--nodes\",\n type=int,\n default=1,\n help=\"Total number of GPU nodes for the inference RayJob. \"\n \"1 (default) keeps the legacy single-pod path. \"\n \">=2: `optimize` provisions the SaFE RayJob before preflight \"\n \"(unless already in the session multi_node_state.json), runs bootstrap \"\n \"once, and exports RAY_ADDRESS for kernel-agent. Does not stop the \"\n \"RayJob on exit; run `python3 -m hyperloom.inference_optimizer.multi_node \"\n \"stop-multi-job` when you want to release it. Requires \"\n \"--mn-image. \"\n \"Default: 1.\",\n )\n opt.add_argument(\n \"--mn-backend\",\n choices=(\"rayjob\", \"infera\"),\n default=None,\n help=\"Multi-node backend when --nodes>=2: 'rayjob' (default, Ray \"\n \"head+workers) or 'infera' (idle InferaDeployment + SSH control \"\n \"plane). Defaults to rayjob when omitted. Single-node runs ignore \"\n \"this flag.\",\n )\n opt.add_argument(\n \"--mn-image\",\n default=None,\n help=\"Container image for the multi-node pods (Infera worker/prefill/\"\n \"decode pods, or RayJob head+workers). Required when --nodes>=2 unless \"\n \"the state file last_create_request.image is present.\",\n )\n opt.add_argument(\n \"--gpus-per-node\",\n type=int,\n default=None,\n help=\"GPUs per multi-node pod (Infera worker/prefill/decode or RayJob \"\n \"head+workers). Defaults to 8 when omitted.\",\n )\n opt.add_argument(\n \"--cpus-per-node\",\n type=int,\n default=None,\n help=\"CPU cores requested per multi-node pod (Infera or RayJob). Resolution: flag > 96 (default).\",\n )\n opt.add_argument(\n \"--mem-per-node\",\n type=int,\n default=None,\n help=\"Memory (GiB) requested per multi-node pod (Infera or RayJob). Resolution: flag > 1024 (default).\",\n )\n # --rayjob-extra-env is a prompt-driven pass-through forwarded verbatim to workload_spec.env; the CLI\n # invents no keys. Reserved RAY_JOB_ENTRYPOINT stripped downstream; credential keys auto-injected elsewhere.\n opt.add_argument(\n \"--rayjob-extra-env\",\n action=\"append\",\n default=[],\n metavar=\"K=V\",\n help=\"Extra env entries to inject into the multi-node RayJob \"\n \"(repeatable). Agent maps each line of the user prompt's \"\n \"`env:` block into one --rayjob-extra-env K=V; the CLI \"\n \"does not own any default. Skip RAY_JOB_ENTRYPOINT \"\n \"(reserved by workload_spec). Only takes effect when \"\n \"--nodes>=2 and this run actually creates the RayJob; \"\n \"idempotent reuse of an existing rayjob_id keeps the env \"\n \"set at original create time.\",\n )\n opt.add_argument(\n \"--tp\",\n type=int,\n default=None,\n help=\"Tensor parallel size. Pass `--tp N` directly from the prompt's \"\n f\"Environment block. Default: {DEFAULT_TP}.\",\n )\n opt.add_argument(\n \"--conc\",\n type=_positive_int_arg,\n default=None,\n help=\"Magpie client concurrency cap (max in-flight requests). \"\n \"Pass `--conc N` directly from the prompt. Use \"\n f\"--conc-sweep-concs for a concurrency ladder. Default: {DEFAULT_CONC}.\",\n )\n opt.add_argument(\n \"--max-model-len\",\n dest=\"max_model_len\",\n type=_positive_int_arg,\n default=None,\n help=\"Explicit server-facing MAX_MODEL_LEN. Resolution: \"\n \"--max-model-len > auto(ISL+OSL+headroom, \"\n \"clamped to native context). Explicit values are preserved and \"\n \"exported into the materialized Magpie YAML.\",\n )\n opt.add_argument(\n \"--server-args\",\n dest=\"server_args\",\n type=str,\n default=\"\",\n help=\"Framework server args to apply in every phase. Routed through \"\n \"the framework-specific EXTRA_*_ARGS env in Magpie YAMLs \"\n \"(EXTRA_VLLM_ARGS / EXTRA_SGLANG_ARGS / EXTRA_ATOM_ARGS). \"\n 'Example: --server-args \"--kv-cache-dtype fp8_e4m3 '\n '--gpu-memory-utilization 0.85\".',\n )\n opt.add_argument(\n \"--ep\",\n type=int,\n default=None,\n help=\"Expert-parallel size for MoE inference. 1 (default) keeps \"\n \"experts sharded by TP (legacy behaviour). >=2 enables true \"\n \"expert parallelism: sglang adds `--expert-parallel-size N`, \"\n \"vllm adds `--enable-expert-parallel`. Typical: EP=TP for \"\n \"DSr1/DSv3 on multi-node. Default: 1. \"\n \"EP > TP is rejected at server-restart time.\",\n )\n opt.add_argument(\n \"--pd-mode\",\n choices=(\"aggregated\", \"disaggregated\"),\n default=\"aggregated\",\n help=\"Prefill-Decode disaggregation mode. ALWAYS defaults to \"\n \"`aggregated` regardless of any inherited $PD_MODE env, so \"\n \"PD only turns on when the agent explicitly passes \"\n \"`--pd-mode disaggregated` (driven by the prompt's \"\n \"Environment block having a PD_MODE=disaggregated line). \"\n \"Stale env from a previous restart cannot accidentally \"\n \"re-enable PD.\",\n )\n opt.add_argument(\n \"--pd-prefill-nodes\",\n type=int,\n default=0,\n help=\"Number of prefill nodes (disaggregated only); pn+dn=nodes\",\n )\n opt.add_argument(\n \"--pd-decode-nodes\",\n type=int,\n default=0,\n help=\"Number of decode nodes (disaggregated only)\",\n )\n opt.add_argument(\n \"--pd-prefill-tp\",\n type=int,\n default=0,\n help=\"TP for prefill group (disaggregated only); default = --tp\",\n )\n opt.add_argument(\n \"--pd-decode-tp\",\n type=int,\n default=0,\n help=\"TP for decode group (disaggregated only); default = --tp\",\n )\n opt.add_argument(\n \"--pd-transfer-backend\",\n type=str,\n default=\"\",\n help=\"sglang: mooncake|nixl ; vllm: NixlConnector|...; empty = default\",\n )\n opt.add_argument(\n \"--pd-ib-device\",\n type=str,\n default=\"\",\n help=\"comma-separated IB/RoCE device list (e.g. mlx5_0,mlx5_1). \"\n \"Empty = use $NCCL_IB_HCA from RayJob pod env at server-launch time.\",\n )\n opt.add_argument(\n \"--pd-prefill-ep\",\n type=int,\n default=0,\n help=\"EP for the prefill group (disaggregated only); 0 = fall back to --ep. Multi-node PD only.\",\n )\n opt.add_argument(\n \"--pd-decode-ep\",\n type=int,\n default=0,\n help=\"EP for the decode group (disaggregated only); 0 = fall back to --ep. Multi-node PD only.\",\n )\n opt.add_argument(\n \"--pd-prefill-extra-args\",\n type=str,\n default=\"\",\n help=\"Per-role sglang server args for the prefill group, appended after \"\n \"the shared server args (disaggregated only). Multi-node PD only.\",\n )\n opt.add_argument(\n \"--pd-decode-extra-args\",\n type=str,\n default=\"\",\n help=\"Per-role sglang server args for the decode group, appended after \"\n \"the shared server args (disaggregated only). Multi-node PD only.\",\n )\n opt.add_argument(\n \"--skip-variants\",\n type=str,\n default=\"\",\n help=\"Comma/whitespace-separated list of variant names or fnmatch \"\n \"globs to drop from the backends/params grids before launch. \"\n \"Examples: `attn_aiter` (exact), `attn_aiter,sched_dfs` (two \"\n \"exacts), `attn_*,vllm_aiter_*` (globs). Exported into \"\n \"the internal SKIP_VARIANTS handoff so all executors and the multi-node orchestrator \"\n \"subprocess see the same value. Dropped variants surface in \"\n \"state.json under each action's `dropped_variants` field tagged \"\n \"`source=user_skip`.\",\n )\n opt.add_argument(\"--max-hours\", type=float, default=2.0, help=\"Wall-clock budget in hours (default 2.0)\")\n opt.add_argument(\n \"--closing-grace-sec\",\n type=float,\n default=None,\n help=(\n \"Extra seconds after the wall-clock deadline for Coordinator to \"\n \"flush a deterministic report task (no LLM). Default: \"\n \"min(120, max_hours * 60 * 0.02). Pass 0 to disable closing phase.\"\n ),\n )\n opt.add_argument(\"--isl\", type=int, default=None, help=f\"Input sequence length (default {DEFAULT_ISL})\")\n opt.add_argument(\"--osl\", type=int, default=None, help=f\"Output sequence length (default {DEFAULT_OSL})\")\n opt.add_argument(\n \"--profile-osl\",\n dest=\"profile_osl\",\n type=int,\n default=None,\n help=(\n \"Profiling-phase output sequence length. When set, it overrides \"\n \"--osl for the roofline/profile server ONLY, so its torch-profiler \"\n \"trace stays serializable; baseline/optimize phases still run at \"\n \"--osl. When unset the profile phase uses \"\n \"min(--osl, 1024) and is auto-lowered further if needed to keep the \"\n \"capture window within the serialization cap.\"\n ),\n )\n opt.add_argument(\n \"--reference-script\",\n dest=\"reference_script\",\n type=str,\n default=None,\n help=(\n \"Reference launch recipe (.sh path or http(s) URL). Its serve \"\n \"flags + whitelisted exports seed the baseline server args at \"\n \"lowest priority (EXPLORE can override). Model-gated: ignored if \"\n \"the run's model differs from the recipe's. If the given path is \"\n \"unreadable / yields no flags, a matching InferenceX single-node \"\n \"recipe is auto-discovered (exact filename match only; fuzzy \"\n \"matches are logged, not used). When this flag is omitted, no \"\n \"discovery runs and the baseline is unchanged.\"\n ),\n )\n opt.add_argument(\"--precision\", type=str, default=None, help=f\"Model precision (default {DEFAULT_PRECISION})\")\n opt.add_argument(\n \"--framework-version\",\n dest=\"framework_version\",\n type=str,\n default=None,\n help=(\n \"Framework version slug for the recipe-snapshot canonical id \"\n \"(scopes recipes to a specific framework release — sglang 0.4.5 \"\n \"and sglang 0.5.x have different scheduler defaults so they \"\n \"deserve separate KB rows). When omitted, auto-detected via \"\n \"importing the framework's top-level package and reading \"\n \"``__version__`` (sglang/vllm/atom supported); auto-detect \"\n \"failure degrades to 'unknown_version'. Override with \"\n \"--framework-version=0.4.5 to pin a specific tag for the run.\"\n ),\n )\n opt.add_argument(\n \"--continue-kernel-after-gemm\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=(\n \"After FP8 GEMM tuning succeeds, continue into source-level \"\n \"kernel_opt. Use --no-continue-kernel-after-gemm for a \"\n \"GEMM-only validation run.\"\n ),\n )\n grp = opt.add_mutually_exclusive_group()\n grp.add_argument(\"--target-gain\", type=float, default=None, help=\"Stop when cumulative_gain >= N%% over baseline\")\n grp.add_argument(\n \"--target-tput\",\n type=float,\n default=None,\n help=\"Stop when current best reaches N (serving: tok/s/GPU; xDiT: img/s)\",\n )\n grp.add_argument(\n \"--target-baseline-dir\", type=str, default=None, help=\"Stop when current best matches the baseline in DIR\"\n )\n opt.add_argument(\n \"--resume\",\n action=\"store_true\",\n default=False,\n help=\"Resume an existing session. Without --resume-from, \"\n \"auto-picks the latest per-session subdir under \"\n \"$USER_DATA_PATH/// (N17 layout) or \"\n \"falls back to $USER_DATA_PATH. \"\n \"USER_DATA_PATH MUST stay at workspace level \"\n \"(/shared/hyperloom-sessions, not the per-session subdir) \"\n \"so runtime/ resolution works. Skips the SharedState \"\n \"seed and lets the Coordinator replay the prior \"\n \"event log + state.json.\",\n )\n opt.add_argument(\n \"--resume-from\",\n type=str,\n default=None,\n help=\"Explicit per-session subdir to resume from. Use \"\n \"when multiple per-launch ts dirs exist under the \"\n \"same model and the latest is not what you want. \"\n \"Must be an absolute path under $USER_DATA_PATH \"\n \"(workspace_root). Implies --resume.\",\n )\n opt.add_argument(\n \"--force-resume\",\n action=\"store_true\",\n default=False,\n help=(\n \"Allow ``--resume`` to push past a terminal \"\n \"``stop_reason='target_reached'``. \"\n \"Without this flag the resume aborts (Issue-G guard, per \"\n \"SKILL.md 'Run-time signals': that terminal requires an \"\n \"operator-side workload / strategy change before resuming). \"\n \"No-op outside ``--resume``.\"\n ),\n )\n opt.add_argument(\n \"--model-class\",\n type=str,\n default=None,\n help=(\n \"Categorical model-class key. It is the deterministic key for \"\n \"several consumers: the atom explore seed grid \"\n \"(action_executors/explore.py), the framework-agent gap search \"\n \"token (action_executors/_framework_gap_composer.py), the recipe \"\n \"key, and the orchestration prompt label. Recognised values \"\n \"(case-insensitive, with -/+/space tolerated): dense / moe_mla / \"\n \"moe_swa / moe_mla_nsa. When unset, Coordinator boot infers and \"\n \"persists it from config.json (num_experts / architectures) or \"\n \"model-path family keywords, replacing the deleted ``classify`` \"\n \"action's lightweight state-write role. For richer *advisory* \"\n \"model context (attention variant, KV/token, experts, MTP, ...) \"\n \"the SKILL launcher writes /model_arch.json, which \"\n \"is injected into prompts but drives no gating.\"\n ),\n )\n opt.add_argument(\"--target-summary\", type=str, default=None, help=\"Free-text goal summary surfaced in prompts\")\n opt.add_argument(\n \"--compare-against-gpu\",\n type=str,\n default=None,\n help=(\n \"Reference GPU hardware key for external baseline comparison \"\n \"(e.g. b300 / mi355x / h200). target_analysis ALWAYS runs first, \"\n \"before baseline, and always writes \"\n \"$SESSION_DIR/target_analysis/target_baseline.json + a short \"\n \"MD report. When this flag is set, the JSON carries the \"\n \"matching InferenceX (https://inferencex.semianalysis.com) \"\n \"reference data point; when unset, the JSON carries a \"\n \"structured reason='no_target_gpu_configured' marker so the \"\n \"report still has a deterministic 'External baseline' \"\n \"section. The reference is API-measured and never influences \"\n \"the Objective, scoring, or any KEEP/REVERT gate; a matching \"\n \"row is surfaced to the EXPLORE gap advisory as direction only. \"\n \"Other dimensions (model / framework / precision / ISL / OSL) \"\n \"are derived from the corresponding CLI arguments.\"\n ),\n )\n opt.add_argument(\"--max-ticks\", type=int, default=None, help=\"Hard tick cap (None = unlimited; mostly for tests)\")\n opt.add_argument(\"--tick-interval-sec\", type=float, default=0.0, help=\"Sleep between ticks (0 = no sleep)\")\n opt.add_argument(\"--claude-model\", type=str, default=_default_claude_model_env())\n opt.add_argument(\"--codex-model\", type=str, default=_default_codex_model_env())\n opt.add_argument(\n \"--allow-mm-text-fallback\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"When a model carries a multimodal signal (e.g. vision_config) \"\n \"but exposes a text-generation path, run it on the TEXT path with \"\n \"a degraded-mode warning instead of fail-fasting. Image/audio \"\n \"inputs are ignored, so numbers reflect the text decoder alone. \"\n \"True VLMs with no text path (Llava / PaliGemma / Qwen-VL / \"\n \"Phi3V) still fail-fast regardless of this flag. Pass \"\n \"--no-allow-mm-text-fallback to fail-fast on text-coercible \"\n \"models too. Default: enabled.\",\n )\n opt.add_argument(\n \"--no-kernel\",\n action=\"store_true\",\n default=False,\n help=\"Disable the Kernel-agent entirely. The run will \"\n \"only do baseline + explore + sweep (pure \"\n \"parameter search). Useful when GEAK/GPU \"\n \"compile env is unavailable or you just want the \"\n \"quick-win parameter path. Default: kernel enabled.\",\n )\n opt.add_argument(\n \"--no-explore\",\n action=\"store_true\",\n default=False,\n help=\"Skip the EXPLORE phase entirely. PRELUDE (and \"\n \"FRAMEWORK, if enabled) route straight to KERNEL \"\n \"— or to SWEEP when --no-kernel is also set. Useful \"\n \"for a baseline -> kernel-only run, or to validate \"\n \"the current recipe via SWEEP without a serving-\"\n \"param search. Default: explore enabled.\",\n )\n opt.add_argument(\n \"--enable-framework-config-exploration\",\n action=\"store_true\",\n default=False,\n help=\"(Stage-1, default OFF) Let the FRAMEWORK_AGENT phase run \"\n \"explore-style config-grid exploration (reusing the ExploreExecutor) \"\n \"before it advances, giving FRAMEWORK the EXPLORE config-search \"\n \"capability. The EXPLORE phase and overall phase flow are unchanged; \"\n \"results share the explore_search dedup ledger.\",\n )\n opt.add_argument(\n \"--launch-info-file\",\n type=str,\n default=None,\n help=\"Write a JSON file with the launched session's pid, \"\n \"session_dir, session_id, run_log, manifest path, gpu_type, \"\n \"framework and model. Launcher scripts can ``jq -r .pid`` / \"\n \"``jq -r .session_dir`` instead of grepping stdout or \"\n \"pgrep'ing. Always emitted alongside the ``HYPERLOOM_LAUNCH \"\n \" ...`` single-line sentinel that is printed to \"\n \"stdout for stream-based parsers.\",\n )\n opt.add_argument(\n \"--framework-discover-timeout-sec\",\n type=float,\n default=0.0,\n help=\"Override the per-call timeout for \"\n \"``fa phase-discover``. 0 (the default) uses \"\n \"framework_agent_client.DEFAULT_FA_PHASE_TIMEOUT_SEC \"\n \"(180s). The Coordinator retries discover up to \"\n \"DISCOVER_FAILURE_RETRY_LIMIT (3) consecutive \"\n \"failures before marking FRAMEWORK done.\",\n )\n opt.add_argument(\n \"--no-framework-agent\",\n action=\"store_true\",\n default=False,\n help=\"Skip the FRAMEWORK_AGENT phase (PRELUDE → EXPLORE \"\n \"directly). The phase pre-scans upstream sglang/\"\n \"vllm PRs via framework-agent and lands KEPT \"\n \"patches before EXPLORE starts. Disable when \"\n \"the framework-agent toolchain is unavailable \"\n \"or you want a faster cold start. \"\n \"Default: framework phase enabled.\",\n )\n opt.add_argument(\n \"--no-framework-local-explore\",\n dest=\"no_framework_local_explore\",\n action=\"store_true\",\n default=False,\n help=\"Disable the FRAMEWORK_AGENT local-exploration arm. By default, \"\n \"when PR discovery is empty/exhausted (or the ranker prefers it), the \"\n \"phase dispatches a write-capable specialist that authors a throughput \"\n \"patch from the live source + profiling evidence (and may web-search \"\n \"the latest upstream code) instead of skipping the phase. Disabling \"\n \"restores the historical behavior of exiting after \"\n \"DISCOVER_FAILURE_RETRY_LIMIT (3) empty/failed discoveries. Requires \"\n \"the authoring track (has no effect under diff-only mode).\",\n )\n opt.add_argument(\n \"--kernel-codex\",\n action=\"store_true\",\n default=True,\n help=(\n \"Use Codex for the Kernel-agent conversation backend (default — \"\n \"faster). This does not select the forge kernel rewrite \"\n \"ladder; use KERNEL_OPT_BACKEND_ORDER for that. Pass --kernel-claude \"\n \"to switch the conversation backend.\"\n ),\n )\n opt.add_argument(\n \"--kernel-claude\",\n action=\"store_false\",\n dest=\"kernel_codex\",\n help=(\n \"Use Claude for the Kernel-agent conversation backend. This does not \"\n \"select the forge kernel rewrite ladder.\"\n ),\n )\n # Critic backend selection; flags are aliases setting the same dest.\n opt.add_argument(\n \"--critic-mock\",\n dest=\"critic_backend\",\n action=\"store_const\",\n const=\"mock\",\n default=None,\n help=\"Force the always-approve mock Critic (offline / smoke tests).\",\n )\n opt.add_argument(\n \"--critic-agent\",\n dest=\"critic_backend\",\n action=\"store_const\",\n const=\"agent\",\n help=\"Force the critic-agent runtime backend (KB + session memory + \"\n \"review_constraints). Requires CRITIC_AGENT_ROOT or a sibling \"\n \"$REPO_ROOT/critic-agent/ directory.\",\n )\n # Robustness backend selection (mirrors critic)\n opt.add_argument(\n \"--robustness-mock\",\n dest=\"robustness_backend\",\n action=\"store_const\",\n const=\"mock\",\n default=None,\n help=\"Force the heartbeat-only mock Robustness backend.\",\n )\n opt.add_argument(\n \"--robustness-agent\",\n dest=\"robustness_backend\",\n action=\"store_const\",\n const=\"agent\",\n help=\"Force the robustness-agent runtime backend (subprocess + JSON, \"\n \"mirrors critic-agent transport). Requires ROBUSTNESS_AGENT_ROOT \"\n \"or a sibling $REPO_ROOT/robustness-agent/ directory.\",\n )\n opt.add_argument(\n \"--robustness-server-url\",\n dest=\"robustness_server_url\",\n type=str,\n default=None,\n help=\"Override the robustness-server base URL forwarded into \"\n \"request.options. Honoured only when --robustness-agent is \"\n \"selected.\",\n )\n opt.add_argument(\n \"--robustness-llm-rca\",\n dest=\"robustness_llm_rca\",\n action=\"store_true\",\n default=None,\n help=\"Forward llm_rca_enabled=true into request.options. The agent \"\n \"still falls back to NoopRcaEngine when LLM credentials aren't \"\n \"set in the runtime env.\",\n )\n opt.add_argument(\n \"--no-robustness-llm-rca\",\n dest=\"robustness_llm_rca\",\n action=\"store_false\",\n help=\"Forward llm_rca_enabled=false into request.options.\",\n )\n opt.add_argument(\n \"--robustness-workload-uid\",\n dest=\"robustness_workload_uid\",\n type=str,\n default=None,\n help=\"Forward workload_uid into request.options. The robustness-server \"\n \"resolves it to every pod (head + workers) backing the RayJob via \"\n \"the cluster/workloads/{uid}/hierarchy endpoint. Falls back to \"\n \"$CLAW_WORKLOAD_UID / $WORKLOAD_UID / $RAY_JOB_ID when unset.\",\n )\n opt.add_argument(\n \"--robustness-disable-local-probe\",\n dest=\"robustness_disable_local_probe\",\n action=\"store_true\",\n default=None,\n help=\"Force disable_local_probe=true. The robustness-agent silences \"\n \"its LocalProbe fallback so per-pod sandbox checks (ps, rocm-smi, \"\n \"local HTTP) cannot emit false-positive symptoms.\",\n )\n opt.add_argument(\n \"--no-robustness-disable-local-probe\",\n dest=\"robustness_disable_local_probe\",\n action=\"store_false\",\n help=\"Force disable_local_probe=false (keep the LocalProbe fallback even in multi-node mode).\",\n )\n opt.add_argument(\n \"--robustness-disable-server-probe\",\n dest=\"robustness_disable_server_probe\",\n action=\"store_true\",\n default=None,\n help=\"Force auto_probe_inference_server=false: stop the robustness-agent \"\n \"from auto-probing the local inference-server health endpoint \"\n \"(http://127.0.0.1:8888/health). Unlike --robustness-disable-local-probe \"\n \"this is surgical — the REST of LocalProbe (gpu-leak, gateway 401, \"\n \"coordinator-zombie, aiter-JIT, disk/fd) stays active. Use on \"\n \"single-node runs where the optimizer restarts the inference server \"\n \"between benchmarks: those restart windows otherwise trip \"\n \"false-positive local_server_unreachable symptoms (which can escalate \"\n \"to a premature skip_to_close / robustness_escalated stop). \"\n \"Auto-enabled in multi-node.\",\n )\n opt.add_argument(\n \"--no-robustness-disable-server-probe\",\n dest=\"robustness_disable_server_probe\",\n action=\"store_false\",\n help=\"Force auto_probe_inference_server=true (keep the 127.0.0.1:8888 \"\n \"/health auto-probe even in multi-node mode).\",\n )\n opt.add_argument(\n \"--robustness-enable-cluster-pod-metrics\",\n dest=\"robustness_enable_cluster_pod_metrics\",\n action=\"store_true\",\n default=None,\n help=\"Force enable_cluster_pod_metrics=true so the robustness-agent \"\n \"fans out per-pod metrics through robustness-server and feeds \"\n \"the local_health rules with cluster-decoded GPU snapshots.\",\n )\n opt.add_argument(\n \"--no-robustness-enable-cluster-pod-metrics\",\n dest=\"robustness_enable_cluster_pod_metrics\",\n action=\"store_false\",\n help=\"Force enable_cluster_pod_metrics=false.\",\n )\n opt.add_argument(\n \"--robustness-pod-metrics-categories\",\n dest=\"robustness_pod_metrics_categories\",\n type=str,\n default=None,\n help=\"Comma-separated metric categories forwarded into \"\n \"pod_metrics_categories (e.g. 'gpu,memory'). Default 'gpu' is \"\n \"applied by the runtime when this flag is omitted.\",\n )\n opt.add_argument(\n \"--orch-prompt\", type=str, default=None, help=\"Override Orchestration system prompt (file path or inline)\"\n )\n opt.add_argument(\"--critic-prompt\", type=str, default=None, help=\"Override Critic system prompt\")\n opt.add_argument(\"--kernel-prompt\", type=str, default=None, help=\"Override Kernel system prompt\")\n opt.add_argument(\n \"--local-kb-root\",\n dest=\"local_kb_root\",\n type=str,\n default=None,\n help=\"Filesystem root for the local recipe-snapshot KB store. \"\n \"All writes (put_recipe / append_attempt / delete_recipe) go \"\n \"here. Defaults to \"\n \"$HYPERLOOM_LOCAL_KB_ROOT, then $USER_DATA_PATH/kb, \"\n \"then /workspace/hyperloom/kb. Layout is a 5-level \"\n \"directory tree keyed by canonical_id components \"\n \"(model -> hardware -> framework -> framework_version -> \"\n \"precision); each leaf holds recipe.json + history/ + \"\n \"attempts.ndjson + .lock. See \"\n \"src/hyperloom/orchestrator/knowledge/recipe_kb/local_store.py for the \"\n \"on-disk contract.\",\n )\n opt.add_argument(\n \"--degraded-kb\",\n dest=\"degraded_kb\",\n action=\"store_true\",\n default=False,\n help=\"Skip the recipe KB integration entirely (T0/T2/T3/T4 become \"\n \"no-ops). Also short-circuits any legacy IR-3 KB probe marker. \"\n \"Manifest records the reason as ``explicit_flag`` when set \"\n \"explicitly.\",\n )\n opt.add_argument(\n \"--recipe-kb-strict-fingerprint\",\n dest=\"recipe_kb_strict_fingerprint\",\n action=\"store_true\",\n default=False,\n help=\"When set, T0 refuses warm_start_recipe rows whose \"\n \"stack_fingerprint does not match the current pod (recorded \"\n \"in manifest.json). Default: lenient (M1 records the flag \"\n \"in manifest only; consumed by M5 specialist assembly).\",\n )\n # Warm-recipe replay: PRELUDE auto-applies KB best_config before EXPLORE.\n opt.add_argument(\n \"--no-warm-replay\",\n dest=\"no_warm_replay\",\n action=\"store_true\",\n default=False,\n help=\"Disable the PRELUDE auto-replay of KB warm-start \"\n \"``best_config``. The warm_start_recipe is still rendered \"\n \"into the specialist prompt as priors, but the Coordinator \"\n \"will NOT auto-run the historical best_config. Use this \"\n \"for cold debugging / ablation runs.\",\n )\n opt.add_argument(\n \"--warm-replay-min-confidence\",\n dest=\"warm_replay_min_confidence\",\n type=float,\n default=0.7,\n help=\"Minimum ``warm_start_recipe.confidence`` required to \"\n \"trigger the auto-replay. Default 0.7 means an ``exact`` \"\n \"5-tuple hit (conf 1.0) and a server-returned ``relative`` \"\n \"match (conf 0.7) both fire, while a ``miss`` (conf 0.0) \"\n \"does not. Raise it above 0.7 to require an exact hit \"\n \"before spending a verify on the warm config.\",\n )\n opt.add_argument(\n \"--warm-replay-min-reproduce-pct\",\n dest=\"warm_replay_min_reproduce_pct\",\n type=float,\n default=0.8,\n help=\"Minimum fraction of the recipe's recorded gain we need \"\n \"to reproduce to count as ``status=reproduced`` and push \"\n \"the warm config onto the optimization stack. Default \"\n \"0.8 — a recipe claiming +25%% counts if we measure \"\n \"+20%% or more. Below the threshold we record \"\n \"``status=drift`` and continue with the regular EXPLORE \"\n \"flow without inheriting the warm config.\",\n )\n # PR Monitor REST + MCP.\n opt.add_argument(\n \"--pr-monitor-url\",\n dest=\"pr_monitor_url\",\n type=str,\n default=(os.environ.get(\"PRIMUS_CORTEX_PR_API\") or \"\").strip() or None,\n help=\"PR Monitor REST URL for this run (flag wins). Default: \"\n \"$PRIMUS_CORTEX_PR_API, else unset. Set this flag or env var to a \"\n \"reachable primus_cortex HTTPS endpoint. Pair with \"\n \"--pr-monitor-mcp-url when exposing the corresponding MCP server.\",\n )\n opt.add_argument(\n \"--pr-monitor-mcp-url\",\n dest=\"pr_monitor_mcp_url\",\n type=str,\n default=_default_pr_monitor_mcp_url(),\n help=\"PR Monitor MCP URL handed to specialist LLM backends (flag \"\n \"wins). Default: $PRIMUS_CORTEX_PR_API + '/mcp/', else unset, which \"\n \"disables PR Monitor MCP tools. The trailing slash is mandatory when \"\n \"configured.\",\n )\n opt.add_argument(\n \"--degraded-pr\",\n dest=\"degraded_pr\",\n action=\"store_true\",\n default=False,\n help=\"Disable the PR Monitor integration entirely. \"\n \"The specialist tool whitelist drops mcp__pr_monitor__* tools. \"\n \"Short-circuits the IR-3 PR Monitor probe; IR-3 sets this \"\n \"automatically when PR Monitor is unreachable (soft degrade).\",\n )\n opt.add_argument(\n \"--pr-feed-window-days\",\n dest=\"pr_feed_window_days\",\n type=int,\n default=30,\n help=\"Look-back window for the PR feed warmup (days). Default: 30.\",\n )\n # specialist research_lane capacity (locked at session start).\n opt.add_argument(\n \"--research-lane-capacity\",\n dest=\"research_lane_capacity\",\n type=int,\n default=_default_research_lane_capacity(),\n help=\"Max concurrent LLM specialist sub-agents on the \"\n \"research_lane. 0 disables specialist \"\n \"dispatch entirely (degrades to LLM-direct grid). The \"\n \"default is the research-lane ceiling (2 x visible GPU \"\n \"count, falling back to a conservative value when no GPU \"\n \"is detected); values above the ceiling are silently \"\n \"clamped down. Locked at session start.\",\n )\n opt.add_argument(\n \"--gpu-specialist-capacity\",\n dest=\"gpu_specialist_capacity\",\n type=int,\n default=_default_gpu_specialist_capacity(),\n help=\"Number of GPUs available to specialists that request \"\n \"needs_gpu=true. Defaults to the whole machine (visible GPU \"\n \"count on the launch host); set \"\n \"--gpu-specialist-capacity 0 to disable GPU specialists. GPU specialists serialize against the \"\n \"serving lanes via gpu_research_lane. \"\n \"Set INFERENCE_OPTIMIZER_GPU_SPECIALIST_DEVICES to a \"\n \"comma-separated GPU id pool when the specialist pool should \"\n \"not use device ids 0..N-1. Locked at session start.\",\n )\n # Advisory specialist-proposal scorer (ProposalScorer): scores each\n # proposal_set with gateway models as a reference for Orchestration; never gates.\n opt.add_argument(\n \"--proposal-scorer-models\",\n dest=\"proposal_scorer_models\",\n type=str,\n default=\",\".join(DEFAULT_SCORER_MODELS),\n help=\"Comma-separated gateway model slugs that independently \"\n \"score each specialist proposal_set (advisory only; never \"\n \"gates; rater identities are anonymized in the orchestration \"\n \"prompt). Only takes effect when --proposal-scoring is also \"\n \"passed (scoring is OFF by default); this flag alone does not \"\n \"enable scoring. Default 'claude-opus-4-8,gpt-5.5,\"\n \"dvue-aoai-005-Kimi-K2.6,gemini/gemini-3.1-pro-preview'. \"\n \"Add a model by appending its slug. Empty list disables scoring \"\n \"even when enabled.\",\n )\n opt.add_argument(\n \"--proposal-scoring\",\n dest=\"proposal_scoring\",\n action=argparse.BooleanOptionalAction,\n default=False,\n help=\"Enable the advisory specialist-proposal scorer (disabled by \"\n \"default). Use --no-proposal-scoring to keep it off explicitly. \"\n \"Even when enabled it is skipped in Anthropic-only deployments \"\n \"(OpenAI-compatible only) or when the model list is empty. \"\n \"Advisory only; never gates.\",\n )\n # specialist sub-agent backend selection: Claude (default), inherits orchestration model.\n opt.add_argument(\n \"--specialist-model\",\n dest=\"specialist_model\",\n type=str,\n default=None,\n help=\"Claude model used for specialist sub-agents (defaults to \"\n \"the orchestration --claude-model). KB_design §3.5 §6.\",\n )\n opt.add_argument(\n \"--specialist-max-turns\",\n dest=\"specialist_max_turns\",\n type=int,\n default=_DEFAULT_SPECIALIST_MAX_TURNS,\n help=\"Hard cap on LLM turns per specialist task (KB_design \"\n \"§3.5 §6). On exhaustion the runner synthesises an empty \"\n \"specialist_done (Inv-5.3).\",\n )\n opt.add_argument(\n \"--specialist-per-turn-max-seconds\",\n dest=\"specialist_per_turn_max_seconds\",\n type=float,\n default=600.0,\n help=\"Wall-clock fallback ceiling per specialist task when no \"\n \"explicit wall_budget_sec is provided (legacy backstop, default \"\n \"600s; production dispatches use the WS1 wall-clock budget).\",\n )\n # specialist dispatch shape\n opt.add_argument(\n \"--specialist-dispatch-mode\",\n dest=\"specialist_dispatch_mode\",\n type=str,\n choices=(\"subprocess\", \"inprocess\"),\n default=\"subprocess\",\n help=\"Specialist execution shape. 'subprocess' (default) spawns \"\n \"a fresh `claude` CLI per task inside a per-task git worktree \"\n \"for isolation (PR-A2). 'inprocess' keeps the legacy M5 path \"\n \"(claude-agent-sdk in the orchestrator process) for tests / \"\n \"environments without the claude binary.\",\n )\n opt.add_argument(\n \"--specialist-mcp-config\",\n dest=\"specialist_mcp_config\",\n type=str,\n default=None,\n help=\"Optional path to an MCP config JSON forwarded to the \"\n \"subprocess claude (`--mcp-config`). Used to wire PR Monitor \"\n \"MCP servers into specialists. Default: None.\",\n )\n\n # Integration toggles. Roofline refresh is unconditional (fires at PRELUDE\n # and every 10% cumulative_gain_validated crossing).\n opt.add_argument(\n \"--allow-empty-kernel-shape\",\n dest=\"allow_empty_kernel_shape\",\n action=\"store_true\",\n default=False,\n help=\"Escape hatch (default off): allow kernel optimization to \"\n \"dispatch a candidate with no trace-anchored shape. Normally \"\n \"a shapeless candidate is rejected with a structured error so \"\n \"the run returns to ``trace_analyze`` instead of burning a \"\n \"kernel-optimization budget on an unanchored kernel.\",\n )\n opt.add_argument(\n \"--enable-roofline\",\n dest=\"enable_roofline\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Select which analysis action the Coordinator enqueues at \"\n \"PRELUDE bootstrap and on every +10%% watermark crossing. \"\n \"Default on: ``roofline`` (composite profile + \"\n \"trace_analyze + analysis.md). Pass ``--no-enable-roofline`` \"\n \"to use plain ``profile`` instead (lighter — captures the \"\n \"trace only, skips trace_analyze). Behaviour is otherwise \"\n \"identical (same idempotency keys, same pending-task \"\n \"dispatch gate, same watermark anchor update).\",\n )\n opt.add_argument(\n \"--research-scout\",\n dest=\"research_scout\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Auto-dispatch a read-only research scout at PRELUDE (and \"\n \"every --research-scout-interval EXPLORE rounds) that \"\n \"collects proven priors — reference launch scripts, model \"\n \"config.json architecture features, and cross-framework / \"\n \"NVIDIA research — into ``research_hints.md`` and seeds \"\n \"high-priority gaps. Default on; pass ``--no-research-scout`` \"\n \"to disable the whole feature.\",\n )\n opt.add_argument(\n \"--research-scout-interval\",\n dest=\"research_scout_interval\",\n type=int,\n default=3,\n help=\"Re-dispatch the research scout every N EXPLORE rounds with \"\n \"the current bottleneck context (append-only). Default 3. \"\n \"Ignored when ``--no-research-scout`` is set.\",\n )\n opt.add_argument(\n \"--static-recon\",\n dest=\"static_recon\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Auto-dispatch a read-only static-recon specialist at PRELUDE \"\n \"that greps the framework source for un-bridged capability \"\n \"switches (predicates that silently disable a faster path for \"\n \"this model/GPU/precision, e.g. a CUDA-only ``*_supported()`` \"\n \"on ROCm) and seeds bridge candidates as gaps[]. Default on; \"\n \"pass ``--no-static-recon`` to disable.\",\n )\n opt.add_argument(\n \"--recipe-sediment\",\n dest=\"recipe_sediment\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Sediment KEEP/REVERT provenance into the persistent recipe: \"\n \"KEEP optimizations traceable to a research hint carry their \"\n \"source + measured gain into ``what_worked``; REVERTs land in \"\n \"``what_failed`` so the next warm-start avoids re-testing them. \"\n \"Default on; pass ``--no-recipe-sediment`` to keep the recipe \"\n \"purely ephemeral.\",\n )\n opt.add_argument(\n \"--target-advisory\",\n dest=\"target_advisory\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Inject an advisory 'External target gap' block (throughput / \"\n \"TPOT / interactivity gap vs the LLM-authored competitor \"\n \"target) into the orchestration and specialist prompts; when \"\n \"the TPOT ratio dominates it nudges toward latency-reducing \"\n \"directions. Advisory only — never gates Objective or scoring. \"\n \"Default on; pass ``--no-target-advisory`` to disable.\",\n )\n # Post-optimization concurrency sweep (on by default): a baseline-vs-optimized\n # Magpie grid across CONC values (see orchestrator/conc_sweep.py).\n opt.add_argument(\n \"--enable-conc-sweep\",\n dest=\"enable_conc_sweep\",\n action=argparse.BooleanOptionalAction,\n default=True,\n help=\"Run a post-optimization concurrency sweep (baseline vs \"\n \"current_best across CONC) and write \"\n \"reports/conc_sweep_summary.json + conc_sweep_raw.csv. \"\n \"On by default; disable with --no-enable-conc-sweep.\",\n )\n opt.add_argument(\n \"--conc-sweep-concs\",\n dest=\"conc_sweep_concs\",\n type=str,\n default=\"256,128,64,32,16,8,4,2\",\n help=\"Comma-separated CONC ladder for --enable-conc-sweep. Default 256,128,64,32,16,8,4,2 (high-to-low for single-server arm reuse).\",\n )\n opt.add_argument(\n \"--conc-sweep-timeout-sec\",\n dest=\"conc_sweep_timeout_sec\",\n type=int,\n default=1800,\n help=\"Per-variant timeout (seconds) for --enable-conc-sweep. \"\n \"Default 1800 (~30 min). Per-variant cap is also clamped \"\n \"by the remaining --conc-sweep-total-budget-sec.\",\n )\n opt.add_argument(\n \"--conc-sweep-total-budget-sec\",\n dest=\"conc_sweep_total_budget_sec\",\n type=int,\n default=9000,\n help=\"Total wall-clock budget (seconds) for the whole conc-sweep \"\n \"action, independent of the per-variant Magpie timeout. \"\n \"Once exhausted, remaining variants are recorded as \"\n \"status=skipped / error_class=budget_exhausted and the \"\n \"JSON envelope carries budget_exhausted=true. Default 9000 \"\n \"(~2.5h); set to 0 to disable. Also bounded above by the \"\n \"main session wall-clock deadline since conc_sweep runs as \"\n \"a SWEEP-phase action.\",\n )\n # Per-variant explore overtime kill ratio (mirrored to\n # SharedState.explore_overtime_kill_ratio). 0 disables.\n opt.add_argument(\n \"--explore-overtime-kill-ratio\",\n dest=\"explore_overtime_kill_ratio\",\n type=float,\n default=2.0,\n help=\"Per-variant explore overtime kill: each single-variant \"\n \"Magpie run in the explore loop is reaped once its \"\n \"POST-READY (pure hot client) wall-clock exceeds \"\n \"``decision_anchor_sec * RATIO`` (the warm-decision anchor is \"\n \"``baseline_warm_runtime_sec``; pre-ready boot / weight load / \"\n \"first-request recompile is excluded — see \"\n \"INFERENCE_OPTIMIZER_SOFT_DEADLINE_FROM_READY). The variant is \"\n \"recorded with outcome=KILLED_OVERTIME + runtime_sec + \"\n \"wall_clock_ratio_vs_baseline (no tput) so the LLM can \"\n \"distinguish it from a hard timeout / crash. Default 2.0 (kill \"\n \"at +100%% over the warm client anchor). Pass 0 to disable.\",\n )\n # Explore variant hard timeout — operator override for the auto-derived cap.\n # 0 (default) keeps auto-derive; mirrored to\n # SharedState.explore_variant_timeout_sec_override.\n opt.add_argument(\n \"--explore-variant-timeout-sec\",\n dest=\"explore_variant_timeout_sec\",\n type=int,\n default=0,\n help=\"Pin the per-variant hard timeout (seconds) inside the \"\n \"EXPLORE phase. ``0`` (default) auto-derives from \"\n \"``baseline_runtime_sec * (--explore-overtime-kill-ratio + \"\n \"--explore-variant-timeout-safety-margin)`` once baseline \"\n \"lands, with a 2400-14400 s range guard. Set to a positive \"\n \"integer to pin (CI smoke runs / debugging).\",\n )\n opt.add_argument(\n \"--explore-variant-timeout-safety-margin\",\n dest=\"explore_variant_timeout_safety_margin\",\n type=float,\n default=0.5,\n help=\"Headroom (as a fraction of baseline_runtime_sec) added on \"\n \"top of --explore-overtime-kill-ratio when the EXPLORE hard \"\n \"cap is auto-derived. Default 0.5 (≈ 50%% of baseline as \"\n \"buffer for variant cold starts: torch.compile AOTI compile, \"\n \"fresh aiter shapes, spec-decoding draft load). Bump for \"\n \"workloads with heavy compile cost; lower to tighten the \"\n \"backstop. No effect when --explore-variant-timeout-sec is \"\n \"set to a positive value.\",\n )\n opt.add_argument(\n \"--reset-state\",\n dest=\"reset_state\",\n action=\"store_true\",\n default=False,\n help=\"Back up the existing ``state.json`` (if any) to \"\n \"``state.json.preReset.`` and start the session \"\n \"from a blank SharedState. Recipe KB is NOT touched.\",\n )\n # observability\n opt.add_argument(\n \"--breakdown-include-transcripts\",\n dest=\"breakdown_include_transcripts\",\n type=str,\n choices=(\"true\", \"false\"),\n default=\"false\",\n help=\"Inline specialist transcript bodies into \"\n \"``specialist_runs`` (true) or reference them by path \"\n \"only (false, default). KB_design §3.12 §7.\",\n )\n # plateau threshold tuning: override defaults; locked at session start.\n opt.add_argument(\n \"--plateau-explore-keep-gain\",\n dest=\"plateau_explore_keep_gain\",\n type=float,\n default=None,\n help=\"EXPLORE plateau: max cumulative KEEP-gain (%%) across the \"\n \"lookback window below which the AND condition fires. \"\n \"Default 0.5.\",\n )\n opt.add_argument(\n \"--plateau-explore-empty-streak\",\n dest=\"plateau_explore_empty_streak\",\n type=int,\n default=None,\n help=\"EXPLORE plateau: required count of *consecutive* specialist \"\n \"rounds with empty proposal_set before the AND condition \"\n \"fires. Default 3.\",\n )\n opt.add_argument(\n \"--plateau-explore-lookback\",\n dest=\"plateau_explore_lookback\",\n type=int,\n default=None,\n help=\"EXPLORE plateau: number of trailing rounds the gain sum is computed over. Default 5.\",\n )\n opt.add_argument(\n \"--plateau-kernel-revert-streak\",\n dest=\"plateau_kernel_revert_streak\",\n type=int,\n default=None,\n help=\"KERNEL plateau: consecutive REVERT / NEEDS_REVIEW integrate \"\n \"attempts to count as plateau (one half of the OR). \"\n \"Default 3.\",\n )\n opt.add_argument(\n \"--plateau-kernel-keep-gain\",\n dest=\"plateau_kernel_keep_gain\",\n type=float,\n default=None,\n help=\"KERNEL plateau: max cumulative KEEP-gain (%%) across the \"\n \"lookback window below which the OR fires. Default 0.5.\",\n )\n opt.add_argument(\n \"--plateau-kernel-lookback\",\n dest=\"plateau_kernel_lookback\",\n type=int,\n default=None,\n help=\"KERNEL plateau: number of trailing integrate attempts the gain sum is computed over. Default 5.\",\n )\n # IR-6 — EXPLORE hard force-exit thresholds (either condition fires; locked at start).\n opt.add_argument(\n \"--explore-force-exit-hours-remaining\",\n dest=\"explore_force_exit_hours_remaining\",\n type=float,\n default=None,\n help=\"EXPLORE force-exit: total wall-clock remaining (hours) \"\n \"below which EXPLORE exits immediately to the next phase, \"\n \"regardless of plateau / steward. Default 3.0 (IR-6).\",\n )\n opt.add_argument(\n \"--explore-force-exit-budget-pct\",\n dest=\"explore_force_exit_budget_pct\",\n type=float,\n default=None,\n help=\"EXPLORE force-exit: phase-budget remaining fraction \"\n \"(0..1) below which EXPLORE exits immediately. Default \"\n \"0.20 (IR-6).\",\n )\n # phase budget percentages: each phase claims a fraction of the wall-clock\n # budget (caps; may exit earlier). Both ``--max-minutes-*-pct`` and\n # ``--phase-budget-*-pct`` spellings are accepted.\n opt.add_argument(\n \"--max-minutes-prelude-pct\",\n \"--phase-budget-prelude-pct\",\n dest=\"phase_budget_prelude_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for PRELUDE as a fraction of --max-hours. Default: 0.03.\",\n )\n opt.add_argument(\n \"--max-minutes-framework-pct\",\n \"--phase-budget-framework-pct\",\n dest=\"phase_budget_framework_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for FRAMEWORK_AGENT. Default: 0.20.\",\n )\n opt.add_argument(\n \"--max-minutes-explore-pct\",\n \"--phase-budget-explore-pct\",\n dest=\"phase_budget_explore_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for EXPLORE. Default: 0.35.\",\n )\n opt.add_argument(\n \"--max-minutes-kernel-pct\",\n \"--phase-budget-kernel-pct\",\n dest=\"phase_budget_kernel_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for KERNEL_AGENT. Default: 0.28.\",\n )\n opt.add_argument(\n \"--max-minutes-sweep-pct\",\n \"--phase-budget-sweep-pct\",\n dest=\"phase_budget_sweep_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for SWEEP. Default: 0.12.\",\n )\n opt.add_argument(\n \"--max-minutes-close-pct\",\n \"--phase-budget-close-pct\",\n dest=\"phase_budget_close_pct\",\n type=float,\n default=None,\n help=\"Wall-clock budget cap for CLOSE. Default: 0.02.\",\n )\n opt.add_argument(\n \"--strict-phase\",\n dest=\"strict_phase\",\n action=\"store_true\",\n default=True,\n help=\"Enforce PolicyGate R1 phase_incompatible. \"\n \"Action proposals outside the current phase's allowlist \"\n \"return policy_denied so the LLM self-corrects.\",\n )\n opt.add_argument(\n \"--no-strict-phase\",\n dest=\"strict_phase\",\n action=\"store_false\",\n help=\"Disable R1 enforcement (warn-only). Useful for back-compat smoke tests; production should stay strict.\",\n )\n\n rec = sub.add_parser(\n \"recover-session\",\n help=\"Rebuild + push the session_breakdown for a session that exited \"\n \"abnormally (crash / SIGKILL) so its breakdown lands on Langfuse.\",\n )\n rec.add_argument(\n \"--session-dir\",\n type=Path,\n required=True,\n help=\"Session directory of the crashed run (contains state.json / reports/trace/ and the recorder fragments).\",\n )\n rec.add_argument(\n \"--force\",\n action=\"store_true\",\n help=\"Re-run even when the session already looks complete (close_sequence_done / breakdown already recorded).\",\n )\n rec.add_argument(\n \"--backfill-trace\",\n action=\"store_true\",\n help=\"Also replay reports/trace/llm_calls.jsonl as Langfuse \"\n \"generations. Use ONLY when the live emitter never ran for this \"\n \"session (e.g. it was disabled during the run); otherwise it \"\n \"duplicates generations already pushed live.\",\n )\n\n return p\n"}}, "src/hyperloom/inference_optimizer/assets/install.sh": {"43b48fa732ad3f48df30f529fb8847286f110a59": {"t": 1786068349.3529205, "n": 80165, "h": "315ef624d4470589", "c": "#!/usr/bin/env bash\n# SPDX-FileCopyrightText: 2026 Advanced Micro Devices, Inc.\n# SPDX-License-Identifier: MIT\n\n# Inference Optimizer installer.\n#\n# Owns the inference_optimizer-side bare-image setup so SKILL.md does\n# not have to hand-roll it. Idempotent — every step skips if the\n# artifact is already present.\n#\n# Stack (in order):\n# 1. inference_optimizer + extras (pulls in claude_agent_sdk via\n# pyproject `[test]` extra)\n# 2. Magpie (benchmark engine) pip-installed from MAGPIE_PACKAGE_SPEC,\n# pinned to MAGPIE_REF (a commit SHA or tag)\n# 2b. Atomic-write patch for Magpie._prepare_benchmark_scripts\n# (root-cause fix for the Hyperloom #C1 script-tearing race;\n# fail-soft — a no-op when the MAGPIE_REF target already has\n# upstream atomic copying)\n# 3. InferenceX checkout: clone from upstream pinned to INFERENCEX_REF\n# (a commit SHA), sets INFERENCEX_PATH for runtime\n# 4. Delegates to src/hyperloom/agents/kernel/scripts/install.sh for ray, ray-head\n# bring-up, TraceLens, GEAK and LLM gateway env setup.\n# kernel-agent itself is the canonical owner of those — we just\n# chain to it so users have a single entry point.\n#\n# kernel-agent's install.sh owns Ray + ray start, TraceLens, GEAK and\n# LLM gateway env. inference_optimizer's install.sh owns Magpie /\n# InferenceX / the inference_optimizer Python package itself. The two\n# are composable: kernel-agent works standalone; inference_optimizer\n# drags kernel-agent in via this script.\n#\n# Open-source deps (InferenceX / TraceLens) are cloned here or by the\n# chained kernel-agent installer.\n\nset -euo pipefail\n\n# Ray/K8s subprocesses may inherit a minimal PATH; git/apt live under /usr/bin.\n# Prepend the standard system bins so multi-node RayJob subprocesses (and any\n# K8s-spawned child shell) still resolve git/apt/python3 when callers only\n# prepend /opt/venv/bin.\nexport PATH=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin${PATH:+:$PATH}\"\n# Re-assert the active virtualenv ahead of the system bins prepended above.\n# Callers may only put the venv on PATH (e.g. /venv/bin) or activate it via\n# $VIRTUAL_ENV; otherwise the system-bins prepend shadows the venv python3\n# with /usr/bin/python3, whose apt-managed packages (e.g. packaging) have no\n# RECORD file and break `pip install`/uninstall. Probe the activated venv\n# first, then the common ROCm image locations (/opt/venv, /venv).\nfor _venv_bin in \"${VIRTUAL_ENV:+${VIRTUAL_ENV}/bin}\" /opt/venv/bin /venv/bin; do\n if [ -n \"${_venv_bin}\" ] && [ -x \"${_venv_bin}/python\" ]; then\n export PATH=\"${_venv_bin}:$PATH\"\n break\n fi\ndone\n\n# Single artefact root: everything writable defaults to $USER_DATA_PATH so\n# operators can monitor a run end-to-end by tailing one directory. Magpie\n# clone, source mirrors, and generated env / GEAK config all derive from\n# $HYPERLOOM_RUNTIME_DIR.\n# Removed envs: WORKSPACE_ROOT / WORKSPACE_PATH (collapsed into USER_DATA_PATH).\n_script_dir=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n\nresolve_repo_root() {\n if [ -n \"${REPO_ROOT:-}\" ]; then\n printf '%s\\n' \"$REPO_ROOT\"\n return 0\n fi\n local source_root packaged_root\n source_root=\"$(cd \"${_script_dir}/../../../..\" && pwd)\"\n packaged_root=\"$(cd \"${_script_dir}/../../..\" && pwd)\"\n if [ -f \"${source_root}/pyproject.toml\" ]; then\n printf '%s\\n' \"$source_root\"\n else\n printf '%s\\n' \"$packaged_root\"\n fi\n}\n\nREPO_ROOT=\"$(resolve_repo_root)\"\nDOTENV_LOADED_COUNT=0\n\nsetup_dotenv_is_authoritative() {\n [ -f \"$REPO_ROOT/.env\" ] || return 1\n grep -q '^HYPERLOOM_RUN_MODE=' \"$REPO_ROOT/.env\" 2>/dev/null\n}\n\nscrub_stale_workspace_env_for_setup_dotenv() {\n setup_dotenv_is_authoritative || return 0\n unset USER_DATA_PATH\n unset HYPERLOOM_RUNTIME_DIR\n unset KERNEL_AGENT_ENV\n unset HYPERLOOM_ROOT\n unset HYPERLOOM_KERNEL_AGENT_ROOT\n unset KERNEL_AGENT_ROOT\n unset FRAMEWORK_AGENT_ROOT\n unset HYPERLOOM_SKILL_PATH\n unset PYTHONPATH\n}\n\nload_dotenv_no_clobber() {\n DOTENV_LOADED_COUNT=0\n [ -f \"$REPO_ROOT/.env\" ] || return 0\n local loaded=0\n local raw key value\n while IFS= read -r raw || [ -n \"$raw\" ]; do\n raw=\"${raw#\"${raw%%[![:space:]]*}\"}\"\n raw=\"${raw%\"${raw##*[![:space:]]}\"}\"\n [ -z \"$raw\" ] && continue\n case \"$raw\" in \\#*) continue ;; esac\n case \"$raw\" in export\\ *) raw=\"${raw#export }\" ;; esac\n case \"$raw\" in *=*) ;; *) continue ;; esac\n key=\"${raw%%=*}\"\n value=\"${raw#*=}\"\n key=\"${key%\"${key##*[![:space:]]}\"}\"\n value=\"${value#\"${value%%[![:space:]]*}\"}\"\n value=\"${value%\"${value##*[![:space:]]}\"}\"\n case \"$value\" in\n \\\"*\\\") value=\"${value#\\\"}\"; value=\"${value%\\\"}\" ;;\n \\'*\\') value=\"${value#\\'}\"; value=\"${value%\\'}\" ;;\n esac\n [ -z \"$key\" ] && continue\n if [ -z \"${!key:-}\" ]; then\n export \"$key=$value\"\n loaded=$((loaded + 1))\n fi\n done < \"$REPO_ROOT/.env\"\n DOTENV_LOADED_COUNT=\"$loaded\"\n return 0\n}\n\n# Load .env before deriving USER_DATA_PATH / HYPERLOOM_RUNTIME_DIR so a\n# freshly-copied .env.template can be the single configuration entrypoint.\n# The loader is no-clobber: explicit shell exports always win.\nscrub_stale_workspace_env_for_setup_dotenv\nload_dotenv_no_clobber\n# Capture whether USER_DATA_PATH was provided BEFORE applying the default so we\n# can warn loudly on the silent fallback. ${VAR:+1} is empty when VAR is unset\n# or empty, which is exactly the case the :- default below would absorb.\n_user_data_was_set=\"${USER_DATA_PATH:+1}\"\nUSER_DATA_PATH=\"${USER_DATA_PATH:-/workspace/hyperloom}\"\nif [ -z \"${_user_data_was_set}\" ]; then\n echo \"[install WARN] USER_DATA_PATH not set; defaulting to /workspace/hyperloom. Set USER_DATA_PATH to persist artifacts under your data root.\" >&2\nfi\nHYPERLOOM_RUNTIME_DIR=\"${HYPERLOOM_RUNTIME_DIR:-${USER_DATA_PATH}/runtime}\"\nKERNEL_AGENT_ENV=\"${KERNEL_AGENT_ENV:-${HYPERLOOM_RUNTIME_DIR}/kernel-agent.env.sh}\"\n# Legacy variable kept for compatibility; open-source checkouts use _open_source_root.\nHYPERLOOM_ROOT=\"${HYPERLOOM_ROOT:-${HYPERLOOM_RUNTIME_DIR}/source-mirrors}\"\n# Writable, repo-local base for auto-cloned deps: $HYPERLOOM_CACHE_DIR else\n# $REPO_ROOT/.cache, cloned per revision (@). Not /tmp (a reaper can\n# wipe it mid-run, leaving TRACELENS_ROOT dangling — #722).\n_open_source_root=\"${HYPERLOOM_CACHE_DIR:-${REPO_ROOT}/.cache}\"\n# tree-reform.MD P2.5: kernel-agent/framework-agent live under the hyperloom\n# package tree in both source and pip-installed layouts. A missing pyproject at\n# REPO_ROOT means setup is running from a pip --target workspace rather than a\n# source checkout, so the editable self-install step below is skipped.\n_hyperloom_pkg_root=\"$(cd \"${_script_dir}/../..\" && pwd)\"\nHYPERLOOM_PACKAGED_INSTALL=0\nif [ ! -f \"${REPO_ROOT}/pyproject.toml\" ] && [ -d \"${_hyperloom_pkg_root}/agents/kernel\" ]; then\n HYPERLOOM_PACKAGED_INSTALL=1\nfi\nKERNEL_AGENT_ROOT=\"${KERNEL_AGENT_ROOT:-${_hyperloom_pkg_root}/agents/kernel}\"\nFRAMEWORK_AGENT_ROOT=\"${FRAMEWORK_AGENT_ROOT:-${_hyperloom_pkg_root}/agents/framework}\"\n# tree-reform.MD P2.5: framework-agent was promoted from a sibling\n# ``framework-agent/`` checkout into the in-tree ``hyperloom`` src-layout\n# namespace (``src/hyperloom/agents/framework``); it no longer has its own\n# installer/venv, so FRAMEWORK_AGENT_ROOT now just points at that in-tree\n# package (still overridable) and the old chain_framework_agent() delegation\n# below is a no-op.\n# Resolve a git ref to a commit SHA: 7-40 hex passes through; branch/tag via\n# ls-remote (falls back to the raw ref). The SHA keys the per-revision cache.\n_resolve_ref_sha() {\n local repo=\"$1\" ref=\"$2\" sha=\"\"\n if [[ \"$ref\" =~ ^[0-9a-fA-F]{7,40}$ ]]; then\n printf '%s' \"$ref\"\n return 0\n fi\n sha=\"$(git ls-remote \"$repo\" \"$ref\" 2>/dev/null | awk 'NR==1{print $1}')\"\n if [ -z \"$sha\" ]; then\n # Loud, not silent: a raw-ref cache key drops the per-revision guarantee.\n echo \"[inference-optimizer WARN] could not resolve '$ref' at $repo to a commit SHA (network or bad ref); using '$ref' as the per-revision cache key -- stale-checkout guard weakened. Pin *_REF to a 40-hex SHA or restore network access.\" >&2\n sha=\"$ref\"\n fi\n printf '%s' \"$sha\"\n}\n\n# Bound cache growth: keep the newest $HYPERLOOM_CACHE_KEEP (default 3, 0 disables)\n# @ checkouts per dep, prune older ones. A moving branch ref (GEAK\n# `main`) resolves to a new SHA each HEAD bump, so the cache would grow unbounded.\n# Lock-held; the just-installed revision is newest, so always retained.\n_prune_dep_cache() {\n local keep=\"${HYPERLOOM_CACHE_KEEP:-3}\"\n case \"$keep\" in ''|*[!0-9]*) keep=3 ;; esac\n [ \"$keep\" -eq 0 ] && return 0\n local name stale listing\n for name in \"$@\"; do\n # `|| true`: no-match glob fails `ls` under `set -euo pipefail`. Collect, then act.\n listing=\"$(ls -dt \"${_open_source_root}/${name}@\"* 2>/dev/null | tail -n +\"$((keep + 1))\" || true)\"\n [ -n \"$listing\" ] || continue\n while IFS= read -r stale; do\n [ -n \"$stale\" ] && [ -d \"$stale\" ] || continue\n log \"pruning stale dep cache (keeping newest ${keep} ${name}@*): ${stale}\"\n rm -rf -- \"$stale\" 2>/dev/null || true\n done <.\nMAGPIE_REF=\"${MAGPIE_REF:-0171222c532db6fc5cb174667db66e34f1d9dd98}\"\nMAGPIE_PACKAGE_SPEC=\"${MAGPIE_PACKAGE_SPEC:-magpie-eval @ git+${MAGPIE_REPO}@${MAGPIE_REF}}\"\n\n# aiperf (SemiAnalysis AgentX benchmark client) — pinned to an immutable commit\n# on the SemiAnalysisAI org repo. Only needed for AgentX mode (HYPERLOOM_AGENTX).\n# Installed fail-soft (see ensure_aiperf): a failure must never block the default\n# synthetic path. Operators can override AIPERF_BIN to skip this install.\nAIPERF_REPO=\"${AIPERF_REPO:-https://github.com/SemiAnalysisAI/aiperf.git}\"\nAIPERF_REF=\"${AIPERF_REF:-dc975aaa4491388defe28725934bd08348253fb8}\"\nAIPERF_PACKAGE_SPEC=\"${AIPERF_PACKAGE_SPEC:-aiperf @ git+${AIPERF_REPO}@${AIPERF_REF}}\"\n# MAGPIE_PATH points install.sh AND the Python optimizer (cli.py /\n# _grid_runner.py / manifest.py) at Magpie's import root. When unset by the\n# operator, ensure_magpie resolves it from the pip-installed package; explicit\n# overrides remain supported for local source checkouts / debugging.\nMAGPIE_PATH_EXPLICIT=0\nif [ -n \"${MAGPIE_PATH:-}\" ]; then\n MAGPIE_PATH_EXPLICIT=1\nfi\nMAGPIE_PATH=\"${MAGPIE_PATH:-${_open_source_root}/Magpie}\"\nINFERENCEX_REPO=\"${INFERENCEX_REPO:-https://github.com/SemiAnalysisAI/InferenceX.git}\"\n# Pin InferenceX to a current default-branch HEAD *commit SHA* so the\n# per-install clone is reproducible (same rationale as MAGPIE_REF). Operators\n# can re-pin with INFERENCEX_REF=.\nINFERENCEX_REF=\"${INFERENCEX_REF:-a4bb43afa7fd74c1356583ed29e51421be010f0f}\"\n_INFERENCEX_SHA=\"$(_resolve_ref_sha \"$INFERENCEX_REPO\" \"$INFERENCEX_REF\")\"\nINFERENCEX_DEFAULT_DIR=\"${INFERENCEX_DEFAULT_DIR:-${_open_source_root}/InferenceX@${_INFERENCEX_SHA}}\"\n\nDRY_RUN=0\nCHECK_ONLY=0\nSKIP_KERNEL_AGENT=0\n\nusage() {\n cat <<'EOF'\nUsage: src/hyperloom/inference_optimizer/assets/install.sh [options]\n\nInstalls:\n - inference_optimizer Python package (with claude_agent_sdk via [test])\n - langfuse SDK, but ONLY when HYPERLOOM_LANGFUSE_ENABLE is on in the\n environment / .env (opt-in live trace push; skipped otherwise)\n - Magpie (pip-installed from MAGPIE_PACKAGE_SPEC)\n - Clones InferenceX pinned to INFERENCEX_REF and exports INFERENCEX_PATH\n - Chains to src/hyperloom/agents/kernel/scripts/install.sh for Ray + ray-head start,\n TraceLens, GEAK, and LLM gateway env.\n - The `fa` CLI (used by the Coordinator-owned FRAMEWORK_AGENT phase at\n optimize-time, candidate discovery via `fa phase-discover`) is provided\n by this same editable install (tree-reform.MD P2.5 promoted\n framework-agent into src/hyperloom/agents/framework/, so it no longer\n has its own separate installer/venv to chain to).\n\nOptions:\n --check-only Verify only, do not install\n --dry-run Print actions without running them\n --skip-kernel-agent Skip the chained kernel-agent installer\n -h, --help Show this help\n\nEnv overrides:\n REPO_ROOT, KERNEL_AGENT_ROOT, FRAMEWORK_AGENT_ROOT, MAGPIE_REPO,\n MAGPIE_REF (commit SHA / tag / branch the Magpie package is pinned to;\n default is a commit that already copies benchmark scripts atomically),\n MAGPIE_PACKAGE_SPEC, MAGPIE_PATH, INFERENCEX_REPO,\n INFERENCEX_REF (commit SHA / tag / branch the InferenceX clone is pinned\n to; default is a current upstream HEAD SHA),\n INFERENCEX_DEFAULT_DIR, INFERENCEX_PATH,\n PYTHON, TRACELENS_ROOT,\n TRACELENS_INTERNAL_ROOT (set to enable the optional internal extension;\n unset => open-source-only),\n USER_DATA_PATH,\n HYPERLOOM_RUNTIME_DIR, KERNEL_AGENT_ENV, HYPERLOOM_ROOT,\n PATCH_MAGPIE (=1; set 0 only if upstream Magpie atomic-write\n PR is already merged into your clone),\n MAGPIE_EVAL_FLAG_STRICT (=1; abort when the redundant\n --concurrent-requests eval flag cannot be removed from a Magpie\n benchmark script. Set 0 only when GSM8K accuracy eval is not\n required — with the flag live, every RUN_EVAL=true baseline aborts)\nEOF\n}\n\nwhile [ \"$#\" -gt 0 ]; do\n case \"$1\" in\n --check-only) CHECK_ONLY=1 ;;\n --dry-run) DRY_RUN=1 ;;\n --skip-kernel-agent) SKIP_KERNEL_AGENT=1 ;;\n -h|--help) usage; exit 0 ;;\n *) echo \"[inference-optimizer] ERROR: unknown option '$1'\" >&2; usage >&2; exit 2 ;;\n esac\n shift\ndone\n\nlog() { echo \"[inference-optimizer] $*\"; }\nwarn() { echo \"[inference-optimizer WARN] $*\" >&2; }\ndie() { echo \"[inference-optimizer ERROR] $*\" >&2; exit 1; }\n\n# Truthy/falsy test for boolean-ish env vars. Numeric `-eq` comparisons choke on\n# string values (`[ false -eq 0 ]` errors and reads as true under set -e), so a\n# user writing MAGPIE_PATCH_STRICT=false would get the OPPOSITE of intent. Accept\n# the common spellings case-insensitively; returns success (0) when falsy.\nis_falsy() {\n case \"$(printf '%s' \"${1:-}\" | tr '[:upper:]' '[:lower:]')\" in\n 0|false|no|off|\"\") return 0 ;;\n *) return 1 ;;\n esac\n}\n\nrun() {\n log \"$*\"\n if [ \"$DRY_RUN\" -eq 0 ] && [ \"$CHECK_ONLY\" -eq 0 ]; then\n \"$@\"\n fi\n}\n\n# Clone a dependency pinned to $ref into $dir, mirroring the GEAK pin in\n# src/hyperloom/agents/kernel/scripts/install.sh. `git clone --branch` only accepts\n# tags/branches, not raw SHAs, so a 7-40 hex char ref triggers a shallow\n# fetch-checkout dance instead (GitHub serves shallow SHA fetches via\n# uploadpack.allowReachableSHA1InWant=true). DRY_RUN / CHECK_ONLY are honoured\n# through the shared `run` helper. On success the checkout has a valid HEAD at\n# $ref, so manifest.py's _git_revision_at() still resolves the pinned commit.\n# Returns non-zero (stopping at the first failed step) so callers can choose\n# fail-loud (Magpie) or fail-soft (InferenceX).\ngit_fetch_pinned() {\n local repo=\"$1\" dir=\"$2\" ref=\"$3\" label=\"$4\"\n if [[ \"$ref\" =~ ^[0-9a-fA-F]{7,40}$ ]]; then\n log \"fetching ${label} pinned to commit ${ref} (shallow fetch-checkout)\"\n run git init -q \"$dir\" || return 1\n run git -C \"$dir\" remote add origin \"$repo\" || return 1\n run git -C \"$dir\" fetch --depth 1 origin \"$ref\" || return 1\n run git -C \"$dir\" checkout -q FETCH_HEAD || return 1\n else\n log \"cloning ${label} pinned to ref ${ref} (--branch)\"\n run git clone --depth 1 --branch \"$ref\" \"$repo\" \"$dir\" || return 1\n fi\n return 0\n}\n\n# Serialize concurrent installs that share one open-source checkout root\n# (Magpie / InferenceX, plus GEAK / TraceLens via the chained\n# kernel-agent installer). With no lock, two installs race and corrupt each\n# other's half-cloned checkouts (observed: GEAK src/minisweagent/... missing,\n# repeated install failures). The lock lives in $_open_source_root (pod-local)\n# so it tracks exactly what it guards; the chained kernel-agent installer uses\n# the same $_open_source_root default, keeping parent/child on one lock path.\n# We hold an flock on $_open_source_root/.install.lock via fd 9 from the first\n# mirror-mutating step until this process exits (fd closes on exit), so it\n# guards every clone/build below and releases automatically at the end.\n# Skipped under --check-only / --dry-run (introspection only, no mutation).\n# When we chain to kernel-agent's installer we export\n# HYPERLOOM_INSTALL_LOCK_HELD=1 so that child does not deadlock re-acquiring\n# the same lock on a second open file description.\nacquire_install_lock() {\n if [ \"$CHECK_ONLY\" -eq 1 ] || [ \"$DRY_RUN\" -eq 1 ]; then\n return 0\n fi\n if [ \"${HYPERLOOM_INSTALL_LOCK_HELD:-0}\" = \"1\" ]; then\n log \"install lock already held by parent installer; not re-locking\"\n return 0\n fi\n mkdir -p \"${_open_source_root}\"\n exec 9>\"${_open_source_root}/.install.lock\"\n if command -v flock >/dev/null 2>&1; then\n log \"waiting for install lock: ${_open_source_root}/.install.lock\"\n flock 9\n log \"acquired install lock\"\n export HYPERLOOM_INSTALL_LOCK_HELD=1\n else\n warn \"flock not available; concurrent installs may race on dependency checkouts\"\n fi\n}\n\n# Preflight credential validation. Mirrors src/hyperloom/agents/kernel/scripts/install.sh:\n# a usable setup needs Anthropic or DeepSeek credentials. The installer gate\n# intentionally does not default or require OpenAI.\n#\n# Loader (env wins; never overwrites a key that is already set):\n# env > $REPO_ROOT/.env\n#\n# Strict mode by design: --check-only / --dry-run is the only path that\n# downgrades the die to a warn (introspection mode, no install runs).\npreflight_load_dotenv() {\n load_dotenv_no_clobber\n if [ \"${DOTENV_LOADED_COUNT:-0}\" -gt 0 ]; then\n log \"loaded ${DOTENV_LOADED_COUNT} missing var(s) from $REPO_ROOT/.env (env wins)\"\n fi\n}\n\n# Reject one provider's base URL paired with only the other provider's key.\n# DeepSeek serves its own Anthropic-compatible endpoint, so its key counts as one.\npreflight_reject_cross_provider() {\n local a_key a_endpoint conflict=\"\"\n a_key=\"${ANTHROPIC_API_KEY:-${ANTHROPIC_AUTH_TOKEN:-${DEEPSEEK_API_KEY:-}}}\"\n a_endpoint=\"${ANTHROPIC_BASE_URL:-}\"\n if [ -z \"$a_endpoint\" ] && [ -n \"${DEEPSEEK_API_KEY:-}\" ]; then\n a_endpoint=\"${DEEPSEEK_BASE_URL:-https://api.deepseek.com/anthropic}\"\n fi\n if [ -n \"${OPENAI_BASE_URL:-}\" ] && [ -z \"${OPENAI_API_KEY:-}\" ] && [ -n \"$a_key\" ]; then\n conflict=\"OPENAI_BASE_URL is set without an OPENAI_API_KEY, while an Anthropic-side key is configured\"\n elif [ -n \"${ANTHROPIC_BASE_URL:-}\" ] && [ -z \"$a_key\" ] && [ -n \"${OPENAI_API_KEY:-}\" ]; then\n conflict=\"ANTHROPIC_BASE_URL is set without an Anthropic-side key, while an OPENAI_API_KEY is configured\"\n elif [ -n \"${OPENAI_BASE_URL:-}\" ] && [ -n \"$a_key\" ] && [ -z \"$a_endpoint\" ]; then\n conflict=\"an Anthropic-side key is configured without ANTHROPIC_BASE_URL, while the OpenAI side points at OPENAI_BASE_URL\"\n elif [ -n \"$a_endpoint\" ] && [ -n \"${OPENAI_API_KEY:-}\" ] && [ -z \"${OPENAI_BASE_URL:-}\" ]; then\n conflict=\"OPENAI_API_KEY is configured without OPENAI_BASE_URL, while the Anthropic side points at ANTHROPIC_BASE_URL\"\n fi\n [ -z \"$conflict\" ] && return 0\n if [ \"$CHECK_ONLY\" -eq 1 ] || [ \"$DRY_RUN\" -eq 1 ]; then\n warn \"conflicting LLM credentials: ${conflict}; continuing because --check-only / --dry-run is active.\"\n return 0\n fi\n cat >&2 <&2 </dev/null 2>&1; then\n PYTHON=\"$(command -v python3)\"\n return 0\n fi\n\n # Bare-image bootstrap (Debian/Ubuntu only). Skipped silently when\n # apt-get is missing (RHEL/Alpine/etc.) or the operator opted out.\n if command -v apt-get >/dev/null 2>&1 \\\n && [ \"$DRY_RUN\" -eq 0 ] && [ \"$CHECK_ONLY\" -eq 0 ] \\\n && [ -z \"${INFERENCE_OPTIMIZER_SKIP_APT_BOOTSTRAP:-}\" ]; then\n log \"no python3 found; attempting bare-image apt bootstrap \" \\\n \"(set INFERENCE_OPTIMIZER_SKIP_APT_BOOTSTRAP=1 to disable)\"\n export DEBIAN_FRONTEND=noninteractive\n if apt-get update -qq >/dev/null 2>&1 \\\n && apt-get install -y --no-install-recommends \\\n python3 python3-venv python3-pip >/dev/null 2>&1; then\n if command -v python3 >/dev/null 2>&1; then\n PYTHON=\"$(command -v python3)\"\n log \"apt bootstrap succeeded: PYTHON=$PYTHON\"\n return 0\n fi\n fi\n warn \"apt bootstrap failed; falling through to die()\"\n fi\n\n die \"no usable python found (set PYTHON, install python3, mount /opt/venv, \" \\\n \"or run on an apt-based image so install.sh can bootstrap python3 itself)\"\n}\n\nresolve_python\nlog \"PYTHON=${PYTHON}\"\n# Export PYTHON + prepend its bin dir so the chained kernel-agent installer's\n# bare `python3 -m pip ...` calls (src/hyperloom/agents/kernel/scripts/install.sh) land in\n# the same interpreter. Otherwise PATH-only resolution can split the\n# installation across two different pythons.\nexport PYTHON\nPATH=\"$(dirname \"$PYTHON\"):${PATH:-/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}\"\nexport PATH\n\n# --- 0a. Torch compatibility gate (ROCm-aware) ---\n# If rocm-smi reports devices, the resolved PYTHON must already have a\n# ROCm-built torch importable. Two failure modes we explicitly catch:\n# 1. torch missing entirely on a ROCm pod -- letting pip install proceed\n# will pull the NVIDIA CUDA wheel from PyPI (default `torch`).\n# 2. torch present but built against CUDA (torch.version.hip is None)\n# -- the chained RAG-index step auto-detects device=cuda and crashes\n# at torch._C._cuda_init() with \"Found no NVIDIA driver\".\nensure_torch_compatible_with_gpu() {\n if ! command -v rocm-smi >/dev/null 2>&1; then\n return 0\n fi\n if ! rocm-smi --showid >/dev/null 2>&1; then\n return 0\n fi\n local probe\n probe=\"$(\"$PYTHON\" - <<'PY' 2>/dev/null || true\nimport json, sys\nout = {\"rc\": 0}\ntry:\n import torch\n out[\"torch_version\"] = torch.__version__\n out[\"hip\"] = getattr(torch.version, \"hip\", None)\n out[\"cuda_str\"] = getattr(torch.version, \"cuda\", None)\nexcept Exception as exc:\n out[\"rc\"] = 2\n out[\"error\"] = type(exc).__name__ + \": \" + str(exc)[:200]\nprint(json.dumps(out))\nPY\n)\"\n if [ -z \"$probe\" ]; then\n warn \"torch probe produced no output (PYTHON=${PYTHON})\"\n return 0\n fi\n local rc; rc=\"$(\"$PYTHON\" -c \"import json,sys; d=json.loads(sys.argv[1]); print(d.get('rc',0))\" \"$probe\" 2>/dev/null || echo 0)\"\n if [ \"$rc\" = \"2\" ]; then\n warn \"torch is NOT importable from PYTHON=${PYTHON}\"\n warn \"this pod has ROCm GPUs (rocm-smi works) -- letting pip install proceed\"\n warn \"would pull plain 'torch' from PyPI (= NVIDIA CUDA wheel) and break\"\n warn \"downstream RAG / baseline / kernel steps with 'Found no NVIDIA driver'.\"\n warn \"Fixes (pick one):\"\n warn \" * use the canonical ROCm stack: unset PYTHON; install.sh will pick /opt/venv\"\n warn \" * install the ROCm torch wheel: \\\"\\$PYTHON\\\" -m pip install --pre torch --index-url https://download.pytorch.org/whl/rocm6.x\"\n warn \" * opt out of this gate: INFERENCE_OPTIMIZER_FORCE_PYTHON=1 INFERENCE_OPTIMIZER_SKIP_TORCH_GATE=1 install.sh\"\n if [ \"${INFERENCE_OPTIMIZER_SKIP_TORCH_GATE:-0}\" != \"1\" ]; then\n die \"refusing to install on ROCm pod with no torch in PYTHON=${PYTHON}\"\n fi\n warn \"INFERENCE_OPTIMIZER_SKIP_TORCH_GATE=1 set; continuing despite missing torch\"\n return 0\n fi\n local hip; hip=\"$(\"$PYTHON\" -c \"import json,sys; d=json.loads(sys.argv[1]); print(d.get('hip') or '')\" \"$probe\" 2>/dev/null || echo \"\")\"\n local tv; tv=\"$(\"$PYTHON\" -c \"import json,sys; d=json.loads(sys.argv[1]); print(d.get('torch_version') or '')\" \"$probe\" 2>/dev/null || echo \"\")\"\n if [ -z \"$hip\" ]; then\n warn \"torch=${tv} in PYTHON=${PYTHON} is NOT a ROCm build (torch.version.hip is None)\"\n warn \"but this pod reports ROCm GPUs via rocm-smi. RAG-index / baseline / kernel\"\n warn \"steps will crash at torch._C._cuda_init() with 'Found no NVIDIA driver'.\"\n warn \"Fixes (pick one):\"\n warn \" * use the canonical ROCm stack: unset PYTHON; install.sh will pick /opt/venv\"\n warn \" * install the ROCm torch wheel: \\\"\\$PYTHON\\\" -m pip install --force-reinstall --pre torch --index-url https://download.pytorch.org/whl/rocm6.x\"\n warn \" * opt out of this gate: INFERENCE_OPTIMIZER_SKIP_TORCH_GATE=1 install.sh\"\n if [ \"${INFERENCE_OPTIMIZER_SKIP_TORCH_GATE:-0}\" != \"1\" ]; then\n die \"refusing to install: torch=${tv} is CUDA-built on a ROCm pod\"\n fi\n warn \"INFERENCE_OPTIMIZER_SKIP_TORCH_GATE=1 set; continuing despite torch/GPU mismatch\"\n return 0\n fi\n log \"torch=${tv} (hip=${hip}) -- ROCm-compatible OK\"\n}\n\nensure_torch_compatible_with_gpu\nlog \"REPO_ROOT=${REPO_ROOT}\"\nlog \"USER_DATA_PATH=${USER_DATA_PATH}\"\nlog \"HYPERLOOM_RUNTIME_DIR=${HYPERLOOM_RUNTIME_DIR}\"\nlog \"HYPERLOOM_ROOT=${HYPERLOOM_ROOT}\"\nlog \"open_source_root=${_open_source_root}\"\nlog \"KERNEL_AGENT_ROOT=${KERNEL_AGENT_ROOT}\"\nlog \"KERNEL_AGENT_ENV=${KERNEL_AGENT_ENV}\"\nlog \"MAGPIE_PATH=${MAGPIE_PATH}\"\nlog \"INFERENCEX_REPO=${INFERENCEX_REPO}\"\nlog \"INFERENCEX_DEFAULT_DIR=${INFERENCEX_DEFAULT_DIR}\"\nexport USER_DATA_PATH HYPERLOOM_RUNTIME_DIR KERNEL_AGENT_ENV\nexport HYPERLOOM_KERNEL_AGENT_ROOT=\"${HYPERLOOM_KERNEL_AGENT_ROOT:-${KERNEL_AGENT_ROOT}}\"\n# Pre-create the writable runtime root so ensure_magpie / chain_kernel_agent\n# never race on missing parents (Magpie's pip install -e writes egg-info\n# under MAGPIE_PATH; kernel-agent install.sh writes kernel-agent.env.sh into\n# HYPERLOOM_RUNTIME_DIR).\nif [ \"$DRY_RUN\" -eq 0 ] && [ \"$CHECK_ONLY\" -eq 0 ]; then\n mkdir -p \"${HYPERLOOM_RUNTIME_DIR}\" \"${_open_source_root}\"\nfi\n\n# pip --break-system-packages when PYTHON is the system interpreter\n# (e.g. bare ubuntu/debian image without a venv). Detect by comparing\n# sys.prefix vs sys.base_prefix; equal == not in venv. The flag was added\n# in pip 23.0.1; older pips reject it as an unknown option, so we probe\n# `pip install --break-system-packages --help` before adopting it.\nPIP_EXTRA=()\nif \"$PYTHON\" - <<'PY' 2>/dev/null\nimport sys\nraise SystemExit(0 if sys.prefix == sys.base_prefix else 1)\nPY\nthen\n if \"$PYTHON\" -m pip install --break-system-packages --help >/dev/null 2>&1; then\n PIP_EXTRA=(--break-system-packages)\n log \"non-venv PYTHON; pip will use --break-system-packages\"\n else\n pip_ver=\"$(\"$PYTHON\" -m pip --version 2>&1 | awk '{print $2}')\"\n warn \"non-venv PYTHON detected (PYTHON=${PYTHON}) but pip ${pip_ver}\"\n warn \"is too old for --break-system-packages (requires >= 23.0.1).\"\n warn \"Fixes (pick one):\"\n warn \" * use the canonical ROCm stack: unset PYTHON; install.sh will pick /opt/venv\"\n warn \" * create a venv: python3 -m venv \\\"\\$USER_DATA_PATH/venv\\\" \\\\\"\n warn \" && \\\"\\$USER_DATA_PATH/venv/bin/python\\\" -m pip install -U pip wheel \\\\\"\n warn \" && export PYTHON=\\\"\\$USER_DATA_PATH/venv/bin/python\\\"\"\n warn \" * upgrade system pip: \\\"\\$PYTHON\\\" -m pip install --user -U 'pip>=23.0.1'\"\n die \"refusing to run pip without a working --break-system-packages on a non-venv interpreter\"\n fi\nfi\n\n# --- 1. inference_optimizer + claude_agent_sdk via [test] ---\nensure_inference_optimizer() {\n if [ \"$HYPERLOOM_PACKAGED_INSTALL\" -eq 1 ]; then\n log \"ensuring inference_optimizer runtime deps (packaged install)\"\n # The bare wheel ships with empty base deps (pip --target stays clean), so\n # the runtime deps are installed here. The parent package imports with no\n # third-party dep, so this import check runs before the pip install below.\n \"$PYTHON\" - <<'PY' || die \"hyperloom.inference_optimizer not importable from installed wheel\"\nimport hyperloom.inference_optimizer # noqa: F401\nPY\n if [ \"$CHECK_ONLY\" -eq 0 ] && [ \"$DRY_RUN\" -eq 0 ]; then\n # PyYAML: hard import-time dep of the CLI startup path. llm extra\n # (claude-agent-sdk/openai/httpx): Coordinator backends.\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" \\\n \"PyYAML>=6.0\" \"claude-agent-sdk>=0.2.110\" \"openai>=1.50\" \"httpx>=0.27\"\n # web extra only when critic web tools are enabled (off by default).\n if [ \"${CRITIC_WEB_TOOLS_ENABLED:-}\" = \"true\" ] || [ \"${CRITIC_WEB_TOOLS_ENABLED:-}\" = \"1\" ]; then\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" \"markdownify>=0.11\" \"cachetools>=5.3\"\n fi\n fi\n if \"$PYTHON\" -c \"import claude_agent_sdk\" >/dev/null 2>&1; then\n log \"claude_agent_sdk OK\"\n else\n warn \"claude_agent_sdk not importable after runtime dep install (Coordinator will fail)\"\n [ \"$CHECK_ONLY\" -eq 1 ] || die \"claude_agent_sdk missing\"\n fi\n return 0\n fi\n log \"ensuring inference_optimizer package + claude_agent_sdk extras\"\n if [ \"$CHECK_ONLY\" -eq 0 ] && [ \"$DRY_RUN\" -eq 0 ]; then\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" -e \"${REPO_ROOT}[test]\"\n fi\n \"$PYTHON\" - <<'PY' || die \"hyperloom.inference_optimizer not importable after install\"\nimport hyperloom.inference_optimizer # noqa: F401\nPY\n if \"$PYTHON\" -c \"import claude_agent_sdk\" >/dev/null 2>&1; then\n log \"claude_agent_sdk OK\"\n else\n warn \"claude_agent_sdk not importable after install (Coordinator will fail)\"\n [ \"$CHECK_ONLY\" -eq 1 ] || die \"claude_agent_sdk missing\"\n fi\n}\n\n# --- 1b. forge-gemm-tune (KernelForge deterministic GEMM tuning CLI) ---\n_forge_gemm_tune_candidates() {\n # Explicit gemm-tune override first.\n [ -n \"${FORGE_GEMM_TUNE_ROOT:-}\" ] && printf '%s\\n' \"$FORGE_GEMM_TUNE_ROOT\"\n # KernelForge root (single canonical var: FORGE_PATH).\n [ -n \"${FORGE_PATH:-}\" ] && printf '%s\\n' \"${FORGE_PATH%/}/src/forge_gemm_tune\" \"${FORGE_PATH%/}/forge_gemm_tune\"\n}\n\n_resolve_forge_gemm_tune_root() {\n local cand\n while IFS= read -r cand; do\n [ -n \"$cand\" ] || continue\n if [ -f \"${cand%/}/pyproject.toml\" ] && { [ -f \"${cand%/}/forge_gemm_tune/cli.py\" ] || [ -f \"${cand%/}/cli.py\" ]; }; then\n realpath \"$cand\" 2>/dev/null || printf '%s\\n' \"$cand\"\n return 0\n fi\n done < <(_forge_gemm_tune_candidates)\n return 1\n}\n\nensure_forge_gemm_tune() {\n local root resolved\n if root=\"$(_resolve_forge_gemm_tune_root)\"; then\n log \"ensuring forge-gemm-tune from ${root}\"\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n \"$PYTHON\" -c \"import forge_gemm_tune\" >/dev/null 2>&1 \\\n && log \"forge-gemm-tune import OK\" \\\n || warn \"forge-gemm-tune not importable (check-only; would install from ${root})\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would run: ${PYTHON} -m pip install -e ${root}\"\n return 0\n fi\n resolved=\"$(\"$PYTHON\" -c 'import forge_gemm_tune, os; print(os.path.realpath(os.path.dirname(forge_gemm_tune.__file__)))' 2>/dev/null || true)\"\n case \"$resolved\" in\n \"$root\" | \"$root\"/*)\n log \"forge-gemm-tune already installed from ${root}; skipping editable reinstall\"\n ;;\n *)\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" -e \"$root\"\n \"$PYTHON\" -c \"import forge_gemm_tune; import forge_gemm_tune.cli\" >/dev/null\n log \"forge-gemm-tune installed OK from ${root}\"\n ;;\n esac\n else\n if \"$PYTHON\" -c \"import forge_gemm_tune\" >/dev/null 2>&1; then\n log \"forge-gemm-tune import OK\"\n else\n log \"forge-gemm-tune source not configured; skipping optional forge GEMM tuning install\"\n fi\n fi\n}\n\n# --- 1c. kernel_agents (KernelForge forge-loop CLI) ---\n# forge-loop shells out to `python -m kernel_agents.cli` (see forge_submit.py).\n# Unlike forge_gemm_tune / forge_fusion — which have standalone sub-pyprojects and\n# get pip-installed by the carrier from their sub-package dirs — `kernel_agents`\n# is only packaged by the KernelForge *root* pyproject and was never installed\n# here. So forge-loop relied entirely on $FORGE_PATH being present and prepended to\n# the child PYTHONPATH by _ensure_forge_on_path() at call time. When FORGE_PATH is\n# unset (as in the 2026-07-28 CI runs) `python -m kernel_agents.cli` dies with\n# `ModuleNotFoundError: No module named 'kernel_agents'` and every forge kernel\n# attempt REVERTs. Installing kernel_agents from the KernelForge root makes the\n# import succeed regardless of FORGE_PATH (root install also covers the two\n# sub-packages, so the carrier's later import checks short-circuit).\n_kernel_forge_root() {\n # KernelForge repo root that actually contains kernel_agents. Keyed on\n # FORGE_PATH only (CI guarantees it is exported; it is also the repo-canonical\n # var that forge_submit reads at runtime and local_setup.sh exports).\n local c=\"${FORGE_PATH:-}\"\n [ -n \"$c\" ] || return 1\n if [ -f \"${c%/}/pyproject.toml\" ] && [ -f \"${c%/}/src/kernel_agents/__init__.py\" ]; then\n printf '%s\\n' \"${c%/}\"\n return 0\n fi\n return 1\n}\n\nensure_kernel_agents() {\n # Gate on checkout availability, NOT on KERNEL_OPT_BACKEND_ORDER (mirrors\n # ensure_forge_gemm_tune). install.sh frequently runs at setup time under the\n # default geak backend, so a backend gate here would skip the install; a later\n # forge session whose child has no FORGE_PATH would then still hit\n # ModuleNotFoundError. Keying on the KernelForge checkout instead covers the\n # \"checkout present at install time, FORGE_PATH absent at runtime\" case.\n local root\n if ! root=\"$(_kernel_forge_root)\"; then\n log \"kernel_agents: FORGE_PATH not set / no KernelForge checkout there; skipping optional forge-loop install\"\n return 0\n fi\n if \"$PYTHON\" -c \"import kernel_agents.cli\" >/dev/null 2>&1; then\n log \"kernel_agents already importable; skipping install\"\n return 0\n fi\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"kernel_agents not importable (check-only; would install from ${root})\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would run: ${PYTHON} -m pip install ${root}\"\n return 0\n fi\n log \"ensuring kernel_agents from ${root} (forge-loop backend)\"\n # Deliberately NON-editable (no -e): ${root} is a shared, often read-only\n # KernelForge checkout used by concurrent sessions. A non-editable install\n # builds in a temp dir and never writes egg-info/build artifacts back into the\n # checkout, so parallel runs can't race on it — this mirrors the carrier's\n # own forge_fusion/forge_gemm_tune install (see _incontainer.sh: \"Non-editable\n # installs build in a temp dir and never write to the read-only shared\n # checkout\"). Installing the root also provides forge_gemm_tune + forge_fusion,\n # so the carrier's later `import forge_fusion` guard short-circuits (verified:\n # it logs \"forge kernel backend ready\" with no reinstall).\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" \"${root}\"\n \"$PYTHON\" -c \"import kernel_agents, kernel_agents.cli\" \\\n && log \"kernel_agents installed OK from ${root}\" \\\n || die \"kernel_agents import failed after install from ${root}\"\n}\n\n# --- 1d. rocprof-compute (rocprofiler-compute) for the forge profiling stage ---\n# forge-loop's profiling stage prefers rocprof-compute (roofline / speed-of-light)\n# and only falls back to the thin rocprofv3 \"PMC\" path when the tool is absent.\n# KernelForge's resolve_rocpc() looks for the tool at\n# `/libexec/rocprofiler-compute/rocprof_compute_base.py`; the stock\n# vllm/sglang ROCm serving images ship rocprofv3 but NOT rocprofiler-compute, so\n# every forge run silently degrades to PMC (no roofline -> optimization-potential\n# is always estimable=NO). The Python deps rocprof-compute needs are already\n# pulled in by the KernelForge root install (its base deps cover dash/kaleido/\n# matplotlib/plotille/tqdm); the only missing piece is the system tool itself,\n# which pip cannot provide — it comes from the ROCm apt package.\n#\n# This step is FAIL-SOFT by design: forge still works on the PMC path, so a\n# missing/failed rocprof-compute must NOT abort the install. Every branch logs\n# (with the concrete \"profiling will degrade to PMC\" consequence) so the\n# post-mortem observability question — \"why did this run profile on PMC?\" — is\n# answerable from the install log alone.\n# rocprof-compute's CSV converter (utils/utils.py, v3->v2) assumes pandas'\n# legacy 'object' string dtype. pandas>=3.0 defaults future.infer_string=True,\n# so the rocprofv3 counter CSV's Agent_Id (\"Agent 9\") is read as the new\n# StringDtype; the converter's `dtype == \"object\"` guard then skips its int\n# coercion and the subsequent Agent_Id<->Node_Id merge dies (\"merge on str and\n# int64\"). Every counter file is dropped -> rocprof-compute reports \"No\n# profiling data found\" -> forge silently degrades to the PMC path (no roofline;\n# optimization-potential estimable=NO). Nothing else in the stack needs\n# pandas>=3 (verified: no installed dist requires it), so <3 is conflict-free.\n#\n# rocprof-compute runs under the interpreter KernelForge's resolve_rocpc() picks:\n# it probes sys.executable, then /usr/bin/python3, then `python3` on PATH, and\n# uses the FIRST that can run `rocprof-compute --help`. We mirror that probe and\n# pin pandas in exactly THAT interpreter (not blindly $PYTHON), so the pin cannot\n# be a silent no-op and the log names the env that will actually run the tool.\n#\n# Two known, accepted deltas vs. resolve_rocpc() (neither is a correctness bug —\n# both fall back safely and only affect which interpreter gets pinned):\n# * First candidate: we probe $PYTHON where resolve_rocpc probes the RUNTIME\n# sys.executable. $PYTHON is install-time sys.executable and, in the shared\n# -venv carrier flow, is the SAME interpreter forge runs under, so they agree.\n# If a deployment splits install-time and runtime Python, the pin may land on\n# a non-preferred interpreter — the fallback + warn below make that visible.\n# * `--help` passing proves rocprof-compute's deps import, NOT that its CSV\n# conversion works on this pandas; the pandas<3 pin (below) is what closes\n# that gap. A deeper check (pandas major inside the probe) would belong in\n# KernelForge's resolve_rocpc(), not here.\n#\n# Fail-soft: a pin failure must NOT abort the install — forge still runs on PMC.\n\n# Echo the interpreter resolve_rocpc() will run rocprof-compute under: the first\n# of $PYTHON (install-time sys.executable), /usr/bin/python3, PATH python3 that\n# can run `/rocprof-compute --help`. Non-zero + no output if none do.\n_rocpc_effective_python() {\n local libexec=\"$1\" py seen=\" \"\n for py in \"$PYTHON\" /usr/bin/python3 \"$(command -v python3 2>/dev/null || true)\"; do\n [ -n \"$py\" ] || continue\n case \"$seen\" in *\" $py \"*) continue ;; esac\n seen=\"${seen}${py} \"\n if \"$py\" \"${libexec}/rocprof-compute\" --help >/dev/null 2>&1; then\n printf '%s\\n' \"$py\"\n return 0\n fi\n done\n return 1\n}\n\n# Print pandas version under $1 and exit: 0 => <3 (ok); 1 => >=3; 3 => absent.\n# Decided in Python (robust vs. bash numeric parsing under set -euo pipefail).\n_pandas_major_ge3() {\n \"$1\" - <<'PY'\nimport sys\ntry:\n import pandas\nexcept Exception:\n sys.exit(3)\nprint(pandas.__version__)\nsys.exit(1 if int(pandas.__version__.split(\".\")[0]) >= 3 else 0)\nPY\n}\n\n_ensure_pandas_lt3_for_rocpc() {\n local py=\"${1:-$PYTHON}\" ver rc why\n if ver=\"$(_pandas_major_ge3 \"$py\")\"; then rc=0; else rc=$?; fi\n\n if [ \"$rc\" -eq 0 ]; then\n log \"rocprof-compute: pandas ${ver} is <3 under ${py} (compatible with rocprof-compute's CSV converter); no pin needed\"\n return 0\n fi\n\n # rc==1 (pandas>=3) OR rc==3 (pandas absent): pin pandas<3 in the interpreter\n # that runs rocprof-compute. This runs LAST in install.sh (after\n # chain_kernel_agent — the final pip-installing step), so no later step can\n # re-pull pandas>=3, and the re-check below is the final, truthful state.\n if [ \"$rc\" -eq 3 ]; then\n why=\"pandas not yet installed\"\n else\n why=\"pandas ${ver} (>=3) breaks rocprof-compute's CSV converter (Agent_Id StringDtype)\"\n fi\n\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"rocprof-compute: ${why} (interpreter ${py}); check-only — would pin 'pandas>=2.2.3,<3'. Until fixed, forge profiling degrades to the PMC path.\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would run: ${py} -m pip install 'pandas>=2.2.3,<3' (${why})\"\n return 0\n fi\n\n log \"rocprof-compute: ${why}; installing 'pandas>=2.2.3,<3' into ${py}\"\n \"$py\" -m pip install --quiet \"${PIP_EXTRA[@]}\" 'pandas>=2.2.3,<3' \\\n || warn \"rocprof-compute: 'pip install pandas>=2.2.3,<3' failed under ${py}; forge profiling will stay on the PMC path. Check pip/network.\"\n\n # Re-check the SAME interpreter, at the END of install.sh, so the logged\n # outcome reflects what forge will actually import at runtime.\n if ver=\"$(_pandas_major_ge3 \"$py\")\"; then rc=0; else rc=$?; fi\n if [ \"$rc\" -eq 0 ]; then\n log \"rocprof-compute: pandas ${ver} in ${py}; forge profiling can use rocprof-compute (roofline)\"\n else\n warn \"rocprof-compute: pandas still incompatible in ${py} (version='${ver}', rc=${rc}); forge profiling will degrade to the PMC path.\"\n fi\n return 0\n}\n\nensure_rocprof_compute() {\n # Gate on the KernelForge checkout ONLY (via _kernel_forge_root, mirroring\n # ensure_kernel_agents), NOT on KERNEL_OPT_BACKEND_ORDER. install.sh runs at\n # setup time under the default geak backend — the carrier sets\n # KERNEL_OPT_BACKEND_ORDER=forge only later on the optimize command, AFTER\n # install.sh has finished (_incontainer.sh) — so a backend gate here would skip\n # the install and a later forge session would still profile on the PMC path.\n # rocprof-compute (~11 MB) + pandas<3 are only useful for forge but harmless\n # otherwise (pandas<3 is conflict-free), so keying on the checkout is the safe,\n # ordering-independent choice. The backend value is logged for context only.\n local root\n if ! root=\"$(_kernel_forge_root)\"; then\n log \"rocprof-compute: FORGE_PATH not set / no KernelForge checkout there; skipping optional roofline-profiling deps (forge, if enabled later, uses the PMC fallback)\"\n return 0\n fi\n log \"rocprof-compute: KernelForge checkout present at ${root} (KERNEL_OPT_BACKEND_ORDER='${KERNEL_OPT_BACKEND_ORDER:-}'); ensuring roofline profiling deps\"\n\n local rocm_root base\n rocm_root=\"${ROCM_PATH:-/opt/rocm}\"\n base=\"${rocm_root%/}/libexec/rocprofiler-compute/rocprof_compute_base.py\"\n\n # --- Step 1: ensure the rocprof-compute tool exists ---\n # It is a ROCm system package (pip cannot provide it). Idempotent: skip the apt\n # install when the file KernelForge's resolve_rocpc() checks is already present.\n if [ -f \"$base\" ]; then\n log \"rocprof-compute already present at ${base}\"\n elif [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"rocprof-compute not found at ${base} (check-only; would apt-get install rocprofiler-compute). Forge profiling would degrade to the PMC path.\"\n elif [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would run: apt-get install -y --no-install-recommends rocprofiler-compute\"\n elif ! command -v apt-get >/dev/null 2>&1; then\n # No apt (RHEL/Alpine/etc.): cannot install the system package here.\n warn \"rocprof-compute: apt-get unavailable; cannot install rocprofiler-compute. Forge profiling will degrade to the PMC path (no roofline; optimization-potential estimable=NO). Bake rocprofiler-compute into the image to enable roofline profiling.\"\n else\n log \"installing rocprofiler-compute (forge profiling backend) via apt into ${rocm_root}\"\n # Fail-soft throughout: never let apt failures (locked dpkg, offline mirror,\n # missing package) abort the install. Capture output to a log so a failure is\n # diagnosable (do not swallow apt errors). Try once, refresh index, retry.\n local apt_log=\"${TMPDIR:-/tmp}/rocpc_apt_$$.log\"\n export DEBIAN_FRONTEND=noninteractive\n if ! apt-get install -y --no-install-recommends rocprofiler-compute >\"$apt_log\" 2>&1; then\n apt-get update -qq >>\"$apt_log\" 2>&1 || true\n apt-get install -y --no-install-recommends rocprofiler-compute >>\"$apt_log\" 2>&1 || true\n fi\n # Verify against the SAME path KernelForge's resolve_rocpc() checks.\n if [ -f \"$base\" ]; then\n log \"rocprof-compute installed OK: ${base} present\"\n else\n warn \"rocprof-compute install did not produce ${base}; forge profiling will degrade to the PMC path (no roofline; optimization-potential estimable=NO). apt output tail (check ROCm repo access / package name for this ROCm version):\"\n # Guard BOTH the missing-file case and pipefail: if the redirect above never\n # created $apt_log (e.g. an unwritable TMPDIR), a bare `tail | while` exits\n # non-zero and set -euo pipefail would abort install.sh — the very\n # fail-soft invariant this diagnostic exists to serve. Only tail when the\n # file exists, and swallow any residual pipe failure.\n if [ -f \"$apt_log\" ]; then\n tail -n 6 \"$apt_log\" 2>/dev/null | while IFS= read -r _ln; do warn \" apt| ${_ln}\"; done || true\n fi\n fi\n rm -f \"$apt_log\" 2>/dev/null || true\n fi\n\n # --- Step 2: pin pandas<3 for rocprof-compute's CSV converter ---\n # Pin in the interpreter resolve_rocpc() will actually run the tool under (probe\n # mirrors KernelForge). Runs when the tool is present; in check/dry-run we\n # surface the plan against $PYTHON even before the tool exists.\n if [ -f \"$base\" ]; then\n local rocpc_py\n if rocpc_py=\"$(_rocpc_effective_python \"$(dirname \"$base\")\")\"; then\n [ \"$rocpc_py\" = \"$PYTHON\" ] \\\n || log \"rocprof-compute: resolve_rocpc will run under ${rocpc_py} (not \\$PYTHON=${PYTHON}); pinning pandas there\"\n else\n rocpc_py=\"$PYTHON\"\n warn \"rocprof-compute: could not confirm which interpreter runs 'rocprof-compute --help'; pinning pandas in \\$PYTHON=${PYTHON} (best effort — verify forge's runtime interpreter has pandas<3)\"\n fi\n _ensure_pandas_lt3_for_rocpc \"$rocpc_py\"\n elif [ \"$CHECK_ONLY\" -eq 1 ] || [ \"$DRY_RUN\" -eq 1 ]; then\n _ensure_pandas_lt3_for_rocpc \"$PYTHON\"\n fi\n return 0\n}\n\n# --- 2. Magpie ---\n# The install state is the pip-installed package specified by\n# $MAGPIE_PACKAGE_SPEC. $MAGPIE_PATH remains exported for runtime code that\n# needs to inspect Magpie's package files (patcher / manifest / InferenceX\n# discovery); when not explicitly set, it resolves to the installed package\n# root after import.\nensure_magpie() {\n log \"ensuring Magpie package ${MAGPIE_PACKAGE_SPEC}\"\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n if \"$PYTHON\" -c \"import Magpie\" >/dev/null 2>&1; then\n log \"Magpie importable\"\n else\n warn \"Magpie not importable (check-only mode, skipping pip install)\"\n fi\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would pip install Magpie package: ${MAGPIE_PACKAGE_SPEC}\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 0 ]; then\n if \"$PYTHON\" -c \"import Magpie\" >/dev/null 2>&1; then\n log \"Magpie already importable; skipping pip install\"\n else\n \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" \"$MAGPIE_PACKAGE_SPEC\"\n \"$PYTHON\" -c \"import Magpie\" >/dev/null\n log \"Magpie installed OK from ${MAGPIE_PACKAGE_SPEC}\"\n fi\n local installed_root\n installed_root=\"$(\"$PYTHON\" - <<'PY'\nfrom pathlib import Path\nimport Magpie\nprint(Path(Magpie.__file__).resolve().parent.parent)\nPY\n)\"\n if [ \"$MAGPIE_PATH_EXPLICIT\" -eq 0 ]; then\n MAGPIE_PATH=\"$installed_root\"\n export MAGPIE_PATH\n log \"MAGPIE_PATH resolved from installed package: ${MAGPIE_PATH}\"\n else\n log \"MAGPIE_PATH override preserved: ${MAGPIE_PATH}\"\n fi\n fi\n}\n\n# --- 2a. aiperf (AgentX benchmark client) — fail-soft, AgentX-only ---\n# Installs the pinned aiperf for HYPERLOOM_AGENTX; only reached when the caller\n# opts in (see the INSTALL_AIPERF / HYPERLOOM_AGENTX gate at the call site). A\n# failure here is NON-fatal: it only warns and leaves aiperf absent, so the\n# default synthetic path is never blocked by an AgentX-only dependency. Skipped\n# when the operator points AIPERF_BIN at their own build.\nensure_aiperf() {\n if [ -n \"${AIPERF_BIN:-}\" ]; then\n log \"AIPERF_BIN set (${AIPERF_BIN}); skipping aiperf install\"\n return 0\n fi\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n if command -v aiperf >/dev/null 2>&1; then log \"aiperf on PATH\"; else warn \"aiperf not found (check-only)\"; fi\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would pip install aiperf (AgentX): ${AIPERF_PACKAGE_SPEC}\"\n return 0\n fi\n if command -v aiperf >/dev/null 2>&1; then\n log \"aiperf already on PATH; skipping install\"\n return 0\n fi\n log \"installing aiperf (AgentX): ${AIPERF_PACKAGE_SPEC}\"\n if \"$PYTHON\" -m pip install --quiet \"${PIP_EXTRA[@]}\" \"$AIPERF_PACKAGE_SPEC\"; then\n log \"aiperf installed OK\"\n else\n warn \"aiperf install failed (${AIPERF_PACKAGE_SPEC}); AgentX mode (HYPERLOOM_AGENTX) stays unavailable until aiperf is installed or AIPERF_BIN is set. Default synthetic path is unaffected.\"\n fi\n}\n\n# --- 2b. Atomic-write patch for Magpie._prepare_benchmark_scripts ---\n# The Hyperloom #C1 script-tearing race (vllm_mi300x.sh / sglang_mi300x.sh\n# sourced by a leaked bash while a new Magpie subprocess is mid-`shutil.copy2` →\n# `syntax error near unexpected token 'fi'`). Magpie is invoked as a\n# subprocess, so monkey-patching from the Coordinator process does not\n# reach it; we patch the cloned source in place at install time. The\n# patcher itself is idempotent + flock-serialised + atomic-rename\n# (see `_magpie_patcher.py`), so re-runs are O(1) no-ops.\n#\n# Fail-soft (was fail-loud): a `False` return means the legacy\n# `shutil.copy2` block was not found. With MAGPIE_REF now pinned to an\n# upstream commit that already copies scripts atomically\n# (`_copy_benchmark_script_atomic`), that is the EXPECTED no-op state —\n# the #C1 race is already mitigated upstream, so we `warn` and continue\n# instead of aborting every install. (A sibling branch makes the patcher\n# itself upstream-aware; this warn is the defense-in-depth complement.) If\n# you re-pin MAGPIE_REF to a pre-refactor commit and the patch still cannot\n# apply, the script-tearing race is genuinely unpatched — review the\n# warning. Override the gate via PATCH_MAGPIE=0 to skip the step entirely.\nensure_magpie_atomic_scripts_patch() {\n if is_falsy \"${PATCH_MAGPIE:-1}\"; then\n log \"PATCH_MAGPIE is falsy — skipping Magpie atomic-write patch (caller asserts upstream already fixed)\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would apply Hyperloom #C1 atomic-write patch to ${MAGPIE_PATH}/Magpie/modes/benchmark/benchmarker.py\"\n return 0\n fi\n log \"applying Hyperloom #C1 atomic-write patch to Magpie._prepare_benchmark_scripts\"\n # Exit-code contract (read below): 0 ok · 2 remote-trust drift only ·\n # 4 GENUINE atomic failure (race unmitigated) · 1 benign atomic no-op.\n # INFERENCEX_PATH is passed explicitly: the patcher also has to scrub the\n # InferenceX ``benchmarks/`` copies Magpie executes and teach\n # ``benchmark_lib.sh::run_lm_eval`` to tolerate the flag. This step therefore\n # MUST run after ensure_inferencex has exported INFERENCEX_PATH — see the\n # call ordering at the bottom of this script.\n if MAGPIE_PATH=\"$MAGPIE_PATH\" INFERENCEX_PATH=\"${INFERENCEX_PATH:-}\" \"$PYTHON\" - <<'PY'\nimport os, sys\nfrom hyperloom.orchestrator.actions.executors._magpie_patcher import (\n magpie_scripts_patch_status,\n)\nstatus = magpie_scripts_patch_status(\n os.environ[\"MAGPIE_PATH\"],\n os.environ.get(\"INFERENCEX_PATH\") or None,\n)\nprint(f\"_magpie_patcher: atomic_reason={status.atomic_reason} \"\n f\"atomic_ok={status.atomic_ok} remote_trust_ok={status.remote_trust_ok} \"\n f\"eval_flag_ok={status.eval_flag_ok}\",\n file=sys.stderr)\nif status.ok:\n sys.exit(0)\n# A GENUINE atomic failure (unrecognized shape / I/O error) means the\n# script-tearing race is actually unmitigated — distinct exit so a strict\n# install can fail-loud instead of swallowing it as an expected no-op.\nif status.atomic_genuine_failure:\n sys.exit(4)\nif not status.atomic_ok:\n sys.exit(1)\nif not status.remote_trust_ok:\n sys.exit(2)\n# eval_flag_ok is False ONLY when a live `run_eval --concurrent-requests`\n# survives in a caller script AND InferenceX's run_lm_eval would reject it\n# (a defence-in-depth patch that merely could not be applied, with no live\n# flag, is NOT counted as a failure -- install-time now matches the run-time\n# ensure_eval_concurrency_compat judgement). This is the genuinely fatal case:\n# every RUN_EVAL=true baseline aborts on 'Unknown parameter'. Distinct exit so\n# install can name the failure mode.\nif not status.eval_flag_ok:\n sys.exit(5)\n# Defensive catch-all: a not-ok status with none of the bits above set should\n# never happen, but exit non-zero so we never fall through to exit 0.\nsys.exit(3)\nPY\n then\n log \"Magpie #C1 patch OK\"\n else\n rc=$?\n if [ \"$rc\" -eq 4 ]; then\n # GENUINE failure: the legacy block is gone AND upstream is not atomic\n # (or a read/write error). The Hyperloom #C1 script-tearing race is NOT\n # mitigated — `profile`/`baseline` can hit `syntax error near unexpected\n # token 'fi'`. Strict mode (default) aborts; a falsy MAGPIE_PATCH_STRICT\n # (0/false/no/off) keeps the legacy fail-soft behaviour and only warns.\n if is_falsy \"${MAGPIE_PATCH_STRICT:-1}\"; then\n warn \"Magpie atomic-write patch GENUINELY failed (race unmitigated); MAGPIE_PATCH_STRICT=${MAGPIE_PATCH_STRICT:-} (falsy), continuing anyway — review _magpie_patcher.py.\"\n else\n die \"Magpie atomic-write patch GENUINELY failed: neither the legacy shutil.copy2 block nor an upstream atomic copy was found in benchmarker.py. The Hyperloom #C1 script-tearing race is unmitigated. Re-pin MAGPIE_REF to a supported commit, review _magpie_patcher.py, or set MAGPIE_PATCH_STRICT=0 to downgrade to a warning (or PATCH_MAGPIE=0 to skip entirely).\"\n fi\n elif [ \"$rc\" -eq 2 ]; then\n warn \"Magpie SGLang remote trust patch did not apply. If MAGPIE_TRUST_REMOTE_CODE=1 is required for custom-code models (for example Kimi/Qwen tokenizer paths), remote benchmark clients may still fail to pass trust; review _magpie_patcher.py or set PATCH_MAGPIE=0 only if this is intentional.\"\n elif [ \"$rc\" -eq 5 ]; then\n # Fail-loud by default: a surviving --concurrent-requests aborts EVERY\n # RUN_EVAL=true baseline in InferenceX's run_lm_eval arg parser, no\n # results*.json is written, and the baseline accuracy gate then stops the\n # whole run with `baseline_accuracy_failed`. There is no salvage: the\n # executor deliberately does NOT fall back to RUN_EVAL=false for a genuine\n # baseline (a throughput-only baseline cannot satisfy the accuracy gate).\n # Set MAGPIE_EVAL_FLAG_STRICT=0 only when accuracy eval is genuinely\n # not required for this deployment.\n if is_falsy \"${MAGPIE_EVAL_FLAG_STRICT:-1}\"; then\n warn \"Magpie redundant --concurrent-requests eval flag could not be stripped from a generic benchmark script (unrecognised run_eval line); MAGPIE_EVAL_FLAG_STRICT=${MAGPIE_EVAL_FLAG_STRICT:-} (falsy), continuing anyway — RUN_EVAL=true baselines will abort on InferenceX's 'Unknown parameter: --concurrent-requests'.\"\n else\n die \"Magpie redundant --concurrent-requests eval flag could not be stripped from a generic benchmark script (unrecognised run_eval line), and InferenceX's run_lm_eval could not be taught to tolerate it. Every RUN_EVAL=true baseline will abort with 'Unknown parameter: --concurrent-requests' and the run will stop with baseline_accuracy_failed. Concurrency must flow via EVAL_CONCURRENT_REQUESTS (fallback CONC), not the flag — fix the script's run_eval line or review _magpie_patcher.py. Set MAGPIE_EVAL_FLAG_STRICT=0 to downgrade to a warning if accuracy eval is not required.\"\n fi\n else\n # Benign no-op (rc=1): MAGPIE_PATH unset / benchmarker.py missing. With\n # MAGPIE_REF pinned to an upstream-atomic commit the patcher reports\n # ``upstream_atomic`` (exit 0) instead, so this branch is just the\n # missing-tree case — warn and continue. PATCH_MAGPIE=0 skips the step.\n warn \"Magpie atomic-write patch skipped (no benchmarker.py under MAGPIE_PATH). Fine for tests/dry-runs; otherwise check MAGPIE_PATH or set PATCH_MAGPIE=0.\"\n fi\n fi\n}\n\n# --- 3. InferenceX checkout: fresh clone from upstream ---\n#\n# Previously this function scanned a list of shared-filesystem candidates\n# (`/shared/hyperloom/InferenceX`, `/shared/fully-local/.../InferenceX`,\n# etc.) and pointed every install at whichever it found first. That\n# multi-install / shared-checkout layout is the upstream source of the\n# concurrent-write races behind the Hyperloom #C1 script-tearing race —\n# every fresh Magpie subprocess `shutil.copy2`'d its scripts on top of\n# the same shared files, while bash interpreters from neighbouring\n# installs were `source`-ing them. Cloning a per-install copy here\n# eliminates the cross-install fan-in (Magpie's in-place atomic-write patch then\n# closes the intra-install race window — both fixes are needed; this\n# one alone is not sufficient).\n#\n# Policy:\n# * INFERENCEX_PATH set and exists -> preserve verbatim. This is the\n# dev / CI override (caller is explicitly opting out of fresh\n# clones, e.g. iterating on a local edit).\n# * Otherwise -> fetch INFERENCEX_REF from INFERENCEX_REPO into\n# INFERENCEX_DEFAULT_DIR via the shared git_fetch_pinned() dance\n# (SHA-aware shallow fetch-checkout, mirrors the GEAK pin). If a clone\n# already exists there from a previous install we leave it as-is\n# (idempotent re-runs) — the per-install isolation guarantee is already\n# met, and re-cloning would just churn benchmark scripts that the Magpie\n# patch already keeps consistent on disk.\n# * Pinned to INFERENCEX_REF (a commit SHA by default) so a fresh install\n# is reproducible. We still record the resolved commit into the session\n# manifest (see manifest.py / _describe_dep) so runs stay traceable even\n# when an operator overrides INFERENCEX_REF.\nensure_inferencex() {\n if [ -n \"${INFERENCEX_PATH:-}\" ] && [ -d \"$INFERENCEX_PATH\" ]; then\n log \"INFERENCEX_PATH = $INFERENCEX_PATH (preserved from env; skipping fresh clone)\"\n export INFERENCEX_PATH\n return 0\n fi\n INFERENCEX_PATH=\"$INFERENCEX_DEFAULT_DIR\"\n if [ -d \"$INFERENCEX_PATH/.git\" ] || [ -d \"$INFERENCEX_PATH/benchmarks\" ]; then\n log \"InferenceX already cloned at ${INFERENCEX_PATH}; preserving existing checkout\"\n export INFERENCEX_PATH\n return 0\n fi\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"InferenceX not present at ${INFERENCEX_PATH} (check-only mode, skipping clone)\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would fetch InferenceX pinned to INFERENCEX_REF=${INFERENCEX_REF} from ${INFERENCEX_REPO} -> ${INFERENCEX_PATH}\"\n export INFERENCEX_PATH\n return 0\n fi\n log \"cloning fresh InferenceX pinned to ${INFERENCEX_REF} from ${INFERENCEX_REPO} -> ${INFERENCEX_PATH}\"\n mkdir -p \"$(dirname \"$INFERENCEX_PATH\")\"\n if ! git_fetch_pinned \"$INFERENCEX_REPO\" \"$INFERENCEX_PATH\" \"$INFERENCEX_REF\" \"InferenceX\"; then\n warn \"InferenceX clone failed. GSM8K eval will fail without it. Set\"\n warn \"INFERENCEX_PATH to a pre-cloned tree to skip this step.\"\n return 0\n fi\n export INFERENCEX_PATH\n log \"InferenceX cloned at ${INFERENCEX_PATH} (pinned ${INFERENCEX_REF})\"\n}\n\n# --- 4. InferenceX bench_serving runtime deps ---\n#\n# `benchmark_serving.py` lives under InferenceX (not under Magpie's\n# pyproject.toml), so installing Magpie does NOT pull its client-side\n# dependencies. Without these, every Magpie variant launch dies with\n# `ModuleNotFoundError: No module named 'aiohttp'` (or transformers,\n# huggingface_hub, datasets, ...) BEFORE the sglang server is even hit.\n#\n# We install into the same $PYTHON that Magpie uses (resolved to\n# `/opt/venv/bin/python3` on Claw sandboxes via the active PATH at run\n# time). The version pins are intentionally loose: these are stable\n# client-only packages and we want to inherit whatever the container's\n# base image already has rather than forcing churn.\n_BENCH_SERVING_DEPS=(\n aiohttp\n tqdm\n numpy\n requests\n transformers\n huggingface_hub\n datasets\n pandas\n)\n\nensure_bench_serving_deps() {\n log \"ensuring InferenceX benchmark_serving client deps in $PYTHON\"\n local missing=()\n for m in \"${_BENCH_SERVING_DEPS[@]}\"; do\n # Map pip name -> import name (only aiohttp/etc. happen to match).\n local import_name=\"$m\"\n case \"$m\" in\n huggingface_hub) import_name=\"huggingface_hub\" ;;\n esac\n if ! \"$PYTHON\" -c \"import ${import_name}\" >/dev/null 2>&1; then\n missing+=(\"$m\")\n fi\n done\n if [ ${#missing[@]} -eq 0 ]; then\n log \"bench_serving deps already satisfied\"\n return 0\n fi\n log \"installing missing bench_serving deps: ${missing[*]}\"\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"check-only mode; would install: ${missing[*]}\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"dry-run; skipping pip install\"\n return 0\n fi\n \"$PYTHON\" -m pip install --quiet --no-cache-dir \\\n \"${PIP_EXTRA[@]}\" \"${missing[@]}\" \\\n || die \"failed to install bench_serving deps: ${missing[*]}\"\n for m in \"${missing[@]}\"; do\n \"$PYTHON\" -c \"import ${m}\" >/dev/null 2>&1 \\\n || die \"bench_serving dep ${m} still not importable after install\"\n done\n log \"bench_serving deps installed OK\"\n}\n\n# --- 4b. xDiT image-quality gate deps (SSIM + LPIPS) ---\n#\n# The scriptable xDiT bench wrapper computes an image-quality gate\n# (LPIPS / SSIM / MSE vs a BF16 reference). torch/torchvision/numpy ship\n# with the pytorch-xdit image, but scikit-image (SSIM) and lpips (LPIPS)\n# do NOT — so without this step the gate silently degrades to MSE-only\n# (the wrapper now reports ssim_available/lpips_available=false). These\n# are pip-name != import-name, so we map them explicitly.\n#\n# Fail-soft: lpips also pulls AlexNet weights on first use (network), so a\n# failed install must NOT abort the whole install — the wrapper degrades\n# gracefully (honest *_available=false) rather than crashing the run.\n_XDIT_QUALITY_DEPS=(\n \"scikit-image:skimage\"\n \"lpips:lpips\"\n)\n\n# Load-bearing packages an OPTIONAL dep install must never move. On a ROCm pod\n# these are vendor ROCm builds from a private index; letting pip's resolver pull\n# a PyPI (CUDA) torch to satisfy e.g. lpips' `torch>=0.4.0` silently bricks GPU\n# access for EVERY framework sharing this venv (that is exactly how this brick\n# shipped: a CUDA torch replaced the ROCm one, exit 0, no visible error).\n_XDIT_CORE_PINS=(torch torchvision torchaudio triton)\n\n# Write a pip constraints file pinning each installed core package to its exact\n# current version. `pip install -c ` then forbids the resolver from moving\n# them, while still letting the requested deps pull their OTHER (safe) deps.\n_write_core_constraints() {\n local dest=\"$1\" pkg ver\n : > \"$dest\"\n for pkg in \"${_XDIT_CORE_PINS[@]}\"; do\n ver=\"$(\"$PYTHON\" -c \"import importlib.metadata as m; print(m.version('$pkg'))\" 2>/dev/null || true)\"\n [ -n \"$ver\" ] && printf '%s==%s\\n' \"$pkg\" \"$ver\" >> \"$dest\"\n done\n return 0\n}\n\n# torch's ROCm/HIP version string (empty if torch is absent OR is a non-ROCm\n# build). The tripwire below reads it before and after the optional install.\n_torch_hip_version() {\n \"$PYTHON\" -c \"import torch; print(torch.version.hip or '')\" 2>/dev/null || true\n}\n\n# Tripwire: if torch was a ROCm build before the optional install but is now a\n# non-ROCm (CUDA-only) build, the resolver swapped the load-bearing wheel. Try a\n# best-effort rollback to the pinned versions, then abort HARD — a silent warn\n# here is exactly how this poison reached every co-tenant framework before.\n_guard_torch_not_clobbered() {\n local constraints=\"$1\" hip_before=\"$2\" hip_after\n [ -n \"$hip_before\" ] || return 0\n hip_after=\"$(_torch_hip_version)\"\n [ -n \"$hip_after\" ] && return 0\n warn \"xDiT quality deps swapped the ROCm torch for a non-ROCm build; attempting rollback to: $(tr '\\n' ' ' < \"$constraints\")\"\n \"$PYTHON\" -m pip install --quiet --no-cache-dir --force-reinstall --no-deps \\\n \"${PIP_EXTRA[@]}\" -r \"$constraints\" \\\n || warn \"rollback reinstall failed (pinned ROCm wheels may need the vendor index); restore torch manually\"\n die \"optional xDiT quality deps clobbered the load-bearing ROCm torch (was hip=${hip_before}, now a non-ROCm build). Aborting instead of poisoning every framework in this shared venv. Preinstall scikit-image/lpips in the image, or extend _XDIT_CORE_PINS.\"\n}\n\nensure_xdit_quality_deps() {\n log \"ensuring xDiT image-quality gate deps (SSIM/LPIPS) in $PYTHON\"\n local missing=()\n local pair pip_name import_name\n for pair in \"${_XDIT_QUALITY_DEPS[@]}\"; do\n pip_name=\"${pair%%:*}\"\n import_name=\"${pair##*:}\"\n if ! \"$PYTHON\" -c \"import ${import_name}\" >/dev/null 2>&1; then\n missing+=(\"$pip_name\")\n fi\n done\n if [ ${#missing[@]} -eq 0 ]; then\n log \"xDiT quality deps already satisfied\"\n return 0\n fi\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"check-only mode; would install xDiT quality deps: ${missing[*]}\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"dry-run; skipping xDiT quality dep install\"\n return 0\n fi\n log \"installing missing xDiT quality deps: ${missing[*]}\"\n # Pin the load-bearing core so this optional install can never move\n # torch/torchvision/triton, and snapshot torch's ROCm build so the tripwire\n # can abort loudly if it got swapped anyway.\n local constraints hip_before\n constraints=\"$(mktemp)\"\n _write_core_constraints \"$constraints\"\n hip_before=\"$(_torch_hip_version)\"\n \"$PYTHON\" -m pip install --quiet --no-cache-dir -c \"$constraints\" \\\n \"${PIP_EXTRA[@]}\" \"${missing[@]}\" \\\n || warn \"failed to install xDiT quality deps: ${missing[*]} (gate degrades to MSE-only)\"\n _guard_torch_not_clobbered \"$constraints\" \"$hip_before\"\n rm -f \"$constraints\"\n for pair in \"${_XDIT_QUALITY_DEPS[@]}\"; do\n import_name=\"${pair##*:}\"\n \"$PYTHON\" -c \"import ${import_name}\" >/dev/null 2>&1 \\\n || warn \"xDiT quality dep '${import_name}' not importable after install (gate excludes it)\"\n done\n}\n\n# --- 4c. Langfuse SDK (opt-in live trace push) ---\n# The local reports/trace/*.jsonl ledger never needs this. Only the opt-in\n# live-Langfuse sink (HYPERLOOM_LANGFUSE_ENABLE=1) imports the SDK, and when\n# absent the emitter degrades to a silent no-op — so a run can look \"fine\"\n# while pushing nothing. Operators kept hitting that gap: they flipped the\n# flag + set the keys but forgot the separate `pip install '...[trace]'`,\n# and only noticed when session_breakdown showed sdk_available=false.\n#\n# Fix: when (and ONLY when) the Langfuse master switch is on in the loaded\n# environment (.env is sourced above by load_dotenv_no_clobber, so the flag\n# is visible here), guarantee the SDK is importable — install it on demand,\n# mirroring ensure_bench_serving_deps (import-probe first, pip only on miss).\n# Switch off => skipped entirely, so environments that don't use Langfuse\n# stay lean. Fail-soft: a failed install warns (the emitter's own no-op\n# fallback still protects the run) rather than aborting the whole install.\n_langfuse_enabled() {\n case \"$(printf '%s' \"${HYPERLOOM_LANGFUSE_ENABLE:-}\" | tr '[:upper:]' '[:lower:]')\" in\n 1|true|yes|on) return 0 ;;\n *) return 1 ;;\n esac\n}\n\nensure_langfuse_when_enabled() {\n if ! _langfuse_enabled; then\n log \"langfuse: HYPERLOOM_LANGFUSE_ENABLE not set; skipping SDK install (local jsonl ledger is unaffected)\"\n return 0\n fi\n if \"$PYTHON\" -c \"import langfuse\" >/dev/null 2>&1; then\n log \"langfuse: SDK already importable\"\n return 0\n fi\n log \"langfuse: HYPERLOOM_LANGFUSE_ENABLE is on but SDK missing — installing langfuse\"\n if [ \"$CHECK_ONLY\" -eq 1 ]; then\n warn \"langfuse: SDK missing (check-only; would install 'langfuse>=2.0')\"\n return 0\n fi\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would install 'langfuse>=2.0'\"\n return 0\n fi\n if \"$PYTHON\" -m pip install --quiet --no-cache-dir \"${PIP_EXTRA[@]}\" \"langfuse>=2.0\" \\\n && \"$PYTHON\" -c \"import langfuse\" >/dev/null 2>&1; then\n log \"langfuse: SDK installed OK\"\n else\n warn \"langfuse: SDK install failed; live push will degrade to a no-op (local jsonl ledger still written). Preinstall 'langfuse' in the image or run: \\\"\\$PYTHON\\\" -m pip install 'langfuse>=2.0'\"\n fi\n}\n\n# --- 5. Chain to kernel-agent ---\nchain_kernel_agent() {\n if [ \"$SKIP_KERNEL_AGENT\" -eq 1 ]; then\n log \"skipping kernel-agent installer (--skip-kernel-agent)\"\n return 0\n fi\n local script=\"${KERNEL_AGENT_ROOT}/scripts/install.sh\"\n if [ ! -f \"$script\" ]; then\n warn \"kernel-agent installer not found at $script\"\n return 0\n fi\n log \"delegating ray + TraceLens + GEAK + LLM gateway env to ${script}\"\n export REPO_ROOT KERNEL_AGENT_ROOT MAGPIE_PATH HYPERLOOM_ROOT\n export USER_DATA_PATH HYPERLOOM_RUNTIME_DIR KERNEL_AGENT_ENV\n export HYPERLOOM_KERNEL_AGENT_ROOT=\"${HYPERLOOM_KERNEL_AGENT_ROOT:-${KERNEL_AGENT_ROOT}}\"\n [ -n \"${INFERENCEX_PATH:-}\" ] && export INFERENCEX_PATH\n # Forward the optional internal extension path when provided; unset =>\n # kernel-agent installer stays open-source-only (no separate toggle).\n [ -n \"${TRACELENS_INTERNAL_ROOT:-}\" ] && export TRACELENS_INTERNAL_ROOT\n local args=()\n [ \"$CHECK_ONLY\" -eq 1 ] && args+=(--check-only)\n [ \"$DRY_RUN\" -eq 1 ] && args+=(--dry-run)\n if [ \"$DRY_RUN\" -eq 1 ]; then\n log \"would run: bash '$script' ${args[*]}\"\n return 0\n fi\n bash \"$script\" \"${args[@]}\"\n}\n\nensure_inference_optimizer\nensure_forge_gemm_tune\nensure_kernel_agents\nensure_langfuse_when_enabled\n# Hold the install lock for the whole mirror-mutating region (Magpie /\n# InferenceX clones + the chained kernel-agent GEAK/TraceLens clones).\nacquire_install_lock\n# Magpie is only needed when the Magpie benchmark backend is active. The\n# bypass backend drives InferenceX directly (see benchmark_backend.py), so\n# skip the Magpie install/import and its script-patch when bypass is selected.\n# Default (unset/blank) stays magpie, preserving existing behavior.\n# Mirror Python's resolve_backend_name() normalization (strip THEN lower):\n# sed trims ONLY leading/trailing whitespace (like str.strip()), so \" bypass\" /\n# \"bypass \" skip Magpie here to match runtime, while an internal-space value\n# such as \"by pass\" stays != \"bypass\" and correctly falls through to Magpie\n# (runtime resolves such unknown values back to magpie). A blanket delete of\n# ALL whitespace would wrongly collapse \"by pass\" -> \"bypass\" and diverge.\nHYPERLOOM_BENCHMARK_BACKEND_LC=\"$(printf '%s' \"${HYPERLOOM_BENCHMARK_BACKEND:-}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr '[:upper:]' '[:lower:]')\"\nif [ \"$HYPERLOOM_BENCHMARK_BACKEND_LC\" = \"bypass\" ]; then\n log \"benchmark backend is bypass; skipping ensure_magpie + ensure_magpie_atomic_scripts_patch\"\nelse\n ensure_magpie\nfi\nensure_inferencex\n# Ordering matters: the Magpie script patch also scrubs the redundant\n# `--concurrent-requests` eval flag from the InferenceX `benchmarks/` copies\n# Magpie actually executes, and teaches `benchmark_lib.sh::run_lm_eval` to\n# tolerate it. Both need $INFERENCEX_PATH, which only ensure_inferencex exports\n# — running the patch before it silently skipped those targets and left\n# RUN_EVAL=true baselines aborting on 'Unknown parameter'.\nif [ \"$HYPERLOOM_BENCHMARK_BACKEND_LC\" != \"bypass\" ]; then\n ensure_magpie_atomic_scripts_patch\nfi\n\n# aiperf (AgentX client) is an OPT-IN Magpie-path add-on: installed only when the\n# operator explicitly asks (INSTALL_AIPERF or HYPERLOOM_AGENTX truthy), so a\n# default install grows no extra network/build dependency. If AgentX is turned on\n# at runtime without aiperf present, the runtime preflight fails loud with\n# guidance (install it, or point AIPERF_BIN at an existing build). Fail-soft\n# inside ensure_aiperf. Never for the bypass backend.\nif [ \"$HYPERLOOM_BENCHMARK_BACKEND_LC\" != \"bypass\" ]; then\n # Strip surrounding whitespace then lowercase, so the installer\n # parses these flags identically to the Python runtime's agentx_enabled()\n # (which .strip()s) — e.g. HYPERLOOM_AGENTX=\" on \" must be ON in both.\n _agx_want=\"$(printf '%s' \"${INSTALL_AIPERF:-}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr '[:upper:]' '[:lower:]')\"\n _agx_sw=\"$(printf '%s' \"${HYPERLOOM_AGENTX:-}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr '[:upper:]' '[:lower:]')\"\n case \"${_agx_want}:${_agx_sw}\" in\n 1:*|true:*|yes:*|on:*|*:1|*:true|*:yes|*:on)\n ensure_aiperf ;;\n *)\n log \"aiperf (AgentX) skipped: set INSTALL_AIPERF=1 or HYPERLOOM_AGENTX=1 to install it (or point AIPERF_BIN at an existing build).\" ;;\n esac\nfi\nensure_bench_serving_deps\nensure_xdit_quality_deps\nchain_kernel_agent\n# rocprof-compute + pandas<3 pin runs LAST — strictly AFTER every pip-installing\n# step (chain_kernel_agent included; nothing below installs packages). This makes\n# the pandas<3 pin the final word (no later `pip install` can re-pull pandas>=3)\n# and its own re-check the truthful end state, not a premature false-positive.\n# Gated on the KernelForge checkout (not the backend): the default-geak install a\n# later forge session inherits still gets rocprof-compute + pandas<3.\nensure_rocprof_compute\n# tree-reform.MD P2.5: framework-agent was promoted into\n# src/hyperloom/agents/framework/ (single hyperloom distribution), so the\n# `fa` CLI is already installed by ensure_inference_optimizer() above; no\n# more separate chain_framework_agent() delegation to a standalone installer.\n\n_write_specialist_secret_env_opt_in() {\n if [ \"$DRY_RUN\" -eq 1 ] || [ \"$CHECK_ONLY\" -eq 1 ]; then\n log \"would append HYPERLOOM_SPECIALIST_INHERIT_SECRET_ENV=1 to ${KERNEL_AGENT_ENV}\"\n return 0\n fi\n mkdir -p \"$(dirname \"$KERNEL_AGENT_ENV\")\"\n if [ -f \"$KERNEL_AGENT_ENV\" ] && grep -q '^export HYPERLOOM_SPECIALIST_INHERIT_SECRET_ENV=' \"$KERNEL_AGENT_ENV\" 2>/dev/null; then\n sed -i 's|^export HYPERLOOM_SPECIALIST_INHERIT_SECRET_ENV=.*|export HYPERLOOM_SPECIALIST_INHERIT_SECRET_ENV=1|' \"$KERNEL_AGENT_ENV\"\n else\n {\n echo \"\"\n echo \"# Production bootstrap: specialist subprocesses need env credentials unless claude CLI auth is preconfigured\"\n echo \"export HYPERLOOM_SPECIALIST_INHERIT_SECRET_ENV=1\"\n } >> \"$KERNEL_AGENT_ENV\"\n fi\n}\n\n_probe_framework_source_roots() {\n log \"probing framework source roots for INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS\"\n local roots\n roots=\"$(\"$PYTHON\" - <<'PY'\nfrom hyperloom.orchestrator.framework.paths import probe_framework_source_roots_for_env\nprint(probe_framework_source_roots_for_env())\nPY\n)\"\n if [ -z \"$roots\" ]; then\n warn \"no framework source roots discovered\"\n return 0\n fi\n log \"discovered framework roots: $roots\"\n # Emit a framework-bucketed one-liner so operators (and the\n # preflight grep) can tell at a glance whether atom was picked up.\n local roots_summary\n roots_summary=\"$(ROOTS_INPUT=\"$roots\" \"$PYTHON\" - <<'PY'\nimport os\nfrom hyperloom.orchestrator.framework.paths import summarise_framework_root_discovery\nprint(summarise_framework_root_discovery(os.environ.get(\"ROOTS_INPUT\", \"\")))\nPY\n)\"\n if [ -n \"$roots_summary\" ]; then\n log \"discovered framework roots: $roots_summary\"\n fi\n if [ \"$DRY_RUN\" -eq 1 ] || [ \"$CHECK_ONLY\" -eq 1 ]; then\n log \"would append INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS=$roots to ${KERNEL_AGENT_ENV}\"\n return 0\n fi\n mkdir -p \"$(dirname \"$KERNEL_AGENT_ENV\")\"\n if [ -f \"$KERNEL_AGENT_ENV\" ] && grep -q '^export INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS=' \"$KERNEL_AGENT_ENV\" 2>/dev/null; then\n sed -i \"s|^export INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS=.*|export INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS=${roots}|\" \"$KERNEL_AGENT_ENV\"\n else\n {\n echo \"\"\n echo \"# Framework source roots for PolicyGate + flag discovery (auto-probed)\"\n echo \"export INFERENCE_OPTIMIZER_FRAMEWORK_SOURCE_ROOTS=${roots}\"\n } >> \"$KERNEL_AGENT_ENV\"\n fi\n}\n\n_write_specialist_secret_env_opt_in\n_probe_framework_source_roots\n\n_prune_dep_cache \"InferenceX\" \"Magpie\"\nlog \"install complete\"\nlog \"kernel-agent env file written: ${KERNEL_AGENT_ENV}\"\nlog \" HYPERLOOM_KERNEL_AGENT_ROOT=${HYPERLOOM_KERNEL_AGENT_ROOT}\"\nlog \"\"\nlog \"next steps — pick ONE:\"\nlog \" (a) source ${KERNEL_AGENT_ENV}, then run hyperloom.inference_optimizer.cli\"\nlog \" (b) just launch hyperloom.inference_optimizer.cli — preflight will auto-source\"\nlog \" \\$KERNEL_AGENT_ENV (or \\$USER_DATA_PATH/runtime/kernel-agent.env.sh)\"\nlog \" via _load_kernel_agent_env_fallback() if HYPERLOOM_KERNEL_AGENT_ROOT\"\nlog \" is unset.\"\nlog \"\"\nlog \"If you skip BOTH and HYPERLOOM_KERNEL_AGENT_ROOT stays unset, the\"\nlog \"roofline composite action's trace_analyze sub-step will fail with\"\nlog \" 'HYPERLOOM_KERNEL_AGENT_ROOT is not set'\"\nlog \"and the whole optimisation loop stalls (PolicyGate blocks every\"\nlog \"downstream action on a missing TraceLens snapshot).\"\n"}}}}