Observed
Confirming the sign-out warning tells the worker to delete everything this device holds, and the worker then stops the run. The worker's own catch-up job — the one that delivers offline play after a reconnect — keeps running through that delete. A catch-up already in flight can write a fresh activity start a moment after the delete, so the delete misses it.
That record survives the sign-out. The next time the same account signs in on this device, the worker delivers it to the server: the exact outcome the warning exists to prevent.
Checkpoints written in the same window are harmless. Each one names an activity whose start row the delete took with it, so no later flush can deliver it. The activity start is the record that does damage, because it stands on its own.
Expected
A confirmed discard leaves the device holding nothing. The worker refuses to start a catch-up while a discard runs, and a catch-up already running finishes or stops before the delete begins.
Repro
No automated repro exists. The window is the length of one delete, so hitting it by hand needs the two to coincide:
- Play offline until the device holds undelivered runs.
- Bring the device back online, which starts the worker's catch-up.
- Open settings and confirm the sign-out warning within the second that catch-up takes.
- Sign in again as the same account on this device.
Expect nothing to deliver. A record the catch-up wrote after the delete delivers instead.
A test drives the two concurrently rather than reproducing the timing: hold the delete open, let a catch-up write its start, then assert the device holds nothing once the discard settles.
Notes
Observed
Confirming the sign-out warning tells the worker to delete everything this device holds, and the worker then stops the run. The worker's own catch-up job — the one that delivers offline play after a reconnect — keeps running through that delete. A catch-up already in flight can write a fresh activity start a moment after the delete, so the delete misses it.
That record survives the sign-out. The next time the same account signs in on this device, the worker delivers it to the server: the exact outcome the warning exists to prevent.
Checkpoints written in the same window are harmless. Each one names an activity whose start row the delete took with it, so no later flush can deliver it. The activity start is the record that does damage, because it stands on its own.
Expected
A confirmed discard leaves the device holding nothing. The worker refuses to start a catch-up while a discard runs, and a catch-up already running finishes or stops before the delete begins.
Repro
No automated repro exists. The window is the length of one delete, so hitting it by hand needs the two to coincide:
Expect nothing to deliver. A record the catch-up wrote after the delete delivers instead.
A test drives the two concurrently rather than reproducing the timing: hold the delete open, let a catch-up write its start, then assert the device holds nothing once the discard settles.
Notes
libs/game/idle-client/src/worker/handle-remove-undelivered-work-message.ts, and the worker serializes its jobs throughlibs/game/idle-client/src/worker/worker-lifecycle-machine.ts. That machine already runs one job at a time, so the fix is a state it does not have yet rather than a new mechanism.