def walk_back(start_id, n_hops=3, role=None, filter_state=None):
    visited = set()
    results = []
    queue = [(start_id, 0)]

    while queue:
        current_id, depth = queue.pop(0)

        if current_id in visited or depth > n_hops:
            continue
        visited.add(current_id)

        edges = reverse_index.get(current_id, [])
        for edge in edges:
            ancestor_id = edge["source"]

            meta = metadata_cache.get(ancestor_id)
            if not meta:
                meta = fetch_metadata_from_dht(ancestor_id)
                metadata_cache[ancestor_id] = meta  # Cache store

            # Role filter
            if role and not meta["role_exposure"].get(role, False):
                continue

            # State filter
            if filter_state and meta["lifecycle_state"] not in filter_state:
                continue

            score = provenance_score(meta, depth)
            results.append({
                "id": ancestor_id,
                "relation": edge["relation"],
                "statement": meta["statement"],
                "timestamp": meta["timestamp"],
                "score": score
            })

            queue.append((ancestor_id, depth + 1))

    # Sort results by score descending
    results.sort(key=lambda r: r["score"], reverse=True)
    return results


def provenance_score(meta, depth):
    """Heuristic scoring for relevance."""
    score = 1.0 / (depth + 1)  # closer ancestors score higher
    if meta["lifecycle_state"] == "rejected":
        score *= 0.9
    if "critical" in meta.get("tags", []):
        score *= 1.2
    return score
