grep -rn "beforeunload" src/ returns nothing. Closing the tab, reloading, or accepting the PWA update discards any edit still inside the autosave debounce window, with no prompt.
src/ui/PwaUpdatePrompt.tsx states the intended guarantee:
the page is never reloaded out from under an unsaved project
but nothing flushes or warns before update() reloads. The only flush trigger is visibilitychange → hidden in session.ts, which is fire-and-forget across a worker boundary and is not guaranteed to complete before the page is torn down.
The unsaved-dot is live in the transport bar, so the app already knows when there is unflushed work — it simply never acts on that knowledge at unload time.
Suggested fix
Register a beforeunload handler while modifiedSinceLastSave is true, and make the update prompt flush (awaiting saveNow()) before calling update(). Note that beforeunload cannot await an async flush, so it should warn rather than promise to save; the reliable flush belongs on the update path and on visibilitychange.
Related: the autosave-on-project-switch gap is tracked separately, and together these mean there is currently no guaranteed flush point at all.
grep -rn "beforeunload" src/returns nothing. Closing the tab, reloading, or accepting the PWA update discards any edit still inside the autosave debounce window, with no prompt.src/ui/PwaUpdatePrompt.tsxstates the intended guarantee:but nothing flushes or warns before
update()reloads. The only flush trigger isvisibilitychange → hiddeninsession.ts, which is fire-and-forget across a worker boundary and is not guaranteed to complete before the page is torn down.The unsaved-dot is live in the transport bar, so the app already knows when there is unflushed work — it simply never acts on that knowledge at unload time.
Suggested fix
Register a
beforeunloadhandler whilemodifiedSinceLastSaveis true, and make the update prompt flush (awaitingsaveNow()) before callingupdate(). Note thatbeforeunloadcannot await an async flush, so it should warn rather than promise to save; the reliable flush belongs on the update path and onvisibilitychange.Related: the autosave-on-project-switch gap is tracked separately, and together these mean there is currently no guaranteed flush point at all.