Skip to content

feat: improve experiment planning and results logic - #536

Merged
Blaumaus merged 11 commits into
mainfrom
feat/experiments
May 20, 2026
Merged

feat: improve experiment planning and results logic#536
Blaumaus merged 11 commits into
mainfrom
feat/experiments

Conversation

@Blaumaus

@Blaumaus Blaumaus commented May 20, 2026

Copy link
Copy Markdown
Member

Changes

If applicable, please describe what changes were made in this pull request.

Community Edition support

  • Your feature is implemented for the Swetrix Community Edition
  • This PR only updates the Cloud (Enterprise) Edition code (e.g. Paddle webhooks, blog, payouts, etc.)

Database migrations

  • Clickhouse / MySQL migrations added for this PR
  • No table schemas changed in this PR

Documentation

  • You have updated the documentation according to your PR
  • This PR did not change any publicly documented endpoints

Summary by CodeRabbit

  • New Features

    • Hypothesis field, planning metrics (sample estimates, MDE, daily exposures) and launch guardrails.
    • Result-windowing with resolved time-buckets, segmented/filters support for charts and queries.
    • Experiment completion flow with confirmation modal and success/error toasts.
    • Linked-flag badges/details, conditional Filters UI, variant split rail, tooltip styling props.
  • Bug Fixes

    • Exposures percent shows 100.0% only when exposures > 0.
  • Chores

    • Enforced limits/validation for analytics filter payloads.
  • Documentation

    • Expanded experiments & feature-flag docs, script reference, tracker README, and multi-language translations.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cbc9d3ea-20f7-41bf-a66d-d9aa384db355

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 53a0379 and 2c5b18e.

πŸ“’ Files selected for processing (1)
  • web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx

πŸ“ Walkthrough

Walkthrough

Adds result-window DTOs and resolved bucketing, threads analytics filters into backend experiment result and chart queries (including segment profile filtering), adds startup validation and launch guardrails, expands frontend wiring and UX (results, completion, settings), and enforces analytics filter size limits.

Changes

Experiment Results Filtering, Time Windows, and Launch Validation

