Conversation
…ontmatter - Change organization persister from JSON to markdown files with frontmatter - Store each organization as organizations/<UUID>.md - Add auto-migration from organizations.json on first load - Add cleanup of orphan files when records are deleted - Follow the same pattern as the human persister from PR #2791 Organization schema fields (user_id, created_at, name) are stored in YAML frontmatter. The markdown body is always empty since organizations have no memo field. Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
✅ Deploy Preview for hyprnote-storybook canceled.
|
✅ Deploy Preview for howto-fix-macos-audio-selection canceled.
|
✅ Deploy Preview for hyprnote canceled.
|
Comment on lines
+25
to
+28
| const dirExists = await exists(organizationsDir); | ||
| if (dirExists) { | ||
| return; | ||
| } |
Contributor
There was a problem hiding this comment.
Critical: Potential data loss during migration
The migration skips if the organizations directory exists, even if it's empty or incomplete. This prevents re-migration if a previous migration failed partway through.
Scenario that breaks:
- User has
organizations.jsonwith data - Migration starts and creates
organizationsdirectory - Migration fails before completing (crash, network issue, etc.)
- On next startup, migration is skipped because directory exists
- Data from
organizations.jsonis never migrated
Fix:
Check if the directory is non-empty instead of just checking existence:
const dirExists = await exists(organizationsDir);
if (dirExists) {
// Check if directory has any .md files before skipping
const entries = await readDir(organizationsDir);
const hasMdFiles = entries.some(e => !e.isDirectory && e.name.endsWith('.md'));
if (hasMdFiles) {
return; // Only skip if there are actual migrated files
}
}
Suggested change
| const dirExists = await exists(organizationsDir); | |
| if (dirExists) { | |
| return; | |
| } | |
| const dirExists = await exists(organizationsDir); | |
| if (dirExists) { | |
| // Check if directory has any .md files before skipping | |
| const entries = await readDir(organizationsDir); | |
| const hasMdFiles = entries.some(e => !e.isDirectory && e.name.endsWith('.md')); | |
| if (hasMdFiles) { | |
| return; // Only skip if there are actual migrated files | |
| } | |
| } | |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
refactor(desktop): store organizations as markdown files with YAML frontmatter
Summary
Changes the organization persister from storing all organizations in a single
organizations.jsonfile to storing each organization as an individual markdown file (organizations/<UUID>.md) with YAML frontmatter. This follows the same pattern established in PR #2791 for the human persister.Organization schema fields (
user_id,created_at,name) are stored in YAML frontmatter. The markdown body is always empty since organizations have no memo field.New files:
utils.ts- Path helpers and frontmatter parsingcollect.ts- Write operation collector for frontmatter batch exportload.ts- Load organizations from markdown files + orphan cleanupmigrate.ts- Auto-migration fromorganizations.jsonon first loadExample output format:
Review & Testing Checklist for Human
migrate.tscorrectly handles edge cases (empty JSON, malformed JSON, partial migration failures). The migration deletesorganizations.jsonafter migrating - confirm this is the desired behavior.cleanupOrphanOrganizationFilesinload.tsto ensure it won't accidentally delete valid organization files ifvalidOrgIdsis incorrectly populated.organizations.jsondata and verify:Notes
parseMarkdownWithFrontmatterfunction is duplicated from the human persister rather than shared - this matches the existing pattern but could be consolidated in a future refactor.Link to Devin run: https://app.devin.ai/sessions/9d5f79c14dcf49bb88c6ffac3866403b
Requested by: yujonglee (@yujonglee)