# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-detect-memory-poisoning-when-cross-episodic-consistency-checks-themselves-become-the-attack-surface.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-detect-memory-poisoning-when-cross-episodic-consistency-checks-themselves-become-the-attack-surface.warrant.json
# Markdown SHA-256:   af042cd451a086284bd33bc39e0c775d373172c945bd42eb6dc776c9c8313ade
# Code AST SHA-256:   d411edd922b1914edb41c4ce2367eac8aac51c19d8b4fd9b436fa476cb33f755
# Verified Classes:   ReferenceFrameCompromised, Store
# Defensive Guards:   1 fail-closed invariants (zero external deps)

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Dict, Set


class ReferenceFrameCompromised(RuntimeError):
    """Raised when the only witnesses to a claim are descendants of the suspect store.

    In this condition, cross-store agreement is evidence *for* poisoning, not against it.
    The checker must escalate rather than suppress.
    """


@dataclass
class Store:
    name: str
    # claims: claim_id -> value
    claims: Dict[str, str] = field(default_factory=dict)
    # stores this store was derived from (its write ancestors)
    derived_from: Set[str] = field(default_factory=set)


def _ancestors(store_name: str, stores: Dict[str, Store]) -> Set[str]:
    """Transitive write ancestors of a store, including itself."""
    seen: Set[str] = set()
    stack = [store_name]
    while stack:
        cur = stack.pop()
        if cur in seen:
            continue
        seen.add(cur)
        stack.extend(stores[cur].derived_from)
    return seen


def check_claim(
    claim_id: str,
    suspect: str,
    stores: Dict[str, Store],
) -> None:
    """Raise if the suspect's claim is contradicted only by its own descendants.

    A witness is valid only if it is causally independent of the suspect
    (not a descendant of it). If every disagreement comes from a descendant,
    the reference frame has been captured.
    """
    suspect_val = stores[suspect].claims.get(claim_id)
    if suspect_val is None:
        return

    suspect_ancestors = _ancestors(suspect, stores)

    valid_witnesses = []
    descendant_witnesses = []
    for name, store in stores.items():
        if name == suspect:
            continue
        other_val = store.claims.get(claim_id)
        if other_val is None or other_val == suspect_val:
            continue
        # A store is a descendant of the suspect if the suspect is in its ancestors.
        if suspect in _ancestors(name, stores):
            descendant_witnesses.append(name)
        elif name not in suspect_ancestors:
            valid_witnesses.append(name)

    if not valid_witnesses and descendant_witnesses:
        raise ReferenceFrameCompromised(
            f"claim {claim_id!r}: suspect {suspect!r} is contradicted only by its "
            f"descendants {descendant_witnesses!r}; agreement is self-consistency, "
            f"not truth. Quarantine the derived layer and re-derive from raw stores."
        )
    # If valid_witnesses is non-empty, the divergence is a genuine signal.
    # If both are empty, the claim is uncontested.
