Skip to content

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Dec 20, 2025

https://linear.app/discourse-graphs/issue/ENG-1153/maximum-update-limit-error-on-canvas-after-adding-supports-relation
The issue was that the reparent arrow function looking at non-arrow siblings in a way that did not take relations into account, leading to a reparenting cascade.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed index calculation logic when reparenting arrows to prevent conflicts with relation bindings.
    • Improved sibling selection and neighbor determination to correctly position arrows relative to adjacent elements.
    • Prevents visual overlap issues when repositioning bound relation arrows, ensuring proper ordering in diagram layout.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Dec 20, 2025

@supabase
Copy link

supabase bot commented Dec 20, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@maparent
Copy link
Collaborator Author

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

📝 Walkthrough

Walkthrough

Modifies arrow reparenting logic in DiscourseRelationBindings to prevent index conflicts with bound relation arrows. Introduces exclusion set logic to filter out relation IDs and current arrow type during sibling calculations, replacing prior type-mismatch filtering with broader exclusion criteria.

Changes

Cohort / File(s) Change Summary
Arrow Index Calculation & Exclusion Logic
apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
Adds import for getDiscourseRelations; builds exclusion set of relation IDs and current arrow type; replaces type-mismatch sibling filtering with exclusion-set-based filtering; updates next non-arrow/non-relation sibling selection and index calculation logic to use exclusion criteria; adjusts placement condition for arrows between siblings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Logic verification: Confirm the exclusion set construction correctly captures all relation IDs and the current arrow type, and that the filtering logic properly excludes these from sibling calculations.
  • Index calculation correctness: Verify that the new index placement logic correctly positions arrows and prevents conflicts with relation bindings, particularly the condition checking arrow index against the next non-excluded sibling.
  • Edge cases: Review boundary conditions when there are no non-excluded siblings or when the exclusion set is empty.

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references the specific issue (ENG-1153) and describes the main problem being fixed: preventing a maximum update limit error that occurs when adding a supports relation between evidence and claim on canvas.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx (2)

233-234: Consider potential performance impact of repeated calls.

The function getDiscourseRelations() is called every time reparentArrow executes. If reparenting occurs frequently or if getDiscourseRelations() is expensive, consider caching the relation IDs at a higher scope.

However, since this change fixes a critical cascading update bug, the current implementation is acceptable as-is.

💡 Optional optimization: cache relation IDs

If performance becomes a concern, consider caching the relation IDs:

+// Cache relation IDs at module level or in a useMemo/useCallback if in a component
+const cachedRelationIds = new Set(getDiscourseRelations().map((r) => r.id));
+
 // eslint-disable-next-line preferArrows/prefer-arrow-functions
 function reparentArrow(editor: Editor, arrowId: TLShapeId) {
   // ... existing code ...
   
-  const relationIds = new Set(getDiscourseRelations().map((r) => r.id));
+  const relationIds = new Set(cachedRelationIds);
   relationIds.add(arrow.type);

Note: Only implement if profiling shows this is a bottleneck.


251-268: Consider renaming variable for clarity.

The variable nextHighestNonArrowSibling now represents the next sibling that is neither an arrow nor a relation (as correctly noted in the comment on lines 236-238). The name could be updated to reflect this broader exclusion.

💡 Optional: rename for clarity
-    const nextHighestNonArrowSibling = higherSiblings[0];
+    const nextHighestNonRelationSibling = higherSiblings[0];
     if (
       // ...then, if we're above the last shape we want to be above...
       reparentedArrow.index > highestSibling.index &&
       // ...but below the next non-arrow sibling...
-      reparentedArrow.index < nextHighestNonArrowSibling.index
+      reparentedArrow.index < nextHighestNonRelationSibling.index
     ) {
       // ...then we're already in the right place. no need to update!
       return;
     }
 
     // otherwise, we need to find the index between the highest sibling
     // we want to be above, and the next highest sibling we want to be
     // below:
     finalIndex = getIndexBetween(
       highestSibling.index,
-      nextHighestNonArrowSibling.index,
+      nextHighestNonRelationSibling.index,
     );

Alternatively: nextHighestNonRelatedSibling or nextNonBoundSibling

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b4cb58 and 90e0c8f.

📒 Files selected for processing (1)
  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx}: Use Tailwind CSS for styling where possible
When refactoring inline styles, use tailwind classes
Prefer type over interface in TypeScript
Use explicit return types for functions
Avoid any types when possible
Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use PascalCase for components and types
Use camelCase for variables and functions
Use UPPERCASE for constants
Function names should describe their purpose clearly
Prefer early returns over nested conditionals for better readability

Files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
apps/roam/**/*.{js,ts,tsx,jsx,json}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Prefer existing dependencies from package.json when working on the Roam Research extension

Files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
apps/roam/**/*.{ts,tsx,jsx,js,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension

Files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
apps/roam/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

apps/roam/**/*.{ts,tsx,js,jsx}: Use the roamAlphaApi docs from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when implementing Roam functionality
Use Roam Depot/Extension API docs from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when implementing extension functionality

Files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
apps/roam/**

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Implement the Discourse Graph protocol in the Roam Research extension

Files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
🧠 Learnings (1)
📚 Learning: 2025-06-17T23:42:29.279Z
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 220
File: apps/roam/src/utils/conceptConversion.ts:95-104
Timestamp: 2025-06-17T23:42:29.279Z
Learning: In the DiscourseGraphs/discourse-graph codebase, DiscourseRelation type properties are either string or Triple[], and the STANDARD_ROLES filter in conceptConversion.ts excludes Triple[] properties, so only string values remain after filtering.

Applied to files:

  • apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx
🔇 Additional comments (1)
apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationBindings.tsx (1)

236-245: Excellent fix for the cascading reparent issue!

The broadened exclusion criteria (from checking sibling.type !== arrow.type to checking !relationIds.has(sibling.type)) correctly prevents index conflicts with all relation bindings, not just the current arrow type. This should resolve the maximum update limit error described in the PR objectives.

@maparent
Copy link
Collaborator Author

@maparent
Copy link
Collaborator Author

I think relations are kinds of arrows, so the variable rename is unnecessary.
The caching makes a lot of sense, there are many ways to do it and I would prefer for Micheal to indicate preference here.

@maparent maparent requested a review from mdroidian December 20, 2025 16:49
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.

2 participants