diff --git a/admin-compliance/app/sdk/agent/_components/AgentTestTab.tsx b/admin-compliance/app/sdk/agent/_components/AgentTestTab.tsx index 4dc40fde..2488e738 100644 --- a/admin-compliance/app/sdk/agent/_components/AgentTestTab.tsx +++ b/admin-compliance/app/sdk/agent/_components/AgentTestTab.tsx @@ -288,6 +288,10 @@ function SlotCard({ slot, output, runId }: { }) { const [showAll, setShowAll] = useState(false) const visibleFindings = showAll ? output.findings : output.findings.slice(0, 8) + const wasSkipped = output.mc_total > 0 && + output.mc_ok === 0 && output.mc_na === 0 && + output.mc_high === 0 && output.mc_medium === 0 && output.mc_low === 0 + const allGreen = !wasSkipped && output.findings.length === 0 return (
@@ -295,6 +299,16 @@ function SlotCard({ slot, output, runId }: { {output.duration_ms} ms · confidence {(output.confidence * 100).toFixed(0)}% + {wasSkipped && ( + + Dokument konnte nicht geladen werden (leer/zu kurz) + + )} + {allGreen && ( + + Keine Findings — alle anwendbaren MCs OK + + )} diff --git a/backend-compliance/compliance/services/specialist_agents/impressum/mcs.py b/backend-compliance/compliance/services/specialist_agents/impressum/mcs.py index f7d1a04e..7e00bb26 100644 --- a/backend-compliance/compliance/services/specialist_agents/impressum/mcs.py +++ b/backend-compliance/compliance/services/specialist_agents/impressum/mcs.py @@ -103,8 +103,11 @@ MCS: tuple[MC, ...] = ( severity_if_missing="HIGH", patterns=( re.compile( - r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hrer|" - r"Vertretungsberechtigt|vertreten\s+durch)" + r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hr(?:er|ung|erin)|" + r"Vorstand(?:svorsitzend(?:er|e))?|" + r"Vertretungsberechtigt|vertreten\s+durch|" + r"Inhaber(?:in)?|" + r"Pers(?:ö|oe)nlich\s+haftend)" r"\s*[:.\s]", re.IGNORECASE, ), @@ -121,9 +124,11 @@ MCS: tuple[MC, ...] = ( norm="§ 5 Abs. 1 Nr. 1 TMG (Deutsch-Pflicht, gerichtsfest)", severity_if_missing="MEDIUM", patterns=(re.compile( - r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hrer|" - r"Vorstand|" - r"Vertretungsberechtigt|vertreten\s+durch)" + r"(?:Gesch(?:ae|ä)ftsf(?:ue|ü)hr(?:er|ung|erin)|" + r"Vorstand(?:svorsitzend(?:er|e))?|" + r"Vertretungsberechtigt|vertreten\s+durch|" + r"Inhaber(?:in)?|" + r"Pers(?:ö|oe)nlich\s+haftend)" r"\s*[:.\s]", re.IGNORECASE, ),), diff --git a/backend-compliance/tests/test_specialist_impressum_v2.py b/backend-compliance/tests/test_specialist_impressum_v2.py index 7bc0beb4..a2754836 100644 --- a/backend-compliance/tests/test_specialist_impressum_v2.py +++ b/backend-compliance/tests/test_specialist_impressum_v2.py @@ -78,6 +78,28 @@ def test_tesla_missing_german_label(monkeypatch): assert "ust_id" in field_ids +def test_safetykon_geschaeftsfuehrung_passes(monkeypatch): + """Geschäftsführung (statt -führer) muss als deutsches Label akzeptiert + werden — sonst False-Positive bei SafetyKon GmbH und ähnlichen.""" + async def _no_cascade(*a, **kw): return None, [] + monkeypatch.setattr( + "compliance.services.specialist_agents.impressum.agent.cascade", + _no_cascade, + ) + txt = ( + "SafetyKon GmbH\nMerzhauser Str. 144\n79100 Freiburg\n" + "Telefon: 0761/48 98 09 01\nE-Mail: info@safetykon.de\n" + "Geschäftsführung: Dr. Oliver Kirchwehm\n" + "Handelsregister AG Freiburg HRB 709859\n" + "USt-Id: DE288952921\n" + ) + agent = ImpressumAgent() + out = _run(agent.evaluate(AgentInput(doc_type="impressum", text=txt))) + field_ids = {f.field_id for f in out.findings} + assert "vertretungsberechtigte" not in field_ids + assert "vertretungsberechtigte_label_korrekt" not in field_ids + + def test_full_impressum_has_no_basic_findings(monkeypatch): async def _no_cascade(*a, **kw): return None, []