"""Deterministic scope-uncertainty signals.

This is an escalation aid, not the security boundary. The signed policy still
decides whether an action is in scope.
"""

from __future__ import annotations

import re

_SIGNALS: tuple[tuple[str, re.Pattern[str]], ...] = (
    (
        "permission_inferred_from_access",
        re.compile(r"\b(can|could) access\b.*\b(so|therefore)\b", re.I),
    ),
    (
        "not_explicitly_forbidden",
        re.compile(r"\bnot explicitly (forbidden|disallowed|blocked)\b", re.I),
    ),
    (
        "assumed_same_scope",
        re.compile(r"\b(assume|assuming|probably|likely)\b.*\b(same|in)[ -]?scope\b", re.I),
    ),
    (
        "scope_uncertainty",
        re.compile(
            r"\b(maybe|probably|likely|appears?)\b.*\b(allowed|authorized|permitted)\b", re.I
        ),
    ),
    ("scope_expansion", re.compile(r"\b(broaden|expand|extend|reinterpret)\b.*\bscope\b", re.I)),
    (
        "outside_scope_acknowledged",
        re.compile(r"\b(outside|beyond|unrelated to)\b.*\bscope\b", re.I),
    ),
    (
        "convenience_override",
        re.compile(r"\bshould be fine\b|\bclose enough\b|\bfor completeness\b", re.I),
    ),
)


def detect_scope_uncertainty(text: str | None) -> tuple[str, ...]:
    if not text:
        return ()
    return tuple(name for name, pattern in _SIGNALS if pattern.search(text))
