```python
def split_agenda(sessions: list, limit: int) -> list:
    """
    Split a list of coaching sessions into smaller blocks based on a maximum duration limit.
    
    Args:
        sessions: A list of [start, end] pairs representing coaching sessions.
        limit: The maximum duration for a single block.
        
    Returns:
        A list of [start, end] pairs representing the split blocks.
        
    Raises:
        ValueError: If inputs are invalid.
    """
    # Validate limit
    if not isinstance(limit, int) or limit < 1:
        raise ValueError("Limit must be an integer of at least 1.")
    
    # Validate sessions structure and content
    if not isinstance(sessions, list):
        raise ValueError("Sessions must be a list.")
        
    prev_end = None
    
    for session in sessions:
        if not isinstance(session, list) or len(session) != 2:
            raise ValueError("Each session must be a list of two elements.")
        
        start, end = session
        
        # Check if bounds are whole numbers (integers)
        if not isinstance(start, int) or not isinstance(end, int):
            raise ValueError("Session bounds must be whole numbers (integers).")
        
        # Check start < end
        if start >= end:
            raise ValueError("Session start must precede its end.")
        
        # Check chronological order
        if prev_end is not None and start < prev_end:
            raise ValueError("A session cannot start before the previous session ends.")
            
        prev_end = end

    result = []
    
    for session in sessions:
        start, end = session
        blocks = _split_session(start, end, limit)
        result.extend(blocks)
        
    return result


def _split_session(start: int, end: int, limit: int) -> list:
    """
    Recursively split a single session into blocks of at most `limit` duration.
    
    Args:
        start: The start time of the session.
        end: The end time of the session.
        limit: The maximum duration for a block.
        
    Returns:
        A list of [start, end] pairs.
    """
    duration = end - start
    
    if duration <= limit:
        return [[start, end]]
    
    # Calculate midpoint
    # "front half taking the extra minute when the length is odd"
    # If duration is odd, e.g., 5, limit is 2.
    # Midpoint calculation: start + duration // 2
    # If duration is 5, duration // 2 is 2. So first block is [start, start+2].
    # Remaining is 3. Next split of 3 with limit 2: midpoint 1. [start+2, start+3], [start+3, start+5].
    # This matches "front half taking the extra minute".
    
    mid = start + (duration // 2)
    
    left_blocks = _split_session(start, mid, limit)
    right_blocks = _split_session(mid, end, limit)
    
    return left_blocks + right_blocks
```