from __future__ import annotations from types import SimpleNamespace from jarvis.runtime_constants import ( VALID_BACKCHANNEL_STYLES, VALID_CONTROL_PRESETS, VALID_OPERATOR_AUTH_MODES, VALID_PERSONA_STYLES, VALID_VOICE_PROFILE_CONFIRMATIONS, VALID_VOICE_PROFILE_PACE, VALID_VOICE_PROFILE_TONE, VALID_VOICE_PROFILE_VERBOSITY, ) from jarvis.runtime_operator_status import normalize_operator_auth_mode, operator_auth_risk from jarvis.runtime_startup import operator_control_schema, startup_blockers, startup_summary_lines from jarvis.voice_attention import VALID_TIMEOUT_PROFILES, VALID_WAKE_MODES def test_operator_control_schema_exposes_expected_actions_and_enums() -> None: schema = operator_control_schema( valid_wake_modes=VALID_WAKE_MODES, valid_timeout_profiles=VALID_TIMEOUT_PROFILES, valid_persona_styles=VALID_PERSONA_STYLES, valid_backchannel_styles=VALID_BACKCHANNEL_STYLES, valid_voice_profile_verbosity=VALID_VOICE_PROFILE_VERBOSITY, valid_voice_profile_confirmations=VALID_VOICE_PROFILE_CONFIRMATIONS, valid_voice_profile_pace=VALID_VOICE_PROFILE_PACE, valid_voice_profile_tone=VALID_VOICE_PROFILE_TONE, valid_control_presets=VALID_CONTROL_PRESETS, ) actions = schema["actions"] assert "set_wake_mode" in actions assert "set_voice_profile" in actions assert "apply_control_preset" in actions assert "list_autonomy_replans" in actions assert "apply_autonomy_replan" in actions assert "copilot_actions" in actions assert "copilot_execute" in actions assert actions["set_wake_mode"]["enum"]["mode"] == sorted(VALID_WAKE_MODES) assert actions["apply_control_preset"]["enum"]["preset"] == sorted( VALID_CONTROL_PRESETS ) def test_startup_blockers_disabled_when_not_strict() -> None: config = SimpleNamespace(startup_strict=False) args = SimpleNamespace(no_tts=False) blockers = startup_blockers( config=config, args=args, valid_operator_auth_modes=VALID_OPERATOR_AUTH_MODES, ) assert blockers == [] def test_startup_blockers_include_security_and_token_requirements() -> None: config = SimpleNamespace( startup_strict=True, elevenlabs_api_key="", operator_server_enabled=True, operator_server_host="", operator_auth_mode="token", operator_auth_token="", skills_require_signature=True, skills_signature_key="", memory_encryption_enabled=True, audit_encryption_enabled=False, data_encryption_key="", webhook_inbound_enabled=True, webhook_inbound_token="", webhook_auth_token="", ) args = SimpleNamespace(no_tts=False) blockers = startup_blockers( config=config, args=args, valid_operator_auth_modes=VALID_OPERATOR_AUTH_MODES, ) assert any("ELEVENLABS_API_KEY" in item for item in blockers) assert any("OPERATOR_SERVER_HOST" in item for item in blockers) assert any("OPERATOR_AUTH_MODE=token" in item for item in blockers) assert any("SKILLS_SIGNATURE_KEY" in item for item in blockers) assert any("JARVIS_DATA_KEY" in item for item in blockers) assert any("WEBHOOK_INBOUND_ENABLED" in item for item in blockers) def test_startup_summary_lines_include_operator_auth_and_error_taxonomy() -> None: runtime = SimpleNamespace( robot=SimpleNamespace(sim=True), args=SimpleNamespace(no_vision=False), tts=None, _voice_attention=SimpleNamespace(mode="wake_word", timeout_profile="normal"), _skills=SimpleNamespace(enabled=True), _observability=SimpleNamespace(), config=SimpleNamespace( motion_enabled=True, hand_track_enabled=False, home_enabled=True, safe_mode_enabled=False, home_conversation_enabled=True, wake_calibration_profile="default", memory_enabled=True, memory_path="/tmp/memory.sqlite", skills_dir="/tmp/skills", operator_server_enabled=True, operator_server_host="127.0.0.1", operator_server_port=8777, operator_auth_mode="token", operator_auth_token="", observability_db_path="/tmp/obs.sqlite", persona_style="composed", startup_warnings=["warn-a"], tool_allowlist=["tool-a"], tool_denylist=["tool-b"], ), ) lines = startup_summary_lines( runtime, normalize_operator_auth_mode_fn=normalize_operator_auth_mode, operator_auth_risk_fn=operator_auth_risk, valid_operator_auth_modes=VALID_OPERATOR_AUTH_MODES, tool_service_error_codes={"timeout", "unknown_error"}, telemetry_service_error_details={"timeout"}, telemetry_storage_error_details={"storage_error"}, ) joined = "\n".join(lines) assert "Mode: simulation" in joined assert "Operator server: on" in joined assert "mode=token" in joined assert "token=missing" in joined assert "Tool policy: allow=1 deny=1" in joined assert "Error taxonomy: total=2 service=1 storage=1" in joined