```python:inference/core/managers/inference_models_cache_watchdog.py
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum
from typing import List, Optional

SECONDS_IN_DAY = 60 * 60 * 24
RECENT_THRESHOLD_DAYS = 1
WARM_THRESHOLD_DAYS = 7
STALE_THRESHOLD_DAYS = 30


@dataclass(frozen=True)
class FileInfo:
    path: str
    size_mb: float
    modified_at: datetime


class StalenessGroup(Enum):
    ABANDONED = 0
    STALE = 1
    WARM = 2
    RECENT = 3


def rank_for_deletion(
    files: List[FileInfo],
    now: Optional[datetime] = None,
    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,
    warm_threshold_days: float = WARM_THRESHOLD_DAYS,
    stale_threshold_days: float = STALE_THRESHOLD_DAYS,
) -> List[FileInfo]:
    if not files:
        return []
    if now is None:
        now = datetime.now()

    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):
        raise ValueError(
            f"Thresholds must be in ascending order: "
            f"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})"
        )

    # Precompute cutoff datetimes to avoid per-file float/timedelta allocation and division.
    stale_cutoff = now - timedelta(seconds=stale_threshold_days * SECONDS_IN_DAY)
    warm_cutoff = now - timedelta(seconds=warm_threshold_days * SECONDS_IN_DAY)
    recent_cutoff = now - timedelta(seconds=recent_threshold_days * SECONDS_IN_DAY)

    # Inline staleness grouping in the key to avoid an extra function call per file.
    return sorted(
        files,
        key=lambda f: (
            0 if f.modified_at < stale_cutoff
            else 1 if f.modified_at < warm_cutoff
            else 2 if f.modified_at < recent_cutoff
            else 3,
            -f.size_mb,
        ),
    )
```