Summary
deepest_predicate_identifier (added in PR #222, crates/codemark-core/src/query/summarizer.rs) walks the entire query tree and returns the #eq?/#match? value bound to the deepest node anywhere:
fn walk(node, source, depth, best) {
if let Some((_, val)) = predicate_capture_and_value(node, source)
&& best.as_ref().is_none_or(|(d, _)| depth >= *d) { *best = Some((depth, val)); }
...
}
A predicate in an unrelated sibling branch that happens to be nested deeper than the node enclosing @target can therefore outrank the true enclosing landmark, so the row shows an identifier from a branch that does not contain the target.
Impact
Low today: queries produced by the generator are a linear nested path (all predicates sit on the target or its ancestors' name fields), so there are no competing sibling predicates. It matters only for hand-crafted / hand-edited bookmark queries with branching predicate landmarks. short_display() is display-only, so the worst case is a slightly wrong list label — never a wrong match/resolution.
Fix
Restrict candidates to node patterns that are ancestors of the @target capture, then pick the deepest qualifying (enclosing) pattern. Add a test with a sibling predicate landmark to confirm it is ignored.
Raised by CodeRabbit on #222.
Summary
deepest_predicate_identifier(added in PR #222,crates/codemark-core/src/query/summarizer.rs) walks the entire query tree and returns the#eq?/#match?value bound to the deepest node anywhere:A predicate in an unrelated sibling branch that happens to be nested deeper than the node enclosing
@targetcan therefore outrank the true enclosing landmark, so the row shows an identifier from a branch that does not contain the target.Impact
Low today: queries produced by the generator are a linear nested path (all predicates sit on the target or its ancestors' name fields), so there are no competing sibling predicates. It matters only for hand-crafted / hand-edited bookmark queries with branching predicate landmarks.
short_display()is display-only, so the worst case is a slightly wrong list label — never a wrong match/resolution.Fix
Restrict candidates to node patterns that are ancestors of the
@targetcapture, then pick the deepest qualifying (enclosing) pattern. Add a test with a sibling predicate landmark to confirm it is ignored.Raised by CodeRabbit on #222.