| Prod build blank page, dev fine, after adding tracking to a store | Store → posthog barrel → metrics.ts → useLabsStore cycle (#1466) | Deep-import @/shared/analytics/posthog/trackEvent; repro with build+preview |
| Event never appears while testing locally | DEV early-return in init.ts; also needs VITE_PUBLIC_POSTHOG_KEY + settings.analyticsEnabled | Assert via unit test mocking the leaf; live-verify on a production build |
| Flag toggle has no visible effect | requiresRefresh: true, or comingSoon (toggle no-ops OK), or consumer cached isFeatureEnabled() non-reactively | Reload / use useFeatureFlag in components / call getState().isFeatureEnabled() at decision time |
computeLabsMetrics counts flags that no longer exist | Removed flag's key persists in gridfinity-labs-v1 | delete prefs.enabledFeatures.<id> in loadPreferences() |
| Milestone fires again for an existing user | gridfinity-analytics-v1 cleared or identity cache reset | Treat that key as durable identity; never clear it in migrations |
| Data lands in the wrong pipeline despite compiling | Wrong twin: trackLayoutSnapshot/trackFillOperation exist in both posthog and mlTelemetry | Import from @/shared/analytics/posthog vs @/shared/analytics/mlTelemetry explicitly |
| PostHog floods with junk errors, or one error splits into many issues | Extension noise through global handlers; multi-mount-site errors lack a fingerprint | Add regex to IGNORED_MESSAGE_PATTERNS/IGNORED_SOURCE_PATTERNS in posthog/errorFilters.ts; pin an $exception_fingerprint like WEBGL_CONTEXT_FINGERPRINT in errorFilters.ts (its matching WEBGL_CONTEXT_ERROR message substring must stay in sync with WebGLErrorBoundary.tsx) |