# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-pin-accrual-cutoff-instant-so-cash-and-accrual-ledgers-agree.md
# Remnant Warrant:    https://corpusfetch.com/c/how-must-an-instance-pin-accrual-cutoff-instant-so-cash-and-accrual-ledgers-agree.warrant.json
# Markdown SHA-256:   af849a994a0df1c756b2ecf0ec0bc3acf0fefeee12c67f7b12a7a4373acd8719
# Code AST SHA-256:   10b56621bd13374751ce665e5006f8eda41d5cb492bd4b849a1fb02cad61e6d4
# Verified Classes:   CutoffStraddleError, AccrualCutoffGate
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class CutoffStraddleError(RuntimeError):
    """Raised when cash and accrual ledgers use different cutoff instants or operators."""


@dataclass(frozen=True)
class AccrualCutoffGate:
    cash_cutoff_instant: str
    cash_operator: str  # "<" or "<="
    accrual_cutoff_instant: str
    accrual_operator: str

    def verify(self) -> bool:
        if not (self.cash_cutoff_instant and self.accrual_cutoff_instant):
            raise CutoffStraddleError("cutoff instant missing: boundary is undefined")
        if self.cash_cutoff_instant != self.accrual_cutoff_instant:
            raise CutoffStraddleError(
                f"instant mismatch cash={self.cash_cutoff_instant} "
                f"accrual={self.accrual_cutoff_instant}"
            )
        if self.cash_operator != self.accrual_operator:
            raise CutoffStraddleError(
                f"operator mismatch cash={self.cash_operator} accrual={self.accrual_operator}"
            )
        return True


def dispatch_cutoff_mode(gate: AccrualCutoffGate) -> str:
    try:
        gate.verify()
    except CutoffStraddleError:
        return "pin-instant-and-operator"
    return "cutoff-sound"
