feat(feedback): gate onboarding survey on first processing, add prompt lifecycle events (#615)

Defers the onboarding usage survey to the instance's first successful processing (the worker writes a one-time onboarding.firstProcessedAt marker and the overlay gates on it), so it reaches engaged users instead of first-landing visitors.

Replaces the two questions telemetry already answers (modality preference from tool_used, install method from instance_started) with what it can't infer: prior tool, self-host motivation, and discovery source.

Adds feedback_prompt_shown and feedback_prompt_dismissed on all five feedback surfaces (usage survey, per-job prompt, admin install card, global nav dialog, search-miss) so skip and completion rates are measurable, not just submissions. New survey strings translated into all 20 non-English locales.
This commit is contained in:
SnapOtter
2026-07-21 16:31:30 +00:00
committed by GitHub
parent b20bca3c3c
commit 129e42b95c
41 changed files with 950 additions and 209 deletions
+23 -8
View File
@@ -97,10 +97,14 @@ describe("shouldShowInstallFeedbackCard", () => {
});
describe("shouldShowUsageSurvey", () => {
it("shows only for admins after analytics config is loaded and enabled", () => {
// The survey now waits for the instance's first successful processing so we
// ask engaged users, not someone staring at an empty app on first landing.
const PROCESSED = { "onboarding.firstProcessedAt": "2026-01-14T00:00:00Z" };
it("shows only for admins after analytics is loaded and enabled, once a processing has completed", () => {
expect(
shouldShowUsageSurvey({
settings: {},
settings: PROCESSED,
role: "admin",
analyticsConfigLoaded: true,
analyticsEnabled: true,
@@ -109,7 +113,7 @@ describe("shouldShowUsageSurvey", () => {
expect(
shouldShowUsageSurvey({
settings: {},
settings: PROCESSED,
role: "user",
analyticsConfigLoaded: true,
analyticsEnabled: true,
@@ -118,7 +122,7 @@ describe("shouldShowUsageSurvey", () => {
expect(
shouldShowUsageSurvey({
settings: {},
settings: PROCESSED,
role: "admin",
analyticsConfigLoaded: false,
analyticsEnabled: true,
@@ -127,7 +131,7 @@ describe("shouldShowUsageSurvey", () => {
expect(
shouldShowUsageSurvey({
settings: {},
settings: PROCESSED,
role: "admin",
analyticsConfigLoaded: true,
analyticsEnabled: false,
@@ -135,10 +139,21 @@ describe("shouldShowUsageSurvey", () => {
).toBe(false);
});
it("stays hidden after answering or permanently dismissing", () => {
it("stays hidden until the instance's first successful processing", () => {
expect(
shouldShowUsageSurvey({
settings: { "onboarding.usageSurvey.answeredAt": "2026-01-14T00:00:00Z" },
settings: {},
role: "admin",
analyticsConfigLoaded: true,
analyticsEnabled: true,
}),
).toBe(false);
});
it("stays hidden after answering or permanently dismissing, even once processing has happened", () => {
expect(
shouldShowUsageSurvey({
settings: { ...PROCESSED, "onboarding.usageSurvey.answeredAt": "2026-01-14T00:00:00Z" },
role: "admin",
analyticsConfigLoaded: true,
analyticsEnabled: true,
@@ -147,7 +162,7 @@ describe("shouldShowUsageSurvey", () => {
expect(
shouldShowUsageSurvey({
settings: { "onboarding.usageSurvey.dismissedAt": "2026-01-14T00:00:00Z" },
settings: { ...PROCESSED, "onboarding.usageSurvey.dismissedAt": "2026-01-14T00:00:00Z" },
role: "admin",
analyticsConfigLoaded: true,
analyticsEnabled: true,