# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-abort-speculative-tool-call-execution-before-rollback.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-abort-speculative-tool-call-execution-before-rollback.warrant.json
# Markdown SHA-256:   5e9fce351342c924999172ea3f7db4ccb10ed0ee17db31a3049776bd05549d45
# Code AST SHA-256:   adf00528171aea6046dc25baa38e74d480029527efd0389efc63853447c4a847
# Verified Classes:   SpeculativeCommitBoundaryError
# Defensive Guards:   1 fail-closed invariants (zero external deps)

class SpeculativeCommitBoundaryError(RuntimeError):
    """Raised when a speculative tool call would cross an externally-observable
    commit point not covered by the rollback ledger."""

    def __init__(self, tool_name: str, visibility: str, compensator: str | None):
        self.tool_name = tool_name
        self.visibility = visibility
        self.compensator = compensator
        super().__init__(
            f"speculative dispatch of {tool_name!r} crosses commit boundary "
            f"(visibility={visibility}, compensator={compensator!r})"
        )


def guard_speculative_dispatch(tool_name: str, visibility: str,
                               compensator: str | None,
                               compensator_preconditions_met: bool) -> None:
    # visibility in {"unobserved", "observed_by_self", "observed_by_others"}
    if visibility != "observed_by_others":
        return  # safe to speculate; local rollback suffices
    if compensator is None or not compensator_preconditions_met:
        raise SpeculativeCommitBoundaryError(tool_name, visibility, compensator)
    # compensator exists and is invokable -> speculation permitted


def dispatch(tool_name: str, *, speculative: bool, visibility: str,
             compensator: str | None = None,
             compensator_preconditions_met: bool = False) -> dict:
    if speculative:
        guard_speculative_dispatch(
            tool_name, visibility, compensator, compensator_preconditions_met
        )
    return {"tool": tool_name, "speculative": speculative, "ok": True}
