|
| 1 | +# Implementation Plan |
| 2 | + |
| 3 | +## Cause |
| 4 | + |
| 5 | +There are two independent fragility points on the renderer side. Both surface |
| 6 | +in packaged builds because timing in production is less forgiving than in dev. |
| 7 | + |
| 8 | +1. `useGuidedOnboardingStep.setStepStatus` returns the previous (possibly |
| 9 | + `null`) value of its internal `onboardingState` ref when the backend IPC |
| 10 | + throws. `continueGuidedOnboardingFromSettings` then resolves a `null` step |
| 11 | + id, hits the fallback branch, and calls `windowPresenter.focusMainWindow()` |
| 12 | + instead of `router.push({ name: 'settings-mcp' })`. The backend state is |
| 13 | + already correct — the renderer just doesn't see it on the relevant tick. |
| 14 | + |
| 15 | +2. `GuidedOnboardingOverlay` always renders the dim `<path>` from |
| 16 | + `OnBoardingSpotlight`, even when `useOnBoarding` has not produced a |
| 17 | + spotlight rect yet (target element not yet sized). With no cutout the path |
| 18 | + covers the entire viewport with `pointer-events: auto`, producing the |
| 19 | + "full-window dim, no popover, can't click" symptom while the layout |
| 20 | + stabilizes. |
| 21 | + |
| 22 | +## Change |
| 23 | + |
| 24 | +- **Renderer composable resilience.** In `useGuidedOnboardingStep`, when an |
| 25 | + onboarding IPC call fails, fall back to fetching fresh state via |
| 26 | + `onboardingClient.getState()` before returning to the caller. Apply to |
| 27 | + `setStepStatus`, `activateStep`, and `forceComplete` paths. |
| 28 | +- **Navigation helper resilience.** `continueGuidedOnboardingFromSettings` |
| 29 | + refreshes its `state` from `onboardingClient.getState()` when the caller |
| 30 | + passes a `null`/stale value, so that a transient renderer hiccup cannot |
| 31 | + force the helper into the "focus main window" branch. |
| 32 | +- **Overlay defensive rendering.** `OnBoardingSpotlight` only renders its |
| 33 | + dim `<path>` when a cutout is present. With no cutout the parent overlay |
| 34 | + still allows the panel to render at its fallback coordinates, but the |
| 35 | + blocking dim no longer covers the window. |
| 36 | + |
| 37 | +## Validation |
| 38 | + |
| 39 | +- `pnpm run format` |
| 40 | +- `pnpm run i18n` |
| 41 | +- `pnpm run lint` |
| 42 | +- `pnpm run typecheck` |
0 commit comments