Guard the composer against draft resurrection now that removeDraft enqueues a
durable DELETE, and fail closed on unreconstructable burn-on-read sends.
- Add per-composer editor_guard module (keyed by serverUrl:channelId:rootId):
tracks genuine unsaved edits + a generation bumped on Send/Delete. Shared by
the save site and the invalidation sites; avoids prop-drilling.
- post_input: route blur/background/unmount through guardedSave, which no-ops
when the editor is clean and discards its write (via a captured-generation
staleness check) if Send/Delete invalidated the editor mid-save. Genuine
typing marks dirty; an external/remote value change resets the baseline clean;
unmount clears the entry.
- draft_handler.clearDraft and deleteDraftConfirmation invalidate the editor so a
pending lifecycle save cannot recreate a just-sent/deleted draft.
- handleDraftUpdate discards stale markdown-image metadata when the editor
generation changed during the async parse.
- handle_send_message: fail-closed burn-on-read guard on both send paths — an
enabled BoR send with invalid/missing durations shows a localized error, keeps
the draft, and never creates a downgraded plain post. Adds one en.json string.
Checks: npm run tsc clean; eslint --quiet clean; 126 Jest tests pass (editor
guard, handle_send_message incl. BoR fail-closed, draft actions, draft utils).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>