diff --git a/frontend/dashboard.js b/frontend/dashboard.js index df47d31..1f4be91 100644 --- a/frontend/dashboard.js +++ b/frontend/dashboard.js @@ -376,7 +376,7 @@ onStatus: (state, detail = {}) => { const status = qs('#today-sync-status'); status.textContent = state === 'saved' ? 'Today saved to account.' : - (state === 'recovered' ? `Recovered ${detail.discarded} Today edit${detail.discarded === 1 ? '' : 's'} · discarded ${detail.discarded} unreadable device record${detail.discarded === 1 ? '' : 's'}.` : + (state === 'recovered' ? `Today queue recovered · discarded ${detail.discarded} unreadable device record${detail.discarded === 1 ? '' : 's'}.` : (state === 'retrying' ? `Today saved on this device · retrying in ${Math.ceil(detail.delayMs / 1000)}s.` : (state === 'pending' ? 'Today saved on this device · sync pending.' : (state === 'full' ? 'Another device filled Today · showing its saved plan.' : diff --git a/frontend/today-sync.js b/frontend/today-sync.js index 2e18ae0..a6bf255 100644 --- a/frontend/today-sync.js +++ b/frontend/today-sync.js @@ -303,8 +303,12 @@ function createTodaySync({ storage, getLogin, fetchJson, onRemoteIds, onRemotePl cancelRetry(); return !hadConflict; } catch (error) { - if (pending().length) scheduleRetry(error, ownerKey); - else onStatus?.('error'); + const stillPending = pending().length; + if (discardedCount) recoveryNotice = { discarded: discardedCount, until: now() + 5000 }; + const recovered = recoveryNotice.until > now() ? recoveryNotice.discarded : 0; + if (stillPending) scheduleRetry(error, ownerKey); + else onStatus?.(recovered ? 'recovered' : 'error', recovered ? { discarded: recovered } : {}); + discardedCount = 0; return false; } } diff --git a/tests/e2e/test_mobile_today_handoff_release.py b/tests/e2e/test_mobile_today_handoff_release.py index c2881b0..d999354 100644 --- a/tests/e2e/test_mobile_today_handoff_release.py +++ b/tests/e2e/test_mobile_today_handoff_release.py @@ -105,7 +105,7 @@ def test_release_artifact_plans_hands_off_and_opens_next_mobile_issue(tmp_path: page.reload(wait_until="networkidle") expect(page.locator("#my-work-status")).to_contain_text("2") expect(page.locator("#today-sync-status")).to_have_text( - "Recovered 1 Today edit · discarded 1 unreadable device record." + "Today queue recovered · discarded 1 unreadable device record." ) assert page.evaluate("""() => !Object.keys(localStorage).some( key => key.startsWith('stackchain.today-sync.v1.timmy.operation.') diff --git a/tests/test_today_sync.py b/tests/test_today_sync.py index 471ece4..41db9ab 100644 --- a/tests/test_today_sync.py +++ b/tests/test_today_sync.py @@ -143,7 +143,7 @@ const sync=createTodaySync({{storage,getLogin:()=> 'timmy', def test_today_sync_reports_queue_recovery_instead_of_plain_saved_status(): source = DASHBOARD.read_text() - assert "Recovered ${detail.discarded} Today edit" in source + assert "Today queue recovered" in source assert "discarded ${detail.discarded} unreadable device record" in source