# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-of-bft-consensus-among-llm-agents-fail-silently-when-the-quorum-is-composed-of-agents-sharing-a-common-retrieval-cache.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-of-bft-consensus-among-llm-agents-fail-silently-when-the-quorum-is-composed-of-agents-sharing-a-common-retrieval-cache.warrant.json
# Markdown SHA-256:   2b617a88177e10c9f116468d63c57985fb23ac8af6489cde36491fb092354e76
# Code AST SHA-256:   5003dd44cc8dd8b7510aea5ec1b5df04e9f3445ad3b508e274a1604eab3885c8
# Verified Classes:   CorrelatedEvidenceError
# Defensive Guards:   1 fail-closed invariants (zero external deps)

class CorrelatedEvidenceError(RuntimeError):
    """Raised when a vote quorum is composed of agents sharing unvalidated evidence."""
    pass


def validate_quorum_evidence(votes, evidence_source_map, n, f_evidence_validated):
    """
    votes: list of (agent_id, vote, evidence_source_id)
    evidence_source_map: dict source_id -> 'independent' | 'shared_mutable'
    n: total replicas
    f_evidence_validated: number of shared_mutable sources already validated
                          by an independent BFT round before this vote
    """
    quorum = (2 * n) // 3 + 1
    if len(votes) < quorum:
        return False  # normal liveness failure, not a safety issue

    shared_sources_in_quorum = {
        src for (_, _, src) in votes
        if evidence_source_map.get(src) == 'shared_mutable'
    }
    unvalidated_shared = shared_sources_in_quorum - set(range(f_evidence_validated))

    if unvalidated_shared:
        raise CorrelatedEvidenceError(
            f"Quorum of {len(votes)} votes draws on {len(unvalidated_shared)} "
            f"unvalidated shared evidence source(s) {sorted(unvalidated_shared)}; "
            f"effective fault bound collapses to f_evidence < 1. "
            f"Commit would be silent and unsafe."
        )
    return True


def commit_transition(votes, evidence_source_map, n, f_evidence_validated):
    if not validate_quorum_evidence(votes, evidence_source_map, n, f_evidence_validated):
        return "NO_COMMIT"
    return "COMMIT"
