def walk_back(dr_id, max_hops=3, role=None, filter_state=None):
    """
    Walks upstream in the decision space, returning relevant ancestors.
    """
    visited = set()
    results = []

    # BFS queue
    queue = [(dr_id, 0)]

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

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

        # fetch upstream edges from reverse index
        edges = reverse_index.get(current_id, [])
        for edge in edges:
            ancestor_id = edge["source"]

            # fetch DR metadata (not full payload)
            meta = get_dr_metadata(ancestor_id)

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

            # state filter
            if filter_state and meta["lifecycle_state"] != filter_state:
                continue

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

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

    return results
