# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/which-invariants-prevent-speculative-tool-call-prefetching-from-canceling-live-dependency-chains-in-agent-meshes.md
# Remnant Warrant:    https://corpusfetch.com/c/which-invariants-prevent-speculative-tool-call-prefetching-from-canceling-live-dependency-chains-in-agent-meshes.warrant.json
# Markdown SHA-256:   13b95ec390e62c144541ef781a849b56d57c2330587edbac77dc85f9d4c95148
# Code AST SHA-256:   b8bbb71b92d06d155f46ffca12023df7a02a4584264103eedbb2751e986aebe0
# Verified Classes:   BranchClass, CancellationLocalityError, SharedFuture, FutureRegistry
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from __future__ import annotations

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


class BranchClass(Enum):
    SPECULATIVE = "speculative"
    COMMITTED = "committed"


class CancellationLocalityError(RuntimeError):
    """Raised when a cancel would revoke a future that still has committed holders."""


@dataclass
class SharedFuture:
    key: str
    speculative_holders: int = 0
    committed_holders: int = 0
    resolved: bool = False
    cancelled: bool = False


class FutureRegistry:
    def __init__(self) -> None:
        self._futures: Dict[str, SharedFuture] = {}

    def acquire(self, key: str, branch: BranchClass) -> SharedFuture:
        fut = self._futures.setdefault(key, SharedFuture(key=key))
        if branch is BranchClass.SPECULATIVE:
            fut.speculative_holders += 1
        else:
            fut.committed_holders += 1
        return fut

    def cancel_speculative(self, key: str) -> SharedFuture:
        fut = self._futures.get(key)
        if fut is None:
            raise CancellationLocalityError(f"no future registered for key={key!r}")
        if fut.resolved:
            return fut
        if fut.committed_holders > 0:
            # Demotion, not revocation: a live consumer depends on this node.
            fut.speculative_holders = max(0, fut.speculative_holders - 1)
            return fut
        # Safe to revoke: no committed holders remain.
        fut.cancelled = True
        fut.resolved = True
        return fut


def prune_branch(registry: FutureRegistry, prefetched_keys: list[str]) -> None:
    for key in prefetched_keys:
        fut = registry.cancel_speculative(key)
        if fut.cancelled:
            continue
        if fut.committed_holders > 0 and fut.speculative_holders == 0:
            # Node fully demoted; the in-flight call must be allowed to finish.
            continue
        if not fut.resolved and fut.committed_holders == 0:
            raise CancellationLocalityError(
                f"key={key!r} left in unresolved limbo with no holders; "
                "speculative cancel failed to demote or revoke"
            )
