"""Tests for Interpretation-in-Map (step 5). Acceptance: a customer interpretation is judged against the existing map, using only assess_interpretation; affected regulations/obligations are referenced from the map; unsupported domains (wastewater/chemicals) are flagged future_corpus_needed, not pseudo-evaluated; output is customer-readable. """ from __future__ import annotations import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from compliance.interpretation_map import interpret_in_map from compliance.profile.canonical import ( CanonicalLifecyclePhase, CanonicalProductRegulatoryProfile, CanonicalProductType, EconomicOperatorRole, EnvironmentalImpact, ) from compliance.reasoning.enums import InterpretationVerdict from compliance.reasoning.interpretation_engine import assess_interpretation from compliance.regulatory_map import render_regulatory_map def ready_profile(**ov) -> CanonicalProductRegulatoryProfile: base = dict( name="Industriespülmaschine", product_type=CanonicalProductType.MACHINERY, markets=["EU", "DE"], economic_operator_role=EconomicOperatorRole.MANUFACTURER, lifecycle_phase=CanonicalLifecyclePhase.PLACING_ON_MARKET, is_machine=True, is_component=False, has_software_updates=True, has_embedded_software=True, has_remote_access=True, technologies=["cloud", "ota_updates"], ) base.update(ov) return CanonicalProductRegulatoryProfile(**base) def _map(**ov): return render_regulatory_map(ready_profile(**ov)) # 1 + 2. evaluated against the map, using ONLY assess_interpretation. def test_uses_assess_interpretation_verdict(): text = "Wir glauben, der CRA gilt nur für neue Produkte." result = interpret_in_map(_map(), text) assert result.assessment == assess_interpretation(text).assessment == InterpretationVerdict.TOO_NARROW assert "CRA" in result.affected_regulations # CRA is in the map assert result.in_scope_of_map is True # 3. the six verdict values pass through unchanged. def test_verdict_values(): m = _map() assert interpret_in_map(m, "CRA gilt nur für neue Produkte.").assessment == InterpretationVerdict.TOO_NARROW assert interpret_in_map(m, "Open Source ist ausgenommen, also betrifft uns der CRA nicht.").assessment == InterpretationVerdict.PARTIALLY_CORRECT assert interpret_in_map(m, "Der Mond beeinflusst unsere Updatezyklen.").assessment == InterpretationVerdict.UNCERTAIN # 4. affected regulations/obligations are referenced FROM the map. def test_affected_refs_from_map(): m = _map() result = interpret_in_map(m, "Eine SBOM reicht, dann sind wir fertig.") map_ob_ids = {o.obligation_id for v in m.applicable_regulations for o in v.obligations} map_reg_ids = {v.regulation_id for v in m.applicable_regulations} | {v.regulation_id for v in m.uncertain_regulations} assert "sbom_creation" in result.affected_obligations assert set(result.affected_obligations) <= map_ob_ids assert set(result.affected_regulations) <= map_reg_ids # 5. environmental aspects are NOT pseudo-evaluated. def test_environmental_not_pseudo_evaluated(): m = _map(environmental=EnvironmentalImpact(discharges_to_wastewater=True)) result = interpret_in_map(m, "Beim Abwasser sind wir nicht betroffen, das spielt für uns keine Rolle.") domains = {d.domain for d in result.future_corpus_domains} assert "environment_water" in domains assert "future_corpus_needed" in result.explanation # 6. output is customer-readable. def test_customer_readable(): result = interpret_in_map(_map(), "Der CRA gilt nur für neue Produkte.") assert "zu eng" in result.explanation assert result.explanation.startswith("Ihre Interpretation ist wahrscheinlich") # affected refs never leave the map (no abstract legal questions). def test_affected_regs_never_outside_map(): m = _map() map_reg_ids = ( {v.regulation_id for v in m.applicable_regulations} | {v.regulation_id for v in m.uncertain_regulations} | {v.regulation_id for v in m.excluded_regulations} ) for text in ["CRA gilt nur für neue Produkte.", "Ohne Funkmodul keine Cyber-Pflichten.", "SBOM reicht."]: result = interpret_in_map(m, text) assert set(result.affected_regulations) <= map_reg_ids # endpoint smoke. @pytest.fixture(scope="module") def client(): from compliance.api.reasoning_routes import router app = FastAPI() app.include_router(router) return TestClient(app) def test_endpoint_interpretation_in_map(client): r = client.post( "/reasoning/interpretation-in-map", json={ "product_profile": { "name": "M", "product_type": "machinery", "markets": ["EU"], "economic_operator_role": "manufacturer", "lifecycle_phase": "placing_on_market", "is_machine": True, "is_component": False, "has_software_updates": True, "has_embedded_software": True, "has_remote_access": True, "technologies": ["cloud"], }, "customer_interpretation": "Der CRA gilt nur für neue Produkte.", }, ) assert r.status_code == 200 body = r.json() assert body["assessment"] == "too_narrow" assert "CRA" in body["affected_regulations"] assert "zu eng" in body["explanation"]