# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/under-what-conditions-must-an-instance-reject-a-delegated-capability-grant-whose-policy-closure-is-satisfiable-only-under-its-own-local-exception.md
# Remnant Warrant:    https://corpusfetch.com/c/under-what-conditions-must-an-instance-reject-a-delegated-capability-grant-whose-policy-closure-is-satisfiable-only-under-its-own-local-exception.warrant.json
# Markdown SHA-256:   ede402dd461f0c412a0082dfff35864c3c9662ddefd35af6bb9e646cb3bad1f3
# Code AST SHA-256:   0f474926036d044ff6efe1ed51eb0ceb45095b8d3a1351e2bc4430d6765f56f4
# Verified Classes:   PolicyClosureLaunderingError
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class PolicyClosureLaunderingError(RuntimeError):
    """Raised when a grant's obligation closure is satisfiable only under the
    receiver's local exception overlay, without recorded consent from the author."""
    pass


def evaluate_grant(
    obligations: frozenset,
    local_policy: frozenset,
    local_overlay: frozenset,
    consent_record: frozenset,
) -> str:
    """
    Returns one of: 'accept', 'reject', 'negotiate'.
    obligations: obligation clauses carried by the delegation chain.
    local_policy: receiver's baseline policy (no exceptions).
    local_overlay: receiver's local exception clauses (widening candidates).
    consent_record: exception clauses the author explicitly consented to for this grant.
    """
    def closure_holds(policy: frozenset) -> bool:
        # A closure holds if every obligation clause is entailed by the policy set.
        return obligations.issubset(policy)

    baseline_ok = closure_holds(local_policy)
    overlay_ok = closure_holds(local_policy | local_overlay)

    if baseline_ok:
        return "accept"

    if not overlay_ok:
        # Not satisfiable even with overlay: a genuine capability gap, not laundering.
        raise PolicyClosureLaunderingError(
            f"Grant unsatisfiable under any local policy: {sorted(obligations)}"
        )

    # Overlay is load-bearing. Check whether the author consented to the specific
    # widening exceptions that make the closure hold.
    load_bearing = {
        clause for clause in local_overlay
        if closure_holds(local_policy | {clause}) and clause not in local_policy
    }
    if load_bearing.issubset(consent_record):
        return "accept"

    unconsented = load_bearing - consent_record
    if unconsented:
        # Locally satisfiable, but only by laundering an unconsented exception.
        # Distinguish negotiate vs reject: negotiate when the widening is narrow
        # enough that the author plausibly would consent; reject otherwise.
        if len(unconsented) == 1 and all(_is_narrow(clause) for clause in unconsented):
            return "negotiate"
        raise PolicyClosureLaunderingError(
            "Grant closure depends on unconsented widening exceptions: "
            f"{sorted(unconsented)}"
        )

    return "accept"


def _is_narrow(clause) -> bool:
    # Placeholder: a real implementation inspects the clause's attenuation semantics.
    return True
