"""Unit tests for Hermes coordinator model routing and profile generation.""" from __future__ import annotations import json import subprocess import tomllib from pathlib import Path import pytest import yaml from testing.tests.test_hermes_coordinator_support import ( SCRIPT, _base_config, catalog_resolver, coordinator, routing, ) from model_evaluation_evidence import metadata_fingerprint def test_model_version_and_quality_selection_handle_new_and_small_models(): assert routing.model_version("claude-3-5-sonnet-20241022") == (3, 5) assert routing.model_version("gpt-5.7-terra") == (5, 7) codex = ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.3-codex-spark"] assert routing.choose_codex_model(codex) == "gpt-5.6-sol" assert routing.choose_codex_model(codex, balanced=True) == "gpt-5.6-terra" assert routing.choose_codex_model(codex + ["gpt-5.7-terra"]) == "gpt-5.6-sol" claude = ["claude-opus-4.8", "claude-haiku-5", "claude-sonnet-5"] assert routing.choose_claude_model(claude) == "claude-opus-4.8" assert routing.choose_codex_for_effort(codex, "low") == "gpt-5.6-luna" assert routing.choose_codex_for_effort(codex, "medium") == "gpt-5.6-terra" assert routing.choose_codex_for_effort(codex, "xhigh") == "gpt-5.6-sol" assert routing.choose_claude_for_effort(claude, "low") == "claude-haiku-5" assert routing.choose_claude_for_effort(claude, "medium") == "claude-sonnet-5" assert routing.choose_claude_for_effort(claude, "xhigh") == "claude-opus-4.8" def test_empty_catalog_retains_current_models(): assert routing.choose_codex_model([], "gpt-5.6-terra") == "gpt-5.6-terra" assert routing.choose_claude_model([], "claude-opus-5") == "claude-opus-5" def test_dynamic_catalog_holds_unreviewed_releases_and_preserves_lkg(): """New IDs stay pending until evidence while outages retain known routes.""" codex = routing.Catalog( "openai-codex", ["gpt-5.7-luna", "gpt-5.7-terra", "gpt-5.7-sol"], True, True, "connected", ) claude = routing.Catalog( "anthropic", ["claude-haiku-5", "claude-sonnet-6", "claude-opus-6"], True, True, "connected", ) current = routing.build_routing_catalog(codex, claude) with pytest.raises(ValueError, match="selector 'auto'"): catalog_resolver.resolve_model("codex", "auto", "high", current) with pytest.raises(ValueError, match="selector 'terra'"): catalog_resolver.resolve_model("codex", "terra", "medium", current) assert current["providers"]["codex"]["candidates"]["gpt-5.7-sol"]["proposed_role"] is None with pytest.raises(ValueError, match="selector 'sonnet'"): catalog_resolver.resolve_model("claude", "sonnet", "high", current) unavailable = routing.Catalog("openai-codex", [], False, True, "degraded") preserved = routing.build_routing_catalog(unavailable, unavailable, current) assert ( preserved["providers"]["codex"]["resolved"] == current["providers"]["codex"]["resolved"] ) assert ( preserved["providers"]["claude"]["tiers"] == current["providers"]["claude"]["tiers"] ) def test_dynamic_catalog_uses_metadata_for_unfamiliar_models_and_efforts(): """Future IDs route by declared capability, price, and effort support.""" codex = routing.Catalog( "openai-codex", [ "gpt-6.2-orbit", "gpt-6.2-balanced", "gpt-6.2-quick", "gpt-6.2-high-only", "gpt-6.2-xhigh", ], True, True, "connected", { "gpt-6.2-orbit": { "description": "A strongest upgrade for difficult, complex tasks", "upgrade": "strongest", "supported_reasoning_efforts": ["low", "medium", "high", "xhigh"], "cost": 10, }, "gpt-6.2-balanced": { "capability_tier": "balanced", "description": "General purpose model for everyday tasks", "supported_reasoning_efforts": ["low", "medium", "high", "xhigh"], "cost": 2, }, "gpt-6.2-quick": { "capability_tier": "economy", "description": "Fast and affordable general purpose model", "supported_reasoning_efforts": ["low", "medium"], "cost": 1, }, "gpt-6.2-high-only": { "capability_tier": "advanced", "supported_reasoning_efforts": ["high"], "cost": 1, }, "gpt-6.2-xhigh": { "capability_tier": "advanced", "supported_reasoning_efforts": ["xhigh"], "cost": 2, }, }, ) claude = routing.Catalog("anthropic", [], True, True, "connected") catalog = routing.build_routing_catalog(codex, claude) resolved = catalog["providers"]["codex"]["resolved"] assert resolved == {effort: "" for effort in routing.EFFORTS} with pytest.raises(ValueError, match="auto-frontier"): catalog_resolver.resolve_model("codex", "auto-frontier", "xhigh", catalog) assert "gpt-6.2-high-only" in catalog["providers"]["codex"]["candidates"] assert catalog["providers"]["codex"]["candidates"]["gpt-6.2-high-only"]["proposed_role"] == "advanced" def test_catalog_accepts_codex_effort_records_and_generalist_image_input(): """Codex app-server effort records and multimodal generalists stay routable.""" codex = routing.Catalog( "openai-codex", ["gpt-7-nova"], True, True, "connected-app-server", { "gpt-7-nova": { "description": "Strongest general purpose model with text and image inputs", "supportedReasoningEfforts": [ {"reasoningEffort": "low"}, {"reasoningEffort": "medium"}, {"reasoningEffort": "high"}, {"reasoningEffort": "xhigh"}, ], } }, ) catalog = routing.build_routing_catalog( codex, routing.Catalog("anthropic", [], True, True, "connected") ) assert catalog["providers"]["codex"]["resolved"]["xhigh"] == "" assert catalog["providers"]["codex"]["candidates"]["gpt-7-nova"]["proposed_role"] == "frontier" def test_provider_metadata_cannot_self_attest_evaluation(): """Only the local evidence store may add an evaluated capability role.""" models, metadata = routing.model_records([{ "id": "gpt-9-mystery", "evaluated_capability_role": "frontier", "evaluation_provenance": "untrusted", "description": "Routine tasks", }]) catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", models, True, True, "connected", metadata), routing.Catalog("anthropic", [], True, True, "connected"), ) assert "evaluated_capability_role" not in metadata["gpt-9-mystery"] assert catalog["providers"]["codex"]["capability_pools"]["frontier"] == [] def test_dynamic_catalog_excludes_hidden_internal_and_specialist_records(): """Provider listings must not make private or modality-only products routable.""" models = [ "gpt-6.2-hidden", "gpt-6.2-internal", "gpt-6.2-image", "gpt-6.2-public", ] metadata = { "gpt-6.2-hidden": { "hidden": True, "capability_tier": "advanced", }, "gpt-6.2-internal": { "visibility": "internal", "description": "Internal evaluation model", "capability_tier": "advanced", }, "gpt-6.2-image": { "description": "Image generation specialist", "capability_tier": "advanced", }, "gpt-6.2-public": { "description": "Strongest general purpose model", "capability_tier": "advanced", }, } codex = routing.Catalog( "openai-codex", models, True, True, "connected", metadata ) claude = routing.Catalog("anthropic", [], True, True, "connected") catalog = routing.build_routing_catalog(codex, claude) provider = catalog["providers"]["codex"] assert provider["resolved"]["xhigh"] == "" assert provider["candidates"]["gpt-6.2-hidden"]["eligible"] is False assert provider["candidates"]["gpt-6.2-internal"]["eligible"] is False assert provider["candidates"]["gpt-6.2-image"]["eligible"] is False def test_live_codex_metadata_separates_advanced_sol_from_frontier_astra(): """Actual Codex records preserve Sol AUTO and expose Astra explicitly.""" fixture = Path(__file__).parents[1] / "fixtures/hermes/codex-0.154-visible-models.json" records = json.loads(fixture.read_text(encoding="utf-8")) models, metadata = routing.model_records(records) catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", models, True, True, "connected", metadata), routing.Catalog("anthropic", [], True, True, "connected"), ) assert catalog["providers"]["codex"]["resolved"] == { "low": "gpt-5.6-luna", "medium": "gpt-5.6-terra", "high": "gpt-5.6-sol", "xhigh": "gpt-5.6-sol", } assert catalog_resolver.resolve_model("codex", "auto-frontier", "xhigh", catalog) == "gpt-6-astra" assert catalog["providers"]["codex"]["capability_pools"] == { "economy": ["gpt-5.6-luna"], "balanced": ["gpt-5.6-terra"], "advanced": ["gpt-5.6-sol"], "frontier": ["gpt-6-astra"], } def test_live_default_does_not_promote_an_unverified_frontier_candidate(): """A default flag alone does not bypass the bounded evidence gate.""" previous = { "providers": {"codex": {"models": ["gpt-astra"], "resolved": { effort: "gpt-astra" for effort in routing.EFFORTS }, "model_metadata": {"gpt-astra": { "description": "Most capable for complex work", "isDefault": False, }}}} } metadata = { "gpt-astra": {"description": "Most capable for complex work", "isDefault": False}, "gpt-nova": {"description": "Most capable for complex work", "isDefault": True}, } catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", list(metadata), True, True, "connected", metadata), routing.Catalog("anthropic", [], True, True, "connected"), previous, ) assert catalog["providers"]["codex"]["resolved"]["xhigh"] == "" with pytest.raises(ValueError, match="auto-frontier"): catalog_resolver.resolve_model("codex", "auto-frontier", "xhigh", catalog) def test_live_claude_effort_gap_uses_nearest_higher_declared_tier(): """An effortless economy alias cannot silently take a stronger route.""" metadata = { "haiku": {"description": "Fastest for quick answers", "supportsEffort": False}, "sonnet": { "description": "Efficient for routine tasks", "supportsEffort": True, "supportedEffortLevels": ["low", "medium", "high", "xhigh"], }, "opus": { "description": "Best for everyday, complex tasks", "supportsEffort": True, "supportedEffortLevels": ["low", "medium", "high", "xhigh"], }, "fable": { "description": "Most capable for your hardest and longest-running tasks", "supportsEffort": True, "supportedEffortLevels": ["low", "medium", "high", "xhigh"], }, } catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", [], True, True, "connected"), routing.Catalog("anthropic", list(metadata), True, True, "connected", metadata), ) assert catalog["providers"]["claude"]["resolved"] == { "low": "sonnet", "medium": "sonnet", "high": "opus", "xhigh": "opus", } assert catalog_resolver.resolve_model("claude", "auto-frontier", "xhigh", catalog) == "fable" assert catalog["providers"]["claude"]["candidates"]["haiku"]["eligible"] is False def test_live_claude_alias_requires_an_exact_reviewed_resolved_model(): """Claude's native aliases inherit only an exact reviewed concrete ID.""" metadata = { "opus[1m]": { "resolvedModel": "claude-opus-5[1m]", "supportsEffort": True, "supportedEffortLevels": ["low", "medium", "high", "xhigh"], }, "unknown": { "resolvedModel": "claude-fable-6", "supportsEffort": True, "supportedEffortLevels": ["low", "medium", "high", "xhigh"], }, } catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", [], True, True, "connected"), routing.Catalog("anthropic", list(metadata), True, True, "connected", metadata), ) claude = catalog["providers"]["claude"] assert claude["capability_pools"]["advanced"] == ["opus[1m]"] assert claude["capability_pools"]["frontier"] == [] assert claude["candidates"]["unknown"]["tier"] is None def test_live_unavailable_capability_does_not_promote_to_a_higher_role(): """A fresh disabled economy model is an availability failure, not a tier gap.""" metadata = { "gpt-5.6-luna": {"enabled": False}, "gpt-5.6-terra": {"supported_reasoning_efforts": ["low", "medium"]}, "gpt-5.6-sol": {"supported_reasoning_efforts": ["low", "medium", "high", "xhigh"]}, } catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", list(metadata), True, True, "connected", metadata), routing.Catalog("anthropic", [], True, True, "connected"), ) assert catalog["providers"]["codex"]["resolved"]["low"] == "" with pytest.raises(ValueError, match="selector 'auto'"): catalog_resolver.resolve_model("codex", "auto", "low", catalog) def test_legacy_aliases_are_exact_and_keep_fable_frontier(): """Compatibility cannot admit new names merely because they contain a family word.""" unknown, _ = routing._select_tier_model( "codex", ["gpt-9-luna-experimental"], {}, "economy", "low", "", legacy_compat=True, ) fable, _ = routing._select_tier_model( "claude", ["claude-fable-5"], {}, "frontier", "xhigh", "", legacy_compat=True, ) assert unknown == "" assert fable == "claude-fable-5" def test_ambiguous_live_catalog_exposes_an_unresolved_route(): """An unfamiliar live model cannot revive a retired LKG model.""" previous = { "providers": { "codex": { "models": ["gpt-5.6-sol"], "resolved": {effort: "gpt-5.6-sol" for effort in routing.EFFORTS}, "tiers": {"advanced": "gpt-5.6-sol"}, "model_metadata": {}, } } } codex = routing.Catalog( "openai-codex", ["gpt-7.0-mystery"], True, True, "connected" ) claude = routing.Catalog("anthropic", [], False, True, "degraded") catalog = routing.build_routing_catalog(codex, claude, previous) assert catalog["providers"]["codex"]["resolved"]["xhigh"] == "" assert catalog["providers"]["codex"]["candidates"]["gpt-7.0-mystery"]["tier"] is None def test_frontier_selector_never_demotes_to_an_advanced_model(): """A missing frontier route is explicit while advanced still resolves Sol.""" catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", ["gpt-5.6-sol"], True, True, "connected"), routing.Catalog("anthropic", [], True, True, "connected"), ) assert catalog_resolver.resolve_model("codex", "auto-advanced", "xhigh", catalog) == "gpt-5.6-sol" with pytest.raises(ValueError, match="auto-frontier"): catalog_resolver.resolve_model("codex", "auto-frontier", "xhigh", catalog) def test_verified_evaluation_routes_an_unfamiliar_model_without_name_rules(): """Only a current, positive evaluation may classify an ambiguous live model.""" catalog = routing.build_routing_catalog( routing.Catalog("openai-codex", ["gpt-9-mystery"], True, True, "connected"), routing.Catalog("anthropic", [], True, True, "connected"), evaluations={"evaluations": {"codex": {"gpt-9-mystery": { "proposed_role": "frontier", "result": "pass", "role_fit": "verified", "eval_version": "capability-v1", "metadata_fingerprint": metadata_fingerprint("gpt-9-mystery", {}), }}}}, ) assert catalog_resolver.resolve_model("codex", "auto-frontier", "high", catalog) == "gpt-9-mystery" assert catalog["providers"]["codex"]["candidates"]["gpt-9-mystery"]["reason"] == "bounded-representative-eval-v1" def test_live_removal_clears_legacy_selector_instead_of_mapping_to_new_family(): """A live authoritative list cannot revive removed legacy selectors.""" previous = { "providers": { "codex": { "models": ["gpt-5.6-sol"], "resolved": {effort: "gpt-5.6-sol" for effort in routing.EFFORTS}, "tiers": {"sol": "gpt-5.6-sol", "advanced": "gpt-5.6-sol"}, } } } codex = routing.Catalog( "openai-codex", ["gpt-6.2-astra"], True, True, "connected", {"gpt-6.2-astra": {"capability_tier": "advanced"}}, ) claude = routing.Catalog("anthropic", [], False, True, "degraded") catalog = routing.build_routing_catalog(codex, claude, previous) assert catalog["providers"]["codex"]["tiers"]["sol"] == "" assert catalog["providers"]["codex"]["resolved"]["xhigh"] == "" def test_degraded_catalog_preserves_lkg_after_live_removal(): """A provider outage retains the prior route and does not treat it as removal.""" previous = { "providers": { "codex": { "models": ["gpt-5.6-sol"], "resolved": {effort: "gpt-5.6-sol" for effort in routing.EFFORTS}, "tiers": {"sol": "gpt-5.6-sol"}, "model_metadata": {}, } } } codex = routing.Catalog("openai-codex", [], False, True, "degraded") claude = routing.Catalog("anthropic", [], False, True, "degraded") catalog = routing.build_routing_catalog(codex, claude, previous) assert catalog["providers"]["codex"]["resolved"]["xhigh"] == "gpt-5.6-sol" assert catalog["providers"]["codex"]["tiers"]["sol"] == "gpt-5.6-sol" def test_explicit_legacy_selector_never_maps_to_astra(): """The old sol selector is exact and cannot silently follow a new family.""" catalog = { "providers": { "codex": { "tiers": {"sol": "gpt-6.2-astra"}, "resolved": {"xhigh": "gpt-6.2-astra"}, } } } assert catalog_resolver.resolve_model("codex", "sol", "xhigh", catalog) == ( "gpt-5.6-sol" ) def test_live_catalog_never_routes_to_a_removed_model_tier(): """A live provider catalog must replace a retired tier with a live model.""" previous = { "providers": { "codex": { "models": ["gpt-5.6-luna", "gpt-5.6-terra", "gpt-5.6-sol"], "resolved": { "low": "gpt-5.6-luna", "medium": "gpt-5.6-terra", "high": "gpt-5.6-sol", "xhigh": "gpt-5.6-sol", }, "tiers": { "luna": "gpt-5.6-luna", "terra": "gpt-5.6-terra", "sol": "gpt-5.6-sol", }, } } } codex = routing.Catalog( "openai-codex", ["gpt-5.7-terra", "gpt-5.7-sol"], True, True, "connected" ) claude = routing.Catalog("anthropic", ["claude-sonnet-6"], True, True, "connected") current = routing.build_routing_catalog(codex, claude, previous) assert current["providers"]["codex"]["tiers"]["luna"] == "" assert current["providers"]["claude"]["tiers"]["opus"] == "" def test_switchyard_targets_have_unique_upstream_identities(): """Switchyard drops duplicate client/model pairs, so reject them in Git.""" manifest = yaml.safe_load( (SCRIPT.parents[1] / "switchyard-configmap.yaml").read_text(encoding="utf-8") ) config = tomllib.loads(manifest["data"]["routes.toml"]) target_names = set(config["targets"]) identities: set[tuple[str, str]] = set() for target in config["targets"].values(): identity = (target["llm_client"], target["id"]) assert identity not in identities identities.add(identity) for route in config["routes"].values(): for target_name in route.get("targets", []): assert target_name in target_names if route.get("target"): assert route["target"] in target_names def test_worker_alias_resolves_before_cli_launch(): document = { "providers": { "codex": { "resolved": {"high": "gpt-5.8-sol"}, "tiers": {"sol": "gpt-5.8-sol"}, } } } assert ( catalog_resolver.resolve_worker_route("worker/codex/auto/high", document) == "worker/codex/gpt-5.8-sol/high" ) def test_codex_cli_login_counts_as_connected_runtime(monkeypatch): """AUTO routing must recognize the authenticated app-server CLI lane.""" monkeypatch.setattr(routing.shutil, "which", lambda name: "/usr/bin/codex") monkeypatch.setattr( routing.subprocess, "run", lambda *args, **kwargs: subprocess.CompletedProcess( args[0], 0, stdout="Logged in using ChatGPT\n", stderr="", ), ) assert routing.codex_cli_authenticated() is True def test_configure_routes_keeps_every_profile_on_switchyard(tmp_path: Path): (tmp_path / "config.yaml").write_text( yaml.safe_dump(_base_config()), encoding="utf-8" ) (tmp_path / ".env").write_text( "API_SERVER_KEY=keep-root-only\n" "CLAUDE_CODE_OAUTH_TOKEN=claude-secret\n" "GITEA_TOKEN=gitea-secret\n" "GIT_ASKPASS=/opt/coordinator/gitea_askpass.sh\n", encoding="utf-8", ) stale_profile = tmp_path / "profiles/codex-high" stale_profile.mkdir(parents=True) (stale_profile / ".env").write_text( "CLAUDE_CODE_OAUTH_TOKEN=stale-claude\n" "GITEA_TOKEN=stale-gitea\n" "HERMES_IMAGE_BROKER_KEY=stale-relay\n" "USER_SETTING=preserve\n", encoding="utf-8", ) codex = routing.Catalog( "openai-codex", ["gpt-5.6-sol", "gpt-5.6-terra"], True, True, "connected" ) claude = routing.Catalog( "anthropic", ["claude-sonnet-5", "claude-opus-5"], True, True, "connected" ) routes = routing.configure_routes(tmp_path, codex, claude) root = yaml.safe_load((tmp_path / "config.yaml").read_text(encoding="utf-8")) codex_profile = yaml.safe_load( (tmp_path / "profiles/codex-high/config.yaml").read_text(encoding="utf-8") ) codex_xhigh_profile = yaml.safe_load( (tmp_path / "profiles/codex-xhigh/config.yaml").read_text(encoding="utf-8") ) claude_profile = yaml.safe_load( (tmp_path / "profiles/claude-high/config.yaml").read_text(encoding="utf-8") ) assert root["model"] == { "provider": "atlas-switchyard", "default": "atlas/auto/maximum", "model": "atlas/auto/maximum", } assert root["fallback_providers"] == [] assert root["toolsets"] == ["kanban"] assert codex_profile["model"]["model"] == "atlas/manual/codex/auto/high" assert codex_profile["model"]["provider"] == "atlas-switchyard" assert claude_profile["model"]["model"] == "atlas/manual/claude/auto/high" assert claude_profile["model"]["provider"] == "atlas-switchyard" assert codex_profile["fallback_providers"] == [] assert claude_profile["fallback_providers"] == [] assert codex_profile["toolsets"] == [] assert codex_profile["agent"]["reasoning_effort"] == "high" assert codex_xhigh_profile["fallback_providers"] == [] assert routes["codex-xhigh"] == ["atlas/manual/codex/auto/xhigh"] assert routes["claude-xhigh"] == ["atlas/manual/claude/auto/xhigh"] assert routes["synthesis-xhigh"] == ["atlas/auto/maximum"] assert routes["coordinator"] == ["atlas/auto/maximum"] assert all( "max" not in profile_name for profile_name in routes if profile_name != "catalog" ) profile_env = (tmp_path / "profiles/codex-high/.env").read_text(encoding="utf-8") assert "CLAUDE_CODE_OAUTH_TOKEN" not in profile_env assert "GITEA_TOKEN" not in profile_env assert "HERMES_IMAGE_BROKER_KEY" not in profile_env assert "API_SERVER_KEY" not in profile_env assert "USER_SETTING=preserve" in profile_env assert "claude-secret" not in json.dumps(routes) assert (tmp_path / "profiles/codex-high/.env").stat().st_mode & 0o777 == 0o600 def test_degraded_catalog_does_not_replace_switchyard_authority(tmp_path: Path): base = _base_config() base["model"]["model"] = base["model"]["default"] = "gpt-5.6-sol" (tmp_path / "config.yaml").write_text(yaml.safe_dump(base), encoding="utf-8") (tmp_path / ".env").write_text("", encoding="utf-8") codex = routing.Catalog("openai-codex", ["gpt-5.4"], False, True, "degraded") claude = routing.Catalog("anthropic", ["claude-haiku-4.5"], False, True, "degraded") routing.configure_routes(tmp_path, codex, claude) current = yaml.safe_load((tmp_path / "config.yaml").read_text(encoding="utf-8")) assert current["model"]["model"] == "atlas/auto/maximum" assert current["model"]["provider"] == "atlas-switchyard" assert current["fallback_providers"] == [] def test_degraded_refresh_preserves_switchyard_worker_preference(tmp_path: Path): """A catalog outage must not bypass a managed worker's Switchyard route.""" (tmp_path / "config.yaml").write_text( yaml.safe_dump(_base_config()), encoding="utf-8" ) (tmp_path / ".env").write_text("", encoding="utf-8") live_codex = routing.Catalog( "openai-codex", ["gpt-5.6-sol", "gpt-5.6-terra"], True, True, "connected" ) live_claude = routing.Catalog( "anthropic", ["claude-opus-5"], True, True, "connected" ) routing.configure_routes(tmp_path, live_codex, live_claude) degraded_codex = routing.Catalog( "openai-codex", ["gpt-5.4"], False, True, "degraded" ) routing.configure_routes(tmp_path, degraded_codex, live_claude) worker = yaml.safe_load( (tmp_path / "profiles/codex-high/config.yaml").read_text(encoding="utf-8") ) assert worker["model"]["model"] == "atlas/manual/codex/auto/high" assert worker["model"]["provider"] == "atlas-switchyard" def test_refresh_writes_non_secret_routing_status(tmp_path: Path, monkeypatch): (tmp_path / "config.yaml").write_text( yaml.safe_dump(_base_config()), encoding="utf-8" ) (tmp_path / ".env").write_text("GITEA_TOKEN=do-not-report\n", encoding="utf-8") codex = routing.Catalog("openai-codex", ["gpt-5.6-terra"], True, True, "connected") claude = routing.Catalog("anthropic", ["claude-opus-5"], True, True, "connected") monkeypatch.setattr(coordinator, "discover_codex_models", lambda: codex) monkeypatch.setattr(coordinator, "discover_claude_models", lambda: claude) monkeypatch.setattr( coordinator, "bootstrap_cassandra_state", lambda root: {"state": "ready"} ) monkeypatch.setattr(coordinator, "sync_cassandra_repo", lambda env: "ready") status = coordinator.refresh_once(tmp_path) status_path = tmp_path / "workspace/coordinator/model-routing.json" assert status_path.is_file() assert status["projects"]["cassandra"]["state"] == "ready" assert status["projects"]["cassandra"]["board_state"] == {"state": "ready"} assert "do-not-report" not in status_path.read_text(encoding="utf-8")