← all branches

feat/discovery

needs attentionviewing older commit
2eadf2a · incrementalPR #305reviewed 2026-07-14 20:12 UTC0H · 1M · 2L · 3I
The branch
Purpose
Land a complete Feature Discovery / Guided Tour system for the Batu platform — in-app onboarding anchors, spotlights, and tour overlays that teach users where key features live.
Goal
Every feature discovery anchor (data-tour attributes) is placed, registered, and covered by E2E smoke tests so onboarding works end-to-end.
Sub-goals
  • SG-discovery-domain: FCIS domain in domains/core/src/discovery/ (type, decisions, errors, queries, shells, mapper, index)
  • SG-cross-domain: feature-discovery decisions, queries, shells in domains/cross-domain/
  • SG-api: discovery contract + handler + mapper in apps/platform/src/api/
  • SG-ui: DescubreMenu, FeatureSpotlight, GuidedTour, RpuSubTour, TourOverlay components
  • SG-analytics: discovery events in packages/analytics/src/events.ts
  • SG-migration: 0061_discovery_state.sql schema + preview-db seed
  • SG-e2e: discovery-anchors.spec.ts smoke tests for data-tour attribute placement
The changes (whole branch)
What
Two commits tighten the E2E anchor test for export_columns: (1) b50b49c5 introduces the count-guard pattern to avoid asserting on a per-row anchor that only renders when contracts exist; (2) 2eadf2a0 refines comments to clarify the best-effort semantics and that the preview seed has no contracts.
Why
The export_columns anchor is on PipelineCell's per-RPU export icon — one element per data row. The preview seed creates no contracts, so in CI the table renders header-only with zero rows, making an unconditional toBeVisible() assertion flake on every run.
Areas
e2e/platform+560apps/platform/src/components/discovery+10460apps/platform/src/api+2780apps/platform/src/app/[locale]/(dashboard)+34232domains/core/src/discovery+3910domains/cross-domain/src+9930packages/analytics/src+920packages/api/src/schemas+870packages/database+134601
Blast
~17 000 lines added across the discovery domain, cross-domain coordinators, API surface, 5 new UI components, analytics events, DB migration, and E2E tests. The incremental window (this review) is 1 file, ~30 lines.
data-dependent E2E assertion — CI coverage gap for export_columns acknowledged
ci· No CI checks recorded for this SHA yetcoderabbit· No .coderabbit.yaml in repo

Findings · 6

correctness2

medium

Best-effort guard means CI never catches export_columns anchor regression

e2e/platform/discovery-anchors.spec.ts:41

The if (count > 0) pattern means the test only fires when export_columns elements are present. Since the preview seed has no contracts, CI always has zero rows — so this assertion is structurally disabled in the required check on every PR. The comment documents this as intentional ('catches rot on dogfooding / future seed'), but the net effect is that removing export_columns from PipelineCell would go undetected in CI until the seed gains contracts. Worth noting as a known coverage gap.

info

No timing gap between .count() and .first().toBeVisible()

hasTable waited 10 s for the DOM to settle. No navigation or mutation occurs between .count() and .toBeVisible(), so the count→assert pattern is timing-safe.

conventions3

low

Missing annotation when export_columns count is zero — inconsistent with existing pattern

e2e/platform/discovery-anchors.spec.ts:41

The hasTable=false branch pushes a skipped-assertion annotation so reviewers can see the skip in the HTML report. When the table is present but has no data rows (the CI case), the export_columns check silently no-ops with no annotation. Adding an else branch with test.info().annotations.push({ type: 'skipped-assertion', description: 'export_columns anchor skipped — no contract rows in seed' }) would make every CI run's skip visible, consistent with the existing pattern.

info

Structural asymmetry of inner conditional is justified

The three column-header anchors (monitoring, payment_monitoring, internal_site_ids) are on the header row and assert unconditionally inside hasTable. export_columns is on per-data-row elements — the extra inner guard is semantically correct. The updated comments explain this clearly.

info

Comment quality is good — distinction between header and row anchors is non-obvious

The new comments correctly distinguish between column-HEADER anchors (render when table is present, even on empty body) and per-DATA-ROW anchors (export_columns). This is non-obvious without reading PipelineCell. Comments add genuine value.

improvement1

low

export_columns locator constructed twice — extract to a const

e2e/platform/discovery-anchors.spec.ts:41

page.locator('[data-tour="export_columns"]') is evaluated twice (once for .count(), once for .first()). No race risk here (DOM is settled after the hasTable wait), but a one-line extraction — const exportAnchor = page.locator('[data-tour="export_columns"]') — removes duplication and matches the style used for the table locator above.

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:12current
  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