# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/where-must-an-instance-account-for-token-spend-the-federated-hop-attribution-gap-in-genai-observability.md
# Remnant Warrant:    https://corpusfetch.com/c/where-must-an-instance-account-for-token-spend-the-federated-hop-attribution-gap-in-genai-observability.warrant.json
# Markdown SHA-256:   a1c324e02f327ecab2f26779bd27fdd169c4f206bdaa36ecff8f9a997882ad4a
# Code AST SHA-256:   31070d9a89a0943f2584c1b6f1906c22855ed5bf0c2966c9c90f333af779e255
# Verified Classes:   AttributionReconciliationError
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class AttributionReconciliationError(RuntimeError):
    """Raised when per-hop token attribution cannot be reconciled to the invoice."""


def reconcile_spend(
    invoice_input_tokens: int,
    invoice_output_tokens: int,
    trace_input_tokens: int,
    trace_output_tokens: int,
    fan_out_depth: int,
    retry_rate: float,
    mean_call_cost_tokens: float,
    tolerance_ratio: float = 0.02,
) -> dict:
    """Reconcile trace-derived attribution against authoritative provider billing.

    The trace sum is an estimate; the invoice is authoritative. A residual that
    exceeds tolerance is a signal, not noise -- it means the serialization
    boundary is unmeasured or a retry loop is double-billing.
    """
    if fan_out_depth < 1:
        raise AttributionReconciliationError(
            f"fan_out_depth must be >= 1, got {fan_out_depth}"
        )

    invoice_total = invoice_input_tokens + invoice_output_tokens
    trace_total = trace_input_tokens + trace_output_tokens
    if invoice_total == 0:
        raise AttributionReconciliationError(
            "invoice reports zero tokens; cannot reconcile against a zero baseline"
        )

    residual = invoice_total - trace_total
    residual_ratio = residual / invoice_total
    retry_tolerance = retry_rate * mean_call_cost_tokens * fan_out_depth
    allowed = max(tolerance_ratio * invoice_total, retry_tolerance)

    # Hop-level attribution is only valid at depth 1 with no re-serialization.
    if fan_out_depth > 1 and abs(residual) > allowed:
        raise AttributionReconciliationError(
            "federated-hop attribution gap exceeds tolerance: "
            f"residual={residual} tokens ({residual_ratio:.2%}), "
            f"allowed={allowed:.0f}, fan_out_depth={fan_out_depth}. "
            "Attribute at the serialization boundary, not the hop."
        )

    return {
        "invoice_total": invoice_total,
        "trace_total": trace_total,
        "residual": residual,
        "residual_ratio": round(residual_ratio, 6),
        "allowed": round(allowed, 2),
        "status": "reconciled" if abs(residual) <= allowed else "drift",
    }
