Skip to content

Bug: Import pipeline does not create mentions relationships for nodespace:// links #868

Description

@malibio

Summary

When importing markdown files via the folder import feature, inter-file links are correctly transformed to nodespace://uuid format in the node content, but the corresponding mentions relationships are never created in the database. This breaks the "Mentioned by" panel for imported documents.

Current Behavior

  1. User imports a folder of markdown files
  2. Phase 1 (sync): Files are parsed, inter-file links are transformed to nodespace://uuid format
  3. Phase 2 (async): Nodes are bulk-created via bulk_create_hierarchy_trusted(), collections are assigned
  4. Missing: No mentions relationships are created for the nodespace:// links in the content

Expected Behavior

After import completes, all nodespace://uuid links in the imported content should have corresponding mentions relationships in the database, enabling:

  • "Mentioned by" panel to show backlinks
  • Graph navigation between linked documents

Root Cause

The import pipeline uses bulk_create_hierarchy_trusted() which bypasses the normal node creation flow. The normal sync_mentions() function is only triggered on node updates (comparing old vs new content), not on initial creation during import.

Technical Analysis

Current import flow (packages/desktop-app/src-tauri/src/commands/import.rs):

  • Phase 2 steps: bulk_resolve_collections → bulk_create_hierarchy_trusted → bulk_add_to_collections → update lifecycle_status
  • No step to create mentions

Link transformation location: transform_links_in_nodes() in markdown.rs:192 is called during Phase 1 (import.rs:672-677). This function already iterates through all nodes and resolves file paths to nodespace://uuid - this is the ideal place to also collect the mentions pairs.

Bulk pattern exists - see bulk_add_to_collections() in surreal_store.rs:5108 for the pattern of building batch RELATE statements with idempotency checks.

Proposed Solution

1. Modify transform_links_in_nodes() to also return mentions

Location: packages/core/src/mcp/handlers/markdown.rs:192

Currently:

pub fn transform_links_in_nodes(
    nodes: &mut [PreparedNode],
    file_to_root_id: &HashMap<PathBuf, String>,
    current_file_path: Option<&Path>,
) {
    // transforms content in-place, returns nothing
}

Should become:

pub fn transform_links_in_nodes(
    nodes: &mut [PreparedNode],
    file_to_root_id: &HashMap<PathBuf, String>,
    current_file_path: Option<&Path>,
) -> Vec<(String, String)> {
    // transforms content in-place
    // ALSO returns Vec<(source_node_id, target_node_id)> for all resolved links
}

The function already has access to:

  • node.id - the source node ID
  • The resolved nodespace://uuid - the target node ID

2. Add bulk_create_mentions() to SurrealStore

Location: packages/core/src/db/surreal_store.rs

Following the bulk_add_to_collections() pattern:

  • Input: Vec<(String, String)> of (source_node_id, target_node_id) pairs
  • Idempotent: skip existing mentions
  • Single transaction for all relationships

3. Update import pipeline

Location: packages/desktop-app/src-tauri/src/commands/import.rs

Phase 1 (line ~672):

// Collect mentions while transforming links
let mut all_mentions: Vec<(String, String)> = Vec::new();
for prepared in &mut prepared_files {
    let mentions = transform_links_in_nodes(
        &mut prepared.children,
        &file_to_uuid_map,
        Some(&prepared.file_path),
    );
    all_mentions.extend(mentions);
}

Phase 2 (after Step 4, line ~820):

// Step 5: Bulk create mentions
if !all_mentions.is_empty() {
    match store.bulk_create_mentions(&all_mentions).await {
        Ok(count) => {
            tracing::info!("Bulk created {} mentions", count);
        }
        Err(e) => {
            tracing::error!("Failed to bulk create mentions: {:?}", e);
        }
    }
}

Acceptance Criteria

  • transform_links_in_nodes() returns Vec<(String, String)> of mentions pairs
  • bulk_create_mentions() method added to SurrealStore
  • Import pipeline collects mentions during Phase 1 link transformation
  • Import pipeline creates mentions in bulk during Phase 2 (Step 5)
  • Self-references are excluded (node linking to itself or its root)
  • Invalid targets are handled gracefully (target doesn't exist in import batch)
  • "Mentioned by" panel works for imported documents with inter-file links
  • Unit tests for bulk_create_mentions()
  • Unit tests for updated transform_links_in_nodes() returning mentions

Files to Modify

  1. packages/core/src/mcp/handlers/markdown.rs - Modify transform_links_in_nodes() to return mentions
  2. packages/core/src/db/surreal_store.rs - Add bulk_create_mentions()
  3. packages/desktop-app/src-tauri/src/commands/import.rs - Collect and create mentions

References

Metadata

Metadata

Assignees

Labels

backendbugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions