← all branches

feat/discovery

needs attentionviewing older commit
d64cd72 · incrementalpre-PRreviewed 2026-07-13 16:27 UTC2H · 3M · 2L
The branch
Purpose
Feature discovery system that guides new Batu users through the platform on first run and surfaces contextual feature spotlights as they navigate.
Goal
Implement Diego's v1 feature discovery direction: a fixed-sequence product tour on the Contratos page backed by server-side gap tracking, plus contextual spotlights for key platform features (CFE setup, contract add, API credentials). Gated behind PostHog flag with Vercel preview bypass.
Sub-goals
  • SG-1: Domain layer — discovery-state FCIS (type, decisions, queries, shells, mapper) + DB schema (discovery_state table, migration 0058)
  • SG-2: API surface — discovery contract/handler/mapper, gap endpoint, recordOutcome mutation
  • SG-3: Cross-domain coordinator — feature-discovery decisions + shells spanning core × utility
  • SG-4: UI — GuidedTour (linear tour), FeatureSpotlight (contextual coachmarks), DescubreMenu (hub with gap badge)
  • SG-5: Analytics — analytics events (tour_started, tour_completed, spotlight_seen, etc.)
  • SG-6: Fix series — concurrency, spotlight self-destruct, preview gating, overflow, anchor correctness, idempotent secrets
The changes (whole branch)
What
Design pass (d64cd721) declutters the tour card: downgrades 'Hazlo ahora' from a competing full-width button to a quiet accent link, removes the redundant 'Saltar' footer text link (X button is the only skip), and replaces the plain step counter with visual progress dots (pill = current, filled = past, outlined = future). One prior fix (c1f337bc) corrected tour step destinations to point to Recibos not Descargas.
Why
Diego's v1 direction to reduce visual noise in the tour card — four controls in a 340px card caused overflow and competed for attention. Von Restorff principle: one clear primary CTA (Siguiente), everything else secondary.
Areas
apps/platform/src/components/discovery+8130apps/platform/src/api (discovery contract/handler/mapper)+2760apps/platform/src/app (layout wiring, pages)+272domains/core/src/discovery (FCIS)+3610domains/cross-domain/src (coordinator)+8980packages (api schemas, analytics events, database schema, secrets)+30112e2e/platform+480
Blast
48 files, +3586/−31 (excluding DB migrations/snapshots). Touches the full FCIS stack (domain → cross-domain → API → UI) plus analytics and E2E. New DB table (discovery_state). No existing functionality removed.
scope.md in .branch/ is for feat/mod-gates (prior branch), not this branch — context above derived from commit log
CI· No PR open — CI status not availablecoderabbit· No .coderabbit.yaml in repo

Findings · 7

conventions3

high

text-brand-electric-violet utility class is not defined — Hazlo-ahora link will render colorless

apps/platform/src/components/discovery/GuidedTour.tsx:258

The diff introduces `text-brand-electric-violet` on the "Hazlo ahora" button. Checked packages/ui/src/styles/components.css — only `.bg-brand-electric-violet`, `.text-brand-heliotrope`, and `.bg-brand-heliotrope` are defined; `.text-brand-electric-violet` is absent. TailwindCSS v4 silently skips unknown utilities, so the link renders with no color (inherits default text color instead of the intended accent). Fix: add `.text-brand-electric-violet { color: hsl(var(--brand-electric-violet)); }` in components.css alongside its `bg-` sibling, or switch to `text-brand-heliotrope` which is already defined.

high

Anterior uses bare <button> while Siguiente uses <Button> — inconsistent focus ring and theme contract

apps/platform/src/components/discovery/GuidedTour.tsx:285

The previous-step control is a hand-rolled `<button>` with manual `h-8 rounded-md px-2.5` classes and no explicit `focus-visible` ring. The old code used `<Button size="sm" variant="cancel">` which carries the design system's shared focus ring, disabled styling, and size contract. Using the system `<Button size="sm" variant="ghost">` (or the `cancel` variant) would keep keyboard focus styling consistent between Anterior and Siguiente, and propagate future theme changes automatically.

medium

Progress dots aria-label is a bare fraction with no semantic context

apps/platform/src/components/discovery/GuidedTour.tsx:268

The dots container has `aria-label={\`${stepIdx + 1}/${total}\`}` which announces as "2/5" — no indication this is tour progress. Additionally, the `<span>` dots are decorative but lack `aria-hidden="true"`, so screen readers may enumerate them as unlabelled elements. Fix: use a localized label (`Paso {n} de {total}` — add i18n key) and add `aria-hidden="true"` to every dot `<span>`.

improvement4

medium

Past-step dot opacity (bg-muted-foreground/50) likely fails WCAG 1.4.11 non-text contrast at 6px

apps/platform/src/components/discovery/GuidedTour.tsx:274

Past-step dots use `bg-muted-foreground/50` (50% opacity) at `h-1.5 w-1.5` (6×6 px). At this size and opacity the contrast ratio against a white card background likely falls below the 3:1 minimum for non-text UI components (WCAG 1.4.11). Bump to `bg-muted-foreground` (full opacity) to preserve the three-state encoding without relying on opacity for differentiation.

medium

ArrowRight icon in Hazlo-ahora link won't flip in RTL locales

apps/platform/src/components/discovery/GuidedTour.tsx:261

The `<ArrowRight>` icon always points right. If the platform is ever used in an RTL context the icon direction should mirror. Low risk today but a known trap for icon-decorated CTA links. Add `rtl:rotate-180` to the icon's className or use a directional icon utility when RTL is first supported.

low

Navigation row lacks a group landmark — AT users can't jump directly to tour controls

apps/platform/src/components/discovery/GuidedTour.tsx:267

The footer `<div>` containing progress dots + Anterior/Siguiente has no landmark or group role. Adding `role="group" aria-label="Navegación del tour"` (or an i18n key) lets screen reader users jump directly to the navigation controls without tabbing through the card body.

low

Dot key={i} is index-based — fragile if steps become dynamic

apps/platform/src/components/discovery/GuidedTour.tsx:271

Safe with the current static `Array.from({ length: total })` shape. If steps are ever made conditional or reordered, React will reuse wrong DOM nodes and `transition-all` will animate incorrectly. Worth keying on step index or step ID if the catalog drives this in future.

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:53
  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:27current
  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