diff --git a/crates/neuromesh-cli/src/commands/packet.rs b/crates/neuromesh-cli/src/commands/packet.rs index f793557..f7698e5 100644 --- a/crates/neuromesh-cli/src/commands/packet.rs +++ b/crates/neuromesh-cli/src/commands/packet.rs @@ -104,6 +104,12 @@ pub fn execute(args: &[String]) -> Result<()> { let selected_paths = neuromesh_context::gold::packet_file_order(&graph, &prompt, &view); let localization = neuromesh_context::gold::localization_order(&graph, &prompt, &view, 20); + let definitions = + if prompt.split_whitespace().count() >= neuromesh_parser::text_normalize::REPORT_WORDS { + neuromesh_context::gold::definition_order(&graph, &prompt, &localization, def_depth()) + } else { + Vec::new() + }; let mut files: Vec = packet_file_names(&view).into_iter().collect(); files.sort(); let reduction = if workspace_tokens > 0 { @@ -134,19 +140,7 @@ pub fn execute(args: &[String]) -> Result<()> { selected_files: files.clone(), selected_paths, localization, - definitions: if prompt.split_whitespace().count() - >= neuromesh_parser::text_normalize::REPORT_WORDS - { - graph - .rank_definitions(&prompt, def_depth()) - .into_iter() - .filter(|d| { - !neuromesh_context::selector::is_noise_path(std::path::Path::new(&d.path)) - }) - .collect() - } else { - Vec::new() - }, + definitions, ranked_paths: graph .file_rank(&prompt, 10) .into_iter() diff --git a/crates/neuromesh-context/src/gold.rs b/crates/neuromesh-context/src/gold.rs index 9730ee6..a584ca5 100644 --- a/crates/neuromesh-context/src/gold.rs +++ b/crates/neuromesh-context/src/gold.rs @@ -1135,6 +1135,40 @@ pub fn localization_order( out } +/// Functions and methods to look at for a report, best first, `k` deep: the +/// definition ranking fused (RRF, k = 60) with the rank of each definition's +/// file in [`localization_order`] — the function step Agentless takes inside +/// the files it chose. SWE-bench dev (190 issues with function gold), func +/// Acc@5/@10: 0.311/0.374 without the file prior → 0.321/0.400 with it. +pub fn definition_order( + graph: &neuromesh_graph::NeuralProjectGraph, + prompt: &str, + files: &[String], + k: usize, +) -> Vec { + const K: f32 = 60.0; + let file_rank: std::collections::HashMap<&str, usize> = files + .iter() + .enumerate() + .map(|(i, f)| (f.as_str(), i)) + .collect(); + let mut scored: Vec<(f32, usize, neuromesh_graph::RankedDefinition)> = graph + .rank_definitions(prompt, 300) + .into_iter() + .filter(|d| !crate::selector::is_noise_path(std::path::Path::new(&d.path))) + .enumerate() + .map(|(i, d)| { + let mut s = 1.0 / (K + i as f32 + 1.0); + if let Some(r) = file_rank.get(d.path.as_str()) { + s += 1.0 / (K + *r as f32 + 1.0); + } + (s, i, d) + }) + .collect(); + scored.sort_by(|a, b| b.0.total_cmp(&a.0).then_with(|| a.1.cmp(&b.1))); + scored.into_iter().take(k).map(|(_, _, d)| d).collect() +} + /// Indexed files a report names, best pointer first: traceback frames /// (`File "…/pkg/mod.py", line 12`) from the deepest up, then any other path /// or file name in order of mention. A path resolves by its longest suffix diff --git a/crates/neuromesh-graph/src/chunk_rank.rs b/crates/neuromesh-graph/src/chunk_rank.rs index 1930533..08c20f6 100644 --- a/crates/neuromesh-graph/src/chunk_rank.rs +++ b/crates/neuromesh-graph/src/chunk_rank.rs @@ -36,6 +36,9 @@ pub(crate) struct ChunkSource { pub spans: Vec>, /// The definition each span is (`Class.method`), same order as `spans`. pub names: Vec, + /// Whether each span holds other definitions (a class): it still votes + /// for its file, but a function-level list names what is inside it. + pub containers: Vec, } /// One definition ranked for a report: where it is and how well it matched. @@ -48,11 +51,10 @@ pub struct RankedDefinition { } /// A file's chunks as term counts, before they are numbered. -type FileChunks = ( - NodeId, - PathBuf, - Vec<(HashMap, String, usize, usize)>, -); +type FileChunks = (NodeId, PathBuf, Vec<(HashMap, Label)>); + +/// A chunk's definition name, first and last line, and whether it is a container. +type Label = (String, usize, usize, bool); #[derive(Default)] pub(crate) struct ChunkRankIndex { @@ -62,7 +64,7 @@ pub(crate) struct ChunkRankIndex { avg_len: f32, post: HashMap>, /// Per chunk: definition name (`` for the file head) and lines. - label: Vec<(String, usize, usize)>, + label: Vec