# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-bound-recursive-delegation-so-a-sub-plan-authority-does-not-exceed-its-parent.md
# Remnant Warrant:    https://corpusfetch.com/c/how-must-an-instance-bound-recursive-delegation-so-a-sub-plan-authority-does-not-exceed-its-parent.warrant.json
# Markdown SHA-256:   7a371e00e511a5325d9af5d97d223af0ea3963267276427a8214a4ab8b457cdb
# Code AST SHA-256:   df3e809bb13942825d0824ba81a65219164028d2bf9a0477be1cc52b0e3236da
# Verified Classes:   AuthorityWashingError, DelegationHop, DelegationPath
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class AuthorityWashingError(RuntimeError):
    """Raised when a delegation composition can grant authority the root never held."""


@dataclass(frozen=True)
class DelegationHop:
    parent_holds: frozenset
    parent_grants: frozenset
    child_uses: frozenset

    def verify(self) -> bool:
        if not self.parent_grants <= self.parent_holds:
            raise AuthorityWashingError(
                f"parent grants {sorted(self.parent_grants)} not subset of holds {sorted(self.parent_holds)}"
            )
        if not self.child_uses <= self.parent_grants:
            raise AuthorityWashingError(
                f"child uses {sorted(self.child_uses)} exceed grants {sorted(self.parent_grants)}"
            )
        return True


@dataclass(frozen=True)
class DelegationPath:
    hops: tuple
    root_holds: frozenset

    def verify(self) -> bool:
        for hop in self.hops:
            if not hop.verify():
                return False
        leaf_uses = self.hops[-1].child_uses if self.hops else frozenset()
        if not leaf_uses <= self.root_holds:
            raise AuthorityWashingError(
                f"leaf uses {sorted(leaf_uses)} exceed root holds {sorted(self.root_holds)}"
            )
        return True


def dispatch_delegation_mode(path: DelegationPath) -> str:
    try:
        path.verify()
    except AuthorityWashingError:
        return "halt-and-reconcile-graph"
    return "dispatch"
