Skip to content

Auto-save annotation drafts to survive server crashes#217

Merged
backnotprop merged 3 commits intomainfrom
feat/auto-save-drafts
Mar 4, 2026
Merged

Auto-save annotation drafts to survive server crashes#217
backnotprop merged 3 commits intomainfrom
feat/auto-save-drafts

Conversation

@backnotprop
Copy link
Owner

Summary

  • Adds server-side draft persistence at ~/.plannotator/drafts/{content-hash}.json so annotations survive server crashes
  • Debounced auto-save (500ms) on annotation changes — silent, no UI indicators
  • On reload with existing draft, a dialog prompts to Restore or Dismiss
  • Drafts auto-deleted on approve/deny/feedback submit
  • Works across all three servers (plan, review, annotate)

Closes #212

Known limitation: Cross-block annotation highlights don't visually restore (pre-existing issue in findTextInDOM(), tracked in #216).

Test plan

  • Add annotations to a plan, kill the server, restart with same plan content — dialog should appear
  • Click Restore — annotations appear in sidebar panel
  • Click Dismiss — draft deleted, no dialog on next reload
  • Approve/deny a plan — draft file cleaned up
  • Same flow works for code review (/plannotator-review)

🤖 Generated with Claude Code

backnotprop and others added 2 commits March 4, 2026 00:29
Adds server-side draft persistence so annotations are not lost when the
server process dies. Drafts are saved to ~/.plannotator/drafts/ keyed by
a SHA-256 content hash, debounced at 500ms. On reload, a dialog prompts
the user to restore or dismiss. Drafts are auto-deleted on approve/deny/feedback.

Closes #212

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@backnotprop
Copy link
Owner Author

Code review

Found 1 issue:

  1. draftKey is computed once at server startup from options.rawPatch but never updated when the user switches diff types via /api/diff/switch. After a switch, currentPatch is updated (line 158) but all draft operations continue using the original key. If the server crashes after a diff switch, restored annotations will be applied against the wrong patch content.

const draftKey = contentHash(options.rawPatch);
// Mutable state for diff switching
let currentPatch = options.rawPatch;
let currentGitRef = options.gitRef;
let currentDiffType: DiffType = options.diffType || "uncommitted";
let currentError = options.error;

The /api/diff/switch handler updates currentPatch but not draftKey:

// Update state
currentPatch = result.patch;
currentGitRef = result.label;
currentDiffType = newDiffType;
currentError = result.error;

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

…s comment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@backnotprop backnotprop merged commit aa71ede into main Mar 4, 2026
1 check passed
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.

Support auto save annotation

1 participant