from __future__ import annotations from unittest.mock import patch import pytest from cognitive_agent.application.assistant_capabilities import AssistantCapabilityCatalog from cognitive_agent.application.mode_profile import ModeProfileRegistry from cognitive_agent.application.scene_composer import normalize_scene_output from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService from cognitive_agent.application.semantic_ir import resolve_scene_seat_scopes @pytest.fixture(scope="module") def scene_service(tmp_path_factory): service = SeatDemoService() service.artifact_root = tmp_path_factory.mktemp("scene-explicit-seat-scope") service.mode_profiles = ModeProfileRegistry( REPOSITORY_ROOT / "config" / "modes", user_root=tmp_path_factory.mktemp("scene-explicit-seat-user-modes"), ) try: yield service, AssistantCapabilityCatalog(service).scene_composition_context() finally: service.close() def _plan(context, scopes): requests = [] if "driver" in scopes: requests.append({ "capability": "seat.set_driver_massage_native", "target_scope": "driver", "parameters": {"action": "mode", "mode": "relax"}, }) if "passenger" in scopes: requests.append({ "capability": "seat.set_backrest_recline", "target_scope": "passenger", "parameters": {"position_pct": 45}, }) requests.append({ "capability": "climate.set_temperature", "target_scope": "vehicle", "parameters": {"temperature_c": 24}, }) return normalize_scene_output({ "requests": requests, "ambiguities": [], "confidence": 0.95, }, context) def _preview( scene_service, message, scopes=("driver", "passenger"), *, execution_mode="hardware", ): service, context = scene_service with patch.object( service.hardware_execution, "reserve", side_effect=AssertionError("scene scope validation must not execute hardware"), ): return service.preview_native_can( message, provider="local", conversation_id="conv-explicit-scene-seat-scope", execution_mode=execution_mode, vehicle_id="denza_n7", assistant_plan=_plan(context, scopes), ) @pytest.mark.parametrize("message", ( "构建一个主驾座椅舒适模式", "创建一个仅主驾舒适模式", "创建一个只给驾驶员坐着放松的功能模式", "构建一个副驾座椅舒适模式", "构建一个仅副驾舒适模式", "构建一个右前座椅舒适模式", "构建一个后排座椅舒适模式", "构建一个主驾座椅与副驾空调舒适模式", "构建一个主驾阅读灯与副驾座椅舒适模式", )) def test_explicit_scene_seat_scope_rejects_cross_seat_plan_atomically(scene_service, message): result = _preview(scene_service, message) assert result["status"] != "succeeded" assert result.get("mode_profile_draft") is None assert result["hardware_execution_allowed"] is False assert result.get("command_plan") is None assert result.get("command_plans") == {} intent = result.get("intent_ir") or {} assert (intent.get("spec") or {}).get("actions", []) == [] assert any( "座位范围" in item["message"] or item.get("code") == "MODE_SEAT_SCOPE_UNAVAILABLE" for item in result["validation"] ) @pytest.mark.parametrize(("message", "scopes"), ( ("构建一个主驾座椅舒适模式", ("driver",)), ("构建一个副驾座椅舒适模式", ("passenger",)), ("创建一个仅主驾舒适模式", ("driver",)), ("构建一个主驾和副驾座椅舒适模式", ("driver", "passenger")), ("构建一个主副驾座椅舒适模式", ("driver", "passenger")), ("构建一个云端座椅舒适模式", ("passenger",)), ("构建一个副驾空调与座椅舒适模式", ("passenger",)), ("构建一个座椅舒适与副驾阅读灯模式", ("passenger",)), ("构建一个主驾座椅与副驾空调舒适模式", ("driver",)), ("构建一个主驾阅读灯与副驾座椅舒适模式", ("passenger",)), )) def test_scene_scope_preserves_supported_targets_without_borrowing_other_device_zones( scene_service, message, scopes, ): result = _preview(scene_service, message, scopes) assert result["status"] == "succeeded", result.get("validation") assert result["mode_profile_draft"] assert result["execution_mode"] == "dry_run" assert result["hardware_execution_allowed"] is False actions = result["intent_ir"]["spec"]["actions"] assert { action["target"]["instance"] for action in actions if action["domain"] == "seat" } == set(scopes) @pytest.mark.parametrize("message", ( "构建一个主驾舒适模式,副驾不要动", "构建一个主驾舒适模式,不要动副驾", )) def test_explicit_atomic_requirements_do_not_receive_scene_scope_relaxation( scene_service, message, ): result = _preview(scene_service, message, execution_mode="dry_run") assert result["status"] != "succeeded" assert result.get("mode_profile_draft") is None assert result["hardware_execution_allowed"] is False def test_unqualified_explicit_seat_requirement_defaults_to_passenger_without_model_additions(scene_service): result = _preview(scene_service, "构建一个舒展模式,座椅靠背调整到45%", execution_mode="dry_run") assert result["status"] == "succeeded", result.get("validation") assert result["execution_mode"] == "dry_run" assert result["hardware_execution_allowed"] is False assert result["mode_profile_draft"]["operation_count"] == 1 actions = result["intent_ir"]["spec"]["actions"] assert len(actions) == 1 assert actions[0]["capability"] == "seat.set_backrest_recline" assert actions[0]["target"]["instance"] == "passenger" assert actions[0]["parameters"] == {"position_pct": 45} def test_explicit_atomic_requirements_override_label_without_adding_model_actions(scene_service): result = _preview(scene_service, "构建一个主驾舒适模式,副驾靠背调整到45%") assert result["status"] == "succeeded" assert result["execution_mode"] == "dry_run" actions = result["intent_ir"]["spec"]["actions"] assert len(actions) == 1 assert actions[0]["capability"] == "seat.set_backrest_recline" assert actions[0]["target"]["instance"] == "passenger" assert actions[0]["parameters"]["position_pct"] == 45 def test_rear_window_scene_is_not_rejected_as_an_unsupported_seat(scene_service): service, context = scene_service plan = normalize_scene_output({ "requests": [{ "capability": "window.set_position", "target_scope": "rear_right", "parameters": {"position_pct": 45}, }], "ambiguities": [], "confidence": 0.95, }, context) result = service.preview_native_can( "构建一个后排换气模式", provider="local", conversation_id="conv-rear-window-not-seat", execution_mode="dry_run", vehicle_id="denza_n7", assistant_plan=plan, ) assert result["status"] == "succeeded" assert result["mode_profile_draft"] @pytest.mark.parametrize(("text", "expected"), ( ("进入主驾舒适模式", frozenset({"driver"})), ("进入仅副驾舒适模式", frozenset({"passenger"})), ("进入主副驾座椅舒适模式", frozenset({"driver", "passenger"})), ("进入主驾座椅与副驾的空调舒适模式", frozenset({"driver"})), ("进入副驾座椅与主驾的阅读灯模式", frozenset({"passenger"})), ("进入座椅舒适与右前车窗模式", None), ("进入座椅舒适与后排阅读灯模式", None), ("进入后排座椅舒适模式", frozenset({"unsupported"})), )) def test_scene_scope_resolution_only_uses_seat_or_unqualified_scene_targets(text, expected): assert resolve_scene_seat_scopes(text) == expected def test_new_creation_cannot_borrow_draft_reference_to_bypass_explicit_scope(scene_service): service, context = scene_service built = _preview(scene_service, "构建一个主驾独享舒适模式", ("driver",)) reference = {key: built["mode_profile_draft"][key] for key in ( "name", "source_request_id", "vehicle_id", )} result = service.preview_native_can( "构建一个主驾独享舒适模式", provider="local", conversation_id="conv-explicit-scene-seat-scope", execution_mode="dry_run", vehicle_id="denza_n7", assistant_plan=_plan(context, ("driver", "passenger")), mode_profile_draft_context=reference, ) assert result["status"] != "succeeded" assert not result.get("mode_profile_draft") @pytest.mark.parametrize(("initial_scope", "name", "change", "added_capability"), ( ("driver", "主驾释压舒适模式", "副驾座椅通风调整为1档", "seat.set_ventilation"), ("passenger", "副驾释压舒适模式", "主驾座椅通风调整为低档", "seat.set_driver_ventilation_native"), )) def test_explicit_revision_can_extend_old_label_scope_then_save_and_replay( scene_service, initial_scope, name, change, added_capability, ): service, _context = scene_service built = _preview(scene_service, f"构建一个{name}", (initial_scope,)) source_draft = built["mode_profile_draft"] reference = {key: source_draft[key] for key in ( "name", "source_request_id", "vehicle_id", )} revised = service.preview_native_can( f"把{name}的{change}", provider="local", conversation_id="conv-explicit-scene-seat-scope", execution_mode="dry_run", vehicle_id="denza_n7", mode_profile_draft_context=reference, ) assert revised["status"] == "succeeded", revised.get("validation") draft = revised["mode_profile_draft"] assert draft["generation_source"] == "draft_revision" assert draft["operation_count"] == source_draft["operation_count"] + 1 actions = revised["intent_ir"]["spec"]["actions"] assert added_capability in {action["capability"] for action in actions} assert { action["target"]["instance"] for action in actions if action["domain"] == "seat" } == {"driver", "passenger"} saved = service.create_mode_profile_card( draft["name"], draft["instruction"], draft["source_request_id"], draft["vehicle_id"], ) assert saved["status"] == "succeeded" replayed = service.execute_mode_profile_card( saved["mode_profile"]["id"], execution_mode="dry_run", vehicle_id="denza_n7", ) assert replayed["status"] == "succeeded", replayed.get("validation") assert { (action["capability"], action["target"]["instance"]) for action in replayed["intent_ir"]["spec"]["actions"] if action["domain"] == "seat" } == { (action["capability"], action["target"]["instance"]) for action in actions if action["domain"] == "seat" }