← all branches

feat/discovery

needs attentionviewing older commit
6f39bb9 · incrementalPR #305reviewed 2026-07-14 21:53 UTC0H · 2M · 7L · 10I
The branch
Purpose
Feature Discovery v1 — help existing users discover unused Batu capabilities through contextual onboarding (spotlights, hub, guided tour), flag-gated off by default.
Goal
Land ambient spotlights, Descubre hub checklist, and a 5-step first-run guided tour with FCIS domain layer, JSend API, and es/en i18n.
Sub-goals
  • Ambient spotlights: contextual coachmarks paced ≤1/rolling-day, 7 signal types
  • Descubre hub: header badge with gap list and re-launch shortcut
  • First-run guided tour: 5 fixed steps with scrim + spotlight cutout
  • discovery_state table (migration 0058, user-scoped RLS)
  • DiscoveryFCIS domain: pure decisions, shells, queries
  • This commit: tour-active-store suppresses ambient spotlight while any tour surface is open
The changes (whole branch)
What
Adds tour-active-store.ts (module-level Set-based external store) and wires FeatureSpotlight to suppress via useSyncExternalStore when any tour is active. Fixes overlapping-layers on fresh accounts.
Why
GuidedTour and RpuSubTour render a dimming scrim; FeatureSpotlight renders a non-dimming coachmark. Both fired on fresh accounts creating two overlapping layers.
Areas
apps/platform/src/components/discovery/+11370domains/core/src/discovery/+3640apps/platform/src/api/+2850apps/platform/src/app/+10032apps/platform/src/messages/+2280
Blast
~41 files, ~2,151+/−49 cumulative. Incremental (this commit): 4 files, ~65 net lines.
flag-gated: feature-discovery-spotlights (OFF by default)
ci· No CI check results availablecoderabbit· No .coderabbit.yaml present

Findings · 14

correctness4

low

RpuSubTour keys suppression on composite enabled gate, not raw active param

apps/platform/src/components/discovery/RpuSubTour.tsx:88

enabled = flagEnabled && isDesktop && !!orgId && active. Resize below 1024px clears suppression while sub-tour also returns null — consistent but edge-case.

low

HMR-stale activeSurfaces — dev-only, self-healing via unmount cleanup

apps/platform/src/components/discovery/tour-active-store.ts

info

DescubreMenu scrim not wired — intentional product decision

apps/platform/src/components/discovery/DescubreMenu.tsx

info

Store notifies on aggregate boolean flip — correct for useSyncExternalStore

apps/platform/src/components/discovery/tour-active-store.ts

security1

info

Module-level singleton safe for SSR — client only, server stub returns false

apps/platform/src/components/discovery/tour-active-store.ts

conventions2

low

id: string — a TourSurfaceId literal union would catch future typos

apps/platform/src/components/discovery/tour-active-store.ts

type TourSurfaceId = 'guided-tour' | 'rpu-subtour' tightens the contract as surfaces grow.

info

ADR-016 FCIS does not apply — correct UI signal store pattern

tests4

medium

No unit tests for tour-active-store.ts — multi-surface Set logic unpinned

apps/platform/src/components/discovery/tour-active-store.ts

Closing one of two active surfaces must not fire listeners or clear the flag. Not covered by spotlight-latch.test.ts (component integration only).

medium

No reset export — module singleton bleeds between test cases

apps/platform/src/components/discovery/tour-active-store.ts

A resetTourActiveStore() export makes unit tests reliable without vi.resetModules() per test.

low

wasActive !== nowActive boundary has no pinned test

apps/platform/src/components/discovery/tour-active-store.ts:7

0→2→1→0 surfaces should fire listeners exactly twice. Prevents silent regression.

low

getAnyTourActiveServer SSR contract undocumented in tests

apps/platform/src/components/discovery/tour-active-store.ts

improvement3

low

Early return may cut in-flight exit animations in FeatureSpotlight

apps/platform/src/components/discovery/FeatureSpotlight.tsx

Verify no exit animation or that CSS handles abrupt unmount gracefully.

low

Aggregate-only notification — worth an inline comment on intent

apps/platform/src/components/discovery/tour-active-store.ts

info

Set-based design is future-proof — new surfaces require no structural changes

History · 36 commits

  1. c1fe7b7needs attentionincremental3H · 4M · 3L2026-07-27 06:02
  2. 414db56safeincremental0H · 0M · 2L2026-07-23 00:52
  3. ea68968needs attentionincremental0H · 4M · 7L2026-07-22 23:01
  4. 4bdb2c9needs attentionincremental1H · 3M · 5L2026-07-21 23:22
  5. 6e3f255safeincremental0H · 0M · 0L2026-07-20 16:46
  6. cc41079blockedincremental5H · 5M · 3L2026-07-20 16:25
  7. 2451ee0needs attentionincremental0H · 5M · 6L2026-07-20 16:09
  8. ab7c103needs attentionincremental0H · 1M · 6L2026-07-20 15:52
  9. 7eff611needs attentionincremental0H · 1M · 2L2026-07-18 00:41
  10. 246c67csafeincremental0H · 0M · 0L2026-07-17 23:58
  11. 7521b17safeincremental0H · 0M · 0L2026-07-17 23:35
  12. 1847ec8needs attentionincremental0H · 2M · 4L2026-07-17 23:28
  13. 5d3175cneeds attentionincremental3H · 6M · 4L2026-07-17 19:31
  14. d3f875dneeds attentionincremental1H · 2M · 4L2026-07-17 18:01
  15. 47d25faneeds attentionincremental1H · 1M · 2L2026-07-17 00:46
  16. 440d838needs attentionincremental4H · 9M · 9L2026-07-17 00:27
  17. 7466f97needs attentionincremental0H · 1M · 5L2026-07-16 23:20
  18. b686d58needs attentionincremental0H · 2M · 2L2026-07-16 14:24
  19. 9ea1446blockedincremental2H · 7M · 10L2026-07-16 13:44
  20. 6f39bb9needs attentionincremental0H · 2M · 7L2026-07-14 21:53current
  21. 2eadf2aneeds attentionincremental0H · 1M · 2L2026-07-14 20:12
  22. 97bd08fneeds attentionincremental0H · 2M · 5L2026-07-14 19:40
  23. a48e3ffneeds attentionincremental5H · 8M · 6L2026-07-14 18:22
  24. 69473b7needs attentionincremental2H · 5M · 3L2026-07-14 01:34
  25. 92e4235needs attentionincremental2H · 1M · 3L2026-07-14 01:04
  26. 6be8018safeincremental0H · 0M · 3L2026-07-14 00:15
  27. 090b4daneeds attentionincremental1H · 3M · 5L2026-07-13 23:50
  28. fa7683bneeds attentionincremental1H · 4M · 3L2026-07-13 18:55
  29. d64cd72needs attentionincremental2H · 3M · 2L2026-07-13 16:27
  30. c1f337bneeds attentionincremental3H · 7M · 14L2026-07-13 13:30
  31. 46e32b2safeincremental0H · 0M · 3L2026-07-11 02:54
  32. 3b30949needs attentionincremental0H · 2M · 3L2026-07-11 02:39
  33. 9f8dbdfneeds attentionincremental3H · 5M · 5L2026-07-11 02:32
  34. 23191eeneeds attentionincremental5H · 12M · 7L2026-07-11 02:18
  35. fa9b88fneeds attentionincremental0H · 1M · 2L2026-07-11 01:30
  36. 6a8bf42blockedfull8H · 11M · 8L2026-07-11 01:08