diff --git a/.github/guardrail-pulse-history.jsonl b/.github/guardrail-pulse-history.jsonl index 411b2135d04..9eec4625564 100644 --- a/.github/guardrail-pulse-history.jsonl +++ b/.github/guardrail-pulse-history.jsonl @@ -1 +1,2 @@ {"date": "2026-07-23", "metrics": {"brand_ui_purple": {"baseline": 1776, "count": 1776}, "deferred_work_markers": {"baseline": 837, "count": 837}, "lifecycle_unlabeled_scripts": {"baseline": 17, "count": 17}, "mapless_packages": {"baseline": 6, "count": 3}, "union_return_isinstance": {"baseline": 0, "count": 0}, "version_prefixed_files": {"baseline": 42, "count": 42}}} +{"date": "2026-08-17", "metrics": {"brand_ui_purple": {"baseline": 1763, "count": 1763}, "deferred_work_markers": {"baseline": 829, "count": 829}, "lifecycle_unlabeled_scripts": {"baseline": 10, "count": 10}, "mapless_packages": {"baseline": 6, "count": 2}, "union_return_isinstance": {"baseline": 0, "count": 0}, "version_prefixed_files": {"baseline": 38, "count": 38}}} diff --git a/desktop/windows/changelog/unreleased/2026-08-onboarding-per-account-reset.json b/desktop/windows/changelog/unreleased/2026-08-onboarding-per-account-reset.json new file mode 100644 index 00000000000..fee74dd0c1e --- /dev/null +++ b/desktop/windows/changelog/unreleased/2026-08-onboarding-per-account-reset.json @@ -0,0 +1,5 @@ +{ + "changes": [ + "Signing in with a different account now resets the onboarding wizard so the new user sees the full setup flow instead of being dropped straight to the home screen." + ] +} diff --git a/desktop/windows/src/renderer/src/lib/authTeardown.test.ts b/desktop/windows/src/renderer/src/lib/authTeardown.test.ts index 738af3e5536..5eaca180879 100644 --- a/desktop/windows/src/renderer/src/lib/authTeardown.test.ts +++ b/desktop/windows/src/renderer/src/lib/authTeardown.test.ts @@ -8,14 +8,18 @@ const h = vi.hoisted(() => ({ invalidateConversationsCache: vi.fn(), clearPendingConversations: vi.fn(), clearUserScopedPreferences: vi.fn(), - clearMemoryCache: vi.fn() + clearMemoryCache: vi.fn(), + resetOnboarding: vi.fn() })) vi.mock('./pageCache', () => ({ invalidateConversationsCache: h.invalidateConversationsCache, clearPendingConversations: h.clearPendingConversations })) -vi.mock('./preferences', () => ({ clearUserScopedPreferences: h.clearUserScopedPreferences })) +vi.mock('./preferences', () => ({ + clearUserScopedPreferences: h.clearUserScopedPreferences, + resetOnboarding: h.resetOnboarding +})) vi.mock('./localAgentMemoryCache', () => ({ clearMemoryCache: h.clearMemoryCache })) import { reconcileAccountForSignIn, teardownUserData } from './authTeardown' @@ -38,6 +42,7 @@ beforeEach(() => { h.clearPendingConversations.mockClear() h.clearUserScopedPreferences.mockClear() h.clearMemoryCache.mockClear() + h.resetOnboarding.mockClear() ;(globalThis as { window: { omi: unknown } }).window.omi = { wipeUserData, byokClearAll, @@ -120,6 +125,8 @@ describe('reconcileAccountForSignIn — account-switch guard', () => { // The prior account's BYOK keys + Gmail session are cleared before B hydrates. expect(byokClearAll).toHaveBeenCalledTimes(1) expect(gmailSessionDisconnect).toHaveBeenCalledTimes(1) + // Onboarding is reset so the incoming account sees the wizard (new user on this device). + expect(h.resetOnboarding).toHaveBeenCalledTimes(1) expect(localStorage.getItem(LAST_UID_KEY)).toBe('userB') // The uid pointer must survive teardown (it's machine-scoped, not in the // user-scoped key list) so the NEXT switch is still detected. @@ -131,6 +138,7 @@ describe('reconcileAccountForSignIn — account-switch guard', () => { await reconcileAccountForSignIn('userA') expect(wipeUserData).not.toHaveBeenCalled() + expect(h.resetOnboarding).not.toHaveBeenCalled() expect(localStorage.getItem(LAST_UID_KEY)).toBe('userA') }) @@ -139,6 +147,7 @@ describe('reconcileAccountForSignIn — account-switch guard', () => { await reconcileAccountForSignIn('userA') expect(wipeUserData).not.toHaveBeenCalled() + expect(h.resetOnboarding).not.toHaveBeenCalled() expect(localStorage.getItem(LAST_UID_KEY)).toBe('userA') }) diff --git a/desktop/windows/src/renderer/src/lib/authTeardown.ts b/desktop/windows/src/renderer/src/lib/authTeardown.ts index 977344fcf59..ed27b3a97ff 100644 --- a/desktop/windows/src/renderer/src/lib/authTeardown.ts +++ b/desktop/windows/src/renderer/src/lib/authTeardown.ts @@ -9,7 +9,7 @@ // (authSession.forceReauth) and never wipes data. import { clearMemoryCache } from './localAgentMemoryCache' import { clearPendingConversations, invalidateConversationsCache } from './pageCache' -import { clearUserScopedPreferences } from './preferences' +import { clearUserScopedPreferences, resetOnboarding } from './preferences' import { CHAT_INFINITE_ID_KEY } from './chatStorageKeys' import { POST_HISTORY_KEY } from './sync/backfillStorageKey' import { resetByokKeys } from './byokKeys' @@ -117,7 +117,10 @@ export async function reconcileAccountForSignIn(uid: string | null): Promise