Shipped
- Implemented the real write-path for
protocol_builder_draft(not just read-only fallback) - Added debounced autosave on meaningful builder state changes (750–1500ms window)
- Added restore flow on builder open:
- If a draft exists and is newer than the last saved routine state, prompt:
- Restore Draft
- Discard Draft
- If a draft exists and is newer than the last saved routine state, prompt:
- Added draft clearing rules:
- Clears on successful routine save/publish
- Clears on explicit discard
- Added draft versioning:
- Safely discards drafts with unsupported
draftVersion(no crashes)
- Safely discards drafts with unsupported
- Added analytics events:
builder_draft_saved{ routine_id? }builder_draft_restored{ routine_id? }builder_draft_discarded{ routine_id? }
Draft Model (minimal)
Stored under protocol_builder_draft:
{ draftVersion: 1, updatedAt, context: { routineId?: string | null }, draft: <builder snapshot> }
Behavior Notes
- Drafts are scoped to editing context:
- Editing existing routine →
routineId = <id> - New routine →
routineId = null
- Editing existing routine →
- If routine validation fails and save is blocked, draft is preserved
- Autosave is disabled when viewing a locked preset unless the user is forking/editing
Why
- Routine building is high-effort authoring—losing state on refresh/back navigation kills trust
- Local-first apps need local reliability: drafts make the builder resilient by default
- Analytics closes the loop so we can measure whether drafts are actually saving users from loss
Next
- Add timestamps / “last autosaved” microcopy in the builder header
- Support multiple drafts later (per-routine draft slots) if needed