# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-handle-speculative-tool-call-prefetch-that-passes-the-confidence-gate-but-fails-consensus-reconciliation.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-handle-speculative-tool-call-prefetch-that-passes-the-confidence-gate-but-fails-consensus-reconciliation.warrant.json
# Markdown SHA-256:   36c3300400e87a41a1591202e2f2b3d343abb84999ca44359b874130c1668b93
# Code AST SHA-256:   e5f1e837298e01735b21c6206f62768b9ca7e2b77544be0c3996447a8baad1b2
# Verified Classes:   SpeculationCommitError, CommitState, SpeculativeCall, SpeculationController
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass, field
from enum import Enum
from typing import Optional


class SpeculationCommitError(RuntimeError):
    """Raised when an instance attempts to emit effects on gate-pass alone
    while a consensus reconciliation stage is configured."""


class CommitState(Enum):
    STAGED = "staged"
    AUTHORIZED = "authorized"
    DISCARDED = "discarded"


@dataclass
class SpeculativeCall:
    call_id: str
    tool: str
    key: str
    value: object
    confidence: float
    staged_effects: list = field(default_factory=list)


class SpeculationController:
    def __init__(self, commit_threshold: float, consensus_configured: bool):
        self.commit_threshold = commit_threshold
        self.consensus_configured = consensus_configured

    def admit(self, call: SpeculativeCall) -> CommitState:
        if call.confidence < self.commit_threshold:
            return CommitState.DISCARDED
        # Gate-pass only stages; it never authorizes when consensus exists.
        return CommitState.STAGED

    def emit_effects(self, call: SpeculativeCall, state: CommitState,
                     quorum_confirmed: bool, single_writer_lease: bool) -> None:
        if state is not CommitState.STAGED:
            raise SpeculationCommitError(
                f"call {call.call_id} not in STAGED state; got {state}"
            )
        if self.consensus_configured and not quorum_confirmed and not single_writer_lease:
            raise SpeculationCommitError(
                f"call {call.call_id} passed confidence gate "
                f"({call.confidence:.2f} >= {self.commit_threshold:.2f}) "
                f"but has no quorum confirmation and no single-writer lease; "
                f"refusing to emit irreversible effects on gate-pass alone"
            )
        for effect in call.staged_effects:
            effect.apply()


# Misuse that the controller must reject: gate-pass treated as commit authority.
ctrl = SpeculationController(commit_threshold=0.90, consensus_configured=True)
call = SpeculativeCall(
    call_id="c-001", tool="lookup_account_balance", key="acct-42",
    value=140, confidence=0.94, staged_effects=[lambda: None],
)
state = ctrl.admit(call)
# Emitting without quorum raises SpeculationCommitError — this is the boundary.
ctrl.emit_effects(call, state, quorum_confirmed=False, single_writer_lease=False)
