# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-equivocation-from-latency-in-byzantine-multi-agent-task-commitment.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-equivocation-from-latency-in-byzantine-multi-agent-task-commitment.warrant.json
# Markdown SHA-256:   17edf117a6400664d5ad9fdeefc875759da0dcc65483ca7f16e3a50aa45e3f39
# Code AST SHA-256:   522fded61a0e56900a04f67c4d3502c3b4cb1aebb0adb971ddddf985b22d4a8d
# Verified Classes:   EquivocationGateError, SignedMessage, EquivocationCertificate
# Defensive Guards:   1 fail-closed invariants (zero external deps)

from dataclasses import dataclass
from typing import Optional


class EquivocationGateError(RuntimeError):
    """Raised when a safety action is attempted without a valid equivocation certificate."""
    pass


@dataclass(frozen=True)
class SignedMessage:
    replica_id: str
    epoch: int
    view: int
    slot: str
    content_hash: str
    signature: bytes


@dataclass(frozen=True)
class EquivocationCertificate:
    replica_id: str
    epoch: int
    view: int
    slot: str
    hash_a: str
    hash_b: str
    sig_a: bytes
    sig_b: bytes


def verify_certificate(cert: Optional[EquivocationCertificate], keyring: dict) -> bool:
    if cert is None:
        return False
    if cert.hash_a == cert.hash_b:
        return False
    if cert.replica_id not in keyring:
        return False
    key = keyring[cert.replica_id]
    return _verify(key, cert)  # signature check omitted for brevity


def apply_penalty(replica_id: str, cert: Optional[EquivocationCertificate],
                  keyring: dict) -> None:
    if not verify_certificate(cert, keyring):
        raise EquivocationGateError(
            f"refusing to penalize {replica_id}: no verified equivocation "
            f"certificate present; timeout is not fault-class evidence"
        )
    # Safety action is now reachable only with a provable conflicting pair.
    _revoke_epoch_commitments(replica_id, cert.epoch)
    _exclude_from_future_quorums(replica_id)


def handle_missed_deadline(replica_id: str, view: int,
                           cert: Optional[EquivocationCertificate],
                           keyring: dict) -> str:
    # Liveness path: never penalize on absence of a message.
    if verify_certificate(cert, keyring):
        apply_penalty(replica_id, cert, keyring)
        return "penalized"
    if view >= MAX_VIEW_CHANGES:
        return "quarantined"  # reversible, no key revocation
    return "view_change_requested"
