"""B5 wiring — AI-Act Art. 50 Transparenzpflicht-Check + HTML block. Runs after B4 (vendor-consistency). Deterministic detection of AI-Provider mentions + disclosure-phrase mentions. When an AI is present but no Art-50-disclosure → HIGH finding; when both present the renderer flags MEDIUM/manual-review because the LIVE pre-chat UI hint cannot be verified without a consent-tester DOM scan. """ from __future__ import annotations import html import logging from compliance.services.ai_act_transparency_check import ( check_ai_act_transparency, ) logger = logging.getLogger(__name__) def run_b5(state: dict) -> None: findings = check_ai_act_transparency(state) state["ai_act_findings"] = findings if not findings: return state["ai_act_html"] = _render(findings) logger.info( "B5 AI-Act: %d findings (HIGH=%d, MEDIUM=%d)", len(findings), sum(1 for f in findings if (f.get("severity") or "") == "HIGH"), sum(1 for f in findings if (f.get("severity") or "") == "MEDIUM"), ) def _render(findings: list[dict]) -> str: cards = [] for f in findings: sev = (f.get("severity") or "").upper() color = "#dc2626" if sev == "HIGH" else "#f59e0b" vendors_html = "" if f.get("ai_vendors"): chips = "".join( f"{html.escape(v.get('vendor') or '—')}" for v in f["ai_vendors"] ) vendors_html = ( "