""" safety.py Two-layer escalation gate: 1. Rule-based: fast regex patterns for high-risk keywords 2. Coverage check: escalate if no good corpus match found """ import re ESCALATION_PATTERNS = [ r"\bfraud\b", r"\bunauthori[sz]ed\b", r"\bstolen\b", r"\bscam\b", r"\bchargeback\b", r"\bdispute\b", r"\brefund\b", r"\bbilling\b", r"\binvoice\b", r"\bhacked\b", r"\bcompromised\b", r"\blocke?d out\b", r"\baccount (?:suspended|banned|deleted|terminated)\b", r"\bpersonal data\b", r"\bGDPR\b", r"\bprivacy\b", r"\blegal\b", r"\blawsuit\b", r"\bcompliance\b", r"\bcard (?:lost|stolen|missing)\b", r"\bplagiar(?:ism|ized)\b", r"\bassessment (?:ban|dispute|appeal)\b", r"\boutage\b", r"\bserver (?:down|error)\b", ] COMPILED = [re.compile(p, re.IGNORECASE) for p in ESCALATION_PATTERNS] HIGH_RISK_AREAS = {"billing", "fraud", "account_security", "legal", "card_dispute", "exam_dispute", "bug_report", "outage"} def should_escalate(ticket: str, product_area: str, docs: list[dict]) -> tuple[bool, str]: """Returns (escalate: bool, reason: str).""" # Layer 1 — keyword patterns matches = [p.search(ticket) for p in COMPILED if p.search(ticket)] if matches: found = list({m.group(0) for m in matches})[:4] return True, f"Sensitive keywords: {', '.join(found)}" # Layer 1b — high-risk product area if product_area.lower().replace(" ", "_") in HIGH_RISK_AREAS: return True, f"High-risk area: {product_area}" # Layer 2 — corpus coverage if not docs: return True, "No relevant documentation found in corpus" best = max((d.get("score", 0) for d in docs), default=0) if best < 0.5: return True, f"Low corpus confidence (best match score: {best:.2f})" return False, ""