# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/which-invariants-prevent-agent-card-discovery-from-silently-succeeding-against-a-stale-or-partially-replicated-registry-in-a2a-v1-0.md
# Remnant Warrant:    https://corpusfetch.com/c/which-invariants-prevent-agent-card-discovery-from-silently-succeeding-against-a-stale-or-partially-replicated-registry-in-a2a-v1-0.warrant.json
# Markdown SHA-256:   e62873db593e58a3cc2dcd997d3cc441c2fb630702ec700c6311219e188d3c99
# Code AST SHA-256:   eddf72262705dc9339ba511dcb2c39e7601c0c0a40522ae20e3b94063347777a
# Verified Classes:   StaleAgentCardError, CapabilityMismatchError, AgentCard, ResolvedCard
# Defensive Guards:   5 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass
from typing import Optional


class StaleAgentCardError(RuntimeError):
    """Raised when a resolved Agent Card cannot be proven fresh and complete."""
    pass


class CapabilityMismatchError(RuntimeError):
    """Raised when a card's capabilities do not cover the intended invocation."""
    pass


@dataclass(frozen=True)
class AgentCard:
    agent_id: str
    version: int
    capabilities: frozenset
    endpoint: str
    card_hash: str


@dataclass(frozen=True)
class ResolvedCard:
    card: AgentCard
    replication_watermark_s: Optional[float]  # None == resolver did not report it


def resolve_for_delegation(
    resolved: ResolvedCard,
    required_capabilities: frozenset,
    min_version: int,
    max_staleness_s: float,
    pinned_hash: Optional[str] = None,
) -> AgentCard:
    card = resolved.card

    # Condition (b): freshness must be verifiable, or pinned out-of-band.
    if pinned_hash is not None:
        if hashlib.sha256(card.card_hash.encode()).hexdigest() != pinned_hash:
            raise StaleAgentCardError(
                f"card hash {card.card_hash!r} does not match pinned hash"
            )
    else:
        if resolved.replication_watermark_s is None:
            raise StaleAgentCardError(
                f"resolver returned no replication watermark for {card.agent_id}; "
                "freshness unverifiable and no card hash pinned — failing closed"
            )
        if resolved.replication_watermark_s > max_staleness_s:
            raise StaleAgentCardError(
                f"replication watermark {resolved.replication_watermark_s}s exceeds "
                f"tolerance {max_staleness_s}s for {card.agent_id}"
            )

    # Condition (a): version floor.
    if card.version < min_version:
        raise StaleAgentCardError(
            f"card version {card.version} < required {min_version} for {card.agent_id}"
        )

    # Condition (c): capability superset.
    missing = required_capabilities - card.capabilities
    if missing:
        raise CapabilityMismatchError(
            f"card for {card.agent_id} missing capabilities {sorted(missing)}"
        )

    return card
