# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-happens-when-an-instance-of-a-long-horizon-agent-state-store-trusts-its-own-write-ahead-log-over-its-retrieval-index-during-partial-compaction.md
# Remnant Warrant:    https://corpusfetch.com/c/what-happens-when-an-instance-of-a-long-horizon-agent-state-store-trusts-its-own-write-ahead-log-over-its-retrieval-index-during-partial-compaction.warrant.json
# Markdown SHA-256:   581b70035b47e5f6696e08f8ce2077ef8a1cc4250b4f0f64a8ccbf78fc4e7a58
# Code AST SHA-256:   c7113addd924dc19c31b2e65eb694739c5308eebe232f14a1b393c9c9fa8adef
# Verified Classes:   CompactionSkewError
# Defensive Guards:   1 fail-closed invariants (zero external deps)

class CompactionSkewError(RuntimeError):
    """Raised when index generation trails WAL head; divergence is not admissible as poisoning evidence."""
    pass


def classify_divergence(record, wal_head_gen, max_lag_cycles=1):
    index_gen = record["index_gen"]
    wal_gen = record["wal_gen"]
    lag = wal_head_gen - index_gen

    if lag > max_lag_cycles:
        # Cannot distinguish staleness from tampering; refuse to classify.
        raise CompactionSkewError(
            f"segment {record['segment_id']} index_gen={index_gen} "
            f"trails wal_head_gen={wal_head_gen} by {lag} cycles; "
            f"reconciliation required before poisoning classification"
        )

    if index_gen < wal_gen:
        # Stale but within tolerance: reconcile via WAL replay, do not flag.
        return "stale_reconcile"

    if record["content_hash"] != record["wal_content_hash"]:
        # Same generation, content differs: admissible as poisoning evidence.
        return "poisoning_candidate"

    return "consistent"


def detect(record, wal_head_gen):
    verdict = classify_divergence(record, wal_head_gen)
    if verdict == "poisoning_candidate":
        quarantine(record["record_id"], reason="content_divergence_same_gen")
    elif verdict == "stale_reconcile":
        enqueue_reconciliation(record["segment_id"])
    return verdict
