fix: stop IdeaLoom sync from resurrecting a note you deleted in Obsidian - #5372
Merged
Conversation
…ian (#5339) A list that had already been exchanged kept its note path forever, so the next export re-created a note the user had deleted in the vault. Deleting the note is now a decision, not drift to repair: both import and export report it as a distinct `missing` outcome and write nothing, and only an explicit "Recreate deleted notes" request (`recreateMissing`) writes it again. An iCloud note that is merely un-downloaded stays `unavailable`, so it is never a recovery candidate. Adds the opt-in automatic export the storage slice left as a dead setting: `autoSync` now debounces a burst of edits into one vault write, re-reads both toggles when the write fires, and calls the exchange with the fail-closed defaults, so it can never delete a note, recreate one, or resolve a conflict. Only a local list edit schedules it — the import and sync routes deliberately do not — and an export whose rendered Markdown already matches the note on disk is skipped, so a freshly imported list cannot export itself back. Documents the base-hash conflict table, the deletion contract, and the automatic-sync limits in the Brain, API, and storage docs, which previously deferred all three to this slice. Closes #5339
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.
Summary
missingoutcome and writes nothing. Before,exportOnere-created the note on the next write, resurrecting data the user deleted on purpose. Recreating it takes an explicit request (recreateMissing), surfaced as a "Recreate N deleted notes" action that only appears after an exchange reported one.unavailable≠missing. The import-side probe usesexistsSyncrather than the scan result, so an iCloud note that has not been downloaded staysunavailableand is never offered as a recovery candidate.autoSyncwas a stored setting nothing read. It now debounces a burst of edits into one vault write, re-reads both toggles when the write fires (so turning either off cancels queued work), and calls the exchange with the fail-closed defaults — it cannot delete a note, recreate one, or resolve a conflict.updateIdeaLoomSettingspreviously had no caller. The exchange summary now names every outcome includingmissing.docs/features/brain-system.mdgains the base-hash conflict table, the deletion contract, and the auto-sync limits — replacing the paragraph that deferred all three to this slice.docs/API.mdnames the sync body flags;docs/STORAGE.mdrecords the conflict/deletion behavior and backup coverage.Closes #5339.
Test plan
server/services/idealoomAutoSync.test.js(new): debounce coalescing, fail-closed on each of the three toggles, toggles re-read at fire time,recreateMissingnever passed, a failed export not crashing the process, unresolved outcomes warned. Fake timers throughout — no production sleeps.server/services/idealoomObsidian.test.js: externally deleted note →missingwith nothing written, then recreated underrecreateMissing; a deleted note surfaced on import without dropping the local list; a note already matching the list is skipped, not rewritten.server/routes/brain.test.js:recreateMissingdefaults tofalseand threads through when set; auto-sync is scheduled by create/update only — never by delete, import, or sync.client/src/components/brain/IdeaLoomLists.test.jsx: the auto-sync toggle is unreachable until sync is enabled and a vault is chosen; recovery is offered only after an exchange reports a deleted note, and the plain export does not ask for a recreate.server(35,453) andclient(10,223) suites pass;clientbiome lint clean; API route catalog regenerated.