```python
def span_merge(spans: list) -> list:
    """Merge overlapping or touching spans into a single span, ordered by start."""
    if not spans:
        return []

    # Validate input spans
    for span in spans:
        if not isinstance(span, (list, tuple)) or len(span) != 2:
            raise ValueError("Each span must be a list or tuple of two elements")
        start, end = span
        if start > end:
            raise ValueError("Span start must not exceed end")

    # Sort spans by start time, then by end time
    sorted_spans = sorted(spans, key=lambda x: (x[0], x[1]))

    merged = []
    for span in sorted_spans:
        start, end = span
        if merged and start <= merged[-1][1]:
            # Overlapping or touching: merge with the last span
            merged[-1] = (merged[-1][0], max(merged[-1][1], end))
        else:
            merged.append([start, end])

    return merged
```