def METHOD_NAME(
    old: "DataIndex",
    new: "DataIndex",
    *,
    granular: bool = False,
    not_in_cache: bool = False,
    not_in_remote: bool = False,
    remote_refresh: bool = False,
    callback: "Callback" = DEFAULT_CALLBACK,
) -> Dict[str, List[str]]:
    from dvc_data.index import StorageError
    from dvc_data.index.diff import UNCHANGED, UNKNOWN, diff
    ret: Dict[str, List[str]] = {}
    def _add_change(typ, change):
        typ = _adapt_typ(typ)
        if typ not in ret:
            ret[typ] = []
        ret[typ].append(_adapt_path(change))
    for change in diff(
        old,
        new,
        with_unchanged=True,
        shallow=not granular,
        hash_only=True,
        with_unknown=True,
        callback=callback,
    ):
        if (
            change.typ == UNCHANGED
            and (not change.old or not change.old.hash_info)
            and (not change.new or not change.new.hash_info)
        ):
            # NOTE: emulating previous behaviour
            continue
        if change.typ == UNKNOWN and not change.new:
            # NOTE: emulating previous behaviour
            continue
        if (
            not_in_cache
            and change.old
            and change.old.hash_info
            and not old.storage_map.cache_exists(change.old)
        ):
            # NOTE: emulating previous behaviour
            _add_change("not_in_cache", change)
        try:
            if (
                not_in_remote
                and change.old
                and change.old.hash_info
                and not old.storage_map.remote_exists(
                    change.old, refresh=remote_refresh
                )
            ):
                _add_change("not_in_remote", change)
        except StorageError:
            pass
        _add_change(change.typ, change)
    return ret