[analytics] Onboarding v2: welcome hero, anchored coach emphasis, demo recipe v4, chaptered tour (epic tripl-odrj)#52
Conversation
…e variable-value drift (tripl-odrj.3) The seeded feature/checkout-funnel branch now carries a deep-copied plan via the extracted non-committing deep_copy_plan_to_branch helper (create_branch behavior unchanged) plus exactly one branch-side edit — a CTA-copy description change on Buy Button Click — so diff and merge preview finally show real content. variables.py seeds one open VariableValueDrift on product_id (observed prod_weekly outside the documented [prod_monthly, prod_annual]), surfacing in the variables drift UI. DEMO_RECIPE_VERSION bumped to 4. Review follow-up: _build_plan_digest_message now scopes all four event counts to the project's main branch — the deep-copied demo branch would otherwise have doubled every digest number (pre-existing bug for any project with an open working branch, now triggered by default on demos). Gates: pytest test_demo_project.py 20 passed; ruff check + format clean.
…(tripl-odrj.1) A brand-new user now lands on a product intro instead of an all-zero dashboard: hero with the README pitch (what tripl is, no new SDK, read-only warehouse), a primary Generate-demo CTA with expectation-setting caption and a secondary New-project CTA, a Plan/Observe/Govern pillar grid (canonical copy in workspace-welcome-pillars.ts), and a muted closing strip linking the docs. Viewers get an ask-an-owner note instead of create buttons. The all-zero stat band and the duplicate header CTA pair are hidden until the first project exists. Gates: vitest workspace-welcome (5) + ProjectsPage (17) green; eslint zero-warning; tsc clean.
…l-odrj.2, tripl-odrj.4) Coach marks now point at the exact control: a pulsing coach-ring beacon overlay (fixed-position, pointer-events-none, aria-hidden; ResizeObserver on anchor + body, resize + capture scroll refresh; static ring under reduced motion), data-coach-target stamped on anchors, one-shot scroll-into-view for off-viewport targets, a popover arrow on the card, step-declared side/align defaults, and a presence registry that lets the strip flag a missing target with recovery copy. Hide hints silences ring, card, scroll and presence through the single existing gate. The scenario becomes a chaptered tour (state v2 under the same localStorage key; v1 blobs migrate onto live-loop): live-loop (unchanged), edit-event, variables, branches (stops at review/merge preview — no merge), reconcile, alerting, explore. Chapters complete via mutation-driven notifies (inert outside the active chapter) or route visits; the strip shows chapter progress and a next-chapter CTA; ProductTour and DemoWelcomePanel share the new ChapterPicker. ~15 new coach anchors across events, variables, branches, reconciliation and alerting surfaces; edit-event deep-links back into the visited editor via a recorded editorPath artifact. Review fixes folded in: dismiss preserves completed status, chapter switch pauses the outgoing chapter, digest-safe copy tweaks, non-vacuous poll test. Gates: tsc clean; eslint zero-warning; vitest green per-file — scenarioModel 55, Provider 21, Strip 20, CoachMark 16, entryPoints 7, EventForm 8, ScansTab 13, ScanDetail 9, ScanConfigDetailView 3, MetricsCatalog 5, MonitoringDetailPage 35.
There was a problem hiding this comment.
Pull request overview
This PR delivers “Onboarding v2” improvements across the demo onboarding experience, adding an empty-workspace welcome hero, stronger in-app coaching emphasis, and a chaptered (multi-area) guided tour that ties real user actions to scenario progress. It also updates the demo seeder (recipe v4) so the branches/variables chapters have real, non-empty content to teach against, and fixes weekly plan digest event counting to avoid double-counting when working branches exist.
Changes:
- Frontend: replace the empty workspace dashboard with a product-intro hero; upgrade ScenarioCoachMark with beacon emphasis, scroll-into-view, missing-target fallback, and chapter-aware scenario strip/picker.
- Frontend: expand the demo scenario from a single 4-step chain into multiple chapters (live-loop, edit-event, variables, branches, reconcile, alerting, explore) with many new anchors and updated tests.
- Backend: bump demo recipe to v4, seed a real working-branch pending change + one open VariableValueDrift, extract reusable deep-copy helper, and scope weekly digest event counts to the main branch.
Reviewed changes
Copilot reviewed 50 out of 50 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/pages/settings/VariablesTab.tsx | Adds demo scenario step notifications and coach mark anchors for variable drift/inspection. |
| frontend/src/pages/settings/ScansTab.tsx | Renames scenario step ids to chapter-scoped ids for live-loop. |
| frontend/src/pages/settings/ScansTab.test.tsx | Updates tests to v2 chaptered scenario state helpers and artifacts. |
| frontend/src/pages/settings/scans/ScanConfigRow.tsx | Updates coach mark step id to chapter-scoped live-loop ids. |
| frontend/src/pages/settings/ScanDetail.tsx | Updates watch-scan coach mark to live-loop chapter step id and defaults. |
| frontend/src/pages/settings/ScanDetail.test.tsx | Migrates tests to v2 chapter state + artifacts for watched scan rows. |
| frontend/src/pages/settings/ScanConfigDetailView.tsx | Updates run-scan coach mark step id to live-loop chapter. |
| frontend/src/pages/settings/ScanConfigDetailView.test.tsx | Updates scenario tests to chapter steps and chapter artifact storage. |
| frontend/src/pages/settings/BranchesTab.tsx | Adds branch chapter anchors + step completion notifications for diff/comment/approve flows. |
| frontend/src/pages/ReconciliationPage.tsx | Adds reconcile chapter step completion and a coach mark on seeded shadow accept. |
| frontend/src/pages/ProjectsPage.tsx | Shows WorkspaceWelcome hero for an empty workspace; hides header CTAs/stat band until first project exists. |
| frontend/src/pages/ProjectsPage.test.tsx | Adds regression coverage for the new empty-workspace hero and CTA behavior. |
| frontend/src/pages/MonitoringDetailPage.tsx | Gates collect-metric coaching to the user’s own scenario metric artifact (chaptered). |
| frontend/src/pages/MonitoringDetailPage.test.tsx | Updates demo scenario tests to v2 chapter artifacts and step ids. |
| frontend/src/pages/metrics/MetricsCatalog.tsx | Updates collect/see-chart coach step ids to live-loop chapter equivalents. |
| frontend/src/pages/metrics/MetricsCatalog.test.tsx | Updates scenario tests to v2 chapter state + artifact storage. |
| frontend/src/pages/events/EventRow.tsx | Adds edit-event chapter coaching for edit affordance and reconcile drift badge anchor. |
| frontend/src/pages/events/EventForm.tsx | Adds edit-event chapter step notifications and coach anchors for templated field + save. |
| frontend/src/pages/events/EventForm.test.tsx | Adds a chaptered scenario test ensuring save mutation completes the edit-event chapter. |
| frontend/src/pages/events/EventDriftBadge.tsx | Notifies reconcile chapter step completion when accepting schema drift. |
| frontend/src/pages/alerting/RuleReplayDialog.tsx | Notifies alerting chapter completion on successful replay/simulate flow. |
| frontend/src/pages/alerting/DestinationCard.tsx | Adds alerting chapter anchors/notifications for create-rule and simulate on seeded rule. |
| frontend/src/index.css | Adds coach beacon ring animation + reduced-motion behavior. |
| frontend/src/demo/scenarioTestState.ts | Introduces test-only constructors for v2 scenario/chapter states. |
| frontend/src/demo/scenarioModel.test.ts | Expands reducer tests for chapter model, migration from v1, and step/path contracts. |
| frontend/src/demo/scenarioEntryPoints.test.tsx | Updates entry-point tests to chapter picker UI and chapter lifecycle behaviors. |
| frontend/src/demo/ScenarioCoachMark.tsx | Implements anchor capture, beacon overlay, scroll-into-view, placement defaults, and presence reporting. |
| frontend/src/demo/ScenarioCoachMark.test.tsx | Adds coverage for beacon ring, target stamping, scroll-into-view, and hide-hints gating. |
| frontend/src/demo/ProductTour.tsx | Replaces “Try it hands-on” single chain with chapter picker handoff. |
| frontend/src/demo/DemoWelcomePanel.tsx | Replaces “Run the scenario” entry with a chapter picker for hands-on chapters. |
| frontend/src/demo/DemoScenarioStrip.tsx | Makes the strip chapter-aware, adds missing-target fallback messaging, and next-chapter CTA. |
| frontend/src/demo/DemoScenarioStrip.test.tsx | Updates strip tests for chapter model, next-chapter CTA, and missing-target fallback timing. |
| frontend/src/demo/DemoScenarioProvider.tsx | Updates provider to v2 chapters, adds presence registry, and supports notify- and visit-driven steps. |
| frontend/src/demo/DemoScenarioProvider.test.tsx | Updates provider tests for v2 chapters, migration, and “don’t poll while other chapter active” behavior. |
| frontend/src/demo/demoScenarioContext.ts | Extends contexts for chapters + coach presence registry + artifact helpers. |
| frontend/src/demo/CoachBeacon.tsx | Adds the ring overlay component rendered via portal and updated on layout changes. |
| frontend/src/demo/ChapterPicker.tsx | Adds reusable chapter picker UI shared by welcome panel and tour. |
| frontend/src/components/workspace-welcome.tsx | Introduces the empty-workspace welcome hero component with CTAs and pillar cards. |
| frontend/src/components/workspace-welcome.test.tsx | Adds unit tests for workspace welcome hero copy, CTA behavior, and viewer mode. |
| frontend/src/components/workspace-welcome-pillars.ts | Extracts welcome pillar content into a shared typed constant. |
| frontend/src/components/ui/popover.tsx | Exports PopoverArrow to support coach mark arrow rendering. |
| frontend/src/components/command-palette.tsx | Notifies explore chapter completion when the command palette is opened. |
| backend/src/tripl/worker/tasks/alerts_messages.py | Scopes plan digest event counts to the main branch to prevent branch duplication. |
| backend/src/tripl/tests/test_demo_project.py | Adds recipe v4 tests: pinned version, real branch diff, seeded value drift, determinism, reset purge. |
| backend/src/tripl/services/plan_branch_service.py | Extracts deep-copy helper for reuse by demo seeder without committing. |
| backend/src/tripl/services/demo/scenario.py | Bumps DEMO_RECIPE_VERSION to 4 and updates scenario build commentary. |
| backend/src/tripl/services/demo/builders/variables.py | Seeds one open VariableValueDrift derived from ctx.now for determinism (recipe v4). |
| backend/src/tripl/services/demo/builders/branches.py | Deep-copies plan to the seeded working branch and applies exactly one branch-side edit (recipe v4). |
| .beads/issues.jsonl | Updates beads issue tracker entries for onboarding epic tasks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| refresh() | ||
| const observer = new ResizeObserver(refresh) | ||
| observer.observe(anchor) | ||
| // The body too: layout shifts that MOVE the anchor without resizing it | ||
| // (a diff row collapsing above it, form hints appearing) change the body's | ||
| // height, so this catches them without any polling loop. | ||
| observer.observe(document.body) | ||
| window.addEventListener('resize', refresh) | ||
| // Capture: the anchor may live inside any scroll container, not just the page. | ||
| window.addEventListener('scroll', refresh, { capture: true, passive: true }) | ||
| return () => { | ||
| observer.disconnect() | ||
| window.removeEventListener('resize', refresh) | ||
| window.removeEventListener('scroll', refresh, { capture: true }) | ||
| } |
There was a problem hiding this comment.
Fixed in db6a873 — CoachBeacon now guards typeof ResizeObserver === 'undefined' and degrades to the existing resize + capture-scroll listeners.
| {available && ( | ||
| <div className="mt-4 max-w-xl"> | ||
| <p className="mb-1.5 text-[10px] font-semibold uppercase tracking-[0.07em]" style={{ color: 'var(--fg-faint)' }}> | ||
| Coached chapters | ||
| </p> |
There was a problem hiding this comment.
Fixed in db6a873 — quick-start.md, use/user-guide.md and use/demo-workspace.md now describe the Coached chapters picker (seven chapters, live-loop steps kept as the first chapter) instead of the retired single 'Run the scenario' flow.
…ssertion, docs synced to coached chapters CI: App.test expected the retired 'No projects yet' page copy — the empty workspace now opens on the welcome hero, so the test asserts the hero heading (the sidebar keeps its own copy for its own states). Copilot: CoachBeacon degrades to resize/scroll listeners when ResizeObserver is unavailable instead of throwing; quick-start, user-guide and demo-workspace docs now describe the chapter picker (Coached chapters / seven chapters) instead of the retired single 'Run the scenario' flow.
…tsFound) The recipe-4 demo branch deep-copies event types under the same names, so the three unscoped by-name lookups in the worker began matching two rows: grouped scans crashed with MultipleResultsFound (test_demo_scans on CI), and the same latent crash sat in metrics find-or-create and catalog sync. New worker/plan_scope.main_branch_id resolves the project's main branch (same idiom as the digest fix); all three lookups now filter branch_id. Pre-recipe-4 projects with an open working branch were exposed to the same crash. Gates: pytest test_demo_scans (7) + test_demo_runtime (12) green; ruff clean.
…5) (#53) * feat(search): keyless semantic search for the demo project via precomputed embedding fixture (tripl-odrj.5) The demo now showcases hybrid semantic search with NO embedding provider configured. A compressed fixture (search_embeddings_v4.npz, 209 KB: float16 vectors + JSON manifest; 66 doc vectors across both demo branches + 8 curated query vectors) ships in the repo, keyed by sha256 of the exact worker embed text — extracted into a shared embed_text_for helper so worker and fixture can never drift, with deterministic ordering of field/meta/tag/variable parts so keys are dialect-stable. reindex_project_branch stamps fixture vectors on demo projects (Postgres-only, recipe/dims/model-guarded, idempotent, corrupt- archive-safe no-op), covering provisioning, the lazily indexed feature branch and manual reindex; fixture-stamped ready rows survive incremental reindexes. At query time a demo project with no live embeddings resolves the normalized query against the canned vectors and runs the real pgvector semantic leg, marking semantic_used. Non-demo behavior is unchanged and a live provider under a different model wins over the fixture. Generation: scripts/generate_demo_search_embeddings.py (injectable embedder, run once by a maintainer with an OpenAI key; the committed fixture was generated after the ordering fix). CI freshness gate rebuilds demo docs and asserts full fixture coverage incl. the advertised queries; it skips only when the fixture is absent. Frontend: explore/use-search step and a new tour step teach 'purchase funnel' / 'money back'; the command palette marks semantic matches with a 'semantic' chip. Docs: searching-events, ai-and-search and demo-workspace document the demo exception to the semantic-requires-provider contract. Gates: mypy strict + ruff clean; pytest — demo_search_embeddings 17, search suites 24, demo_project 20; tsc + eslint zero-warning; vitest — tourSteps 5, scenarioModel 56, command-palette 7. numpy added as a direct dependency. * fix(tests): derive ProductTour step count from buildTourSteps (CI, PR #53) The new Smart search tour step made the tour 11 steps; four ProductTour tests hardcoded 'of 10' and the 9-advance finish walk. The count is now derived from buildTourSteps so adding a step never breaks these tests again.
What
Second onboarding wave from the owner's live walkthrough (epic tripl-odrj, issues .1-.4):
Workspace welcome hero (tripl-odrj.1). The empty post-registration page now explains the product instead of showing an all-zero dashboard: README-sourced hero pitch, primary Generate-demo CTA with an expectation-setting caption, secondary New-project CTA, Plan/Observe/Govern pillar cards, docs link. Viewers get an ask-an-owner note. The zero stat band and duplicate header CTAs are hidden until the first project exists.
Anchored coach emphasis (tripl-odrj.2). Coach marks now visibly point at the control to click: pulsing ring beacon overlay (a11y-invisible, layout-neutral, reduced-motion static), data-coach-target attributes, one-shot scroll-into-view, popover arrow, step-declared placement defaults, and a presence registry so the strip flags a missing target with recovery copy. Hide hints silences everything through the one existing gate.
Demo recipe v4 (tripl-odrj.3). The seeded branch carries a deep-copied plan plus exactly one pending change (Buy Button Click description), so diff/merge preview finally show content; one open VariableValueDrift on product_id (observed prod_weekly outside documented values). Deep-copy logic extracted into a non-committing helper; create_branch behavior unchanged. Includes a review-found fix: weekly plan digest now scopes event counts to the main branch (it would otherwise double on any project with a working branch — demos by default after this recipe).
Chaptered tour v2 (tripl-odrj.4). The 4-step scenario becomes a 7-chapter coached tour under the same localStorage key (v1 state migrates): live-loop, edit-event, variables, branches (stops at review/merge preview), reconcile, alerting, explore. Completion via mutation-driven notifies (inert outside the active chapter) or route visits; strip shows chapter progress + next-chapter CTA; ProductTour and DemoWelcomePanel share the ChapterPicker; ~15 new coach anchors.
How it was built and verified
Multi-agent workflow: 3 parallel implementers + chapters agent, then 3 review lenses (React/backend/product-contract) with adversarial verification — 9 confirmed findings, all fixed (completed-status preserved on dismiss, outgoing chapter paused on switch, beacon body-observer, digest branch scoping, docstring accuracy, non-vacuous poll test, consumed-artifact fallback copy, editor deep-link artifact).
Local gates (serial, per machine constraints): backend pytest test_demo_project.py 20 passed, ruff check+format clean; frontend tsc -b clean, eslint zero-warning on all touched files, vitest green per file (scenarioModel 55, Provider 21, Strip 20, CoachMark 16, entryPoints 7, EventForm 8, workspace-welcome 5, ProjectsPage 17, ScansTab 13, ScanDetail 9, ScanConfigDetailView 3, MetricsCatalog 5, MonitoringDetailPage 35).
Test plan
Notes for reviewers