```python
def span_merge(spans: list) -> list:
    if not spans:
        return []

    # Sort spans by start time, then end time to handle touching spans correctly
    spans.sort(key=lambda x: (x[0], x[1]))

    merged = [spans[0]]
    for current in spans[1:]:
        last_merged = merged[-1]
        if current[0] <= last_merged[1]:
            # Merge overlapping or touching spans
            merged[-1] = (last_merged[0], max(last_merged[1], current[1]))
        else:
            merged.append(current)

    return merged
```