Skip to content

Audit and Fix: Complete Parent Relationship Migration for Graph-Native Architecture #530

Closed as not planned

Description

@malibio

Audit and Fix: Complete Parent Relationship Migration for Graph-Native Architecture

Problem

Issue #528 fixed placeholder promotion to include _parentId/_containerId transient fields, but there are 128 other references to parentId in the frontend codebase that may need similar fixes. Without these fields, nodes are created as orphans with no has_child edges, breaking the tree structure and reactivity.

Status

Partially Fixed in #528:

  • ✅ Placeholder promotion in base-node-viewer now includes _parentId/_containerId
  • ✅ Typing in placeholder nodes works
  • ❌ Other node creation paths still broken

See: #528

Root Cause

The graph-native migration (#511, #514) moved parent-child relationships from fields (parent_id, container_node_id) to graph edges (has_child), but the frontend still has code paths that:

  1. Try to read node.parentId (no longer exists)
  2. Create nodes without establishing parent edges
  3. Query by parent without using the new hierarchy APIs

Scope

Found: 128 references to parentId in frontend (excluding tests)

Critical paths that need parent relationship:

  • Placeholder promotion (✅ FIXED in Bug: Placeholder node loses focus immediately after typing, preventing text input #528)
  • Node splitting operations (❓ needs verification)
  • Indent/outdent operations (❓ needs verification)
  • Enter key creating sibling/child nodes (❓ needs verification)
  • Slash command node creation (❓ needs verification)
  • Mention node creation (❓ needs verification)
  • Manual node creation APIs (❓ needs verification)

Audit Checklist

Phase 1: Identify All Node Creation Points

Files to audit:

For each createNode() call, verify:

  • Does it pass _parentId and _containerId?
  • If not, should it? (Is this a child node or root node?)
  • Is the parent relationship established via set_parent() afterward?

Phase 2: Categorize by Fix Needed

Category A: Needs _parentId/_containerId (like #528 fix)

  • Nodes created as children of existing nodes
  • Need parent edge created immediately

Category B: Needs Explicit setParent() Call

  • Complex creation where parent isn't known at creation time
  • Two-step: create node, then establish relationship

Category C: Already Correct (Root Nodes)

  • Container nodes (dates, etc.)
  • Should NOT have parent
  • No fix needed

Phase 3: Fix Each Category

For Category A nodes:

// Add transient fields before createNode
const nodeToCreate = {
    ...node,
    _parentId: currentParentId,
    _containerId: currentContainerId
};
await tauriNodeService.createNode(nodeToCreate);

For Category B nodes:

// Create first
const newNode = await tauriNodeService.createNode(node);

// Then establish relationship
await tauriNodeService.setParent(newNode.id, parentId);

Implementation Plan

Step 1: Comprehensive Audit

Create a spreadsheet/document listing:

  • File:Line number
  • Function name
  • Current code
  • Category (A, B, or C)
  • Fix needed (yes/no)
  • Priority (critical/high/medium/low)

Step 2: Fix Critical Paths First

Priority order:

  1. Placeholder typing (✅ DONE in Bug: Placeholder node loses focus immediately after typing, preventing text input #528)
  2. Enter key operations (create sibling/child)
  3. Indent/outdent (moves nodes, changes parent)
  4. Node splitting (creates new node with same parent)
  5. Slash commands (create typed nodes)
  6. Mention creation (create referenced nodes)

Step 3: Update Shared Services

Centralize parent handling in shared-node-store:

// shared-node-store.ts

/**
 * Helper: Enrich node with parent context before persistence
 * Adds transient _parentId/_containerId fields for backend edge creation
 */
function enrichNodeWithParentContext(
    node: Node,
    parentCache: Map<string, string>
): Node & { _parentId?: string; _containerId?: string } {
    const parentId = parentCache.get(node.id);

    if (!parentId) {
        // Root node - no parent fields
        return node;
    }

    return {
        ...node,
        _parentId: parentId,
        _containerId: parentId  // Assuming parent === container for most cases
    };
}

// Use in all createNode paths
async function persistNode(node: Node) {
    const enrichedNode = enrichNodeWithParentContext(node, this.parentChildCache);
    await tauriNodeService.createNode(enrichedNode);
}

Step 4: Testing Strategy

For each fixed createNode() path:

  • Unit test: Verify _parentId field is included
  • Integration test: Verify has_child edge is created
  • Manual test: Verify tree structure appears correctly

Regression tests:

Acceptance Criteria

Functional

  • All node creation paths establish parent relationships correctly
  • Tree structure is correct (can query children via getChildren())
  • No orphan nodes created (except intentional root nodes)
  • Reactivity works (UI updates when hierarchy changes)

Technical

  • All 128 parentId references audited and categorized
  • Critical paths (placeholder, Enter, indent/outdent) fixed
  • Less critical paths (mentions, slash commands) fixed
  • Shared services centralize parent context handling
  • All tests pass

Testing

  • Unit tests for each fix
  • Integration tests verify has_child edges created
  • Manual testing confirms tree operations work
  • No regressions in existing functionality

Known Issues

Fixed in #528:

  • ✅ Placeholder promotion in base-node-viewer

Likely Still Broken (needs verification):

  • ❓ Node splitting (creates sibling without parent edge?)
  • ❓ Indent/outdent (changes parent but edge not updated?)
  • ❓ Enter key (creates sibling/child - edge created?)
  • ❓ Slash command nodes (created with parent edge?)
  • ❓ Mention autocomplete creating referenced nodes

Related Issues

Estimated Effort

  • Audit: 2-3 hours (catalog all 128 references)
  • Critical fixes: 4-6 hours (Enter, indent/outdent, split)
  • Remaining fixes: 6-8 hours (mentions, slash commands, etc.)
  • Testing: 4-6 hours (unit + integration + manual)
  • Total: 16-23 hours (2-3 days)

Priority

CRITICAL - Core functionality (typing, tree manipulation) is broken without these fixes.

Activity

  1. malibio commented on Nov 17, 2025

    @malibio
    CollaboratorAuthor

    Combining with #531 into a single comprehensive issue

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions