feat/discovery
needs attentionviewing older commit7466f97 · incrementalPR #305reviewed 2026-07-16 23:20 UTC0H · 1M · 5L- Purpose
- Deliver contextual feature discovery for existing users — spotlights for unused capabilities, a Descubre hub, and a first-run guided product tour.
- Goal
- Ship Feature Discovery v1 fully flag-gated so nothing reaches users until the PostHog flag is flipped.
- Sub-goals
- SG-1: Ambient spotlights — one coachmark per session from real rows, paced ≤1/rolling-day, retire-on-dismiss
- SG-2: Descubre hub — header badge listing user gaps
- SG-3: First-run linear product tour — 5 steps, dimmed scrim + spotlight cutout
- SG-4: FCIS domain layer — discovery_state table (user-scoped RLS), API, analytics
- SG-5: Adversarial review fixes — preview bypass (VERCEL_ENV) and spotlight self-destruct (render latch)
- What
- Add anchor highlight ring and viewport-out guard. Ring visually connects coachmark to its target; guard hides both when anchor scrolls off-screen. GAP 10→14 to clear ring extent.
- Why
- Arrow alone was invisible against white table; fixed elements overdrew sticky chrome on scroll.
- Areas
- apps/platform/src/components/discovery+1569−0domains/cross-domain/src+1035−0domains/core/src/discovery+462−0apps/platform/src/api+287−0packages+396−16apps/platform/src/messages+232−0e2e/platform+56−0apps/platform/src/app/(dashboard)+95−62
- Blast
- 62 files, +18296/−62; concentrated in discovery UI, cross-domain shells, core FCIS, DB schema, API contracts, analytics, i18n. All flag-gated.
Findings · 6
correctness2
Ring flash: ring renders at full opacity before card fade-in completes
apps/platform/src/components/discovery/FeatureSpotlight.tsx:364
Ring has no entrance animation; card has animate-in fade-in-0 zoom-in-95. Brief (<100ms) logical inconsistency. Since ring cannot animate (scroll-lag), card could drop its animation or accept the asymmetry.
GAP=14 comment understates value — sum is 8 but 6px breathing room is undocumented
apps/platform/src/components/discovery/FeatureSpotlight.tsx:305
Suggest: // Clears the ring (inset 4 + ring-2 + offset-2 = 8px) plus 6px breathing room.
conventions2
Multi-line block comment on anchor ring div violates no-multi-line-comment-blocks rule
apps/platform/src/components/discovery/FeatureSpotlight.tsx
Condense to: {/* Anchor ring: visually connects coachmark to its target — pointer-events-none so control stays usable */}
Multi-line block comment on viewport guard (same rule)
apps/platform/src/components/discovery/FeatureSpotlight.tsx
Condense to: // Anchor off-screen: hide ring + card to avoid drawing over sticky chrome.
tests1
Viewport-out guard has no unit or component test
apps/platform/src/components/discovery/FeatureSpotlight.tsx:353
Both branches (above/below viewport) are untested. Existing latch tests are pure-function. A RTL test with mocked getBoundingClientRect covering {bottom: -1} and {top: 1000} would pin both branches.
improvement1
Ring geometry magic numbers lack a named constant
apps/platform/src/components/discovery/FeatureSpotlight.tsx
const RING_INSET = 4 would make the relationship to ring-2 ring-offset-2 explicit and appear once instead of four times.
History · 36 commits
- c1fe7b7needs attentionincremental3H · 4M · 3L2026-07-27 06:02
- 414db56safeincremental0H · 0M · 2L2026-07-23 00:52
- ea68968needs attentionincremental0H · 4M · 7L2026-07-22 23:01
- 4bdb2c9needs attentionincremental1H · 3M · 5L2026-07-21 23:22
- 6e3f255safeincremental0H · 0M · 0L2026-07-20 16:46
- cc41079blockedincremental5H · 5M · 3L2026-07-20 16:25
- 2451ee0needs attentionincremental0H · 5M · 6L2026-07-20 16:09
- ab7c103needs attentionincremental0H · 1M · 6L2026-07-20 15:52
- 7eff611needs attentionincremental0H · 1M · 2L2026-07-18 00:41
- 246c67csafeincremental0H · 0M · 0L2026-07-17 23:58
- 7521b17safeincremental0H · 0M · 0L2026-07-17 23:35
- 1847ec8needs attentionincremental0H · 2M · 4L2026-07-17 23:28
- 5d3175cneeds attentionincremental3H · 6M · 4L2026-07-17 19:31
- d3f875dneeds attentionincremental1H · 2M · 4L2026-07-17 18:01
- 47d25faneeds attentionincremental1H · 1M · 2L2026-07-17 00:46
- 440d838needs attentionincremental4H · 9M · 9L2026-07-17 00:27
- 7466f97needs attentionincremental0H · 1M · 5L2026-07-16 23:20current
- b686d58needs attentionincremental0H · 2M · 2L2026-07-16 14:24
- 9ea1446blockedincremental2H · 7M · 10L2026-07-16 13:44
- 6f39bb9needs attentionincremental0H · 2M · 7L2026-07-14 21:53
- 2eadf2aneeds attentionincremental0H · 1M · 2L2026-07-14 20:12
- 97bd08fneeds attentionincremental0H · 2M · 5L2026-07-14 19:40
- a48e3ffneeds attentionincremental5H · 8M · 6L2026-07-14 18:22
- 69473b7needs attentionincremental2H · 5M · 3L2026-07-14 01:34
- 92e4235needs attentionincremental2H · 1M · 3L2026-07-14 01:04
- 6be8018safeincremental0H · 0M · 3L2026-07-14 00:15
- 090b4daneeds attentionincremental1H · 3M · 5L2026-07-13 23:50
- fa7683bneeds attentionincremental1H · 4M · 3L2026-07-13 18:55
- d64cd72needs attentionincremental2H · 3M · 2L2026-07-13 16:27
- c1f337bneeds attentionincremental3H · 7M · 14L2026-07-13 13:30
- 46e32b2safeincremental0H · 0M · 3L2026-07-11 02:54
- 3b30949needs attentionincremental0H · 2M · 3L2026-07-11 02:39
- 9f8dbdfneeds attentionincremental3H · 5M · 5L2026-07-11 02:32
- 23191eeneeds attentionincremental5H · 12M · 7L2026-07-11 02:18
- fa9b88fneeds attentionincremental0H · 1M · 2L2026-07-11 01:30
- 6a8bf42blockedfull8H · 11M · 8L2026-07-11 01:08