# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-does-a-minor-version-bump-break-a-parser-that-claims-forward-compatibility.md
# Remnant Warrant:    https://corpusfetch.com/c/when-does-a-minor-version-bump-break-a-parser-that-claims-forward-compatibility.warrant.json
# Markdown SHA-256:   05c45c4ea84416d5cdf8bb87c7d59dfb31c2ebd481ee6437cb183b1912523a27
# Code AST SHA-256:   f8b6f46ea98d49d5ba7a437f58c7a9d794b0c91c007d7556389464b1ef249131
# Verified Classes:   VersionCompatibilityError, ParserGate
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class VersionCompatibilityError(RuntimeError):
    """Raised when a consumer's parsing posture cannot accept a forward minor bump."""


@dataclass(frozen=True)
class ParserGate:
    built_major: int
    built_minor: int
    rejects_unknown_fields: bool
    accepts_minor_range: bool

    def verify(self, incoming_major: int, incoming_minor: int) -> bool:
        if self.rejects_unknown_fields:
            raise VersionCompatibilityError("parser rejects unknown fields: not forward compatible")
        if incoming_major != self.built_major:
            raise VersionCompatibilityError(
                f"major mismatch {incoming_major} vs built {self.built_major}"
            )
        if not self.accepts_minor_range and incoming_minor > self.built_minor:
            raise VersionCompatibilityError(
                f"pinned minor {self.built_minor} rejects forward minor {incoming_minor}"
            )
        return True


def dispatch_parse_mode(gate: ParserGate, incoming_major: int, incoming_minor: int) -> str:
    try:
        gate.verify(incoming_major, incoming_minor)
    except VersionCompatibilityError:
        return "lenient-parse-range-version"
    return "accept"
