Skip to content

symfonic.agent.cutover.lazy_palette

lazy_palette

Compatibility composition of a real router or explicit full-palette decline.

Missing prerequisites are not routing evidence. The host already issued the legacy construction warning; this seam transports its facts without another warning or an invented empty procedural source. Unexpected composition faults are still handled by the host's existing default-deny seam.

CORE-227: only a procedural row selected by cue match narrows the palette. Importance-fallback and empty-cue rows are not routing evidence, so the turn keeps every registered tool and says why. With registered tools, a layer that cannot report row origin composes no router and the host's counted refusal applies. Served memory with nothing registered always composes the uncounted no-registered-tools decline, never a router. No decline this host composes over zero registered tools is counted, memory off included. Narrowing on a matched cue is an Agent improvement, not legacy bind_tools parity.

serves_unavailable_palette

serves_unavailable_palette(bundle: Any) -> bool

Only a real, folded full-palette resolution stage is serving evidence.

Source code in src/symfonic/agent/cutover/lazy_palette.py
def serves_unavailable_palette(bundle: Any) -> bool:
    """Only a real, folded full-palette resolution stage is serving evidence."""
    from symfonic.capabilities.tools.capability import ToolsCapability
    from symfonic.capabilities.tools.routing import RoutingUnavailable

    router = getattr(bundle, "router", None)
    return (
        type(router) is ToolsCapability
        and type(router.routing_unavailable) is RoutingUnavailable
        and "tools" in bundle.capability_names
        and callable(bundle.stage_handlers.get("tools.routing"))
        and any(
            stage.stage_id == "tools.routing"
            and stage.emits == frozenset({"tools.routing_unavailable"})
            for stage in bundle.stages
        )
    )