# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-a-poisoned-litmus-baseline-from-a-genuine-capability-regression.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-a-poisoned-litmus-baseline-from-a-genuine-capability-regression.warrant.json
# Markdown SHA-256:   1ff0ae6b2720ba53482874446269a4c58157fdba8b984105d0a8d75d75a39f2a
# Code AST SHA-256:   9d1ac60ea471061789ba1bed78198c4c053488e829350197c814efc6c4587740
# Verified Classes:   BaselinePoisoningError, ProbeResult
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass


class BaselinePoisoningError(RuntimeError):
    """Raised when a gate failure cannot be attributed to the subject under test."""


@dataclass(frozen=True)
class ProbeResult:
    probe_id: str
    passed: bool
    reason_class: str  # "model_output" | "tool_error" | "timeout" | "fixture_drift"


def verify_baseline_attribution(
    baseline_checkpoint_hash: str,
    candidate_checkpoint_hash: str,
    pinned_baseline_manifest: str,
    current_manifest: str,
    replay_results: list[ProbeResult],
    gate_failures: list[str],
) -> str:
    if current_manifest != pinned_baseline_manifest:
        raise BaselinePoisoningError(
            f"environment manifest drift: pinned={pinned_baseline_manifest} "
            f"current={current_manifest}; gate verdict is not attributable to the subject"
        )

    failing = [r for r in replay_results if r.probe_id in set(gate_failures)]
    if not failing:
        return "gate_passed"

    drift = [r for r in failing if r.reason_class == "fixture_drift"]
    if len(drift) * 2 >= len(failing):
        raise BaselinePoisoningError(
            f"majority of gate failures are fixture_drift ({len(drift)}/{len(failing)}); "
            "quarantine probes and regenerate a candidate baseline"
        )

    if any(r.passed for r in failing):
        raise BaselinePoisoningError(
            "baseline checkpoint passes probes the candidate fails under identical "
            "manifest; failure is attributable to the skill edit, not the harness — "
            "do not regenerate baseline"
        )

    return "attributable_to_skill_edit"
