"""C2.5 ReRankStrategy error taxonomy (AZ-342).

The family is intentionally narrow: a per-candidate failure is the
normal case (drop-and-continue, INV-8) and is signalled via
``candidates_dropped`` in the returned :class:`RerankResult` —
NOT via an exception. An exception escapes ``rerank`` only when
EVERY candidate fails (:class:`RerankAllCandidatesFailedError`)
which is the C5 → VIO-only-fallback trigger per AC-3.5.

:class:`RerankBackboneError` is raised INSIDE the per-candidate loop,
caught by the strategy, logged ERROR, FDR-stamped, and the
candidate is dropped. It is exposed publicly so the per-candidate
log + FDR taxonomy is observable and so future re-rankers using a
different backbone can re-raise the same kind.

``TileFetchError`` is C6-owned
(``c6_tile_cache.errors.TileNotFoundError`` / ``TileFsError``); the
strategy catches it in the per-candidate loop and treats it
identically to :class:`RerankBackboneError`.
"""

from __future__ import annotations

__all__ = [
    "RerankAllCandidatesFailedError",
    "RerankBackboneError",
    "RerankError",
]


class RerankError(Exception):
    """Base class for the C2.5 rerank error family.

    Caught at the runtime root only when
    :class:`RerankAllCandidatesFailedError` fires; per-candidate
    failures stay inside the strategy.
    """


class RerankBackboneError(RerankError):
    """Per-candidate LightGlue forward-pass failure.

    CUDA OOM, TRT engine deserialize mismatch. Logged at ERROR; one
    FDR record per occurrence; the offending candidate is dropped
    from the rerank set; the surrounding ``rerank`` call continues
    with the remaining candidates (INV-8).
    """


class RerankAllCandidatesFailedError(RerankError):
    """Zero survivors after the per-candidate loop.

    Every candidate's LightGlue or tile fetch failed. Logged at
    ERROR; FDR record ``kind=rerank.all_failed``. C5 falls back to
    VIO-only with provenance ``visual_propagated`` (AC-3.5).
    """
