# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/in-what-scenarios-must-an-instance-of-the-litmus-harness-refuse-to-emit-a-safety-verdict-rather-than-emit-a-degraded-one.md
# Remnant Warrant:    https://corpusfetch.com/c/in-what-scenarios-must-an-instance-of-the-litmus-harness-refuse-to-emit-a-safety-verdict-rather-than-emit-a-degraded-one.warrant.json
# Markdown SHA-256:   74d14f5cffdb63c072880e48e47e32e684790370dc65682ad2034df51a7b8bc3
# Code AST SHA-256:   fd9fcdbae34914379d230881f3700772600fd8879d86949e1757d09a24c34d8e
# Verified Classes:   InvalidVerdictConditions, RunResult
# Defensive Guards:   4 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class InvalidVerdictConditions(RuntimeError):
    """Raised when a LITMUS run cannot support a gating verdict."""
    pass


@dataclass
class RunResult:
    cases_declared: int
    cases_scored: int
    cases_skipped_runtime: int
    judge_digest_resolved: str
    judge_digest_pinned: str
    ci_half_width: float
    decision_margin: float
    trials: int
    min_trials: int


def assert_verdict_eligible(run: RunResult) -> None:
    if run.cases_skipped_runtime > 0:
        raise InvalidVerdictConditions(
            f"{run.cases_skipped_runtime} cases skipped at runtime; "
            "population is not decision-equivalent to declared set"
        )
    if run.judge_digest_resolved != run.judge_digest_pinned:
        raise InvalidVerdictConditions(
            f"judge digest {run.judge_digest_resolved!r} != pinned "
            f"{run.judge_digest_pinned!r}; verdict emitted against uncalibrated judge"
        )
    if run.ci_half_width >= run.decision_margin:
        raise InvalidVerdictConditions(
            f"CI half-width {run.ci_half_width:.3f} >= margin "
            f"{run.decision_margin:.3f}; result is indeterminate, not PASS"
        )
    if run.trials < run.min_trials:
        raise InvalidVerdictConditions(
            f"{run.trials} trials < required {run.min_trials}; "
            "nondeterminism budget unverified"
        )


def emit_verdict(run: RunResult, score: float) -> str:
    try:
        assert_verdict_eligible(run)
    except InvalidVerdictConditions as exc:
        # Fail closed: gate treats NO_VERDICT as failure.
        return f"NO_VERDICT: {exc}"
    return "PASS" if score < run.decision_margin else "FAIL"
