Skip to content

eng-1344 f10b upload obsidian relations and their schemas#721

Merged
maparent merged 4 commits intomainfrom
eng-1344-upload-relation-and-rel-schema
Feb 25, 2026
Merged

eng-1344 f10b upload obsidian relations and their schemas#721
maparent merged 4 commits intomainfrom
eng-1344-upload-relation-and-rel-schema

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Jan 22, 2026

This uploads relationship schemas to supabase.

https://www.loom.com/share/ce2382d45c6741838fa6cf6b6f7e3d97


Open with Devin

@linear
Copy link

linear bot commented Jan 22, 2026

@supabase
Copy link

supabase bot commented Jan 22, 2026

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 maparent force-pushed the eng-1343-f10a-sync-node-schema-definitions branch from 6bfab2f to 408ef40 Compare January 24, 2026 15:54
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch 2 times, most recently from f966a5b to 7f0a45d Compare January 24, 2026 18:30
@maparent maparent force-pushed the eng-1343-f10a-sync-node-schema-definitions branch from 5fdb70d to 0b3d0cb Compare January 25, 2026 15:07
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch 2 times, most recently from 3d49688 to 3b0a73a Compare January 25, 2026 15:21
@maparent maparent force-pushed the eng-1343-f10a-sync-node-schema-definitions branch from 3fb53ae to f661f0f Compare January 27, 2026 17:08
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 3b0a73a to 6c48b9f Compare January 27, 2026 17:11
@maparent maparent force-pushed the eng-1343-f10a-sync-node-schema-definitions branch from f661f0f to df19c3c Compare January 27, 2026 19:25
Base automatically changed from eng-1343-f10a-sync-node-schema-definitions to main January 27, 2026 19:27
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch 3 times, most recently from ea45b20 to 9e74420 Compare February 1, 2026 21:59
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 9e74420 to 63c0832 Compare February 5, 2026 15:37
maparent added a commit that referenced this pull request Feb 5, 2026
trangdoan982 pushed a commit that referenced this pull request Feb 7, 2026
trangdoan982 pushed a commit that referenced this pull request Feb 8, 2026
maparent added a commit that referenced this pull request Feb 8, 2026
trangdoan982 pushed a commit that referenced this pull request Feb 8, 2026
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 63c0832 to 982652f Compare February 11, 2026 00:51
@maparent maparent marked this pull request as ready for review February 11, 2026 18:52
devin-ai-integration[bot]

This comment was marked as resolved.

trangdoan982 added a commit that referenced this pull request Feb 11, 2026
#722)

* eng-1344 f10b upload obsidian relations and their schemas

* current progress

* feature finished

* address PR comments

* address PR comments

* remove local test file

* curr progress

* revert what is handled in #721

* Use SpaceURI rather than spaceId in frontmatter

* address PR comments

* address PR comments

* cleanup

* Update apps/obsidian/src/utils/importNodes.ts

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* normalize on using numbers for dates

* correction

* apply ctime, mtime to assets

* spurious log

* Preserve ctime, mtime in processFrontMatter. Also timezone correction

* add lastModified in frontMatter

* make sure import image works

* add recursive folder creation

* modify the fetchNodeContent flow; simplify the pathMapping

* WIP: shuffle the filePath around

* send originalPathDepth

* actually send path itself

* clarify var name

* make sure fileImport works for all possible settings

* store relative path when rewrite the wikilink instead of default to fileToLinkText

* cleanup logs

* nit

* AI corrections

* Update apps/obsidian/src/utils/importNodes.ts

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* address PR comments

---------

Co-authored-by: Marc-Antoine Parent <maparent@acm.org>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch 2 times, most recently from e82b16b to 376b1a4 Compare February 11, 2026 23:20
devin-ai-integration[bot]

This comment was marked as resolved.

@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from d406e78 to 0f8912b Compare February 11, 2026 23:48
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 595e8a2 to 30e40b2 Compare February 22, 2026 14:37
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 19 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 Missing legacy importedFromSpaceUri check in collectDiscourseNodesFromPaths allows imported nodes to sync as local

When checking whether to skip imported files during sync, collectDiscourseNodesFromPaths only checks for importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

The shared collectDiscourseNodesFromVault in apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both keys:

if (
  (frontmatter.importedFromRid || frontmatter.importedFromSpaceUri) &&
  includeImported !== true
) { continue; }

But collectDiscourseNodesFromPaths at apps/obsidian/src/utils/syncDgNodesToSupabase.ts:717 only checks the new key:

if (frontmatter.importedFromRid) {
  continue;
}

