```python
"""The cheapest set of travel passes covering every trip day."""


def _validate_plan(trip_days, passes):
    for day in trip_days:
        if isinstance(day, bool) or not isinstance(day, int) or day < 1:
            raise ValueError("trip days must be positive integers")
    for earlier, later in zip(trip_days, trip_days[1:]):
        if later <= earlier:
            raise ValueError("trip days must be strictly increasing")
    if not passes:
        raise ValueError("at least one pass kind is required")
    for cover in passes:
        span = cover["span"]
        cost = cover["cost"]
        if isinstance(span, bool) or not isinstance(span, int) or span < 1:
            raise ValueError("pass span must be a positive integer")
        if isinstance(cost, bool) or not isinstance(cost, int) or cost < 0:
            raise ValueError("pass cost must be a non-negative integer")


def cheapest_pass_plan(trip_days: list, passes: list) -> dict:
    _validate_plan(trip_days, passes)
    
    if not trip_days:
        return {"total": 0, "purchases": []}
    
    # dp[i] is the min cost to cover trip_days[i:]
    # We process from the last trip day backwards to the first.
    # State: index into trip_days (0 to len(trip_days))
    # Base case: dp[len(trip_days)] = 0 (no trips left to cover)
    
    n = len(trip_days)
    # dp[i] = min cost to cover trips from index i to n-1
    dp = [0] * (n + 1)
    
    # best_pass[i] stores the index of the pass kind chosen at trip i
    # to achieve the optimal cost.
    best_pass = [-1] * n
    
    for i in range(n - 1, -1, -1):
        current_day = trip_days[i]
        min_cost = float('inf')
        chosen_idx = -1
        
        for p_idx, p in enumerate(passes):
            span = p["span"]
            cost = p["cost"]
            
            # This pass covers days [current_day, current_day + span - 1]
            # We need to find the first trip index j such that trip_days[j] > current_day + span - 1
            # All trips from i to j-1 are covered by this pass.
            # The remaining cost is dp[j].
            
            # Find j using binary search or linear scan (since we go backwards, 
            # but trips are sorted, we can just scan forward from i)
            # Optimization: since we iterate i backwards, we can maintain a pointer?
            # Actually, for each i, we just need to find the next uncovered trip.
            # Let's just scan. n is likely small enough for this DP approach.
            
            limit = current_day + span - 1
            j = i
            while j < n and trip_days[j] <= limit:
                j += 1
            
            total_cost = cost + dp[j]
            if total_cost < min_cost:
                min_cost = total_cost
                chosen_idx = p_idx
            elif total_cost == min_cost:
                # Tie-breaking: if costs are equal, we don't change choice 
                # based on pass index here because the problem says "when several 
                # pass kinds tie for a