feat(path): rename-aware ambiguity resolution for suffix probe

When a bare filename like 'operators.ts' matches multiple full paths,
check if they are the same file connected by renames (via BFS on
mr_file_changes). If so, auto-resolve to the newest path instead of
erroring. Also wires path resolution into file-history and trace
commands so bare filenames work everywhere.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
teernisse
2026-02-17 15:05:47 -05:00
parent 171260a772
commit 714c8c2623
7 changed files with 632 additions and 100 deletions

View File

@@ -39,6 +39,7 @@ use lore::core::dependent_queue::release_all_locked_jobs;
use lore::core::error::{LoreError, RobotErrorOutput};
use lore::core::logging;
use lore::core::metrics::MetricsLayer;
use lore::core::path_resolver::{build_path_query, normalize_repo_path};
use lore::core::paths::{get_config_path, get_db_path, get_log_dir};
use lore::core::project::resolve_project;
use lore::core::shutdown::ShutdownSignal;
@@ -1874,9 +1875,27 @@ fn handle_file_history(
.effective_project(args.project.as_deref())
.map(String::from);
let normalized = normalize_repo_path(&args.path);
// Resolve bare filenames before querying (same path resolution as trace/who)
let db_path_tmp = get_db_path(config.storage.db_path.as_deref());
let conn_tmp = create_connection(&db_path_tmp)?;
let project_id_tmp = project
.as_deref()
.map(|p| resolve_project(&conn_tmp, p))
.transpose()?;
let pq = build_path_query(&conn_tmp, &normalized, project_id_tmp)?;
let resolved_path = if pq.is_prefix {
// Directory prefix — file-history is file-oriented, pass the raw path.
// Don't use pq.value which contains LIKE-escaped metacharacters.
normalized.trim_end_matches('/').to_string()
} else {
pq.value
};
let result = run_file_history(
&config,
&args.path,
&resolved_path,
project.as_deref(),
args.no_follow_renames,
args.merged,
@@ -1901,7 +1920,8 @@ fn handle_trace(
let start = std::time::Instant::now();
let config = Config::load(config_override)?;
let (path, line_requested) = parse_trace_path(&args.path);
let (raw_path, line_requested) = parse_trace_path(&args.path);
let normalized = normalize_repo_path(&raw_path);
if line_requested.is_some() && !robot_mode {
eprintln!(
@@ -1920,6 +1940,16 @@ fn handle_trace(
.map(|p| resolve_project(&conn, p))
.transpose()?;
// Resolve bare filenames (e.g. "operators.ts" -> "src/utils/operators.ts")
let pq = build_path_query(&conn, &normalized, project_id)?;
let path = if pq.is_prefix {
// Directory prefix — trace is file-oriented, pass the raw path.
// Don't use pq.value which contains LIKE-escaped metacharacters.
normalized.trim_end_matches('/').to_string()
} else {
pq.value
};
let result = run_trace(
&conn,
project_id,