# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/under-what-conditions-must-an-instance-refuse-a-delegated-agent-token-whose-attenuation-proof-verifies-but-whose-scope-lattice-is-non-idempotent.md
# Remnant Warrant:    https://corpusfetch.com/c/under-what-conditions-must-an-instance-refuse-a-delegated-agent-token-whose-attenuation-proof-verifies-but-whose-scope-lattice-is-non-idempotent.warrant.json
# Markdown SHA-256:   66e3d0782485920c997c804223878b60fa3efce7abf74e23b6dcadd3554dac9b
# Code AST SHA-256:   4829a1d782f9f13b050fd9800884b3da5be17078045e085c612b64583c1a57bc
# Verified Classes:   UnverifiableAttenuation, AttenuationViolation
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class UnverifiableAttenuation(RuntimeError):
    """Raised when a delegated token's attenuation cannot be checked
    against the downstream authorizer's normalization."""
    pass


class AttenuationViolation(RuntimeError):
    """Raised when a witness action proves the child scope escapes the
    parent scope under the downstream normalizer."""
    pass


def admit_delegation(
    parent_scope,
    child_scope,
    proof,
    downstream_normalizer,
    candidate_actions,
):
    # Step 1: the proof must verify under the verifier's normalizer.
    if not proof.verifies(child_scope, parent_scope):
        raise AttenuationViolation(
            f"proof does not verify: {child_scope} ⊄ {parent_scope}"
        )

    # Step 2: opaque downstream authorizer -> cannot construct a witness.
    if downstream_normalizer is None:
        raise UnverifiableAttenuation(
            "downstream normalizer unavailable; cannot witness-check "
            f"attenuation of {child_scope} under {parent_scope}"
        )

    # Step 3: search for a witness action that escapes the parent scope
    # under the downstream normalizer.
    for action in candidate_actions:
        child_admits = downstream_normalizer.admits(child_scope, action)
        parent_admits = downstream_normalizer.admits(parent_scope, action)
        if child_admits and not parent_admits:
            raise AttenuationViolation(
                f"witness action {action!r} admitted by child {child_scope} "
                f"but not by parent {parent_scope} under downstream "
                f"normalizer {downstream_normalizer.name!r}"
            )

    return True
