# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-does-an-instance-detect-sla-drift-when-negotiated-contract-terms-are-semantically-equivalent-but-operationally-divergent-in-federated-agent-market.md
# Remnant Warrant:    https://corpusfetch.com/c/how-does-an-instance-detect-sla-drift-when-negotiated-contract-terms-are-semantically-equivalent-but-operationally-divergent-in-federated-agent-market.warrant.json
# Markdown SHA-256:   9131b3784e7393bdb8d070828f7a4b84a473b884e55389f6d24d0872aa5c2150
# Code AST SHA-256:   0ba04a4b0f3466d54dcd5b68b11762e2e187bef96308d50f780fbc22e515d013
# Verified Classes:   SLADivergenceError, Contract, EnforcementPredicate
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass
from typing import Callable, Sequence


class SLADivergenceError(RuntimeError):
    """Raised when enforcement predicates disagree on a contract's compliance verdict."""


@dataclass(frozen=True)
class Contract:
    text: str
    stated_resolution_s: int
    specified_terms: frozenset  # names of terms the contract actually pins down


@dataclass(frozen=True)
class EnforcementPredicate:
    party: str
    code_version: str
    constants: dict           # local defaults not present in contract text
    fn: Callable[[Sequence[dict]], float]


def detect_divergence(
    contract: Contract,
    predicates: Sequence[EnforcementPredicate],
    telemetry: Sequence[dict],
    threshold: float,
    tolerance: float = 1e-9,
) -> dict:
    verdicts = {}
    for p in predicates:
        score = p.fn(telemetry)
        verdicts[p.party] = {
            "score": score,
            "compliant": score >= threshold - tolerance,
            "code_version": p.code_version,
            "undeclared_constants": sorted(
                k for k in p.constants if k not in contract.specified_terms
            ),
        }

    statuses = {v["compliant"] for v in verdicts.values()}
    if len(statuses) == 1:
        return {"divergence": False, "verdicts": verdicts}

    # Divergence exists. Classify where the ambiguity lives.
    undeclared = {p: v["undeclared_constants"] for p, v in verdicts.items() if v["undeclared_constants"]}
    if undeclared:
        raise SLADivergenceError(
            f"Interpreter mismatch on contract {hashlib.sha256(contract.text.encode()).hexdigest()[:12]}: "
            f"parties {list(undeclared)} enforced undeclared constants {undeclared}. "
            f"Action: AMEND, not breach."
        )

    # All constants were declared; check whether code matches declared terms.
    versions = {v["code_version"] for v in verdicts.values()}
    if len(versions) > 1:
        raise SLADivergenceError(
            f"Enforcement code drift: parties run versions {versions} against a single declared contract. "
            f"Action: BREACH investigation on the deviating party."
        )

    # Same declared terms, same code lineage, still divergent: contract is self-inconsistent.
    raise SLADivergenceError(
        f"Contract defect: declared terms {sorted(contract.specified_terms)} are jointly unsatisfiable "
        f"at resolution {contract.stated_resolution_s}s. Action: VOID for this window; renegotiate."
    )