The migration from importedFromSpaceUriimportedFromRid runs inside initializeSupabaseSync which is fire-and-forget (void) at apps/obsidian/src/index.ts:47. The FileChangeListener starts immediately after and calls syncDiscourseNodeChangescollectDiscourseNodesFromPaths. If migration hasn't completed yet, or if it fails (the error is caught and only logged at apps/obsidian/src/syncDgNodesToSupabase.ts:916-918), files with the legacy importedFromSpaceUri would pass this check and be incorrectly synced to Supabase as locally-authored nodes.

Impact: Imported nodes could be re-uploaded to Supabase as new local concepts/content, causing duplicate data in the user's space.

(Refers to lines 717-720)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 30e40b2 to bb38514 Compare February 23, 2026 16:30
@maparent maparent force-pushed the eng-1461-use-full-rid-instead-of-just-spaceuri-as-marker-of-import branch from 6983308 to 5699c31 Compare February 23, 2026 16:30
devin-ai-integration[bot]

This comment was marked as resolved.

@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from bb38514 to 6784bf7 Compare February 23, 2026 17:17
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 21 additional findings in Devin Review.

Open in Devin Review

...otherData
} = node;
/* eslint-disable @typescript-eslint/naming-convention */
const literal_content: Record<string, Json> = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm thinking maybe we should have a stronger type system for Concepts.literal_content and Content.metadata. We already use metadata for Wikilink import (we store the full path of the file there). with different types that we upload here (Node, Relation, schemas), it might get messy really soon if we don't enforce the type and still read data from these json columns. It's not blocking for now, we can make this a separate ticket and create the corresponding literal_content type for each Node/Relation Instance-schema separately. or if you prefer to just add the Type in this PR for relation instance and schema that works too

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This one I want to address later, it requires thought.

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes non blocking for now

Base automatically changed from eng-1461-use-full-rid-instead-of-just-spaceuri-as-marker-of-import to main February 23, 2026 18:59
@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from 6784bf7 to 91b4992 Compare February 23, 2026 19:02
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 22 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 20 additional findings in Devin Review.

Open in Devin Review

@@ -470,29 +490,103 @@ const convertDgToSupabaseConcepts = async ({
const lastSchemaSync = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

ok so on my local test there's a problem with using this lastSchemaSync to fetch relationType to sync:

  • all the instances were uploaded but not the relation schemas
  • i think the reason is that lastSchema sync is for node type. and since the local relation types were modified before we uploaded the node types, this isn't picked up by the system.
    • this could be the consequence of us shipping the publish nodes before shipping publishing relations in our dev flow. but since Holehouse lab will also use the publish nodes first we should use a different way to get lastSchemaSync separately for node vs relation schema.

Copy link
Collaborator

Choose a reason for hiding this comment

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

here's the screenshot of my local test: no relationType or relationTripletSchema is uploaded:

Image

@@ -470,29 +490,103 @@ const convertDgToSupabaseConcepts = async ({
const lastSchemaSync = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

here's the screenshot of my local test: no relationType or relationTripletSchema is uploaded:

Image

@maparent maparent force-pushed the eng-1344-upload-relation-and-rel-schema branch from cc52d2f to a6f2d9e Compare February 24, 2026 20:26
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 21 additional findings in Devin Review.

Open in Devin Review

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

🐛 1 issue in files not directly in the diff

🐛 Missing legacy importedFromSpaceUri check in shouldSyncFile allows imported file changes to be queued (apps/obsidian/src/utils/fileChangeListener.ts:101-103)

The FileChangeListener.shouldSyncFile gating function only checks importedFromRid but not the legacy importedFromSpaceUri frontmatter key.

Root Cause and Impact

At apps/obsidian/src/utils/fileChangeListener.ts:101, only importedFromRid is checked:

if (frontmatter?.importedFromRid) {
  return false;
}

But the shared collectDiscourseNodesFromVault at apps/obsidian/src/utils/getDiscourseNodes.ts:32-38 correctly checks both:

(frontmatter.importedFromRid || frontmatter.importedFromSpaceUri)

The FileChangeListener is initialized immediately at apps/obsidian/src/index.ts:56-58, while the migration from importedFromSpaceUri to importedFromRid runs asynchronously in a fire-and-forget initializeSupabaseSync call at line 47. If a user modifies an imported file (still bearing importedFromSpaceUri) before migration completes, shouldSyncFile returns true and the change is queued for sync as if it were a locally-authored node.

Impact: Imported files could be incorrectly identified as needing sync, leading to them being treated as local nodes in the sync pipeline.

View 21 additional findings in Devin Review.

Open in Devin Review

@maparent maparent merged commit 4d43317 into main Feb 25, 2026
10 checks passed
@maparent maparent deleted the eng-1344-upload-relation-and-rel-schema branch February 25, 2026 18:26
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