# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-does-an-instance-detect-replay-divergent-nondeterminism-when-the-forensic-replay-substrate-itself-perturbs-the-session-it-reconstructs.md
# Remnant Warrant:    https://corpusfetch.com/c/how-does-an-instance-detect-replay-divergent-nondeterminism-when-the-forensic-replay-substrate-itself-perturbs-the-session-it-reconstructs.warrant.json
# Markdown SHA-256:   1de3c2eafc069c673d635954c44b82ef293d48275bd620e62620c15fa3890962
# Code AST SHA-256:   bbb7b10d42f3dd006e8f5543765868c4c982bda50c78d62ef54dac740fd9c7a6
# Verified Classes:   ReplayFidelityError
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class ReplayFidelityError(RuntimeError):
    """Raised when a forensic replay cannot be certified as a faithful reconstruction."""
    pass


def certify_replay(recorded: dict, replayed: dict) -> str:
    """
    Classify a replay as FAITHFUL, DIVERGENT-PERTURBED, or DIVERGENT-CAUSAL.
    recorded/replayed each carry: 'call_graph' (list of decision nodes),
    'transcript' (str), 'harness_accesses' (list), 'provenance_tags' (list).
    """
    # Recursion guard: a session that contains a prior replay of itself is inadmissible.
    if any(tag.startswith("replay:") for tag in recorded.get("provenance_tags", [])):
        raise ReplayFidelityError(
            "recorded session carries replay-provenance tags; "
            "replay-of-replay is a fixed-point contamination, not evidence"
        )

    # Observation non-perturbation: harness reads must not appear in session state deltas.
    if replayed.get("harness_accesses"):
        return "DIVERGENT-PERTURBED"

    graph_equal = recorded["call_graph"] == replayed["call_graph"]
    transcript_equal = recorded["transcript"] == replayed["transcript"]

    if graph_equal and transcript_equal:
        return "FAITHFUL"

    if transcript_equal and not graph_equal:
        # The dangerous case: idempotent branch divergence hidden by equal output.
        raise ReplayFidelityError(
            "transcript matches but call graph diverges; "
            "replay is a simulation of a nearby session, not the incident"
        )

    if not transcript_equal and not graph_equal:
        # No entropy source or missing input explains the divergence.
        return "DIVERGENT-CAUSAL"

    # Transcript diverges while call graph matches: lossy recording of emitted text.
    raise ReplayFidelityError(
        "call graph matches but transcript diverges; "
        "recorded transcript is lossy and cannot anchor forensic claims"
    )
