Files
2026-06-18 22:21:38 -04:00

11 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, gap_closure, requirements, must_haves
phase plan type wave depends_on files_modified autonomous gap_closure requirements must_haves
12-initial-setup-wizard 07 execute 1
apps/pwa/src/App.tsx
apps/pwa/src/App.test.tsx
apps/pwa/src/components/SetupBanner.tsx
true true
SETUP-01
SETUP-04
truths artifacts key_links
After setup is complete, manually visiting /setup shows the 'already complete' surface (or redirects away) — not the wizard
After completing the wizard (incl. Fastmail credential) and landing in the app, the /calendar 'Set up your calendar' banner does NOT show for the operator
The setup gate respects the loading state to avoid a flash of the wizard
path provides contains
apps/pwa/src/App.tsx /setup route gated on setupComplete (alreadyLocked or redirect); ['me'] freshness reconciled with wizard completion alreadyLocked
from to via pattern
App.tsx /setup route setupQuery.data.setupComplete alreadyLocked={setupComplete === true} or Navigate to /calendar alreadyLocked|setupComplete
from to via pattern
SetupBanner needsProviderSetup ['me'] query freshness ['me'] refetched after wizard completion so the banner reflects the claimed credential needsProviderSetup|invalidateQueries
Close UAT gaps 5 and 6 — both on the PWA app-shell gate (`App.tsx`), with the banner component (`SetupBanner.tsx`).

Gap 5 (major): App.tsx renders <Route path="/setup" element={<SetupPage />} /> with no alreadyLocked prop and no setupComplete check. The * gate only redirects OTHER routes TO /setup when incomplete; there is no reverse guard. When setupComplete === true, manually visiting /setup still mounts the full wizard. The backend already 423s mutations, so this is purely a frontend gating gap. Fix: gate the /setup route on setupComplete — pass alreadyLocked={setupComplete === true} (SetupPage already supports this prop → renders Surface 8 "Setup already complete") or Navigate to /calendar; respect setupLoading to avoid a flash.

Gap 6 (major, root_cause PRELIMINARY): after finishing the wizard and landing on /calendar, the "Set up your calendar / Set up now" banner still shows. Task 1 is an investigation step to confirm the mechanism before prescribing the exact fix; Task 2 implements the confirmed fix.

Purpose: A completed instance must not re-expose the wizard, and must not nag the operator to set up a calendar they already configured in the wizard. Output: /setup route gated post-completion; ['me'] reconciled so the banner does not show after wizard completion.

<execution_context> @$HOME/.claude/gsd-core/workflows/execute-plan.md @$HOME/.claude/gsd-core/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/12-initial-setup-wizard/12-UAT.md @.planning/phases/12-initial-setup-wizard/12-03-SUMMARY.md @.planning/phases/12-initial-setup-wizard/12-04-SUMMARY.md

Files to edit + investigate

@apps/pwa/src/App.tsx @apps/pwa/src/App.test.tsx @apps/pwa/src/components/SetupBanner.tsx

Reference (do not edit unless Task 1 investigation proves a backend linking gap)

@apps/api/src/routes/me.ts @apps/api/src/routes/setup.ts @apps/api/src/auth/user.ts

Task 1: Gate the /setup route on setupComplete (gap 5) apps/pwa/src/App.tsx, apps/pwa/src/App.test.tsx In apps/pwa/src/App.tsx, the `} />` (line ~139) currently mounts the wizard unconditionally. Add a reverse guard using the already-present `setupComplete` / `setupLoading` values (derived at lines ~132-133 from `setupQuery`): - While `setupLoading` is true → render the existing no-flash placeholder (`