Here's the refactored package structure with clean separation of concerns, type hints, and proper module boundaries:

### `queue/__init__.py`
```python
"""Job Queue Package - Public API"""

from .core import Job, JobQueue

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

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

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


@dataclass
class Job:
    """Represents a unit of work in the queue."""
    id: str
    payload: Any
    status: str = "pending"
    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: Optional[datetime] = None

    def mark_updated(self) -> None:
        """Update the job's timestamp."""
        self.updated_at = datetime.now(timezone.utc)


class JobQueue:
    """Basic FIFO job queue implementation."""

    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 not self._queue:
            return None
        return self._queue.pop(0)

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

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

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

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

import heapq
from typing import Any, Optional

from .core import Job


class PriorityQueue:
    """Priority-aware job queue. Lower priority values are processed first."""

    def __init__(self) -> None:
        self._heap: list = []
        self._counter: int = 0  # Ensures FIFO order for equal priorities

    def enqueue(self, job: Job, priority: int = 0) -> None:
        """Add a job with a given priority."""
        # heapq is a min-heap; counter breaks ties deterministically
        entry = (priority, self._counter, job)
        self._counter += 1
        heapq.heappush(self._heap, entry)

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

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

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

    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."""

import logging
import time
from typing import Any, Callable, Optional, Tuple, Type

from .core import Job

logger = logging.getLogger(__name__)


def process_with_retry(
    job: Job,
    processor: Callable[[Job], Any],
    max_retries: int = 3,
    base_delay: float = 1.0,
    exponential_base: float = 2.0,
    retryable_exceptions: Tuple[Type[Exception], ...] = (Exception,),
) -> Any:
    """
    Execute a job processor with exponential backoff retry logic.

    Args:
        job: The job to process.
        processor: Callable that accepts a Job and returns a result.
        max_retries: Maximum number of retry attempts.
        base_delay: Initial delay in seconds.
        exponential_base: Multiplier for backoff calculation.
        retryable_exceptions: Tuple of exception types that trigger a retry.

    Returns:
        The result of the processor on success.

    Raises:
        The last caught exception if max_retries is exceeded.
    """
    last_exception: Optional[Exception] = None

    for attempt in range(max_retries):
        try:
            result = processor(job)
            job.status = "completed"
            job.mark_updated()
            return result

        except retryable_exceptions as e:
            last_exception = e
            job.status = f"retry_{attempt + 1}"
            job.mark_updated()
            logger.warning(
                "Job %s failed (attempt %d/%d): %s",
                job.id,
                attempt + 1,
                max_retries,
                e,
            )

            if attempt < max_retries - 1:
                delay = base_delay * (exponential_base ** attempt)
                logger.info("Retrying in %.2f seconds...", delay)
                time.sleep(delay)
            else:
                job.status = "failed"
                job.mark_updated()
                logger.error(
                    "Job %s permanently failed after %d attempts: %s",
                    job.id,
                    max_retries,
                    e,
                )
                raise

    # Fallback for type checkers; should never be reached
    raise last_exception  # type: ignore[misc]
```

### Key Design Decisions:
1. **Single Responsibility**: Each module handles exactly one concern (`core.py` for data/basic queue, `priority.py` for ordering, `retry.py` for resilience)
2. **Relative Imports**: Uses `from .core import Job` to avoid circular dependencies and work correctly within the package
3. **Clean Public API**: `__init__.py` explicitly exports only `Job` and `JobQueue`, hiding implementation details while keeping the main entry point simple
4. **Type Safety**: Full type hints throughout, with proper handling of `Optional` and generic types
5. **Deterministic Priority**: Uses a monotonic counter in `PriorityQueue` to break ties, ensuring FIFO behavior for equal priorities
6. **Observability**: Jobs track status updates and timestamps; retry logic logs appropriately without breaking the call chain

You can now import cleanly via:
```python
from queue import Job, JobQueue
from queue.priority import PriorityQueue
from queue.retry import process_with_retry
```