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

### `queue/__init__.py`
```python
"""Queue package initialization. Exposes the public API for job handling."""

from .core import Job, JobQueue
from .priority import PriorityQueue
from .retry import process_with_retry

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

### `queue/core.py`
```python
"""Core data models and basic FIFO queue operations."""

from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Optional


@dataclass
class Job:
    """Represents a unit of work to be processed."""
    job_id: str
    payload: Any
    status: str = "pending"
    created_at: datetime = field(default_factory=datetime.now)


class JobQueue:
    """Basic FIFO queue for managing jobs."""

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

    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 first job in the queue."""
        if self.is_empty():
            return None
        return self._queue.pop(0)

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

    def size(self) -> int:
        """Return the number of jobs in the queue."""
        return len(self._queue)
```

### `queue/priority.py`
```python
"""Priority queue implementation using a min-heap."""

import heapq
from typing import Optional

from .core import Job


class PriorityQueue:
    """Priority-aware queue where lower integer values indicate higher priority."""

    def __init__(self) -> None:
        self._heap: list[tuple[int, int, Job]] = []
        self._counter: int = 0  # Ensures stable ordering for equal priorities

    def enqueue(self, job: Job, priority: int = 0) -> None:
        """Add a job with the given priority."""
        # Tuple comparison uses priority first, then counter for stability
        entry = (priority, self._counter, job)
        self._counter += 1
        heapq.heappush(self._heap, entry)

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

    def is_empty(self) -> bool:
        """Check if the queue contains no jobs."""
        return len(self._heap) == 0

    def size(self) -> int:
        """Return the number of jobs in the queue."""
        return len(self._heap)
```

### `queue/retry.py`
```python
"""Retry logic with exponential backoff and optional jitter."""

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

from .core import Job

R = TypeVar("R")


def process_with_retry(
    job: Job,
    func: Callable[[Job], R],
    max_retries: int = 3,
    base_delay: float = 1.0,
    max_delay: float = 60.0,
    exponential_base: float = 2.0,
    jitter: bool = True,
) -> R:
    """Execute a function on a job with exponential backoff retry logic.
    
    Args:
        job: The job instance to process.
        func: Callable that accepts a Job and returns a result.
        max_retries: Maximum number of retry attempts after the first failure.
        base_delay: Initial delay in seconds before the first retry.
        max_delay: Maximum delay cap in seconds.
        exponential_base: Base for exponential backoff calculation.
        jitter: Whether to add random variance to delay times.
        
    Returns:
        The result of the successful function call.
        
    Raises:
        The last exception caught if all retries are exhausted.
    """
    last_exception = None

    for attempt in range(max_retries + 1):
        try:
            result = func(job)
            job.status = "completed"
            return result
        except Exception as e:
            last_exception = e
            if attempt >= max_retries:
                break

            # Calculate delay with exponential growth
            delay = min(base_delay * (exponential_base ** attempt), max_delay)
            if jitter:
                delay *= (0.5 + random.random() * 0.5)
            
            time.sleep(delay)

    job.status = "failed"
    raise last_exception
```

### Key Improvements Made:
1. **Single Responsibility**: Each module handles exactly one domain concept (data/basic queue, priority ordering, retry mechanics)
2. **Safe Imports**: Uses relative imports (`.core`, `.priority`, `.retry`) preventing circular dependency issues and making the package portable
3. **Type Safety**: Added full type hints, `TypeVar` for generic return types, and `Optional` where appropriate
4. **Stable Priority Queue**: Uses a monotonic counter as a tie-breaker in the heap tuple so jobs with equal priority are processed in FIFO order
5. **Production-Ready Retry**: Includes jitter to prevent thundering herd problems, delay capping, and proper exception propagation
6. **Clean API**: `__init__.py` explicitly controls what's exposed, making `import queue` predictable and IDE-friendly