Layer / File(s) Summary
Result window and segmentation DTO contracts
backend/apps/cloud/src/experiment/dto/experiment.dto.ts, backend/apps/community/src/experiment/dto/experiment.dto.ts, web/app/api/api.server.ts
Adds ExperimentResultWindow DTO/interface and extends ExperimentResults/DTOs with resolvedTimeBucket, resultWindow, and isSegmented.
Backend Day.js and analytics imports
backend/apps/cloud/src/experiment/experiment.controller.ts, backend/apps/community/src/experiment/experiment.controller.ts
Register Day.js utc/timezone plugins, import analytics DataType, and declare internal ExperimentResultWindow type used in result logic.
Experiment startup configuration validation
backend/apps/cloud/src/experiment/experiment.controller.ts, backend/apps/community/src/experiment/experiment.controller.ts
Adds validateStartConfiguration(experiment) and invokes it from startExperiment; preserves experiment.startedAt when provided.
Result window resolution and filter-aware query computation
backend/apps/cloud/src/experiment/experiment.controller.ts, backend/apps/community/src/experiment/experiment.controller.ts
getExperimentResults accepts filters, computes effective resultWindow (selected/final/active_overlap), derives resolvedTimeBucket, builds ClickHouse filters SQL/params, sets isSegmented, and updates exposure/conversion queries to use resolved window and include filter params.
Exposure attribution subquery & segmentation
backend/apps/cloud/src/experiment/experiment.controller.ts, backend/apps/community/src/experiment/experiment.controller.ts
getExposureAttributionSubquery now accepts filtersQuery; adds getSegmentProfileFilter(filtersQuery) to constrain profile selection by filters and wires this into exposure attribution SQL.
Chart generation, date helpers, and result-window utilities
backend/apps/cloud/src/experiment/experiment.controller.ts, backend/apps/community/src/experiment/experiment.controller.ts
generateExperimentChart accepts filtersQuery/filtersParams, uses resultWindow-derived chart bounds and resolvedTimeBucket, and new helpers normalize ClickHouse date formatting and determine effective result windows.
Analytics filter size limits
backend/apps/cloud/src/analytics/analytics.service.ts, backend/apps/community/src/analytics/analytics.service.ts
Adds MAX_FILTERS and MAX_FILTER_VALUES and enforces them during filter parsing/expansion, rejecting invalid shapes or oversized arrays with UnprocessableEntityException.
Frontend API and route wiring for filters
web/app/api/api.server.ts, web/app/routes/api.analytics.ts, web/app/routes/projects.$id.tsx
Adds ExperimentResultWindow interface and extends ExperimentResults; getExperimentResultsServer accepts filters and JSON-stringifies them; routes/actions forward filters to backend.
Results page health warnings, window notices, and completion flow
web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
Wires project filters into results fetch, computes health warnings and stopRecommendation, shows overlap-aware result window notices, prefers results.resolvedTimeBucket for charts, adds completion modal/flow with toasts and reload, and displays feature-flag/variant metadata.
Experiment settings: hypothesis, sample estimate, and launch guardrails
web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
Adds hypothesis input, baseline/MDE/daily exposure planning inputs, computes sampleEstimate and runtime, produces launchGuardrails (blockers/warnings), prevents cross-linking feature flags, includes hypothesis in submission, and renders variant mapping/sample-estimate/guardrails UI.
Experiments list and feature flag linking UI
web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx, web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx
Adds getLaunchGuardrails used to render Launch blocked / Review config badges and metadata rows; FeatureFlagsView adds an Experiment linked badge and hint with navigation query.
Tooltip and small UI adjustments
web/app/ui/Tooltip.tsx
Adds contentClassName and arrowClassName props and forwards them to TooltipContent/Arrow.
Tracker docs and JSDoc updates
packages/tracker-js/*
Docs updated to document per-event profileId override and shared cache/fallback-variant examples for flags/experiments.
Documentation and localization updates
docs/content/docs/*, web/public/locales/*
Expanded experiments and feature-flags docs; added/updated en/de/fr/pl/uk translations for hypothesis, guardrails, results, and feature-flag linkage UI.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Swetrix/swetrix#527: Related changes to experiment chart/results SQL and exposure attribution.
  • Swetrix/swetrix#536: Overlapping work implementing resultWindow/filters/resolvedTimeBucket across backend and frontend.
  • Swetrix/swetrix#418: Related work on analytics filters and getFiltersQuery enhancements.

"I hopped through windows, buckets, and charts with care,
Filters in paw and guardrails in my hair,
Hypotheses penned, samples tallied true,
Segments respected and charts refreshed anew. πŸ₯•"

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The PR title accurately describes the main focus: improvements to experiment planning logic and results handling, which is reflected across controller/DTO changes, new guardrails system, and enhanced UI features.
Description check βœ… Passed The PR description covers the required template sections with checked items indicating Community Edition support and no schema changes, though specific change details are minimal.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/experiments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx (1)

274-286: ⚑ Quick win

Localize the new experiment-link badge and helper copy.

These new user-facing strings are hardcoded and should go through t(...) to keep the feature flags view fully localized.

Also applies to: 293-298

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx` around lines
274 - 286, The new hardcoded user-facing strings for the experiment badge and
its helper text need localization: replace the literal 'Experiment linked' label
inside the Badge (rendered when flag.experimentId is truthy in the JSX branch
that uses Link and Badge) with a call to t('...') and similarly wrap any other
hardcoded strings in the nearby experiment-related block (the similar code
around the other branch at lines 293-298) with t(...) so both the Badge label
and any helper/copy use the translation function; import or use the existing
i18n/t function in this file if not already present and pass appropriate
translation keys for each string.
web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx (2)

889-892: ⚑ Quick win

Use a stable unique key in variant mapping rows.

This list currently keys by variant.key, but duplicate keys are a valid transient state while editing and will cause reconciliation glitches.

Suggested fix
- {variants.map((variant) => (
+ {variants.map((variant, index) => (
    <div
-     key={variant.key}
+     key={`${variant.key}-${index}`}
      className='flex items-center justify-between gap-3 text-xs'
    >
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx` around
lines 889 - 892, The list item keys use variant.key which can be non-unique
while editing; change the key strategy in the variants.map rendering so each row
uses a stable unique identifier (e.g., a persistent variant.id or a composite
fallback that includes the map index) instead of relying solely on variant.key;
update the JSX key expression where variants.map is used (the element with
key={variant.key}) to reference the stable id or a deterministic composite key
to prevent reconciliation glitches during editing.

273-278: πŸ—οΈ Heavy lift

Localize newly added UI/validation copy.

New labels, guardrail messages, and helper text are hardcoded English. This will create mixed-language UI in non-English locales.

Example pattern
- newErrors.featureFlag = 'This feature flag is already linked elsewhere.'
+ newErrors.featureFlag = t('experiments.featureFlagAlreadyLinked')
...
- <Text size='sm' weight='semibold'>Sample size estimate</Text>
+ <Text size='sm' weight='semibold'>{t('experiments.sampleSizeEstimate')}</Text>

Also applies to: 495-575, 671-683, 1001-1112, 1117-1163, 1258-1279

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx` around
lines 273 - 278, The validation/UI copy in ExperimentSettingsModal.tsx is
hardcoded (e.g., the string assigned to newErrors.featureFlag when
selectedFeatureFlag is set) and must be localized; replace literal strings like
"This feature flag is already linked elsewhere." with i18n lookups using the
project's translation helper (e.g., use the t(...) or intl.formatMessage(...)
pattern used elsewhere) and add appropriate translation keys (suggest names like
experiment.settings.featureFlag.alreadyLinked); apply the same change to the
other hardcoded labels/messages in the indicated regions (lines ~495-575,
671-683, 1001-1112, 1117-1163, 1258-1279) so all UI/validation copy in
ExperimentSettingsModal uses translation keys instead of plain English literals.
web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx (1)

112-153: ⚑ Quick win

Move new guardrail/badge/metadata text to translation keys.

The added draft badges, guardrail phrases, and metadata labels are hardcoded and won’t localize with the rest of the page.

Also applies to: 252-267, 280-297

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx` around lines 112
- 153, The guardrail/warning strings in ExperimentsView.tsx (e.g., 'Missing
goal', 'Needs at least two variants', 'Needs one control', 'Allocation must
total 100%', 'Every variant needs traffic', 'Missing exposure event', 'Missing
linked feature flag', 'Uneven allocation', 'Low traffic variant', 'No
hypothesis' and the other hardcoded draft/metadata labels in the ranges
mentioned) are hardcoded; replace each literal with a call to the translation
function (e.g., t('experiments.guardrails.missingGoal')) and add corresponding
keys to the i18n resource files, updating any components that render these
messages to accept translated strings so the page localizes correctly. Ensure
you use descriptive key names matching the strings above and apply the same
change for the other occurrences mentioned (lines ~252-267 and ~280-297).
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx`:
- Around line 747-750: The helper formatWindowDate currently formats dates in
the viewer's local timezone; change it to accept a timezone parameter (e.g.,
formatWindowDate(value?: string | null, timezone?: string)) and use dayjs.tz
(ensure dayjs timezone/utc plugins are initialized) to format the value in the
provided timezone before returning (e.g., dayjs.tz(value,
timezone).format(...)). Update all callers in ExperimentResults.tsx that render
the resolved window to pass the backend-resolved timezone variable (the same
`timezone` used to resolve the window) so the displayed "from"/"to" range
matches the analytics timezone. Ensure null/undefined handling remains intact.
- Around line 905-1056: The new warnings and notices embed raw English strings
and use titles for logic, which breaks localization and fragile branching;
update the HealthWarning objects created in healthWarnings (and the
resultWindowNotice) to include a stable code/key (e.g., code: 'NO_EXPOSURES' |
'EXTREME_IMBALANCE' | 'VARIANT_NO_TRAFFIC' | 'LOW_CONVERSION' | 'STALE_RUNNING'
| 'GOAL_MISSING') and replace all user-facing title/message literals with
t('...') calls when rendering; then change stopRecommendation to check those
stable codes (e.g., healthWarnings.some(w =>
['EXTREME_IMBALANCE','VARIANT_NO_TRAFFIC'].includes(w.code))) instead of
matching English titles, and ensure resultWindowNotice also uses t(...) for its
suffixes and messages.
- Around line 1266-1298: The CTA to open the completion modal is currently only
rendered inside the stopRecommendation conditional; make the complete action
available for all experiments by moving or duplicating the completion Button
(the one that calls setIsCompleteModalOpen(true)) out of the
stopRecommendation-only block so it renders regardless of stopRecommendation
being truthy; ensure the visual layout matches design (e.g., keep the Button
beside the banner when stopRecommendation exists and render the same Button in
the same container/row when it does not) and update any surrounding container
markup in ExperimentResults.tsx so no duplicate IDs or accessibility issues are
introduced.

---

Nitpick comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx`:
- Around line 889-892: The list item keys use variant.key which can be
non-unique while editing; change the key strategy in the variants.map rendering
so each row uses a stable unique identifier (e.g., a persistent variant.id or a
composite fallback that includes the map index) instead of relying solely on
variant.key; update the JSX key expression where variants.map is used (the
element with key={variant.key}) to reference the stable id or a deterministic
composite key to prevent reconciliation glitches during editing.
- Around line 273-278: The validation/UI copy in ExperimentSettingsModal.tsx is
hardcoded (e.g., the string assigned to newErrors.featureFlag when
selectedFeatureFlag is set) and must be localized; replace literal strings like
"This feature flag is already linked elsewhere." with i18n lookups using the
project's translation helper (e.g., use the t(...) or intl.formatMessage(...)
pattern used elsewhere) and add appropriate translation keys (suggest names like
experiment.settings.featureFlag.alreadyLinked); apply the same change to the
other hardcoded labels/messages in the indicated regions (lines ~495-575,
671-683, 1001-1112, 1117-1163, 1258-1279) so all UI/validation copy in
ExperimentSettingsModal uses translation keys instead of plain English literals.

In `@web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx`:
- Around line 112-153: The guardrail/warning strings in ExperimentsView.tsx
(e.g., 'Missing goal', 'Needs at least two variants', 'Needs one control',
'Allocation must total 100%', 'Every variant needs traffic', 'Missing exposure
event', 'Missing linked feature flag', 'Uneven allocation', 'Low traffic
variant', 'No hypothesis' and the other hardcoded draft/metadata labels in the
ranges mentioned) are hardcoded; replace each literal with a call to the
translation function (e.g., t('experiments.guardrails.missingGoal')) and add
corresponding keys to the i18n resource files, updating any components that
render these messages to accept translated strings so the page localizes
correctly. Ensure you use descriptive key names matching the strings above and
apply the same change for the other occurrences mentioned (lines ~252-267 and
~280-297).

In `@web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx`:
- Around line 274-286: The new hardcoded user-facing strings for the experiment
badge and its helper text need localization: replace the literal 'Experiment
linked' label inside the Badge (rendered when flag.experimentId is truthy in the
JSX branch that uses Link and Badge) with a call to t('...') and similarly wrap
any other hardcoded strings in the nearby experiment-related block (the similar
code around the other branch at lines 293-298) with t(...) so both the Badge
label and any helper/copy use the translation function; import or use the
existing i18n/t function in this file if not already present and pass
appropriate translation keys for each string.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 021736b0-a404-457b-84ff-f3e886e6834a

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 593fc92 and 2d696be.

πŸ“’ Files selected for processing (11)
  • backend/apps/cloud/src/experiment/dto/experiment.dto.ts
  • backend/apps/cloud/src/experiment/experiment.controller.ts
  • backend/apps/community/src/experiment/dto/experiment.dto.ts
  • backend/apps/community/src/experiment/experiment.controller.ts
  • web/app/api/api.server.ts
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx
  • web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx
  • web/app/routes/api.analytics.ts
  • web/app/routes/projects.$id.tsx

Comment thread web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx Outdated
Comment thread web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx Outdated
Comment thread web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx (1)

1350-1366: ⚑ Quick win

Hardcoded English strings in feature flag relationship section.

These strings should use t() for consistency with the rest of the localized file.

♻️ Suggested i18n conversion
             <Text as='p' size='sm' weight='semibold'>
-              Feature flag relationship
+              {t('experiments.featureFlagRelationship.title')}
             </Text>
             <Text as='p' size='xs' colour='muted'>
-              The flag controls eligibility. Experiment exposures use actual
-              evaluations and variant events.
+              {t('experiments.featureFlagRelationship.description')}
             </Text>
           </div>
           <Text as='span' size='xs' colour='secondary' code>
             {experiment.featureFlagKey ||
               experiment.featureFlagId ||
-              'created on launch'}
+              t('experiments.featureFlagRelationship.createdOnLaunch')}
           </Text>
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx` around lines
1350 - 1366, Summary: Several hardcoded English strings in the Feature flag
relationship JSX need to be localized with t(). Replace the literal texts inside
the Text components β€” the heading "Feature flag relationship", the descriptive
line "The flag controls eligibility. Experiment exposures use actual evaluations
and variant events.", and the fallback string 'created on launch' used alongside
experiment.featureFlagKey/featureFlagId β€” with calls to the i18n function t(...)
and supply appropriate translation keys; ensure the component imports/uses the
existing t hook or i18n function used elsewhere in ExperimentResults.tsx and
keep the Text props unchanged (e.g., update the Text children for the heading,
description, and the code span fallback).
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx`:
- Around line 1345-1349: The fallback branch always renders
completeExperimentButton even when stopRecommendation(status) returns null,
causing a Complete button to appear for completed or draft experiments; update
the rendering condition to check the experiment status (use the same status
values checked in stopRecommendation such as 'running' or 'paused') and only
render completeExperimentButton when status is one of those allowed states
(e.g., status === 'running' || status === 'paused'), otherwise render nothing or
the appropriate UI for completed/draft.

---

Nitpick comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx`:
- Around line 1350-1366: Summary: Several hardcoded English strings in the
Feature flag relationship JSX need to be localized with t(). Replace the literal
texts inside the Text components β€” the heading "Feature flag relationship", the
descriptive line "The flag controls eligibility. Experiment exposures use actual
evaluations and variant events.", and the fallback string 'created on launch'
used alongside experiment.featureFlagKey/featureFlagId β€” with calls to the i18n
function t(...) and supply appropriate translation keys; ensure the component
imports/uses the existing t hook or i18n function used elsewhere in
ExperimentResults.tsx and keep the Text props unchanged (e.g., update the Text
children for the heading, description, and the code span fallback).
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b51e359-881d-47fd-9530-0204099f22e4

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2d696be and b57e198.

πŸ“’ Files selected for processing (9)
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx
  • web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx
  • web/public/locales/de.json
  • web/public/locales/en.json
  • web/public/locales/fr.json
  • web/public/locales/pl.json
  • web/public/locales/uk.json
βœ… Files skipped from review due to trivial changes (2)
  • web/public/locales/de.json
  • web/public/locales/en.json

Comment thread web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx Outdated
@Blaumaus
Blaumaus force-pushed the feat/experiments branch from 10a0b92 to 91f31d4 Compare May 20, 2026 03:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
web/public/locales/fr.json (1)

1576-1579: πŸ’€ Low value

Verify terminology consistency for "feature flag".

The JSON structure and French translation are correct. However, I noticed a minor potential inconsistency: line 1577 uses "feature flag" (keeping the English term), while other parts of this file use just "flag" in French contexts (e.g., line 1347: "Filtrer les flags", line 1349: "CrΓ©er un flag").

This might be intentional to provide clarity in this specific context, but it's worth verifying whether it should be:

  • "Relation du flag" (consistent with simplified usage elsewhere)
  • "Relation du feature flag" (current, more explicit)

If "feature flag" is the standard technical term used throughout French technical documentation for this product, then the current form is fine.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/public/locales/fr.json` around lines 1576 - 1579, The translation for the
"featureFlagRelationship" key uses the English term "feature flag" which is
inconsistent with other French entries that use "flag" (e.g., keys that render
"Filtrer les flags" and "CrΓ©er un flag"); update the "title" value for
featureFlagRelationship to "Relation du flag" and review other featureFlag* keys
to ensure all UI labels consistently use "flag" (or alternatively confirm
product-wide policy if you prefer to keep the English term) so terminology is
consistent across the locale file.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web/public/locales/fr.json`:
- Around line 1576-1579: The translation for the "featureFlagRelationship" key
uses the English term "feature flag" which is inconsistent with other French
entries that use "flag" (e.g., keys that render "Filtrer les flags" and "CrΓ©er
un flag"); update the "title" value for featureFlagRelationship to "Relation du
flag" and review other featureFlag* keys to ensure all UI labels consistently
use "flag" (or alternatively confirm product-wide policy if you prefer to keep
the English term) so terminology is consistent across the locale file.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44c54457-3f5a-4245-9a49-dac4c4f4fd15

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between b57e198 and 10a0b92.

πŸ“’ Files selected for processing (6)
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/public/locales/de.json
  • web/public/locales/en.json
  • web/public/locales/fr.json
  • web/public/locales/pl.json
  • web/public/locales/uk.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx (1)

1017-1023: ⚠️ Potential issue | 🟠 Major | ⚑ Quick win

Block stop recommendations when the goal warning is active.

stopRecommendation still runs when GOAL_MISSING is present, so the screen can recommend completing an experiment while the warning above says the conversion data is unreliable. That creates conflicting guidance on a decision-making path.

Suggested fix
     if (
       healthWarnings.some((warning) =>
-        ['EXTREME_IMBALANCE', 'VARIANT_NO_TRAFFIC'].includes(warning.code),
+        [
+          'EXTREME_IMBALANCE',
+          'VARIANT_NO_TRAFFIC',
+          'GOAL_MISSING',
+        ].includes(warning.code),
       )
     ) {
       return null
     }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx` around lines
1017 - 1023, The code hides stop recommendations for EXTREME_IMBALANCE and
VARIANT_NO_TRAFFIC but still shows stopRecommendation when a GOAL_MISSING health
warning exists; update the logic that decides whether to render
stopRecommendation in ExperimentResults (the place that checks healthWarnings
and calls stopRecommendation) to also treat 'GOAL_MISSING' as a blocking
warningβ€”i.e., include 'GOAL_MISSING' in the array checked by
healthWarnings.some(...) or add an explicit guard that returns null / skips
rendering stopRecommendation when any healthWarnings contains code ===
'GOAL_MISSING', so the recommendation UI is suppressed whenever the goal warning
is active.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx`:
- Around line 1017-1023: The code hides stop recommendations for
EXTREME_IMBALANCE and VARIANT_NO_TRAFFIC but still shows stopRecommendation when
a GOAL_MISSING health warning exists; update the logic that decides whether to
render stopRecommendation in ExperimentResults (the place that checks
healthWarnings and calls stopRecommendation) to also treat 'GOAL_MISSING' as a
blocking warningβ€”i.e., include 'GOAL_MISSING' in the array checked by
healthWarnings.some(...) or add an explicit guard that returns null / skips
rendering stopRecommendation when any healthWarnings contains code ===
'GOAL_MISSING', so the recommendation UI is suppressed whenever the goal warning
is active.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46bf3698-a0a3-48a8-851e-5f634fee973b

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 10a0b92 and 8cc0e42.

πŸ“’ Files selected for processing (9)
  • backend/apps/cloud/src/analytics/analytics.service.ts
  • backend/apps/community/src/analytics/analytics.service.ts
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/app/routes/projects.$id.tsx
  • web/public/locales/de.json
  • web/public/locales/en.json
  • web/public/locales/fr.json
  • web/public/locales/pl.json
  • web/public/locales/uk.json
βœ… Files skipped from review due to trivial changes (2)
  • web/public/locales/en.json
  • web/public/locales/de.json

@Blaumaus

Copy link
Copy Markdown
Member Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
βœ… Actions performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx`:
- Line 95: The showPlanning state can persist across modal opens because
resetForm isn't always called (edit path uses loadExperiment), so ensure
showPlanning is reset whenever the modal opens: add setShowPlanning(false) to
the modal-open flow (either call it inside resetForm and also call it at the
start of loadExperiment, or add a useEffect that watches the modal open prop and
calls setShowPlanning(false)). Reference showPlanning, setShowPlanning,
resetForm and loadExperiment to locate where to add the call so planner inputs
and readiness summary are cleared on every open.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 732a1257-7d80-4431-a5c9-e945da51624c

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 8cc0e42 and 350244d.

πŸ“’ Files selected for processing (4)
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx
  • web/public/locales/en.json
βœ… Files skipped from review due to trivial changes (1)
  • web/public/locales/en.json

Comment thread web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
Comment thread web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx (1)

138-140: ⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Reset the full planning state here, not just the accordion.

This clears the open/closed state, but the edit path still carries over baselineConversionRate, minimumDetectableEffect, and dailyExposures from the previous modal session. That keeps the collapsed sample estimate and guardrails based on stale planner inputs until the user changes them manually.

πŸ” Minimal fix
   const loadExperiment = async () => {
     if (!experimentId) return
     setShowPlanning(false)
+    setBaselineConversionRate(5)
+    setMinimumDetectableEffect(10)
+    setDailyExposures(500)
     setIsLoading(true)
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx` around
lines 138 - 140, The loadExperiment function currently only collapses the
planner accordion via setShowPlanning(false) but leaves planner inputs
(baselineConversionRate, minimumDetectableEffect, dailyExposures β€” or the
planningState object) populated from the prior session; update loadExperiment to
fully reset the planner state when opening a new experiment by clearing those
variables (or calling an existing resetPlanningState helper) to their
initial/default values (e.g., undefined or defaults) so the collapsed sample
estimate and guardrails do not reflect stale inputs; locate loadExperiment and
update it to call setBaselineConversionRate(...),
setMinimumDetectableEffect(...), setDailyExposures(...) or resetPlanningState()
immediately after setShowPlanning(false).
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx`:
- Around line 138-140: The loadExperiment function currently only collapses the
planner accordion via setShowPlanning(false) but leaves planner inputs
(baselineConversionRate, minimumDetectableEffect, dailyExposures β€” or the
planningState object) populated from the prior session; update loadExperiment to
fully reset the planner state when opening a new experiment by clearing those
variables (or calling an existing resetPlanningState helper) to their
initial/default values (e.g., undefined or defaults) so the collapsed sample
estimate and guardrails do not reflect stale inputs; locate loadExperiment and
update it to call setBaselineConversionRate(...),
setMinimumDetectableEffect(...), setDailyExposures(...) or resetPlanningState()
immediately after setShowPlanning(false).

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7355eb94-8845-43de-9f30-09852337f6d9

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 350244d and 53a0379.

πŸ“’ Files selected for processing (11)
  • docs/content/docs/analytics-dashboard/experiments.mdx
  • docs/content/docs/analytics-dashboard/feature-flags.mdx
  • docs/content/docs/script-reference.mdx
  • packages/tracker-js/README.md
  • packages/tracker-js/src/Lib.ts
  • packages/tracker-js/src/index.ts
  • web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx
  • web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx
  • web/app/ui/Tooltip.tsx
  • web/public/locales/en.json
βœ… Files skipped from review due to trivial changes (3)
  • packages/tracker-js/src/Lib.ts
  • packages/tracker-js/src/index.ts
  • docs/content/docs/analytics-dashboard/feature-flags.mdx

@Blaumaus
Blaumaus merged commit 4290b3b into main May 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant