From b3280e646565b471f83c3d13ec2694f7590122a2 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 16:20:30 -0800 Subject: [PATCH 01/13] perf(proximity): bound qualitative caller neighborhood reads Avoid materializing graph-impact reports for relationship hints. Refuse incomplete caller closures instead of treating them as absent. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 159 +++++++++++++++--- 1 file changed, 131 insertions(+), 28 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index a96c577499a..f7f3b82705f 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -951,6 +951,57 @@ fn graph_relation( (None, false) } +/// Collect only the bounded incoming caller closure needed for qualitative +/// proximity hints. A budget refusal cannot silently turn an uncertain +/// relationship into a negative result. The real producer supplies one +/// generation-pinned caller batch per hop; the injected reader lets tests +/// exercise cycles and incomplete batches rather than inspecting source text. +fn caller_neighborhood( + seeds: &[SymbolOccurrenceId], + max_symbols: usize, + mut read_callers: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, +) -> Option<(BTreeSet, BTreeSet)> { + if max_symbols == 0 { + return None; + } + let mut seen = seeds.iter().cloned().collect::>(); + let mut frontier = seeds.to_vec(); + let mut callers = BTreeSet::new(); + let mut tests = BTreeSet::new(); + for depth in 1..=3 { + if frontier.is_empty() { + break; + } + let batches = read_callers(&frontier)?; + if batches.len() != frontier.len() { + return None; + } + let mut next = Vec::new(); + for neighbor in batches.into_iter().flatten() { + let occurrence = neighbor.occurrence.clone(); + if !seen.insert(occurrence.clone()) { + continue; + } + if seen.len().saturating_sub(seeds.len()) > max_symbols { + return None; + } + if depth <= 2 { + callers.insert(occurrence.clone()); + } + if neighbor + .metadata + .as_ref() + .is_some_and(|metadata| metadata.kind.eq_ignore_ascii_case("test")) + { + tests.insert(occurrence.clone()); + } + next.push(occurrence); + } + frontier = next; + } + Some((callers, tests)) +} + fn graph_neighborhood( graph: &CodeGraphInteractiveReader, cancellation: Arc, @@ -960,34 +1011,26 @@ fn graph_neighborhood( BTreeSet, BTreeSet, )> { - let impact = graph - .impact( - seeds, - &[RelationEdgeKindV1::Calls], - 3, - 100_000, - 100_000, - Arc::clone(&cancellation), - ) - .ok()?; - let callers = impact - .impacted - .iter() - .filter(|symbol| symbol.depth <= 2) - .map(|symbol| symbol.summary.occurrence.clone()) - .collect(); - let tests = impact - .impacted - .iter() - .filter(|symbol| { - symbol - .summary - .metadata - .as_ref() - .is_some_and(|metadata| metadata.kind.eq_ignore_ascii_case("test")) - }) - .map(|symbol| symbol.summary.occurrence.clone()) - .collect(); + // The former graph.impact() created a complete impact report, then kept + // only depth-2 callers and test identities. Read those actual caller + // edges directly and refuse incomplete closures instead of accepting + // impact.complete=false as if the relationship were known absent. + let (callers, tests) = caller_neighborhood(seeds, 100_000, |frontier| { + graph + .callers( + frontier, + &[RelationEdgeKindV1::Calls], + 100_000, + Arc::clone(&cancellation), + ) + .ok() + .map(|batches| { + batches + .into_iter() + .map(|edges| edges.into_iter().map(|edge| edge.neighbor).collect()) + .collect() + }) + })?; let mut dependencies = BTreeSet::new(); let mut frontier = seeds.to_vec(); for _ in 0..2 { @@ -1233,6 +1276,66 @@ mod tests { ); } + + #[test] + fn caller_neighborhood_preserves_depth_bounds_cycles_and_refusals() { + let root = SymbolOccurrenceId::new("symbol.root").unwrap(); + let first = SymbolOccurrenceId::new("symbol.first").unwrap(); + let second = SymbolOccurrenceId::new("symbol.second").unwrap(); + let third = SymbolOccurrenceId::new("symbol.third").unwrap(); + let node = |id| { + callable( + id, + SourceSpan { + start_byte: 0, + end_byte: 1, + }, + ) + }; + let mut reads = 0; + let (callers, tests) = caller_neighborhood(std::slice::from_ref(&root), 3, |frontier| { + reads += 1; + Some( + frontier + .iter() + .map(|id| match id.as_str() { + "symbol.root" => vec![node("symbol.first")], + "symbol.first" => vec![node("symbol.root"), node("symbol.second")], + "symbol.second" => vec![node("symbol.third")], + _ => Vec::new(), + }) + .collect(), + ) + }) + .expect("complete bounded caller closure"); + assert_eq!(reads, 3, "one generation-pinned caller batch per depth"); + assert_eq!(callers, BTreeSet::from([first, second])); + assert!(!callers.contains(&third), "third hop is not a direct hint"); + assert!(tests.is_empty()); + + assert!( + caller_neighborhood(std::slice::from_ref(&root), 2, |frontier| { + Some( + frontier + .iter() + .map(|id| match id.as_str() { + "symbol.root" => vec![node("symbol.first")], + "symbol.first" => vec![node("symbol.second")], + "symbol.second" => vec![node("symbol.third")], + _ => Vec::new(), + }) + .collect(), + ) + }) + .is_none(), + "exhaustion is partial, never a false negative" + ); + assert!( + caller_neighborhood(std::slice::from_ref(&root), 10, |_| Some(Vec::new())).is_none(), + "incomplete per-seed evidence is refused" + ); + } + #[test] fn edited_path_evidence_accepts_only_valid_typed_ranges() { let root = Path::new("/repo"); From bb99ed2ef9faf17c40feed9af3fef5d363de3ffb Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 16:27:32 -0800 Subject: [PATCH 02/13] style(proximity): normalize caller regression formatting --- .../src/advisory/proximity_runtime/authority.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index f7f3b82705f..f78ab363324 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1276,7 +1276,6 @@ mod tests { ); } - #[test] fn caller_neighborhood_preserves_depth_bounds_cycles_and_refusals() { let root = SymbolOccurrenceId::new("symbol.root").unwrap(); From 1826d40513d343cf39b087b9742cd801fea815bc Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 17:12:56 -0800 Subject: [PATCH 03/13] fix(proximity): bound unique caller roots and neighbor budget --- .../advisory/proximity_runtime/authority.rs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index f78ab363324..b08d280bbf3 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -965,7 +965,10 @@ fn caller_neighborhood( return None; } let mut seen = seeds.iter().cloned().collect::>(); - let mut frontier = seeds.to_vec(); + // Duplicate seed identities must neither consume extra caller reads nor + // grant extra traversal budget for unrelated neighbors. + let seed_count = seen.len(); + let mut frontier = seen.iter().cloned().collect::>(); let mut callers = BTreeSet::new(); let mut tests = BTreeSet::new(); for depth in 1..=3 { @@ -982,7 +985,7 @@ fn caller_neighborhood( if !seen.insert(occurrence.clone()) { continue; } - if seen.len().saturating_sub(seeds.len()) > max_symbols { + if seen.len() - seed_count > max_symbols { return None; } if depth <= 2 { @@ -1333,6 +1336,29 @@ mod tests { caller_neighborhood(std::slice::from_ref(&root), 10, |_| Some(Vec::new())).is_none(), "incomplete per-seed evidence is refused" ); + + let repeated_roots = [root.clone(), root.clone()]; + let mut duplicate_reads = 0; + assert!( + caller_neighborhood(&repeated_roots, 2, |frontier| { + assert_eq!(frontier.len(), 1, "each unique seed is read once"); + duplicate_reads += 1; + Some( + frontier + .iter() + .map(|id| match id.as_str() { + "symbol.root" => vec![node("symbol.first")], + "symbol.first" => vec![node("symbol.second")], + "symbol.second" => vec![node("symbol.third")], + _ => Vec::new(), + }) + .collect(), + ) + }) + .is_none(), + "duplicate roots must not extend the unique-neighbor budget" + ); + assert_eq!(duplicate_reads, 3); } #[test] From 2f0930f4d2fdcdcf8c31d864073343bb75b5adec Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 18:15:13 -0800 Subject: [PATCH 04/13] fix(proximity): deduplicate dependency roots before graph reads --- .../advisory/proximity_runtime/authority.rs | 97 ++++++++++++++++--- 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index b08d280bbf3..c36e7c331c8 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1005,6 +1005,38 @@ fn caller_neighborhood( Some((callers, tests)) } +/// Read the two-hop outgoing dependency closure without charging duplicate +/// seed identities to the graph's batch-wide relation budget. Fail closed if +/// a batch loses a seed's adjacency rather than turning missing evidence into +/// a negative relationship result. +fn dependency_neighborhood( + seeds: &[SymbolOccurrenceId], + mut read_callees: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, +) -> Option> { + let mut frontier = seeds + .iter() + .cloned() + .collect::>() + .into_iter() + .collect::>(); + let mut dependencies = BTreeSet::new(); + for _ in 0..2 { + if frontier.is_empty() { + break; + } + let batches = read_callees(&frontier)?; + if batches.len() != frontier.len() { + return None; + } + frontier = batches + .into_iter() + .flatten() + .filter(|occurrence| dependencies.insert(occurrence.clone())) + .collect(); + } + Some(dependencies) +} + fn graph_neighborhood( graph: &CodeGraphInteractiveReader, cancellation: Arc, @@ -1034,27 +1066,27 @@ fn graph_neighborhood( .collect() }) })?; - let mut dependencies = BTreeSet::new(); - let mut frontier = seeds.to_vec(); - for _ in 0..2 { - let edges = graph + let dependencies = dependency_neighborhood(seeds, |frontier| { + graph .callees( - &frontier, + frontier, &[RelationEdgeKindV1::Calls], 100_000, Arc::clone(&cancellation), ) - .ok()?; - frontier = edges - .into_iter() - .flatten() - .map(|edge| edge.edge.to_occurrence) - .filter(|occurrence| dependencies.insert(occurrence.clone())) - .collect(); - if frontier.is_empty() { - break; - } - } + .ok() + .map(|batches| { + batches + .into_iter() + .map(|edges| { + edges + .into_iter() + .map(|edge| edge.edge.to_occurrence) + .collect() + }) + .collect() + }) + })?; Some((callers, dependencies, tests)) } @@ -1361,6 +1393,39 @@ mod tests { assert_eq!(duplicate_reads, 3); } + #[test] + fn dependency_neighborhood_deduplicates_seed_reads_and_refuses_missing_adjacency() { + let root = SymbolOccurrenceId::new("symbol.root").unwrap(); + let direct = SymbolOccurrenceId::new("symbol.direct").unwrap(); + let transitive = SymbolOccurrenceId::new("symbol.transitive").unwrap(); + let mut reads = 0; + let result = dependency_neighborhood(&[root.clone(), root.clone()], |frontier| { + reads += 1; + assert_eq!( + frontier.len(), + 1, + "duplicate seeds must not consume the read budget" + ); + Some( + frontier + .iter() + .map(|id| match id.as_str() { + "symbol.root" => vec![direct.clone()], + "symbol.direct" => vec![root.clone(), transitive.clone()], + _ => Vec::new(), + }) + .collect(), + ) + }) + .expect("two complete dependency hops"); + assert_eq!(reads, 2); + assert_eq!(result, BTreeSet::from([root.clone(), direct, transitive])); + assert!( + dependency_neighborhood(std::slice::from_ref(&root), |_| Some(Vec::new())).is_none(), + "truncated seed adjacency cannot prove absence of shared dependencies" + ); + } + #[test] fn edited_path_evidence_accepts_only_valid_typed_ranges() { let root = Path::new("/repo"); From cb30baf862259b92f1b5a9f6875129a3b60d138c Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 19:11:28 -0800 Subject: [PATCH 05/13] perf(proximity): reuse validated direct graph adjacency --- .../advisory/proximity_runtime/authority.rs | 128 +++++++++++++----- 1 file changed, 91 insertions(+), 37 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index c36e7c331c8..75e024de5b1 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -834,6 +834,18 @@ fn participant_graph_address( }) } +const MAX_GRAPH_RELATION_SEEDS: usize = 32; + +fn relation_seeds(ids: &BTreeSet) -> (Vec, bool) { + ( + ids.iter() + .take(MAX_GRAPH_RELATION_SEEDS) + .cloned() + .collect(), + ids.len() > MAX_GRAPH_RELATION_SEEDS, + ) +} + #[derive(Clone)] struct GraphRelation { warning_class: ProximityWarningClassV1, @@ -864,8 +876,9 @@ fn graph_relation( ); } - let left_seeds = left_ids.iter().take(32).cloned().collect::>(); - let right_seeds = right_ids.iter().take(32).cloned().collect::>(); + let (left_seeds, left_truncated) = relation_seeds(&left_ids); + let (right_seeds, right_truncated) = relation_seeds(&right_ids); + let incomplete_seed_coverage = left_truncated || right_truncated; let Ok(left_edges) = graph.callees( &left_seeds, &[RelationEdgeKindV1::Calls], @@ -874,7 +887,10 @@ fn graph_relation( ) else { return (None, true); }; - for edges in left_edges { + if left_edges.len() != left_seeds.len() { + return (None, true); + } + for edges in &left_edges { if edges .iter() .any(|edge| right_ids.contains(&edge.edge.to_occurrence)) @@ -884,7 +900,7 @@ fn graph_relation( warning_class: ProximityWarningClassV1::Neighborhood, kinds: vec![ProximityRelationPathKindV1::DirectDependency], }), - false, + incomplete_seed_coverage, ); } } @@ -896,7 +912,10 @@ fn graph_relation( ) else { return (None, true); }; - for edges in right_edges { + if right_edges.len() != right_seeds.len() { + return (None, true); + } + for edges in &right_edges { if edges .iter() .any(|edge| left_ids.contains(&edge.edge.to_occurrence)) @@ -906,18 +925,28 @@ fn graph_relation( warning_class: ProximityWarningClassV1::Neighborhood, kinds: vec![ProximityRelationPathKindV1::DirectCaller], }), - false, + incomplete_seed_coverage, ); } } + // The direct relationship checks already read the first outgoing hop. + // Reuse those generation-pinned batches for transitive discovery. + let left_first_hop = left_edges + .into_iter() + .map(|edges| edges.into_iter().map(|edge| edge.edge.to_occurrence).collect()) + .collect(); + let right_first_hop = right_edges + .into_iter() + .map(|edges| edges.into_iter().map(|edge| edge.edge.to_occurrence).collect()) + .collect(); let Some((left_callers, left_dependencies, left_tests)) = - graph_neighborhood(graph, Arc::clone(&cancellation), &left_seeds) + graph_neighborhood(graph, Arc::clone(&cancellation), &left_seeds, left_first_hop) else { return (None, true); }; let Some((right_callers, right_dependencies, right_tests)) = - graph_neighborhood(graph, cancellation, &right_seeds) + graph_neighborhood(graph, cancellation, &right_seeds, right_first_hop) else { return (None, true); }; @@ -927,7 +956,7 @@ fn graph_relation( warning_class: ProximityWarningClassV1::SharedCaller, kinds: vec![ProximityRelationPathKindV1::TransitiveCaller], }), - false, + incomplete_seed_coverage, ); } if !left_dependencies.is_disjoint(&right_dependencies) { @@ -936,7 +965,7 @@ fn graph_relation( warning_class: ProximityWarningClassV1::SharedDependency, kinds: vec![ProximityRelationPathKindV1::TransitiveDependency], }), - false, + incomplete_seed_coverage, ); } if !left_tests.is_disjoint(&right_tests) { @@ -945,10 +974,10 @@ fn graph_relation( warning_class: ProximityWarningClassV1::SharedTest, kinds: vec![ProximityRelationPathKindV1::AffectedTest], }), - false, + incomplete_seed_coverage, ); } - (None, false) + (None, incomplete_seed_coverage) } /// Collect only the bounded incoming caller closure needed for qualitative @@ -1011,6 +1040,7 @@ fn caller_neighborhood( /// a negative relationship result. fn dependency_neighborhood( seeds: &[SymbolOccurrenceId], + first_hop: Vec>, mut read_callees: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, ) -> Option> { let mut frontier = seeds @@ -1020,11 +1050,16 @@ fn dependency_neighborhood( .into_iter() .collect::>(); let mut dependencies = BTreeSet::new(); + let mut first_hop = Some(first_hop); for _ in 0..2 { if frontier.is_empty() { break; } - let batches = read_callees(&frontier)?; + let batches = if let Some(first) = first_hop.take() { + first + } else { + read_callees(&frontier)? + }; if batches.len() != frontier.len() { return None; } @@ -1041,6 +1076,7 @@ fn graph_neighborhood( graph: &CodeGraphInteractiveReader, cancellation: Arc, seeds: &[SymbolOccurrenceId], + first_hop: Vec>, ) -> Option<( BTreeSet, BTreeSet, @@ -1066,7 +1102,7 @@ fn graph_neighborhood( .collect() }) })?; - let dependencies = dependency_neighborhood(seeds, |frontier| { + let dependencies = dependency_neighborhood(seeds, first_hop, |frontier| { graph .callees( frontier, @@ -1394,35 +1430,53 @@ mod tests { } #[test] - fn dependency_neighborhood_deduplicates_seed_reads_and_refuses_missing_adjacency() { + fn relation_seeds_mark_unexamined_symbols_as_partial() { + let symbols = (0..33) + .map(|index| SymbolOccurrenceId::new(format!("symbol.{index:02}")).unwrap()) + .collect::>(); + let (seeds, truncated) = relation_seeds(&symbols); + assert_eq!(seeds.len(), MAX_GRAPH_RELATION_SEEDS); + assert!(truncated, "skipped graph nodes make a negative hint inconclusive"); + assert!(!seeds.contains(&SymbolOccurrenceId::new("symbol.32").unwrap())); + let (complete_seeds, incomplete) = relation_seeds(&seeds.iter().cloned().collect()); + assert!(!incomplete); + assert_eq!(complete_seeds, seeds); + } + + #[test] + fn dependency_neighborhood_reuses_first_hop_and_refuses_missing_adjacency() { let root = SymbolOccurrenceId::new("symbol.root").unwrap(); let direct = SymbolOccurrenceId::new("symbol.direct").unwrap(); let transitive = SymbolOccurrenceId::new("symbol.transitive").unwrap(); let mut reads = 0; - let result = dependency_neighborhood(&[root.clone(), root.clone()], |frontier| { - reads += 1; - assert_eq!( - frontier.len(), - 1, - "duplicate seeds must not consume the read budget" - ); - Some( - frontier - .iter() - .map(|id| match id.as_str() { - "symbol.root" => vec![direct.clone()], - "symbol.direct" => vec![root.clone(), transitive.clone()], - _ => Vec::new(), - }) - .collect(), - ) - }) + let result = dependency_neighborhood( + &[root.clone(), root.clone()], + vec![vec![direct.clone()]], + |frontier| { + reads += 1; + assert_eq!(frontier, &[direct.clone()], "only the second hop is read"); + Some(vec![vec![root.clone(), transitive.clone()]]) + }, + ) .expect("two complete dependency hops"); - assert_eq!(reads, 2); - assert_eq!(result, BTreeSet::from([root.clone(), direct, transitive])); + assert_eq!(reads, 1, "the first direct-edge read is reused"); + assert_eq!(result, BTreeSet::from([root.clone(), direct.clone(), transitive])); + assert!( - dependency_neighborhood(std::slice::from_ref(&root), |_| Some(Vec::new())).is_none(), - "truncated seed adjacency cannot prove absence of shared dependencies" + dependency_neighborhood(std::slice::from_ref(&root), Vec::new(), |_| { + panic!("incomplete first-hop evidence must not trigger another read") + }) + .is_none(), + "missing direct adjacency cannot prove absence of relationships" + ); + assert!( + dependency_neighborhood( + std::slice::from_ref(&root), + vec![vec![direct]], + |_| Some(Vec::new()) + ) + .is_none(), + "missing second-hop adjacency cannot prove absence of relationships" ); } From b5ad3684839748d35e24a9ae809e547e6a0c3248 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 19:34:31 -0800 Subject: [PATCH 06/13] test(proximity): cover third-hop evidence and read failures Exercise exact-budget test identity retention, failed caller reads at all three hops, and empty adjacency without additional graph reads. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 75e024de5b1..22dc2e4034c 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1480,6 +1480,106 @@ mod tests { ); } + #[test] + fn caller_neighborhood_retains_third_hop_tests_without_expanding_them() { + let root = SymbolOccurrenceId::new("symbol.root").unwrap(); + let first = SymbolOccurrenceId::new("symbol.first").unwrap(); + let second = SymbolOccurrenceId::new("symbol.second").unwrap(); + let test_id = SymbolOccurrenceId::new("symbol.test").unwrap(); + let span = SourceSpan { + start_byte: 0, + end_byte: 1, + }; + let mut test_node = callable(test_id.as_str(), span); + let digest = format!("sha256:{}", "a".repeat(64)); + test_node.metadata = Some(tracedecay_code_index::lineage::LineageSymbolRecordV1 { + occurrence: test_id.clone(), + identity: digest.clone().try_into().unwrap(), + qualified_name: "tests::shared".to_owned(), + simple_name: "shared".to_owned(), + kind: "TeSt".to_owned(), + visibility: "private".to_owned(), + branches: 0, + loops: 0, + max_nesting: 0, + complexity_analysis: tracedecay_domain::ComplexityAnalysisV1::Complete, + line_span: 1, + start_line: 0, + signature: None, + docstring: None, + is_async: false, + derives: Vec::new(), + skip_test_coverage: false, + file_identity: digest.try_into().unwrap(), + content_digest: ContentDigest::of_bytes(b"shared test"), + }); + let mut frontiers = Vec::new(); + let (callers, tests) = caller_neighborhood(std::slice::from_ref(&root), 3, |frontier| { + frontiers.push(frontier.to_vec()); + assert_eq!(frontier.len(), 1); + let neighbors = match frontier[0].as_str() { + "symbol.root" => vec![callable(first.as_str(), span)], + "symbol.first" => vec![callable(second.as_str(), span)], + "symbol.second" => vec![test_node.clone(), test_node.clone()], + _ => panic!("third-hop tests must not trigger a fourth graph read"), + }; + Some(vec![neighbors]) + }) + .expect("three unique neighbors fit the budget exactly"); + assert_eq!( + frontiers, + vec![vec![root], vec![first.clone()], vec![second.clone()]] + ); + assert_eq!(callers, BTreeSet::from([first, second])); + assert_eq!(tests, BTreeSet::from([test_id.clone()])); + assert!(!callers.contains(&test_id)); + } + + #[test] + fn caller_neighborhood_refuses_failed_reads_at_every_hop() { + let root = SymbolOccurrenceId::new("symbol.root").unwrap(); + for failed_hop in 1..=3 { + let mut reads = 0; + let result = caller_neighborhood(std::slice::from_ref(&root), 3, |_| { + reads += 1; + if reads == failed_hop { + return None; + } + Some(vec![vec![callable( + &format!("symbol.hop.{reads}"), + SourceSpan { + start_byte: 0, + end_byte: 1, + }, + )]]) + }); + assert!( + result.is_none(), + "hop {failed_hop} cannot publish partial evidence as complete" + ); + assert_eq!(reads, failed_hop, "a failed read must stop traversal"); + } + } + + #[test] + fn empty_neighborhoods_do_not_issue_additional_graph_reads() { + let empty = caller_neighborhood(&[], 3, |_| { + panic!("an empty caller seed set requires no read") + }) + .expect("empty caller closure is complete"); + assert!(empty.0.is_empty()); + assert!(empty.1.is_empty()); + + let root = SymbolOccurrenceId::new("symbol.root").unwrap(); + let dependencies = dependency_neighborhood( + std::slice::from_ref(&root), + vec![Vec::new()], + |_| panic!("empty first-hop adjacency requires no second-hop read"), + ) + .expect("empty dependency closure is complete"); + assert!(dependencies.is_empty()); + } + #[test] fn edited_path_evidence_accepts_only_valid_typed_ranges() { let root = Path::new("/repo"); From cb519ba1654bf5b4060ad5cbdf64e7d97cc7f3ff Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 20:14:42 -0800 Subject: [PATCH 07/13] perf(proximity): reuse seeded graph adjacency across cycles Skip outgoing second-hop reads for roots whose adjacency was already fetched in the first hop. Preserve the reached-root relationship evidence while avoiding redundant graph queries and exhausting fewer read budgets. Add regressions for connected roots and self-/cross-root cycles; previous behavior issues redundant reads and fails those assertions. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 22dc2e4034c..7cb545da618 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1043,12 +1043,8 @@ fn dependency_neighborhood( first_hop: Vec>, mut read_callees: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, ) -> Option> { - let mut frontier = seeds - .iter() - .cloned() - .collect::>() - .into_iter() - .collect::>(); + let seed_ids = seeds.iter().cloned().collect::>(); + let mut frontier = seed_ids.iter().cloned().collect::>(); let mut dependencies = BTreeSet::new(); let mut first_hop = Some(first_hop); for _ in 0..2 { @@ -1066,7 +1062,10 @@ fn dependency_neighborhood( frontier = batches .into_iter() .flatten() + // Seed adjacency was already read in the first batch. A cycle back + // to any root still contributes evidence, but needs no second read. .filter(|occurrence| dependencies.insert(occurrence.clone())) + .filter(|occurrence| !seed_ids.contains(occurrence)) .collect(); } Some(dependencies) @@ -1580,6 +1579,44 @@ mod tests { assert!(dependencies.is_empty()); } + #[test] + fn dependency_neighborhood_reuses_adjacency_between_distinct_seeds() { + let first = SymbolOccurrenceId::new("symbol.first").unwrap(); + let second = SymbolOccurrenceId::new("symbol.second").unwrap(); + let direct = SymbolOccurrenceId::new("symbol.direct").unwrap(); + let transitive = SymbolOccurrenceId::new("symbol.transitive").unwrap(); + let mut reads = 0; + let result = dependency_neighborhood( + &[first.clone(), second.clone()], + vec![vec![second.clone()], vec![direct.clone()]], + |frontier| { + reads += 1; + assert_eq!( + frontier, + std::slice::from_ref(&direct), + "seed adjacency is already supplied by the first hop" + ); + Some(vec![vec![first.clone(), transitive.clone()]]) + }, + ) + .expect("overlapping roots retain two-hop evidence"); + assert_eq!(reads, 1); + assert_eq!(result, BTreeSet::from([first, second, direct, transitive])); + } + + #[test] + fn dependency_neighborhood_preserves_seed_cycles_without_extra_reads() { + let first = SymbolOccurrenceId::new("symbol.first").unwrap(); + let second = SymbolOccurrenceId::new("symbol.second").unwrap(); + let result = dependency_neighborhood( + &[first.clone(), second.clone()], + vec![vec![first.clone(), second.clone()], vec![first.clone()]], + |_| panic!("seed cycles must not issue another adjacency read"), + ) + .expect("supplied adjacency completely covers the seed cycle"); + assert_eq!(result, BTreeSet::from([first, second])); + } + #[test] fn edited_path_evidence_accepts_only_valid_typed_ranges() { let root = Path::new("/repo"); From 21898591b38f17440fc896fc14daa25811f05ac6 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 21:14:49 -0800 Subject: [PATCH 08/13] perf(proximity): skip discarded dependency expansions Evaluate complete shared-caller adjacency before lower-priority outgoing second-hop dependencies. Preserve an already-proven caller hint when an unneeded dependency lookup would refuse its read budget. Keep direct relation precedence, bounded seed coverage, and cached first hops. Add two behavioral regressions that require no dependency queries for shared callers, and exact second-hop reads for real shared dependencies. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 287 ++++++++++++------ 1 file changed, 199 insertions(+), 88 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 7cb545da618..8ab025489b9 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -940,44 +940,17 @@ fn graph_relation( .into_iter() .map(|edges| edges.into_iter().map(|edge| edge.edge.to_occurrence).collect()) .collect(); - let Some((left_callers, left_dependencies, left_tests)) = - graph_neighborhood(graph, Arc::clone(&cancellation), &left_seeds, left_first_hop) - else { - return (None, true); - }; - let Some((right_callers, right_dependencies, right_tests)) = - graph_neighborhood(graph, cancellation, &right_seeds, right_first_hop) - else { - return (None, true); - }; - if !left_callers.is_disjoint(&right_callers) { - return ( - Some(GraphRelation { - warning_class: ProximityWarningClassV1::SharedCaller, - kinds: vec![ProximityRelationPathKindV1::TransitiveCaller], - }), - incomplete_seed_coverage, - ); - } - if !left_dependencies.is_disjoint(&right_dependencies) { - return ( - Some(GraphRelation { - warning_class: ProximityWarningClassV1::SharedDependency, - kinds: vec![ProximityRelationPathKindV1::TransitiveDependency], - }), - incomplete_seed_coverage, - ); - } - if !left_tests.is_disjoint(&right_tests) { - return ( - Some(GraphRelation { - warning_class: ProximityWarningClassV1::SharedTest, - kinds: vec![ProximityRelationPathKindV1::AffectedTest], - }), - incomplete_seed_coverage, - ); - } - (None, incomplete_seed_coverage) + // Evaluate bounded caller evidence before any outgoing second-hop work. + // A proven shared caller must survive an unrelated dependency budget refusal. + let (relation, partial) = graph_relation_neighborhood( + graph, + cancellation, + &left_seeds, + &right_seeds, + left_first_hop, + right_first_hop, + ); + (relation, incomplete_seed_coverage || partial) } /// Collect only the bounded incoming caller closure needed for qualitative @@ -1071,58 +1044,119 @@ fn dependency_neighborhood( Some(dependencies) } -fn graph_neighborhood( +fn graph_relation_neighborhood( graph: &CodeGraphInteractiveReader, cancellation: Arc, - seeds: &[SymbolOccurrenceId], - first_hop: Vec>, -) -> Option<( - BTreeSet, - BTreeSet, - BTreeSet, -)> { - // The former graph.impact() created a complete impact report, then kept - // only depth-2 callers and test identities. Read those actual caller - // edges directly and refuse incomplete closures instead of accepting - // impact.complete=false as if the relationship were known absent. - let (callers, tests) = caller_neighborhood(seeds, 100_000, |frontier| { - graph - .callers( - frontier, - &[RelationEdgeKindV1::Calls], - 100_000, - Arc::clone(&cancellation), - ) - .ok() - .map(|batches| { - batches - .into_iter() - .map(|edges| edges.into_iter().map(|edge| edge.neighbor).collect()) - .collect() - }) - })?; - let dependencies = dependency_neighborhood(seeds, first_hop, |frontier| { - graph - .callees( - frontier, - &[RelationEdgeKindV1::Calls], - 100_000, - Arc::clone(&cancellation), - ) - .ok() - .map(|batches| { - batches - .into_iter() - .map(|edges| { - edges - .into_iter() - .map(|edge| edge.edge.to_occurrence) - .collect() - }) - .collect() - }) - })?; - Some((callers, dependencies, tests)) + left_seeds: &[SymbolOccurrenceId], + right_seeds: &[SymbolOccurrenceId], + left_first_hop: Vec>, + right_first_hop: Vec>, +) -> (Option, bool) { + graph_relation_neighborhood_with_reads( + left_seeds, + right_seeds, + left_first_hop, + right_first_hop, + |frontier| { + graph + .callers( + frontier, + &[RelationEdgeKindV1::Calls], + 100_000, + Arc::clone(&cancellation), + ) + .ok() + .map(|batches| { + batches + .into_iter() + .map(|edges| edges.into_iter().map(|edge| edge.neighbor).collect()) + .collect() + }) + }, + |frontier| { + graph + .callees( + frontier, + &[RelationEdgeKindV1::Calls], + 100_000, + Arc::clone(&cancellation), + ) + .ok() + .map(|batches| { + batches + .into_iter() + .map(|edges| { + edges + .into_iter() + .map(|edge| edge.edge.to_occurrence) + .collect() + }) + .collect() + }) + }, + ) +} + +/// Use the incoming adjacency to establish a higher-precedence shared caller +/// before reading lower-precedence outgoing dependencies. The supplied first +/// hops have already passed the direct-adjacency completeness checks. +fn graph_relation_neighborhood_with_reads( + left_seeds: &[SymbolOccurrenceId], + right_seeds: &[SymbolOccurrenceId], + left_first_hop: Vec>, + right_first_hop: Vec>, + mut read_callers: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, + mut read_callees: impl FnMut(&[SymbolOccurrenceId]) -> Option>>, +) -> (Option, bool) { + let Some((left_callers, left_tests)) = + caller_neighborhood(left_seeds, 100_000, &mut read_callers) + else { + return (None, true); + }; + let Some((right_callers, right_tests)) = + caller_neighborhood(right_seeds, 100_000, &mut read_callers) + else { + return (None, true); + }; + if !left_callers.is_disjoint(&right_callers) { + return ( + Some(GraphRelation { + warning_class: ProximityWarningClassV1::SharedCaller, + kinds: vec![ProximityRelationPathKindV1::TransitiveCaller], + }), + false, + ); + } + + let Some(left_dependencies) = + dependency_neighborhood(left_seeds, left_first_hop, &mut read_callees) + else { + return (None, true); + }; + let Some(right_dependencies) = + dependency_neighborhood(right_seeds, right_first_hop, &mut read_callees) + else { + return (None, true); + }; + if !left_dependencies.is_disjoint(&right_dependencies) { + return ( + Some(GraphRelation { + warning_class: ProximityWarningClassV1::SharedDependency, + kinds: vec![ProximityRelationPathKindV1::TransitiveDependency], + }), + false, + ); + } + if !left_tests.is_disjoint(&right_tests) { + return ( + Some(GraphRelation { + warning_class: ProximityWarningClassV1::SharedTest, + kinds: vec![ProximityRelationPathKindV1::AffectedTest], + }), + false, + ); + } + (None, false) } fn exact_graph_address( @@ -1617,6 +1651,83 @@ mod tests { assert_eq!(result, BTreeSet::from([first, second])); } + #[test] + fn shared_caller_does_not_read_discarded_dependency_hops() { + let left = SymbolOccurrenceId::new("symbol.left").unwrap(); + let right = SymbolOccurrenceId::new("symbol.right").unwrap(); + let span = SourceSpan { + start_byte: 0, + end_byte: 1, + }; + let common = callable("symbol.shared-caller", span); + let mut caller_reads = 0; + let (relation, partial) = graph_relation_neighborhood_with_reads( + std::slice::from_ref(&left), + std::slice::from_ref(&right), + vec![vec![SymbolOccurrenceId::new("symbol.left-dependency").unwrap()]], + vec![vec![SymbolOccurrenceId::new("symbol.right-dependency").unwrap()]], + |frontier| { + caller_reads += 1; + Some( + frontier + .iter() + .map(|seed| match seed.as_str() { + "symbol.left" | "symbol.right" => vec![common.clone()], + "symbol.shared-caller" => Vec::new(), + _ => panic!("unexpected caller frontier"), + }) + .collect(), + ) + }, + |_| panic!("shared caller must not be erased by an unused dependency read"), + ); + let relation = relation.expect("proven shared caller must survive"); + assert_eq!(relation.warning_class, ProximityWarningClassV1::SharedCaller); + assert_eq!( + relation.kinds, + vec![ProximityRelationPathKindV1::TransitiveCaller] + ); + assert!(!partial); + assert_eq!(caller_reads, 4, "both incoming closures are fully read"); + } + + #[test] + fn unmatched_callers_still_read_two_hop_shared_dependencies() { + let left = SymbolOccurrenceId::new("symbol.left").unwrap(); + let right = SymbolOccurrenceId::new("symbol.right").unwrap(); + let common = SymbolOccurrenceId::new("symbol.common").unwrap(); + let mut outgoing_reads = 0; + let (relation, partial) = graph_relation_neighborhood_with_reads( + std::slice::from_ref(&left), + std::slice::from_ref(&right), + vec![vec![SymbolOccurrenceId::new("symbol.left-dependency").unwrap()]], + vec![vec![SymbolOccurrenceId::new("symbol.right-dependency").unwrap()]], + |frontier| Some(vec![Vec::new(); frontier.len()]), + |frontier| { + outgoing_reads += 1; + Some( + frontier + .iter() + .map(|seed| match seed.as_str() { + "symbol.left-dependency" | "symbol.right-dependency" => { + vec![common.clone()] + } + _ => panic!("first-hop adjacency must be reused"), + }) + .collect(), + ) + }, + ); + let relation = relation.expect("real two-hop dependency is preserved"); + assert_eq!(relation.warning_class, ProximityWarningClassV1::SharedDependency); + assert_eq!( + relation.kinds, + vec![ProximityRelationPathKindV1::TransitiveDependency] + ); + assert!(!partial); + assert_eq!(outgoing_reads, 2, "one extra read per side"); + } + #[test] fn edited_path_evidence_accepts_only_valid_typed_ranges() { let root = Path::new("/repo"); From 2fd8d4bf4d7384d3c554600c4a0919cb161843f7 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 22:10:52 -0800 Subject: [PATCH 09/13] fix(proximity): retain proven test hints on partial graph reads Preserve a shared third-hop affected-test relationship when the later higher-priority dependency closure refuses a read. Mark the known positive hint partial instead of publishing no relation; complete shared-dependency evidence still takes precedence. Factor the existing test metadata fixture and add nonzero behavioral regression covering left/right second-hop refusal, short-circuit read counts, and successful dependency precedence. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 162 ++++++++++++++---- 1 file changed, 127 insertions(+), 35 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 8ab025489b9..31d7bd9549f 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1128,15 +1128,22 @@ fn graph_relation_neighborhood_with_reads( ); } + // The incoming closure can already prove an affected test even when a + // later, higher-precedence dependency read cannot finish. Retain that + // positive evidence as partial rather than incorrectly returning no hint. + let shared_test = (!left_tests.is_disjoint(&right_tests)).then(|| GraphRelation { + warning_class: ProximityWarningClassV1::SharedTest, + kinds: vec![ProximityRelationPathKindV1::AffectedTest], + }); let Some(left_dependencies) = dependency_neighborhood(left_seeds, left_first_hop, &mut read_callees) else { - return (None, true); + return (shared_test, true); }; let Some(right_dependencies) = dependency_neighborhood(right_seeds, right_first_hop, &mut read_callees) else { - return (None, true); + return (shared_test, true); }; if !left_dependencies.is_disjoint(&right_dependencies) { return ( @@ -1147,16 +1154,7 @@ fn graph_relation_neighborhood_with_reads( false, ); } - if !left_tests.is_disjoint(&right_tests) { - return ( - Some(GraphRelation { - warning_class: ProximityWarningClassV1::SharedTest, - kinds: vec![ProximityRelationPathKindV1::AffectedTest], - }), - false, - ); - } - (None, false) + (shared_test, false) } fn exact_graph_address( @@ -1329,6 +1327,33 @@ mod tests { } } + fn test_callable(id: &str, span: SourceSpan) -> CodeGraphSymbolSummaryV1 { + let mut node = callable(id, span); + let digest = format!("sha256:{}", "a".repeat(64)); + node.metadata = Some(tracedecay_code_index::lineage::LineageSymbolRecordV1 { + occurrence: node.occurrence.clone(), + identity: digest.clone().try_into().unwrap(), + qualified_name: "tests::shared".to_owned(), + simple_name: "shared".to_owned(), + kind: "TeSt".to_owned(), + visibility: "private".to_owned(), + branches: 0, + loops: 0, + max_nesting: 0, + complexity_analysis: tracedecay_domain::ComplexityAnalysisV1::Complete, + line_span: 1, + start_line: 0, + signature: None, + docstring: None, + is_async: false, + derives: Vec::new(), + skip_test_coverage: false, + file_identity: digest.try_into().unwrap(), + content_digest: ContentDigest::of_bytes(b"shared test"), + }); + node + } + #[test] fn same_symbol_requires_each_typed_edit_range_to_resolve_to_that_symbol() { let nodes = vec![ @@ -1523,29 +1548,7 @@ mod tests { start_byte: 0, end_byte: 1, }; - let mut test_node = callable(test_id.as_str(), span); - let digest = format!("sha256:{}", "a".repeat(64)); - test_node.metadata = Some(tracedecay_code_index::lineage::LineageSymbolRecordV1 { - occurrence: test_id.clone(), - identity: digest.clone().try_into().unwrap(), - qualified_name: "tests::shared".to_owned(), - simple_name: "shared".to_owned(), - kind: "TeSt".to_owned(), - visibility: "private".to_owned(), - branches: 0, - loops: 0, - max_nesting: 0, - complexity_analysis: tracedecay_domain::ComplexityAnalysisV1::Complete, - line_span: 1, - start_line: 0, - signature: None, - docstring: None, - is_async: false, - derives: Vec::new(), - skip_test_coverage: false, - file_identity: digest.try_into().unwrap(), - content_digest: ContentDigest::of_bytes(b"shared test"), - }); + let test_node = test_callable(test_id.as_str(), span); let mut frontiers = Vec::new(); let (callers, tests) = caller_neighborhood(std::slice::from_ref(&root), 3, |frontier| { frontiers.push(frontier.to_vec()); @@ -1651,6 +1654,95 @@ mod tests { assert_eq!(result, BTreeSet::from([first, second])); } + #[test] + fn shared_third_hop_test_survives_unavailable_dependency_evidence() { + let symbol = |id| SymbolOccurrenceId::new(id).unwrap(); + let left = symbol("symbol.left"); + let right = symbol("symbol.right"); + let span = SourceSpan { + start_byte: 0, + end_byte: 1, + }; + let shared_test = test_callable("symbol.shared-test", span); + let shared_dependency = symbol("symbol.shared-dependency"); + + // One side may reject its second hop after both three-hop caller + // closures have proven a shared affected test. A complete dependency + // proof still outranks the test, but refusal cannot erase it. + for failed_second_hop in [ + Some("symbol.left-direct"), + Some("symbol.right-direct"), + None, + ] { + let mut reads = 0; + let (relation, partial) = graph_relation_neighborhood_with_reads( + std::slice::from_ref(&left), + std::slice::from_ref(&right), + vec![vec![symbol("symbol.left-direct")]], + vec![vec![symbol("symbol.right-direct")]], + |frontier| { + Some( + frontier + .iter() + .map(|seed| match seed.as_str() { + "symbol.left" => vec![callable("symbol.left-1", span)], + "symbol.left-1" => vec![callable("symbol.left-2", span)], + "symbol.left-2" => vec![shared_test.clone()], + "symbol.right" => vec![callable("symbol.right-1", span)], + "symbol.right-1" => vec![callable("symbol.right-2", span)], + "symbol.right-2" => vec![shared_test.clone()], + _ => panic!("third-hop tests do not require further reads"), + }) + .collect(), + ) + }, + |frontier| { + reads += 1; + if frontier + .iter() + .any(|seed| Some(seed.as_str()) == failed_second_hop) + { + return None; + } + Some( + frontier + .iter() + .map(|_| vec![shared_dependency.clone()]) + .collect(), + ) + }, + ); + let relation = relation.expect("proven evidence must not be discarded"); + let failed = failed_second_hop.is_some(); + assert_eq!( + relation.warning_class, + if failed { + ProximityWarningClassV1::SharedTest + } else { + ProximityWarningClassV1::SharedDependency + } + ); + assert_eq!( + relation.kinds, + vec![if failed { + ProximityRelationPathKindV1::AffectedTest + } else { + ProximityRelationPathKindV1::TransitiveDependency + }] + ); + assert_eq!(partial, failed, "unread adjacency makes coverage partial"); + assert_eq!( + reads, + if failed_second_hop == Some("symbol.left-direct") { + 1 + } else { + 2 + }, + "stop at the refusing hop, retaining the known test relation" + ); + } + } + #[test] fn shared_caller_does_not_read_discarded_dependency_hops() { let left = SymbolOccurrenceId::new("symbol.left").unwrap(); From cbbf871490720bab8b1aa49f6a0b39c36c310b10 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 7 Nov 2026 23:07:05 -0800 Subject: [PATCH 10/13] style(proximity): match pinned Rust formatting Apply all eleven exact rustfmt corrections reported by the hosted Repository gates on the existing issue-specific PR. No intended behavior changes; preserve every concurrent graph repair. Refs #4416 --- .../advisory/proximity_runtime/authority.rs | 74 ++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 31d7bd9549f..d826d5f1187 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -838,10 +838,7 @@ const MAX_GRAPH_RELATION_SEEDS: usize = 32; fn relation_seeds(ids: &BTreeSet) -> (Vec, bool) { ( - ids.iter() - .take(MAX_GRAPH_RELATION_SEEDS) - .cloned() - .collect(), + ids.iter().take(MAX_GRAPH_RELATION_SEEDS).cloned().collect(), ids.len() > MAX_GRAPH_RELATION_SEEDS, ) } @@ -934,11 +931,21 @@ fn graph_relation( // Reuse those generation-pinned batches for transitive discovery. let left_first_hop = left_edges .into_iter() - .map(|edges| edges.into_iter().map(|edge| edge.edge.to_occurrence).collect()) + .map(|edges| { + edges + .into_iter() + .map(|edge| edge.edge.to_occurrence) + .collect() + }) .collect(); let right_first_hop = right_edges .into_iter() - .map(|edges| edges.into_iter().map(|edge| edge.edge.to_occurrence).collect()) + .map(|edges| { + edges + .into_iter() + .map(|edge| edge.edge.to_occurrence) + .collect() + }) .collect(); // Evaluate bounded caller evidence before any outgoing second-hop work. // A proven shared caller must survive an unrelated dependency budget refusal. @@ -1494,7 +1501,10 @@ mod tests { .collect::>(); let (seeds, truncated) = relation_seeds(&symbols); assert_eq!(seeds.len(), MAX_GRAPH_RELATION_SEEDS); - assert!(truncated, "skipped graph nodes make a negative hint inconclusive"); + assert!( + truncated, + "skipped graph nodes make a negative hint inconclusive" + ); assert!(!seeds.contains(&SymbolOccurrenceId::new("symbol.32").unwrap())); let (complete_seeds, incomplete) = relation_seeds(&seeds.iter().cloned().collect()); assert!(!incomplete); @@ -1518,7 +1528,10 @@ mod tests { ) .expect("two complete dependency hops"); assert_eq!(reads, 1, "the first direct-edge read is reused"); - assert_eq!(result, BTreeSet::from([root.clone(), direct.clone(), transitive])); + assert_eq!( + result, + BTreeSet::from([root.clone(), direct.clone(), transitive]) + ); assert!( dependency_neighborhood(std::slice::from_ref(&root), Vec::new(), |_| { @@ -1528,11 +1541,9 @@ mod tests { "missing direct adjacency cannot prove absence of relationships" ); assert!( - dependency_neighborhood( - std::slice::from_ref(&root), - vec![vec![direct]], - |_| Some(Vec::new()) - ) + dependency_neighborhood(std::slice::from_ref(&root), vec![vec![direct]], |_| Some( + Vec::new() + )) .is_none(), "missing second-hop adjacency cannot prove absence of relationships" ); @@ -1607,12 +1618,11 @@ mod tests { assert!(empty.1.is_empty()); let root = SymbolOccurrenceId::new("symbol.root").unwrap(); - let dependencies = dependency_neighborhood( - std::slice::from_ref(&root), - vec![Vec::new()], - |_| panic!("empty first-hop adjacency requires no second-hop read"), - ) - .expect("empty dependency closure is complete"); + let dependencies = + dependency_neighborhood(std::slice::from_ref(&root), vec![Vec::new()], |_| { + panic!("empty first-hop adjacency requires no second-hop read") + }) + .expect("empty dependency closure is complete"); assert!(dependencies.is_empty()); } @@ -1756,8 +1766,12 @@ mod tests { let (relation, partial) = graph_relation_neighborhood_with_reads( std::slice::from_ref(&left), std::slice::from_ref(&right), - vec![vec![SymbolOccurrenceId::new("symbol.left-dependency").unwrap()]], - vec![vec![SymbolOccurrenceId::new("symbol.right-dependency").unwrap()]], + vec![vec![ + SymbolOccurrenceId::new("symbol.left-dependency").unwrap(), + ]], + vec![vec![ + SymbolOccurrenceId::new("symbol.right-dependency").unwrap(), + ]], |frontier| { caller_reads += 1; Some( @@ -1774,7 +1788,10 @@ mod tests { |_| panic!("shared caller must not be erased by an unused dependency read"), ); let relation = relation.expect("proven shared caller must survive"); - assert_eq!(relation.warning_class, ProximityWarningClassV1::SharedCaller); + assert_eq!( + relation.warning_class, + ProximityWarningClassV1::SharedCaller + ); assert_eq!( relation.kinds, vec![ProximityRelationPathKindV1::TransitiveCaller] @@ -1792,8 +1809,12 @@ mod tests { let (relation, partial) = graph_relation_neighborhood_with_reads( std::slice::from_ref(&left), std::slice::from_ref(&right), - vec![vec![SymbolOccurrenceId::new("symbol.left-dependency").unwrap()]], - vec![vec![SymbolOccurrenceId::new("symbol.right-dependency").unwrap()]], + vec![vec![ + SymbolOccurrenceId::new("symbol.left-dependency").unwrap(), + ]], + vec![vec![ + SymbolOccurrenceId::new("symbol.right-dependency").unwrap(), + ]], |frontier| Some(vec![Vec::new(); frontier.len()]), |frontier| { outgoing_reads += 1; @@ -1811,7 +1832,10 @@ mod tests { }, ); let relation = relation.expect("real two-hop dependency is preserved"); - assert_eq!(relation.warning_class, ProximityWarningClassV1::SharedDependency); + assert_eq!( + relation.warning_class, + ProximityWarningClassV1::SharedDependency + ); assert_eq!( relation.kinds, vec![ProximityRelationPathKindV1::TransitiveDependency] From f32face1d77f6253a55366228cbb768013449c45 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sun, 8 Nov 2026 00:09:48 -0800 Subject: [PATCH 11/13] fix(proximity): avoid cloned-ref Clippy failure Use std::slice::from_ref in the real dependency traversal regression. This resolves the exact blocking -D warnings diagnostic reported by hosted Clippy on the current PR head; test behavior stays unchanged. Refs #4416 --- .../src/advisory/proximity_runtime/authority.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index d826d5f1187..2bdba9b491a 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1522,7 +1522,7 @@ mod tests { vec![vec![direct.clone()]], |frontier| { reads += 1; - assert_eq!(frontier, &[direct.clone()], "only the second hop is read"); + assert_eq!(frontier, std::slice::from_ref(&direct), "only the second hop is read"); Some(vec![vec![root.clone(), transitive.clone()]]) }, ) From 8bae143a4e339d13267573f88f6946c319ceaebe Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sun, 8 Nov 2026 02:13:43 -0800 Subject: [PATCH 12/13] style(proximity): match hosted Rustfmt for caller test Apply the exact source changes requested by the first failing hosted Bazel Rustfmt gate at the preceding PR head. No behavior or assertions change; all existing regression tests are preserved. Refs #4416 Verification: source contexts checked against hosted Rustfmt diffs. New-head Rust/Bazel tests require hosted CI. --- .../src/advisory/proximity_runtime/authority.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs index 2bdba9b491a..73750b90b24 100644 --- a/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs +++ b/crates/tracedecay-application/src/advisory/proximity_runtime/authority.rs @@ -1522,7 +1522,11 @@ mod tests { vec![vec![direct.clone()]], |frontier| { reads += 1; - assert_eq!(frontier, std::slice::from_ref(&direct), "only the second hop is read"); + assert_eq!( + frontier, + std::slice::from_ref(&direct), + "only the second hop is read" + ); Some(vec![vec![root.clone(), transitive.clone()]]) }, ) From bf85d1e2582521b758f51c1f7f1650ee8e4bf984 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sun, 8 Nov 2026 01:52:34 -0800 Subject: [PATCH 13/13] test(automation): bind scheduler fixtures to backend identities Repair three hosted automation_runner_test failures by supplying the configured executable identity required by the production prefilter. Use the same identity for the prefilter and retained runner, preserving manual-schedule, exact-ledger, live-lock and lock-race assertions. Add a production-prefilter regression for unconfigured refusal, deduplication and same-occurrence recovery after binding, with zero backend calls and no effectful terminal. Do not relax backend admission, change timeouts, or alter the graph publication changes. Refs #4532 --- .../tests/automation_runner_test/jobs.rs | 124 ++++++++++++++++-- 1 file changed, 110 insertions(+), 14 deletions(-) diff --git a/crates/tracedecay/tests/automation_runner_test/jobs.rs b/crates/tracedecay/tests/automation_runner_test/jobs.rs index 740283d56e8..7342786381b 100644 --- a/crates/tracedecay/tests/automation_runner_test/jobs.rs +++ b/crates/tracedecay/tests/automation_runner_test/jobs.rs @@ -86,6 +86,7 @@ fn enabled_job_config() -> AutomationSettingsV1 { struct ContentBackend { calls: AtomicUsize, content: &'static str, + executable: Option, } impl ContentBackend { @@ -93,9 +94,15 @@ impl ContentBackend { Self { calls: AtomicUsize::new(0), content, + executable: None, } } + fn with_executable(mut self, executable: &Path) -> Self { + self.executable = Some(executable.to_path_buf()); + self + } + fn calls(&self) -> usize { self.calls.load(Ordering::SeqCst) } @@ -126,7 +133,7 @@ impl AgentTaskBackend for ContentBackend { } fn executable(&self) -> Option<&std::path::Path> { - None + self.executable.as_deref() } } @@ -988,6 +995,10 @@ async fn scheduler_trigger_skips_repeat_and_respects_lock_discipline() { let mut job = sample_job("sched-job"); job.schedule = Some("manual".to_string()); let config = enabled_job_config(); + // Reach the schedule gate with a bound identity, not the earlier + // backend-unconfigured refusal. This gate never invokes the backend. + let executable = tempfile::NamedTempFile::new().unwrap(); + let backend = ContentBackend::new("unused").with_executable(executable.path()); // Manual schedule: every scheduler tick of the same occurrence reaches // the prefilter, which records the skip once. @@ -996,7 +1007,7 @@ async fn scheduler_trigger_skips_repeat_and_respects_lock_discipline() { let run = evaluate_and_record_scheduler_skip( &dashboard_root, &config, - None, + backend.executable(), &job, "sched-occurrence", None, @@ -1019,7 +1030,7 @@ async fn scheduler_trigger_skips_repeat_and_respects_lock_discipline() { let repeated = evaluate_and_record_scheduler_skip( &dashboard_root, &config, - None, + backend.executable(), &job, "sched-occurrence", None, @@ -1031,6 +1042,76 @@ async fn scheduler_trigger_skips_repeat_and_respects_lock_discipline() { repeated.ledger_record, records[0], "an immediate repeat skip must return the exact durable prior row" ); + assert_eq!(backend.calls(), 0); +} + +#[tokio::test] +async fn scheduler_prefilter_rejects_unconfigured_backend_and_recovers_without_effect() { + let temp = tempdir().unwrap(); + let dashboard_root = temp.path().join("dashboard"); + let job = sample_job("backend-recovery"); + let config = enabled_job_config(); + let occurrence = "backend-recovery-occurrence"; + let backend = ContentBackend::new("unused"); + + let first = evaluate_and_record_scheduler_skip( + &dashboard_root, + &config, + backend.executable(), + &job, + occurrence, + None, + ) + .await + .unwrap() + .expect("a due job still requires a configured backend"); + assert_eq!(first.report["reason"], json!("backend_unconfigured")); + assert_eq!(first.ledger_record.status, AutomationRunStatus::Skipped); + assert_ne!(first.run_id, occurrence); + let repeated = evaluate_and_record_scheduler_skip( + &dashboard_root, + &config, + backend.executable(), + &job, + occurrence, + None, + ) + .await + .unwrap() + .unwrap(); + assert_eq!(repeated.ledger_record, first.ledger_record); + + let executable = tempfile::NamedTempFile::new().unwrap(); + let backend = backend.with_executable(executable.path()); + assert!( + evaluate_and_record_scheduler_skip( + &dashboard_root, + &config, + backend.executable(), + &job, + occurrence, + None, + ) + .await + .unwrap() + .is_none(), + "binding the backend must admit the same due occurrence without cooldown" + ); + assert_eq!(backend.calls(), 0); + assert_eq!( + load_run_records(&dashboard_root, 10).await.unwrap(), + vec![first.ledger_record], + "advisory admission must not append an effectful terminal" + ); + assert!( + tracedecay_automation_runtime::automation::run_ledger::find_run_record_exact_bounded( + &dashboard_root, + occurrence, + ) + .await + .unwrap() + .is_none() + ); } #[tokio::test] @@ -1206,15 +1287,22 @@ async fn scheduler_prefilter_live_lock_wins_over_not_due_summary() { let config = enabled_job_config(); let occurrence = "locked-prefilter-occurrence"; - let prefilter = - evaluate_and_record_scheduler_skip(&dashboard_root, &config, None, &job, occurrence, None) - .await - .unwrap() - .expect("the live job lock must produce a diagnostic"); + let executable = tempfile::NamedTempFile::new().unwrap(); + let backend = ContentBackend::new("unused").with_executable(executable.path()); + let prefilter = evaluate_and_record_scheduler_skip( + &dashboard_root, + &config, + backend.executable(), + &job, + occurrence, + None, + ) + .await + .unwrap() + .expect("the live job lock must produce a diagnostic"); assert_eq!(prefilter.report["reason"], json!("scheduler_lock_active")); assert_ne!(prefilter.run_id, occurrence); - let backend = ContentBackend::new("unused"); let admitted_job = tracedecay_automation_runtime::automation::jobs::admit_job(&job).unwrap(); let retained = run_user_job_with_backend_for_retained_settlement( &dashboard_root, @@ -1262,12 +1350,21 @@ async fn retained_scheduler_runner_reacquires_after_due_prefilter() { job.schedule = Some("every 1h".to_owned()); let config = enabled_job_config(); let occurrence = "prefilter-gap-occurrence"; + let executable = tempfile::NamedTempFile::new().unwrap(); + let backend = ContentBackend::new("unused").with_executable(executable.path()); assert!( - evaluate_and_record_scheduler_skip(&dashboard_root, &config, None, &job, occurrence, None) - .await - .unwrap() - .is_none(), + evaluate_and_record_scheduler_skip( + &dashboard_root, + &config, + backend.executable(), + &job, + occurrence, + None, + ) + .await + .unwrap() + .is_none(), "a new interval job is advisory-due before effect admission" ); let _raced_in = @@ -1276,7 +1373,6 @@ async fn retained_scheduler_runner_reacquires_after_due_prefilter() { .unwrap() .expect("the advisory prefilter must release its reservation lock"); - let backend = ContentBackend::new("unused"); let admitted_job = tracedecay_automation_runtime::automation::jobs::admit_job(&job).unwrap(); let retained = run_user_job_with_backend_for_retained_settlement( &dashboard_root,