Skip to content

Support repo-local custom relationship edge kinds#710

Open
muness wants to merge 1 commit into
mainfrom
issue/707
Open

Support repo-local custom relationship edge kinds#710
muness wants to merge 1 commit into
mainfrom
issue/707

Conversation

@muness

@muness muness commented Jun 27, 2026

Copy link
Copy Markdown
Member

Closes #707

Summary

  • Add EdgeKind::Other(String) with string-label serde/display parsing for repo-local relationship kinds.
  • Preserve unknown edge labels through LanceDB load and edge-type filters.
  • Cover custom edge round-trip, grouped traversal, and MCP/search-facing label rendering.

Verification

  • cargo test custom_edge_kind --lib
  • cargo test format_neighbors_grouped_preserves_custom_edge_label --lib
  • cargo test builtin_edge_kind_json_serialization_stays_string_label --lib
  • cargo check --lib

Review

  • sg review unavailable: error: command not found: sg; performed manual staged-diff review instead.

Summary by CodeRabbit

  • Bug Fixes
    • Preserved custom relationship labels when saving, loading, and displaying graph data.
    • Improved handling of unknown edge types so they no longer disappear during import or filtering.
    • Fixed traversal output to show custom edge names in grouped results.
    • Corrected graph scoring behavior so custom edge types are weighted more conservatively in ranking and community detection.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Custom edge labels now round-trip through EdgeKind, LanceDB persistence, and grouped neighbor output. Unknown non-empty labels become EdgeKind::Other(...), keep their label in serde, and receive a conservative graph weight.

Changes

Repo-local custom edge kinds

Layer / File(s) Summary
EdgeKind parsing and serde
src/graph/mod.rs, src/graph/index.rs
EdgeKind now orders custom labels, parses unknown non-empty strings into Other, serializes labels as strings, round-trips built-in and custom cases in tests, and gives Other(_) a 0.05 weight.
Store parsing and grouped output
src/server/store/mod.rs, src/server/helpers.rs
parse_edge_kind now delegates to EdgeKind::from_label, and grouped neighbor rendering shows custom edge labels in traversal output.
Custom edge persistence round-trip
src/server/store/persist.rs
persist_graph_to_lance and load_graph_from_lance are exercised with a custom supports edge that reloads as a graph edge and survives grouped traversal; the existing referenced-by test formatting is updated.

Sequence Diagram(s)

sequenceDiagram
  participant Test as custom edge round trip test
  participant Persist as persist_graph_to_lance
  participant DB as LanceDB
  participant Load as load_graph_from_lance
  participant Parse as parse_edge_kind
  participant FromLabel as EdgeKind from_label
  participant Format as format_neighbors_grouped

  Test->>Persist: persist supports edge
  Persist->>DB: store edge_type supports
  DB-->>Load: reload persisted edge_type
  Load->>Parse: parse edge_type
  Parse->>FromLabel: delegate label parsing
  FromLabel-->>Load: return EdgeKind Other supports
  Test->>Format: render grouped traversal
  Format-->>Test: return custom edge group
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through labels, soft and bright,
supports stayed cozy through the night.
LanceDB held my carrot trail,
And grouped neighbors waved their tail.
✨ No edge was lost to foggy air.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding support for repo-local custom relationship edge kinds.
Linked Issues check ✅ Passed The patch adds EdgeKind::Other, preserves custom labels through persistence and traversal, and includes tests covering round-trips and output.
Out of Scope Changes check ✅ Passed The changes stay focused on custom edge kinds, their parsing/serialization, and related tests; no unrelated functionality stands out.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue/707

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/server/store/persist.rs (1)

916-973: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the workaround assertion exercise the same traversal path.

wrong_workaround starts at metadata_only, but the grouped traversal starts from claimant, so !groups.contains_key(&EdgeKind::References) passes even if a same-source workaround edge would leak into the supports traversal. Put the workaround on claimant and filter traversal to the custom supports kind so the regression test is adversarial.

Proposed test tightening
+        let supports_kind = EdgeKind::Other("supports".to_string());
         let mut metadata_only = make_test_node("metadata_only");
         metadata_only
             .metadata
             .insert("relationship".to_string(), "supports".to_string());
         let wrong_workaround = Edge {
-            from: metadata_only.id.clone(),
+            from: claimant.id.clone(),
             to: evidence.id.clone(),
             kind: EdgeKind::References,
             source: ExtractionSource::Markdown,
             confidence: Confidence::Detected,
         };
         let custom_edge = Edge {
             from: claimant.id.clone(),
             to: evidence.id.clone(),
-            kind: EdgeKind::Other("supports".to_string()),
+            kind: supports_kind.clone(),
             source: ExtractionSource::Markdown,
             confidence: Confidence::Detected,
         };
@@
             .edges
             .iter()
-            .filter(|e| e.kind == EdgeKind::Other("supports".to_string()))
+            .filter(|e| e.kind == supports_kind)
             .collect();
@@
-        let groups = state.index.neighbors_grouped(
+        let supports_filter = [supports_kind.clone()];
+        let groups = state.index.neighbors_grouped(
             &claimant.stable_id(),
-            None,
+            Some(&supports_filter),
             petgraph::Direction::Outgoing,
         );
         let supports_group = groups
-            .get(&EdgeKind::Other("supports".to_string()))
+            .get(&supports_kind)
             .expect("custom supports edge missing from grouped traversal");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/store/persist.rs` around lines 916 - 973, The regression test in
persist_graph_to_lance is not exercising the same traversal path as the custom
supports edge because wrong_workaround is anchored at metadata_only instead of
claimant. Update the test data so the workaround edge originates from claimant,
and make the neighbor-group assertion inspect only the custom
EdgeKind::Other("supports") path used by neighbors_grouped. Keep the
load_graph_from_lance and grouped traversal checks aligned around claimant,
evidence, EdgeKind::References, and EdgeKind::Other("supports") so the test
fails if a same-source workaround leaks into the supports traversal.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/server/store/persist.rs`:
- Around line 916-973: The regression test in persist_graph_to_lance is not
exercising the same traversal path as the custom supports edge because
wrong_workaround is anchored at metadata_only instead of claimant. Update the
test data so the workaround edge originates from claimant, and make the
neighbor-group assertion inspect only the custom EdgeKind::Other("supports")
path used by neighbors_grouped. Keep the load_graph_from_lance and grouped
traversal checks aligned around claimant, evidence, EdgeKind::References, and
EdgeKind::Other("supports") so the test fails if a same-source workaround leaks
into the supports traversal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5d0478b2-117b-4c24-ab60-6bfa8d33bf42

📥 Commits

Reviewing files that changed from the base of the PR and between 9deab3d and fa2732f.

📒 Files selected for processing (5)
  • src/graph/index.rs
  • src/graph/mod.rs
  • src/server/helpers.rs
  • src/server/store/mod.rs
  • src/server/store/persist.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support repo-local custom relationship edge kinds

1 participant