Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/amd-agi_hyperloom.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
1.2 MiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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[<action_name>]`` 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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(\"<Q\", len(header)))\n f.write(header)\n\n\ndef test_detect_vocab_shape_mismatch_blocks(tmp_path):\n m = tmp_path / \"qwen_vocab_mismatch\"\n _write_config(\n m,\n model_type=\"qwen2\",\n architectures=[\"Qwen2ForCausalLM\"],\n max_position_embeddings=4096,\n vocab_size=152064,\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 \"lm_head.weight\": {\n \"dtype\": \"BF16\",\n \"shape\": [151936, 1536],\n \"data_offsets\": [0, 0],\n },\n },\n )\n reason = cli._detect_incompatible_model_config(str(m))\n assert reason is not None\n assert \"vocab_size=152064\" in reason\n assert \"151936\" in reason\n\n\ndef test_detect_vocab_shape_match_not_blocked(tmp_path):\n # config vocab_size matches the weight output dim -> 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(\"<Q\", 999) + b\"{\") # claims 999, has 1\n assert cli._read_safetensors_header(truncated) is None\n\n short = tmp_path / \"short.safetensors\"\n short.write_bytes(b\"\\x01\\x02\") # < 8-byte length prefix\n assert cli._read_safetensors_header(short) is None\n\n\n# ---------------------------------------------------------------------------\n# Gemma2 detection helpers (model_config_utils)\n# ---------------------------------------------------------------------------\n@pytest.mark.parametrize(\n \"name,expected\",\n [\n (\"gemma2\", True),\n (\"gemma2-9b\", True),\n (\"google-gemma-2-9b-it\", True),\n (\"gemma_2_2b\", True),\n (\"llama-gemma2-test\", True),\n (\"gemma-3-12b\", False),\n (\"gemma3-12b\", False),\n (\"gemma25\", False),\n (\"notgemma2\", False),\n (\"mygemma2\", False),\n (\"gemma12-model\", False),\n (\"\", False),\n ],\n)\ndef test_path_looks_like_gemma2(name, expected):\n from hyperloom.inference_optimizer import model_config_utils as mcu\n\n assert mcu._path_looks_like_gemma2(name) is expected\n\n\ndef test_model_is_gemma2_falls_back_to_path_on_residual_config(tmp_path):\n # config.json present but empty (no model_type/architectures) -> 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 ``<base>/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/<model>/<UTC ts>/ (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 <session_dir>/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 \"<key=value> ...`` 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.<unix_ts>`` 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 (<name>@<sha>). 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# <name>@<sha> 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 <<EOF\n$listing\nEOF\n done\n}\n\nMAGPIE_REPO=\"${MAGPIE_REPO:-https://github.com/AMD-AGI/Magpie.git}\"\n# Pin Magpie to a release commit/tag instead of the default branch. Operators can\n# re-pin with MAGPIE_REF=<tag|sha>.\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=<tag|branch|sha>.\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 <<EOF\n[inference-optimizer ERROR] Conflicting LLM credentials: ${conflict}.\n\nHyperloom never borrows one provider's key or endpoint for the other. Give each\nside its own base URL and key, or drop the other provider's key.\nEOF\n return 1\n}\n\npreflight_validate_credentials() {\n preflight_load_dotenv\n local missing=()\n local has_anthropic=0 has_openai=0\n # Each side needs its own base URL and key; an unset side is fine.\n { { [ -n \"${ANTHROPIC_BASE_URL:-}\" ] || [ -n \"${DEEPSEEK_BASE_URL:-}\" ] || [ -n \"${DEEPSEEK_API_KEY:-}\" ]; } &&\n { [ -n \"${ANTHROPIC_API_KEY:-}\" ] || [ -n \"${ANTHROPIC_AUTH_TOKEN:-}\" ] || [ -n \"${DEEPSEEK_API_KEY:-}\" ]; }; } &&\n has_anthropic=1\n { [ -n \"${OPENAI_BASE_URL:-}\" ] && [ -n \"${OPENAI_API_KEY:-}\" ]; } && has_openai=1\n preflight_reject_cross_provider || return 1\n if [ \"$has_anthropic\" -eq 1 ] || [ \"$has_openai\" -eq 1 ]; then\n log \"credentials preflight: at least one self-consistent provider side present\"\n return 0\n fi\n missing+=(\"a self-consistent provider side: ANTHROPIC_BASE_URL + ANTHROPIC_API_KEY (DeepSeek may omit the URL), or OPENAI_BASE_URL + OPENAI_API_KEY\")\n local env_file_status\n if [ -f \"$REPO_ROOT/.env\" ]; then\n env_file_status=\"present\"\n else\n env_file_status=\"not found\"\n fi\n if [ \"$CHECK_ONLY\" -eq 1 ] || [ \"$DRY_RUN\" -eq 1 ]; then\n warn \"missing credential(s): ${missing[*]} (.env=${env_file_status}); \" \\\n \"continuing because --check-only / --dry-run is active. The \" \\\n \"chained kernel-agent installer will still fail later unless \" \\\n \"these are set before a real install.\"\n return 0\n fi\n cat >&2 <<EOF\n[inference-optimizer ERROR] Missing required credential group(s): ${missing[*]}\n\nTried loading from:\n - shell environment\n - \\$REPO_ROOT/.env (${env_file_status}: ${REPO_ROOT}/.env)\n\nFix one of:\n 1. Anthropic:\n export ANTHROPIC_BASE_URL=https://api.anthropic.com\n export ANTHROPIC_API_KEY=sk-ant-...\n 2. DeepSeek:\n export DEEPSEEK_API_KEY=sk-...\n # optional: export DEEPSEEK_BASE_URL=https://api.deepseek.com/anthropic\n 3. Copy .env from a working worktree into this one:\n cp /path/to/main-worktree/.env \"${REPO_ROOT}/.env\"\nEOF\n exit 2\n}\npreflight_validate_credentials\n\n# --- 0. Resolve PYTHON ---\n# On hyperloom / sgl-workspace containers the canonical ROCm stack lives in\n# /opt/venv (preinstalled torch+rocm, sglang, vllm, aiter, sgl_kernel,\n# triton, Magpie, inference_optimizer, claude_agent_sdk, ray). Always\n# prefer that interpreter — bare-image PYTHONs (e.g. /usr/bin/python3) on a\n# ROCm pod silently pull plain `torch` from PyPI on `pip install -e .[test]`,\n# which is the NVIDIA CUDA wheel and crashes downstream RAG / baseline\n# steps with \"Found no NVIDIA driver\". Operators who really need a custom\n# interpreter can opt out with INFERENCE_OPTIMIZER_FORCE_PYTHON=1.\n#\n# bare-image bootstrap fallback: when nothing in the search order exists AND\n# apt-get is available (Debian/Ubuntu sandbox), try a best-effort\n# `apt-get install -y python3 python3-venv python3-pip` before giving up.\n# Gated by apt-get present, not --check-only / --dry-run, and\n# INFERENCE_OPTIMIZER_SKIP_APT_BOOTSTRAP unset.\nresolve_python() {\n if [ -x \"/opt/venv/bin/python\" ] && [ \"${INFERENCE_OPTIMIZER_FORCE_PYTHON:-0}\" != \"1\" ]; then\n if [ -n \"${PYTHON:-}\" ] && [ \"${PYTHON}\" != \"/opt/venv/bin/python\" ]; then\n log \"preferring /opt/venv/bin/python over PYTHON=${PYTHON} (canonical ROCm stack)\"\n log \" set INFERENCE_OPTIMIZER_FORCE_PYTHON=1 to honor PYTHON verbatim\"\n fi\n PYTHON=\"/opt/venv/bin/python\"\n return 0\n fi\n if [ -n \"${PYTHON:-}\" ] && [ -x \"$PYTHON\" ]; then\n return 0\n fi\n if command -v python3 >/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# `<ROCM_PATH>/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 `<libexec>/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 <file>` 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"}}}}