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
from .priority import PriorityQueue
from .retry import process_with_retry

# Public API
__all__ = ["Job", "JobQueue", "PriorityQueue", "process_with_retry"]
```

### `queue/core.py`
```python
from __future__ import annotations
import dataclasses
import time
from typing import Callable, Any, Optional

@dataclasses.dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str
    func: Callable[..., Any]
    args: tuple = ()
    kwargs: dict = None
    priority: int = 0
    max_retries: int = 3
    created_at: float = dataclasses.field(default_factory=time.time)

    def __post_init__(self):
        if self.kwargs is None:
            self.kwargs = {}


class JobQueue:
    """Basic FIFO queue implementation for processing jobs."""
    def __init__(self):
        self._jobs: list[Job] = []

    def add(self, job: Job) -> None:
        self._jobs.append(job)

    def get_next(self) -> Optional[Job]:
        if not self._jobs:
            return None
        return self._jobs.pop(0)

    def is_empty(self) -> bool:
        return len(self._jobs) == 0

    def size(self) -> int:
        return len(self._jobs)
```

### `queue/priority.py`
```python
from __future__ import annotations
import heapq
from typing import Optional
from .core import Job


class PriorityQueue:
    """Priority-based queue implementation using a min-heap."""
    def __init__(self):
        self._heap: list[tuple[int, int, Job]] = []
        self._counter: int = 0  # Tie-breaker for stable ordering

    def add(self, job: Job) -> None:
        # Lower priority value = higher priority
        entry = (job.priority, self._counter, job)
        self._counter += 1
        heapq.heappush(self._heap, entry)

    def get_next(self) -> Optional[Job]:
        if not self._heap:
            return None
        _, _, job = heapq.heappop(self._heap)
        return job

    def is_empty(self) -> bool:
        return len(self._heap) == 0

    def size(self) -> int:
        return len(self._heap)
```

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

logger = logging.getLogger(__name__)


def process_with_retry(
    job: Job,
    max_retries: Optional[int] = None,
    base_delay: float = 1.0,
    max_delay: float = 60.0
) -> Any:
    """Execute a job with exponential backoff retry logic."""
    retries = max_retries if max_retries is not None else job.max_retries
    last_exception = None

    for attempt in range(retries + 1):
        try:
            return job.func(*job.args, **job.kwargs)
        except Exception as e:
            last_exception = e
            if attempt == retries:
                logger.error(
                    f"Job {job.id} permanently failed after {retries + 1} "
                    f"attempts: {e}"
                )
                raise
            delay = min(base_delay * (2 ** attempt), max_delay)
            logger.warning(
                f"Job {job.id} attempt {attempt + 1} failed: {e}. "
                f"Retrying in {delay}s..."
            )
            time.sleep(delay)

    raise RuntimeError("Retry loop completed without returning or raising")
```

### Key Improvements
1. **Single Responsibility**: 
   - `core.py`: Job data structure & basic FIFO queue
   - `priority.py`: Heap-based ordering logic
   - `retry.py`: Exponential backoff & error handling
   - `__init__.py`: Package boundary & public API
2. **Proper Imports**: All cross-module references use relative imports (`.core`, `.priority`, etc.), making the package self-contained and import-safe.
3. **Clean API**: `__all__` explicitly defines the public interface. Users can do `from queue import Job, JobQueue, PriorityQueue, process_with_retry`.
4. **Type Safety**: Full type hints with `from __future__ import annotations` for forward compatibility.
5. **Extensible**: Each module can be tested, versioned, or replaced independently without touching the others.

### Usage Example
```python
from queue import Job, JobQueue, PriorityQueue, process_with_retry
import logging

logging.basicConfig(level=logging.INFO)

# Basic queue
q = JobQueue()
q.add(Job(id="job1", func=lambda: print("Hello")))
while not q.is_empty():
    job = q.get_next()
    process_with_retry(job)

# Priority queue
pq = PriorityQueue()
pq.add(Job(id="low", func=lambda: print("Low"), priority=5))
pq.add(Job(id="high", func=lambda: print("High"), priority=1))
while not pq.is_empty():
    job = pq.get_next()
    process_with_retry(job)
```