from __future__ import annotations from opensquilla.health.evaluator import ( evaluate_channels, evaluate_image_generation, evaluate_logs, evaluate_memory, evaluate_memory_embedding, evaluate_provider, evaluate_router, evaluate_sandbox, evaluate_search, evaluate_squilla_router_runtime, ) def _impact(finding) -> str: return finding.to_dict()["readinessImpact"] def test_readiness_impact_matrix_matches_user_visible_strategy() -> None: provider = evaluate_provider( { "activeProvider": "openrouter", "providers": [ { "providerId": "openrouter", "active": True, "configured": False, "buildable": True, } ], } )[0] assert provider.id == "provider.active.not_configured" assert _impact(provider) == "blocks_ready" router_required = evaluate_router( { "enabled": True, "rolloutPhase": "full", "runtimeValid": False, "requireRouterRuntime": True, } )[0] assert router_required.id == "router.runtime.missing" assert _impact(router_required) == "blocks_ready" memory = evaluate_memory({"backend": "sqlite", "status": "unavailable"})[0] assert memory.id == "memory.status.error" assert _impact(memory) == "degrades" logs = evaluate_logs( { "gateway_file_log": { "enabled": True, "path": "/tmp/missing-debug.log", "exists": False, "active_tail_path_exists": False, } } )[0] assert logs.id == "logs.gateway_file_log.missing" assert _impact(logs) == "degrades" search = evaluate_search( { "provider": "brave", "activeProvider": "brave", "configured": False, "runtimeSupported": True, "requiresApiKey": True, "apiKeyConfigured": False, "buildable": False, } )[0] assert search.id == "search.provider.not_configured" assert _impact(search) == "degrades" image = evaluate_image_generation( { "enabled": True, "configured": False, "status": "missing", "provider": "openai", "primary": "openai/gpt-image-1", } )[0] assert image.id == "image_generation.credentials.missing" assert _impact(image) == "degrades" channel = evaluate_channels( {"channels": [{"name": "feishu", "enabled": True, "status": "dead"}]} )[0] assert channel.id == "channel.feishu.dead" assert _impact(channel) == "degrades" no_channels = evaluate_channels({"channels": []})[0] assert no_channels.id == "channels.none_configured" assert _impact(no_channels) == "optional" sandbox = evaluate_sandbox({"posture": "bypass"})[0] assert sandbox.id == "sandbox.posture.bypass" assert _impact(sandbox) == "optional" router_optional = evaluate_router( {"enabled": False, "runtimeValid": False, "requireRouterRuntime": False} )[0] assert router_optional.id == "router.disabled" assert _impact(router_optional) == "optional" def test_provider_evaluator_flags_active_provider_missing_key() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [ { "providerId": "openrouter", "active": True, "configured": False, "buildable": True, "apiKeyConfigured": False, "model": "openai/gpt-5.1", } ], } ) assert findings[0].id == "provider.active.not_configured" assert findings[0].severity == "error" assert findings[0].restart_required is True assert "opensquilla providers configure openrouter" in findings[0].fix_steps[0].command def test_provider_evaluator_explains_missing_configured_api_key_env() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [ { "providerId": "openrouter", "active": True, "configured": False, "buildable": True, "requiresApiKey": True, "apiKeyConfigured": False, "apiKeyEnv": "OPENSQUILLA_PROVIDER_KEY", "model": "openai/gpt-5.1", } ], } ) finding = findings[0] assert finding.id == "provider.active.not_configured" assert finding.evidence["apiKeyEnv"] == "OPENSQUILLA_PROVIDER_KEY" assert "OPENSQUILLA_PROVIDER_KEY" in finding.detail assert any( step.detail and "OPENSQUILLA_PROVIDER_KEY" in step.detail for step in finding.fix_steps ) def test_provider_evaluator_uses_configured_active_provider_when_missing_row() -> None: findings = evaluate_provider( { "activeProvider": "zhipu", "providers": [ { "providerId": "zhipu", "active": False, "configured": False, "buildable": False, } ], } ) assert findings[0].id == "provider.active.missing" assert findings[0].evidence["activeProvider"] == "zhipu" assert findings[0].fix_steps[0].command == ( "opensquilla providers configure zhipu --api-key YOUR_API_KEY" ) def test_provider_evaluator_reports_missing_diagnostic_shape_as_incomplete() -> None: findings = evaluate_provider({}) assert findings[0].id == "provider.diagnostic.incomplete" assert findings[0].severity == "error" assert _impact(findings[0]) == "blocks_ready" assert "providers" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla providers status --json", "opensquilla gateway restart", ] def test_provider_evaluator_flags_unknown_active_provider() -> None: findings = evaluate_provider( { "activeProvider": "zai", "providers": [ {"providerId": "openrouter", "active": False}, {"providerId": "zhipu", "active": False}, ], } ) assert findings[0].id == "provider.active.unknown" assert findings[0].severity == "error" assert findings[0].evidence["activeProvider"] == "zai" commands = [step.command for step in findings[0].fix_steps] assert "opensquilla providers list --json" in commands assert "opensquilla providers configure zhipu --api-key YOUR_API_KEY" in commands assert "opensquilla providers configure zai --api-key YOUR_API_KEY" not in commands def test_provider_evaluator_reports_ready_active_provider() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [ { "providerId": "openrouter", "active": True, "configured": True, "buildable": True, "apiKeyConfigured": True, "baseUrlConfigured": True, "model": "openai/gpt-5.1", } ], } ) assert findings[0].id == "provider.active.ready" assert findings[0].severity == "ok" def _healthy_active_row(**extra: object) -> dict[str, object]: row: dict[str, object] = { "providerId": "openrouter", "active": True, "configured": True, "buildable": True, "apiKeyConfigured": True, "baseUrlConfigured": True, "model": "openai/gpt-5.1", } row.update(extra) return row def test_provider_evaluator_warns_on_url_shaped_api_key() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [_healthy_active_row(apiKeyShape="looks_like_url")], } ) assert len(findings) == 1 finding = findings[0] assert finding.id == "provider.active.api_key_shape" assert finding.severity == "warn" assert _impact(finding) == "degrades" assert finding.evidence == {"providerId": "openrouter", "shape": "looks_like_url"} assert "verbatim as the request credential" in finding.detail assert "401" in finding.detail assert ( "opensquilla providers configure openrouter --api-key YOUR_API_KEY" in [step.command for step in finding.fix_steps] ) assert any( step.detail and "Settings" in step.detail and "Chat Model" in step.detail for step in finding.fix_steps ) def test_provider_evaluator_warns_on_env_name_shaped_api_key() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [_healthy_active_row(apiKeyShape="looks_like_env_name")], } ) assert len(findings) == 1 finding = findings[0] assert finding.id == "provider.active.api_key_shape" assert finding.severity == "warn" assert finding.evidence == { "providerId": "openrouter", "shape": "looks_like_env_name", } assert "environment variable NAME" in finding.detail def test_provider_evaluator_ok_api_key_shape_stays_ready() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [_healthy_active_row(apiKeyShape="ok")], } ) assert len(findings) == 1 assert findings[0].id == "provider.active.ready" assert findings[0].severity == "ok" def test_provider_evaluator_missing_api_key_shape_stays_ready() -> None: """Old payloads / offline doctor rows without apiKeyShape behave as today.""" findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [_healthy_active_row()], } ) assert len(findings) == 1 assert findings[0].id == "provider.active.ready" assert findings[0].severity == "ok" def test_provider_evaluator_shape_warning_never_carries_key_material() -> None: findings = evaluate_provider( { "activeProvider": "openrouter", "providers": [_healthy_active_row(apiKeyShape="looks_like_url")], } ) rendered = repr(findings[0].to_dict()) assert "https://" not in rendered assert "OPENROUTER_API_KEY=" not in rendered def test_provider_evaluator_does_not_report_unidentified_active_row_as_ready() -> None: findings = evaluate_provider( { "activeProvider": "", "providers": [ { "active": True, "configured": True, "buildable": True, "apiKeyConfigured": True, "model": "openai/gpt-5.1", } ], } ) assert findings[0].id == "provider.active.unidentified" assert findings[0].severity == "error" assert _impact(findings[0]) == "blocks_ready" assert "did not include a provider id" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla providers status --json", "opensquilla providers configure openrouter --api-key YOUR_API_KEY", "opensquilla gateway restart", ] def test_memory_evaluator_flags_degraded_backend() -> None: findings = evaluate_memory( { "backend": "sqlite", "status": "degraded", "vecAvailable": False, "ftsAvailable": True, "pendingRepairCount": 2, } ) ids = [finding.id for finding in findings] assert "memory.status.degraded" in ids assert "memory.repair.pending" in ids def test_memory_evaluator_does_not_report_unknown_status_as_ready() -> None: findings = evaluate_memory({"backend": "sqlite", "status": "unknown"}) assert findings[0].id == "memory.status.unknown" assert findings[0].severity == "warn" assert findings[0].fix_steps[0].command == "opensquilla memory status --deep --json" def test_memory_evaluator_treats_missing_status_as_incomplete() -> None: findings = evaluate_memory({"backend": "sqlite"}) assert findings[0].id == "memory.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "status" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla memory status --deep --json", "opensquilla gateway restart", ] def test_memory_repair_guidance_uses_existing_cli_options() -> None: findings = evaluate_memory( { "backend": "sqlite", "status": "ok", "pendingRepairCount": 2, } ) repair = next(finding for finding in findings if finding.id == "memory.repair.pending") commands = [step.command for step in repair.fix_steps] assert "opensquilla memory repair run --json" in commands assert "opensquilla memory repair run --yes" not in commands def test_memory_repair_guidance_accepts_pending_repairs_alias() -> None: findings = evaluate_memory( { "backend": "sqlite", "status": "ok", "pendingRepairs": 2, } ) assert any(finding.id == "memory.repair.pending" for finding in findings) def test_logs_evaluator_flags_missing_debug_log_path() -> None: findings = evaluate_logs( { "gateway_file_log": { "enabled": True, "path": "/tmp/missing-debug.log", "exists": False, "active_tail_path_exists": False, }, "raw_turn_call_log": { "enabled": False, "directory": {"path": "/tmp/raw", "exists": False}, }, "diagnostics_enabled": {"effective": False, "detail": "off"}, } ) assert findings[0].id == "logs.gateway_file_log.missing" assert findings[0].severity == "warn" commands = [step.command for step in findings[0].fix_steps] assert "opensquilla diagnostics status" in commands assert "opensquilla gateway restart" in commands assert "opensquilla logs tail" not in commands def test_logs_evaluator_does_not_treat_missing_diagnostic_shape_as_optional() -> None: findings = evaluate_logs({}) assert findings[0].id == "logs.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "Log diagnostics did not include gateway_file_log" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla diagnostics status", "opensquilla gateway restart", ] def test_optional_surface_evaluators_do_not_treat_missing_diagnostic_shape_as_optional() -> None: cases = [ ("search", evaluate_search, "search.diagnostic.incomplete"), ("image_generation", evaluate_image_generation, "image_generation.diagnostic.incomplete"), ("router", evaluate_router, "router.diagnostic.incomplete"), ( "memory_embedding", evaluate_memory_embedding, "memory_embedding.diagnostic.incomplete", ), ("channels", evaluate_channels, "channels.diagnostic.incomplete"), ] for surface, evaluator, finding_id in cases: findings = evaluator({}) assert findings[0].id == finding_id, surface assert findings[0].severity == "warn", surface assert _impact(findings[0]) == "degrades", surface assert "diagnostics did not include" in findings[0].detail def test_search_evaluator_treats_partial_provider_diagnostic_as_incomplete() -> None: findings = evaluate_search({"provider": "duckduckgo", "activeProvider": "duckduckgo"}) assert findings[0].id == "search.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "runtimeSupported" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla search status --json", "opensquilla gateway restart", ] def test_logs_evaluator_treats_disabled_file_logging_as_optional_setup() -> None: findings = evaluate_logs( { "gateway_file_log": { "enabled": False, "path": "/tmp/opensquilla-debug.log", "exists": False, } } ) assert len(findings) == 1 assert findings[0].id == "logs.gateway_file_log.disabled" assert findings[0].severity == "info" assert _impact(findings[0]) == "optional" assert "Persistent gateway file logging is optional" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla config set log_file_enabled true", "opensquilla gateway restart", ] assert findings[0].restart_required is True def test_channels_evaluator_flags_dead_enabled_channel() -> None: findings = evaluate_channels( { "channels": [ { "name": "slack-main", "type": "slack", "enabled": True, "configured": True, "status": "dead", "connected": False, } ] } ) assert findings[0].id == "channel.slack-main.dead" assert findings[0].severity == "error" assert findings[0].fix_steps[0].command == "opensquilla channels restart slack-main --yes" def test_channels_evaluator_flags_stopped_enabled_channel() -> None: findings = evaluate_channels( { "channels": [ { "name": "slack-main", "type": "slack", "enabled": True, "configured": True, "status": "stopped", "connected": False, } ] } ) assert findings[0].id == "channel.slack-main.stopped" assert findings[0].severity == "warn" commands = [step.command for step in findings[0].fix_steps] assert "opensquilla channels status slack-main --json" in commands assert "opensquilla channels restart slack-main --yes" in commands def test_channels_evaluator_quotes_channel_names_in_recovery_commands() -> None: findings = evaluate_channels( { "channels": [ { "name": "feishu work", "type": "feishu", "enabled": True, "configured": True, "status": "dead", "connected": False, } ] } ) commands = [step.command for step in findings[0].fix_steps] assert "opensquilla channels restart 'feishu work' --yes" in commands assert "opensquilla channels status 'feishu work' --json" in commands def test_channels_evaluator_treats_disabled_channel_as_optional_info() -> None: findings = evaluate_channels( { "channels": [ { "name": "slack-main", "type": "slack", "enabled": False, "configured": True, "status": "disabled", "connected": False, } ] } ) assert findings[0].id == "channel.slack-main.disabled" assert findings[0].severity == "info" assert findings[0].restart_required is True commands = [step.command for step in findings[0].fix_steps] assert "opensquilla channels enable slack-main" in commands assert "opensquilla configure --section channels" not in commands def test_channels_evaluator_treats_no_channels_as_optional_setup() -> None: findings = evaluate_channels({"channels": []}) assert len(findings) == 1 assert findings[0].id == "channels.none_configured" assert findings[0].severity == "info" assert _impact(findings[0]) == "optional" assert "No channel entrypoints are configured" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla configure --section channels" ] def test_channels_evaluator_treats_malformed_channels_shape_as_incomplete() -> None: findings = evaluate_channels({"channels": {"name": "slack-main"}}) assert findings[0].id == "channels.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "channels" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla channels status --json", "opensquilla gateway restart", ] def test_channels_evaluator_treats_malformed_channel_rows_as_incomplete() -> None: findings = evaluate_channels({"channels": ["slack-main"]}) assert findings[0].id == "channels.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "channel rows" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla channels status --json", "opensquilla gateway restart", ] def test_channels_evaluator_ready_finding_summarizes_checked_channels() -> None: findings = evaluate_channels( { "channels": [ { "name": "slack-main", "type": "slack", "enabled": True, "configured": True, "status": "connected", "connected": True, }, { "name": "feishu-main", "type": "feishu", "enabled": True, "configured": True, "status": "connected", "connected": True, }, ] } ) assert len(findings) == 1 assert findings[0].id == "channels.ready" assert findings[0].severity == "ok" assert "2 configured channel entrypoints" in findings[0].detail assert findings[0].evidence == { "channelCount": 2, "enabledCount": 2, "statuses": {"connected": 2}, "types": ["feishu", "slack"], } def test_channels_evaluator_does_not_report_unknown_enabled_status_as_ready() -> None: findings = evaluate_channels( { "channels": [ { "name": "slack-main", "type": "slack", "enabled": True, "configured": True, "status": "warming_up", "connected": False, } ] } ) assert len(findings) == 1 assert findings[0].id == "channel.slack-main.unknown_status" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "not recognized" in findings[0].detail assert findings[0].evidence == { "name": "slack-main", "status": "warming_up", "type": "slack", } assert [step.command for step in findings[0].fix_steps] == [ "opensquilla channels status slack-main --json", "opensquilla channels restart slack-main --yes", ] def test_sandbox_evaluator_surfaces_bypass_posture_as_info() -> None: findings = evaluate_sandbox( { "posture": "bypass", "sandbox": {"sandbox": False, "security_grading": False}, "permissions": {"default_mode": "bypass"}, "restart_required": False, } ) assert findings[0].id == "sandbox.posture.bypass" assert findings[0].severity == "info" assert findings[0].restart_required is True assert "restart_required" not in findings[0].evidence assert "opensquilla sandbox on" in findings[0].fix_steps[0].command def test_sandbox_evaluator_does_not_report_unknown_posture_as_ready() -> None: findings = evaluate_sandbox( { "posture": "unknown", "sandbox": {"sandbox": False, "security_grading": False}, "permissions": {"default_mode": "unknown"}, } ) assert findings[0].id == "sandbox.posture.unknown" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert findings[0].fix_steps[0].command == "opensquilla sandbox status --json" def test_sandbox_evaluator_does_not_report_custom_posture_as_ready() -> None: findings = evaluate_sandbox( { "posture": "custom", "sandbox": {"sandbox": True, "security_grading": False}, "permissions": {"default_mode": "full"}, } ) assert findings[0].id == "sandbox.posture.custom" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert findings[0].restart_required is True assert [step.command for step in findings[0].fix_steps] == [ "opensquilla sandbox status --json", "opensquilla sandbox on", "opensquilla gateway restart", ] def test_search_evaluator_flags_missing_key_without_blocking_core_runtime() -> None: findings = evaluate_search( { "provider": "brave", "activeProvider": "brave", "configured": False, "runtimeSupported": True, "requiresApiKey": True, "apiKeyConfigured": False, "buildable": False, "fallbackPolicy": "off", } ) assert findings[0].id == "search.provider.not_configured" assert findings[0].severity == "warn" assert "opensquilla configure search" in findings[0].fix_steps[0].command def test_search_evaluator_explains_missing_configured_api_key_env() -> None: findings = evaluate_search( { "activeProvider": "brave", "provider": "brave", "configured": False, "runtimeSupported": True, "requiresApiKey": True, "apiKeyConfigured": False, "apiKeyEnv": "CUSTOM_SEARCH_KEY", "buildable": False, } ) finding = findings[0] assert finding.id == "search.provider.not_configured" assert finding.evidence["apiKeyEnv"] == "CUSTOM_SEARCH_KEY" assert "CUSTOM_SEARCH_KEY" in finding.detail assert any( step.detail and "CUSTOM_SEARCH_KEY" in step.detail for step in finding.fix_steps ) def test_search_evaluator_treats_empty_provider_as_optional_setup() -> None: findings = evaluate_search( { "provider": "", "activeProvider": "", "configured": False, "runtimeSupported": False, "requiresApiKey": False, "apiKeyConfigured": False, "buildable": False, "fallbackPolicy": "off", } ) assert findings[0].id == "search.provider.disabled" assert findings[0].severity == "info" assert _impact(findings[0]) == "optional" assert "not configured" in findings[0].detail assert findings[0].restart_required is True assert [step.command for step in findings[0].fix_steps] == [ "opensquilla configure search --search-provider duckduckgo", "opensquilla gateway restart", ] def test_search_evaluator_flags_unknown_provider_with_supported_fallback() -> None: findings = evaluate_search( { "provider": "serpapi", "activeProvider": "serpapi", "unknownProvider": True, "configured": False, "runtimeSupported": False, "requiresApiKey": False, "apiKeyConfigured": False, "buildable": False, "error": "Unknown search provider 'serpapi'", } ) assert findings[0].id == "search.provider.unknown" assert findings[0].severity == "warn" commands = [step.command for step in findings[0].fix_steps] assert "opensquilla search list --json" in commands assert "opensquilla configure search --search-provider duckduckgo" in commands assert all("serpapi" not in command for command in commands) def test_search_evaluator_reports_ready_provider() -> None: findings = evaluate_search( { "provider": "duckduckgo", "activeProvider": "duckduckgo", "configured": True, "runtimeSupported": True, "requiresApiKey": False, "apiKeyConfigured": False, "buildable": True, "fallbackPolicy": "off", "maxResults": 8, "proxyConfigured": True, "useEnvProxy": False, "diagnostics": True, } ) assert findings[0].id == "search.provider.ready" assert findings[0].severity == "ok" assert findings[0].evidence["maxResults"] == 8 assert findings[0].evidence["proxyConfigured"] is True assert findings[0].evidence["diagnostics"] is True def test_image_generation_evaluator_treats_disabled_as_optional_info() -> None: findings = evaluate_image_generation( { "enabled": False, "configured": False, "status": "optional", "provider": "", "primary": "openai/gpt-image-1", "source": "none", } ) assert findings[0].id == "image_generation.disabled" assert findings[0].severity == "info" assert findings[0].restart_required is True assert [step.command for step in findings[0].fix_steps] == [ "opensquilla configure image-generation --image-provider openai --api-key YOUR_API_KEY", "opensquilla gateway restart", ] def test_image_generation_evaluator_treats_partial_enabled_diagnostic_as_incomplete() -> None: findings = evaluate_image_generation({"enabled": True, "provider": "openai"}) assert findings[0].id == "image_generation.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "configured" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla onboard status --json", "opensquilla gateway restart", ] def test_image_generation_evaluator_flags_enabled_missing_credentials() -> None: findings = evaluate_image_generation( { "enabled": True, "configured": False, "status": "missing", "provider": "openai", "primary": "openai/gpt-image-1", "source": "none", } ) assert findings[0].id == "image_generation.credentials.missing" assert findings[0].severity == "warn" assert "opensquilla configure image-generation" in findings[0].fix_steps[0].command def test_image_generation_evaluator_explains_missing_configured_api_key_env() -> None: findings = evaluate_image_generation( { "enabled": True, "configured": False, "status": "degraded", "provider": "openrouter", "primary": "openrouter/google/gemini-3.1-flash-image-preview", "source": "none", "apiKeyEnv": "CUSTOM_IMAGE_KEY", } ) finding = findings[0] assert finding.id == "image_generation.credentials.missing" assert finding.evidence["apiKeyEnv"] == "CUSTOM_IMAGE_KEY" assert "CUSTOM_IMAGE_KEY" in finding.detail assert any( step.detail and "CUSTOM_IMAGE_KEY" in step.detail for step in finding.fix_steps ) def test_image_generation_unknown_provider_uses_supported_default_recovery() -> None: findings = evaluate_image_generation( { "enabled": True, "configured": False, "status": "unknown", "provider": "", "primary": "foo/image-model", "source": "none", } ) assert findings[0].id == "image_generation.provider.unknown" commands = [step.command for step in findings[0].fix_steps] assert ( "opensquilla configure image-generation --image-provider openai --api-key YOUR_API_KEY" in commands ) assert all("--image-provider foo" not in command for command in commands) def test_router_evaluator_treats_disabled_router_as_optional_info() -> None: findings = evaluate_router( { "enabled": False, "rolloutPhase": "observe", "strategy": "v4_phase3", "tierProfile": "openrouter", "runtimeValid": True, "requireRouterRuntime": False, } ) assert findings[0].id == "router.disabled" assert findings[0].severity == "info" assert findings[0].restart_required is True def test_router_evaluator_treats_partial_enabled_diagnostic_as_incomplete() -> None: findings = evaluate_router({"enabled": True}) assert findings[0].id == "router.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "runtimeValid" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla diagnostics status", "opensquilla gateway restart", ] def test_router_evaluator_marks_observe_only_recovery_as_restart_required() -> None: findings = evaluate_router( { "enabled": True, "rolloutPhase": "observe", "strategy": "v4_phase3", "tierProfile": "openrouter", "runtimeValid": True, "requireRouterRuntime": False, } ) assert findings[0].id == "router.observe_only" assert findings[0].severity == "info" assert findings[0].restart_required is True def test_router_evaluator_does_not_treat_unknown_rollout_phase_as_optional() -> None: findings = evaluate_router( { "enabled": True, "rolloutPhase": "mystery", "strategy": "v4_phase3", "tierProfile": "openrouter", "runtimeValid": True, "requireRouterRuntime": False, } ) assert findings[0].id == "router.rollout_phase.unknown" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "mystery" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla configure router --router recommended", "opensquilla gateway restart", ] def test_router_evaluator_flags_required_missing_runtime_as_action_required() -> None: findings = evaluate_router( { "enabled": True, "rolloutPhase": "full", "strategy": "v4_phase3", "tierProfile": "openrouter", "runtimeValid": False, "requireRouterRuntime": True, "error": "missing V4 bundle files", } ) assert findings[0].id == "router.runtime.missing" assert findings[0].severity == "error" assert "opensquilla configure router --router disabled" in findings[0].fix_steps[0].command def test_router_evaluator_gives_macos_libomp_recovery() -> None: findings = evaluate_router( { "enabled": True, "rolloutPhase": "full", "strategy": "v4_phase3", "tierProfile": "openrouter", "runtimeValid": False, "requireRouterRuntime": True, "runtimeErrorKind": "macos_libomp_missing", "error": "Library not loaded: @rpath/libomp.dylib", } ) finding = findings[0] assert finding.id == "router.runtime.missing" assert finding.severity == "error" assert finding.title == "Router native dependency is missing" assert "libomp.dylib" in finding.detail assert finding.evidence["runtimeErrorKind"] == "macos_libomp_missing" assert [step.command for step in finding.fix_steps] == [ "brew install libomp", "opensquilla gateway restart", "opensquilla configure router --router disabled", ] def test_memory_embedding_evaluator_flags_explicit_remote_without_key() -> None: findings = evaluate_memory_embedding( { "status": "error", "requestedProvider": "openai", "effectiveProvider": "none", "model": "text-embedding-3-small", "retrievalMode": "hybrid", "error": "memory.embedding.remote.api_key is required", } ) assert findings[0].id == "memory_embedding.config.error" assert findings[0].severity == "warn" assert "opensquilla configure memory-embedding" in findings[0].fix_steps[0].command def test_memory_embedding_evaluator_treats_config_error_status_as_repairable() -> None: findings = evaluate_memory_embedding( { "status": "config_error", "requestedProvider": "openai", "effectiveProvider": None, "model": "text-embedding-3-small", "retrievalMode": "hybrid", "error": "missing", } ) assert findings[0].id == "memory_embedding.config.error" assert findings[0].severity == "warn" def test_memory_embedding_evaluator_treats_fts_fallback_as_optional_info() -> None: findings = evaluate_memory_embedding( { "status": "fts_only", "requestedProvider": "auto", "effectiveProvider": "none", "model": "fts-only", "retrievalMode": "hybrid", "reason": "local_unavailable", } ) assert findings[0].id == "memory_embedding.fts_only" assert findings[0].severity == "info" def test_memory_embedding_evaluator_treats_partial_ready_diagnostic_as_incomplete() -> None: findings = evaluate_memory_embedding({"status": "ok"}) assert findings[0].id == "memory_embedding.diagnostic.incomplete" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "effectiveProvider" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla memory status --deep --json", "opensquilla gateway restart", ] def test_memory_embedding_evaluator_does_not_report_unknown_status_as_ready() -> None: findings = evaluate_memory_embedding( { "status": "warming_up", "requestedProvider": "auto", "effectiveProvider": "local", "model": "bge-small", "retrievalMode": "hybrid", "reason": "local_available", } ) assert findings[0].id == "memory_embedding.status.unknown" assert findings[0].severity == "warn" assert _impact(findings[0]) == "degrades" assert "warming_up" in findings[0].detail assert [step.command for step in findings[0].fix_steps] == [ "opensquilla memory status --deep --json", "opensquilla gateway restart", ] def test_squilla_router_runtime_evaluator_silent_when_router_disabled() -> None: assert ( evaluate_squilla_router_runtime( {"enabled": False, "requireRouterRuntime": True} ) == [] ) def test_squilla_router_runtime_evaluator_silent_before_strategy_initializes() -> None: # Transient startup state: the gateway preloads the strategy in a # background boot task, so an uninitialized cache is not a failure. assert ( evaluate_squilla_router_runtime( { "enabled": True, "requireRouterRuntime": True, "initialized": False, "loaded": False, "code": None, "strategy": "unavailable", "error": None, } ) == [] ) def test_squilla_router_runtime_evaluator_reports_loaded_runtime_ok() -> None: findings = evaluate_squilla_router_runtime( { "enabled": True, "requireRouterRuntime": True, "initialized": True, "loaded": True, "code": None, "strategy": "v4_phase3", "error": None, } ) assert findings[0].id == "squilla_router.runtime.ready" assert findings[0].severity == "ok" assert _impact(findings[0]) == "none" assert findings[0].evidence["strategy"] == "v4_phase3" def test_squilla_router_runtime_evaluator_warns_when_required_runtime_failed() -> None: findings = evaluate_squilla_router_runtime( { "enabled": True, "requireRouterRuntime": True, "initialized": True, "loaded": False, "code": "macos_libomp_missing", "strategy": "heuristic", "error": "Library not loaded: @rpath/libomp.dylib", } ) finding = findings[0] assert finding.id == "squilla_router.runtime.unavailable" assert finding.severity == "warn" assert _impact(finding) == "degrades" assert finding.evidence["runtimeErrorKind"] == "macos_libomp_missing" assert 'routing source "heuristic"' in finding.detail assert "brew install libomp" in finding.detail assert finding.restart_required is True assert [step.command for step in finding.fix_steps] == [ "brew install libomp", "opensquilla gateway restart", "opensquilla configure router --router disabled", ] def test_squilla_router_runtime_evaluator_softens_to_info_when_flag_false() -> None: findings = evaluate_squilla_router_runtime( { "enabled": True, "requireRouterRuntime": False, "initialized": True, "loaded": False, "code": "router_python_dependency_missing", "strategy": "heuristic", "error": "No module named 'onnxruntime'", } ) finding = findings[0] assert finding.id == "squilla_router.runtime.unavailable" # Operator explicitly opted out of requiring the runtime: keep the state # visible, but do not degrade readiness. assert finding.severity == "info" assert _impact(finding) == "optional" assert finding.evidence["runtimeErrorKind"] == "router_python_dependency_missing" def test_squilla_router_runtime_evaluator_describes_default_tier_degradation() -> None: findings = evaluate_squilla_router_runtime( { "enabled": True, "requireRouterRuntime": True, "initialized": True, "loaded": False, "code": "router_runtime_unavailable", "strategy": "unavailable", "error": "synthetic failure", } ) finding = findings[0] assert finding.severity == "warn" assert "default tier" in finding.detail assert 'routing source "heuristic"' not in finding.detail