# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/where-must-an-instance-refuse-to-expand-a-federated-capability-graph-when-trust-attenuation-and-capability-composition-disagree.md
# Remnant Warrant:    https://corpusfetch.com/c/where-must-an-instance-refuse-to-expand-a-federated-capability-graph-when-trust-attenuation-and-capability-composition-disagree.warrant.json
# Markdown SHA-256:   c6a3fd493e72ea9156d8fb14968b24363d8a91f76031f095bd18477d11c37466
# Code AST SHA-256:   899bc12cbe15a47fe409c2a5b30d48610cc8916a95023637f2b3c76c360ed045
# Verified Classes:   FederationExpansionError
# Defensive Guards:   5 fail-closed invariants (zero external deps)

class FederationExpansionError(RuntimeError):
    """Raised when a capability graph expansion would enqueue an inadmissible child."""
    pass


def should_expand(parent_trust: float, edge_attenuation: float,
                  child_min_trust: float, child_capability_id: str) -> bool:
    """Edge-local admissibility check. Returns True iff the prospective child
    is admissible under the composed trust of the path about to be traversed.

    Refuses (returns False) when composed trust falls below the CHILD's
    threshold -- not the parent's. This is the boundary invariant.
    """
    if not (0.0 <= parent_trust <= 1.0):
        raise FederationExpansionError(
            f"parent_trust out of range: {parent_trust!r}"
        )
    if not (0.0 < edge_attenuation <= 1.0):
        # attenuation must be non-amplifying for this check to be sound;
        # amplifying brokers require re-attestation, not this function.
        raise FederationExpansionError(
            f"non-monotone attenuation {edge_attenuation!r} on edge to "
            f"{child_capability_id!r}; recompute with re-attestation"
        )
    if not (0.0 <= child_min_trust <= 1.0):
        raise FederationExpansionError(
            f"child_min_trust out of range for {child_capability_id!r}: "
            f"{child_min_trust!r}"
        )

    composed = parent_trust * edge_attenuation
    if composed < child_min_trust:
        # Boundary failure: do NOT enqueue this child. Prune this edge and
        # continue with sibling paths -- do not abort the whole expansion.
        return False
    return True


def expand_node(parent_trust: float, children: list[dict]) -> list[str]:
    """Expand a node's children, enqueueing only admissible ones."""
    admitted = []
    for child in children:
        cap_id = child["capability_id"]
        try:
            ok = should_expand(
                parent_trust=parent_trust,
                edge_attenuation=child["attenuation"],
                child_min_trust=child["min_execution_trust"],
                child_capability_id=cap_id,
            )
        except FederationExpansionError as exc:
            # Malformed edge metadata is a hard stop: we cannot reason about
            # admissibility, so we must not guess.
            raise FederationExpansionError(
                f"cannot evaluate edge to {cap_id!r}: {exc}"
            ) from exc
        if ok:
            admitted.append(cap_id)
    return admitted


if __name__ == "__main__":
    # Reproduces the observed three-hop failure: 0.90^3 = 0.729 < 0.80.
    children = [
        {"capability_id": "gamma:batch-write",
         "attenuation": 0.90, "min_execution_trust": 0.80},
        {"capability_id": "delta:nested-decompose",
         "attenuation": 0.90 * 0.90, "min_execution_trust": 0.80},
    ]
    admitted = expand_node(parent_trust=0.90, children=children)
    assert "delta:nested-decompose" not in admitted, (
        "phantom child leaked into expansion"
    )
    print("admitted:", admitted)
