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

### `queue/__init__.py`
```python
"""Job queue package with core, priority, and retry capabilities."""
from .core import Job, JobQueue

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

### `queue/core.py`
```python
"""Core job definitions and basic FIFO queue operations."""
from __future__ import annotations

import time
from collections import deque
from dataclasses import dataclass, field
from typing import Any, Optional


@dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str
    payload: Any
    status: str = "pending"
    created_at: float = field(default_factory=time.time)
    attempts: int = 0
    max_retries: int = 3

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


class JobQueue:
    """A simple FIFO queue for processing jobs."""

    def __init__(self) -> None:
        self._queue: deque[Job] = deque()

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

    def dequeue(self) -> Optional[Job]:
        """Remove and return the job at the front of the queue."""
        return self._queue.popleft() if self._queue else None

    def peek(self) -> Optional[Job]:
        """Return the job at the front without removing it."""
        return self._queue[0] if self._queue else None

    def is_empty(self) -> bool:
        """Check if the queue is empty."""
        return len(self._queue) == 0

    def __len__(self) -> int:
        return len(self._queue)
```

### `queue/priority.py`
```python
"""Priority queue implementation for job scheduling."""
from __future__ import annotations

import heapq
from typing import Optional

from .core import Job


class PriorityQueue:
    """A min-heap based priority queue for jobs."""

    def __init__(self) -> None:
        self._heap: list[tuple[int, int, Job]] = []
        self._counter: int = 0  # Tie-breaker to preserve FIFO order for equal priorities

    def enqueue(self, job: Job, priority: int = 0) -> None:
        """Add a job with the given priority (lower number = higher priority)."""
        heapq.heappush(self._heap, (priority, self._counter, job))
        self._counter += 1

    def dequeue(self) -> Optional[Job]:
        """Remove and return the job with the highest priority."""
        if self._heap:
            _, _, job = heapq.heappop(self._heap)
            return job
        return None

    def peek(self) -> Optional[Job]:
        """Return the highest priority job without removing it."""
        if self._heap:
            return self._heap[0][2]
        return None

    def is_empty(self) -> bool:
        """Check if the queue is empty."""
        return len(self._heap) == 0
```

### `queue/retry.py`
```python
"""Retry logic with exponential backoff for job processing."""
from __future__ import annotations

import random
import time
from typing import Any, Callable, Optional

from .core import Job


def process_with_retry(
    job: Job,
    handler: Callable[[Job], Any],
    base_delay: float = 1.0,
    max_retries: Optional[int] = None
) -> Any:
    """
    Execute a job handler with exponential backoff retry logic.

    Args:
        job: The job instance to process.
        handler: Callable that processes the job.
        base_delay: Base delay in seconds for the first retry.
        max_retries: Maximum number of retry attempts. Defaults to job.max_retries.

    Returns:
        The result of the handler.

    Raises:
        Exception: Re-raises the last exception if max retries are exceeded.
    """
    retries = max_retries if max_retries is not None else job.max_retries

    for attempt in range(retries + 1):
        try:
            job.attempts = attempt + 1
            return handler(job)
        except Exception as e:
            if attempt == retries:
                raise
            # Exponential backoff with jitter to prevent thundering herd
            delay = base_delay * (2 ** attempt) + random.uniform(0, base_delay * 0.5)
            time.sleep(delay)

    # Fallback to satisfy type checkers, though logically unreachable
    raise RuntimeError("Unexpected retry loop exit")
```

### Key Design Decisions:
1. **Single Responsibility**: `core.py` handles data modeling & FIFO operations, `priority.py` encapsulates heap-based scheduling, and `retry.py` isolates failure recovery logic.
2. **Relative Imports**: All cross-module imports use `from .module import ...` to prevent circular dependencies and keep the package self-contained.
3. **Clean Public API**: `__init__.py` explicitly controls what's exposed via `__all__`. Internal or advanced classes (`PriorityQueue`, `process_with_retry`) remain accessible via direct imports if needed: `from queue.priority import PriorityQueue`.
4. **Type Safety & Modern Python**: Uses `from __future__ import annotations` for forward compatibility, standard library `dataclass`/`heapq`/`deque`, and consistent type hints.
5. **Jitter in Retry**: Added random jitter to exponential backoff to prevent synchronized retry storms in distributed systems.