New module: core::file_history with resolve_rename_chain() that traces
a file path through its rename history in mr_file_changes using
bidirectional BFS (forward: old_path->new_path, backward: new_path->old_path).
Key design decisions:
- Depth-bounded BFS: each queue entry carries its distance from the
origin, so max_hops correctly limits by graph distance (not by total
nodes discovered). This matters for branching rename graphs where a
file was renamed differently in parallel MRs.
- Cycle-safe: visited set prevents infinite loops from circular renames.
- Project-scoped: queries are always scoped to a single project_id.
- Deterministic: output is sorted for stable results.
Tests cover: linear chains (forward/backward), cycles, max_hops=0,
depth-bounded linear chains, branching renames, diamond patterns,
and cross-project isolation (9 tests total).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>