Here's the refactored package structure with clean separation of concerns, proper relative imports, and a focused public API.

### `queue/__init__.py`
```python
from .core import Job, JobQueue

__all__ = ["Job", "JobQueue"]
```

### `queue/core.py`
```python
from dataclasses import dataclass, field
from typing import Any, Callable, Optional
import time
import uuid

@dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str = field(default_factory=lambda: str(uuid.uuid4()))
    payload: Any = None
    status: str = "pending"
    created_at: float = field(default_factory=time.time)

    def __repr__(self) -> str:
        return f"Job(id={self.id}, status={self.status})"


class JobQueue:
    """Basic FIFO queue for job management."""
    def __init__(self) -> None:
        self._storage: list[Job] = []

    def enqueue(self, job: Job) -> None:
        """Add a job to the back of the queue."""
        self._storage.append(job)

    def dequeue(self) -> Optional[Job]:
        """Remove and return the job at the front of the queue."""
        if not self._storage:
            return None
        return self._storage.pop(0)

    def process(self, handler: Callable[[Job], Any]) -> None:
        """Process all jobs in the queue using the provided handler."""
        while True:
            job = self.dequeue()
            if job is None:
                break
            job.status = "processing"
            handler(job)  # Exceptions propagate to caller
```

### `queue/priority.py`
```python
from .core import Job, JobQueue
import heapq

class PriorityQueue(JobQueue):
    """Priority-aware queue that processes higher-priority jobs first."""
    def __init__(self) -> None:
        super().__init__()
        self._heap: list[tuple[int, int, Job]] = []
        self._counter: int = 0

    def enqueue(self, job: Job, priority: int = 0) -> None:
        """Add a job with a priority level (lower number = higher priority)."""
        self._counter += 1
        # Tuple: (priority, insertion_order, job) ensures stable sorting
        heapq.heappush(self._heap, (priority, self._counter, job))

    def dequeue(self) -> Job | None:
        """Remove and return the highest priority job."""
        if not self._heap:
            return None
        _, _, job = heapq.heappop(self._heap)
        return job
```

### `queue/retry.py`
```python
import time
from .core import Job
from typing import Callable, Any, Optional

def process_with_retry(
    job: Job,
    handler: Callable[[Job], Any],
    max_retries: int = 3,
    base_delay: float = 1.0,
    max_delay: float = 60.0
) -> Optional[Any]:
    """
    Execute a job handler with exponential backoff retry logic.
    
    Args:
        job: The job instance to process and update status on.
        handler: Callable that accepts a Job and performs the work.
        max_retries: Maximum number of retry attempts.
        base_delay: Initial delay in seconds before first retry.
        max_delay: Cap on delay duration in seconds.
        
    Returns:
        The result of the handler on success, or None if all retries fail.
        
    Raises:
        The last exception raised by the handler after max retries exhausted.
    """
    last_exception = None
    
    for attempt in range(max_retries + 1):
        try:
            job.status = "processing"
            result = handler(job)
            job.status = "completed"
            return result
        except Exception as e:
            last_exception = e
            job.status = f"failed_attempt_{attempt + 1}"
            
            if attempt == max_retries:
                job.status = "failed"
                break
                
            # Exponential backoff with cap
            delay = min(base_delay * (2 ** attempt), max_delay)
            time.sleep(delay)
            
    raise last_exception
```

### Key Refactoring Decisions:
1. **Single Responsibility**: 
   - `core.py` handles job representation & basic queue mechanics
   - `priority.py` extends queue behavior with heap-based ordering
   - `retry.py` isolates failure recovery & backoff logic
2. **Inheritance Strategy**: `PriorityQueue` inherits `JobQueue` but overrides `enqueue`/`dequeue` to use a heap. The inherited `process` method automatically respects priority ordering since it calls `self.dequeue()`.
3. **Clean API**: `__init__.py` explicitly controls the public surface via `__all__`, while internal modules use relative imports to avoid circular dependencies.
4. **Status Management**: Job status transitions are handled consistently across modules, with `retry.py` explicitly tracking attempt counts for observability.
5. **Modern Python**: Uses `dataclass`, type hints, and Python 3.9+ syntax (`list[Job]`, `Job | None`). Can be easily downgraded to `typing.List`/`Optional` if targeting older versions.