Preventative measures for cell deletion when syncing.#769
Preventative measures for cell deletion when syncing.#769
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
|
||
| debug("Notebook deserialization complete", { cellCount: cells.length }); | ||
| return notebookData as CodexNotebookAsJSONData; | ||
| debug("Successfully parsed notebook contents", { cellCount: raw.cells.length }); |
There was a problem hiding this comment.
Debug statement crash path moved outside try-catch
Low Severity
The debug(...) call accessing raw.cells.length was moved from inside the try-catch to outside it. JavaScript evaluates function arguments eagerly, so { cellCount: raw.cells.length } is always evaluated regardless of the DEBUG flag. If the JSON is valid but lacks a cells property (e.g., {}), raw.cells is undefined at runtime despite the RawNotebookData type assertion, producing an uncaught TypeError instead of the friendly "Failed to deserialize codex notebook" error from the catch block. Previously this was caught by the try-catch and handled with the empty-notebook fallback.


Closes #766
Guard 1 -- codexDocument.ts: Added _loadFailed boolean flag with a public getter. Set to true in the constructor's catch block when JSON parsing fails and the fallback empty document is created.
Guard 2 -- codexDocument.ts save(): Added an early-exit check at the top of save(). If the in-memory document has 0 cells, it reads the disk file. If disk has cells, the save is aborted with a [SAVE GUARD] warning log, preserving the on-disk data.
Guard 3 -- codexDocument.ts save(): After the merge produces a candidate string but before atomicWriteUriText, the candidate is parsed and compared against the disk version. If the merge produced 0 cells but disk has cells, it falls back to the disk content.
Guard 4 -- merge/index.ts: Added auditCodexFilesBeforeSync() which scans all .codex files after saveAll() completes but before syncChanges() commits. For any file that now has 0 cells, it checks the HEAD commit -- if HEAD has cells, it restores the file from git.
Guard 5 -- serializer.ts: Changed deserializeNotebook to throw on JSON parse failure instead of silently returning an empty notebook. Removed the now-unreachable dead code that constructed NotebookCellData from the empty fallback.
Note
Cursor Bugbot is generating a summary for commit 01b881f. Configure here.