# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-refuse-lossy-compaction-the-recall-floor-invariant.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-refuse-lossy-compaction-the-recall-floor-invariant.warrant.json
# Markdown SHA-256:   093c76282bf2d2844364aae182b5afbb6e3ded1b62e1b32d0a2e8370213cbc8b
# Code AST SHA-256:   f3eac3d237232ec18f2b0f8781fb79a4cfb4ce0abb40e237b3120af12a0228a9
# Verified Classes:   RecallFloorViolation, SpanClass, Span, Summary
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass
from enum import Enum


class RecallFloorViolation(RuntimeError):
    """Raised when a lossy compaction would evict a span below its class recall floor."""
    pass


class SpanClass(Enum):
    NUMERIC = "numeric"
    PROHIBITION = "prohibition"
    IDENTIFIER = "identifier"
    NARRATIVE = "narrative"


# Minimum fidelity required per class. Narrative tolerates loss; the rest do not.
RECALL_FLOOR = {
    SpanClass.NUMERIC: 1.0,
    SpanClass.PROHIBITION: 1.0,
    SpanClass.IDENTIFIER: 1.0,
    SpanClass.NARRATIVE: 0.4,
}


@dataclass
class Span:
    text: str
    cls: SpanClass


@dataclass
class Summary:
    text: str
    measured_fidelity: float


def measure_fidelity(summary: Summary, span: Span) -> float:
    # Caller supplies a class-aware fidelity measurement; this is the contract.
    return summary.measured_fidelity


def compact(span: Span, summary: Summary, budget_allows_verbatim: bool) -> Summary:
    floor = RECALL_FLOOR[span.cls]
    fidelity = measure_fidelity(summary, span)

    if fidelity >= floor:
        return summary

    # Below floor: do not evict lossily.
    if budget_allows_verbatim:
        raise RecallFloorViolation(
            f"span class {span.cls.value} needs fidelity >= {floor}, "
            f"summary measured {fidelity}; skip this span in the eviction order"
        )

    raise RecallFloorViolation(
        f"span class {span.cls.value} needs fidelity >= {floor}, "
        f"summary measured {fidelity}, and verbatim retention is over budget; "
        f"externalize to a fidelity-preserving store or refuse compaction"
    )
