# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-agent-emit-a-causal-link-span-before-it-acknowledges-a-federated-parent.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-agent-emit-a-causal-link-span-before-it-acknowledges-a-federated-parent.warrant.json
# Markdown SHA-256:   121bf9331425b68f81a8f398f7a558f93e09bc6ca8e1ce61be145949efb3cf71
# Code AST SHA-256:   12b06b059b07b73d143e9abb37756de041bb8b6ff6fbacff6b69374c0f0ca8a3
# Verified Classes:   LinkNotDurableError, LinkReceipt
# Defensive Guards:   2 fail-closed invariants (zero external deps)

import time
from dataclasses import dataclass


class LinkNotDurableError(RuntimeError):
    """Raised when a causal link is not durable at acknowledgment time."""


@dataclass
class LinkReceipt:
    durable: bool
    link_id: str
    minted_by_child: bool


def acknowledge_with_causal_link(
    link_store,
    parent_span_id: str,
    child_domain: str,
    timeout_s: float = 2.0,
) -> LinkReceipt:
    # Child must mint its own token bound to the parent span.
    link_id = f"{child_domain}:{parent_span_id}:{int(time.time() * 1000)}"
    deadline = time.monotonic() + timeout_s

    while time.monotonic() < deadline:
        receipt = link_store.write_durable(link_id, parent_span_id)
        if receipt.durable:
            if not receipt.minted_by_child:
                raise LinkNotDurableError(
                    f"link {link_id} inherited parent token; reachability unverifiable"
                )
            return receipt
        time.sleep(0.01)

    # Backpressure or eventual consistency: do NOT acknowledge as complete.
    raise LinkNotDurableError(
        f"causal link {link_id} not durable within {timeout_s}s; "
        "acknowledge provisionally and mark span link_pending"
    )
