"""One execution gate; invalid plans remain valid diagnostic objects."""

from src.domain.app_blocks.errors import UnsatisfiableAppBlockPlanError
from src.domain.app_blocks.schemas import AppBlockPlan


def assert_install_plan_installable(plan: AppBlockPlan) -> None:
    """Reject before side effects without changing or repairing the plan."""
    if plan.unsatisfiable:
        raise UnsatisfiableAppBlockPlanError(
            [gap for gap in plan.gaps if gap.severity == "build_blocking"]
        )
