@posthog/wizard 2.13.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +0 -26
  2. package/README.md +1 -1
  3. package/dist/TextBlock-B3cm43YY.js +244 -0
  4. package/dist/TextBlock-B3cm43YY.js.map +1 -0
  5. package/dist/{add-mcp-server-to-clients-CUNR00bB.js → add-mcp-server-to-clients-BTW9Ey5Z.js} +7 -7
  6. package/dist/{add-mcp-server-to-clients-CUNR00bB.js.map → add-mcp-server-to-clients-BTW9Ey5Z.js.map} +1 -1
  7. package/dist/{agent-interface-CV0-vtxj.js → agent-interface-gP4pkZgS.js} +534 -256
  8. package/dist/agent-interface-gP4pkZgS.js.map +1 -0
  9. package/dist/{agent-runner-LvVQH31D.js → agent-runner-Bxi71jnp.js} +102 -20
  10. package/dist/agent-runner-Bxi71jnp.js.map +1 -0
  11. package/dist/{analytics-VM7laaFx.js → analytics-Dmnxu2zE.js} +2 -2
  12. package/dist/{analytics-VM7laaFx.js.map → analytics-Dmnxu2zE.js.map} +1 -1
  13. package/dist/analytics-tslsXyf9.js +2 -0
  14. package/dist/bin.js +951 -141
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{debug-Cqi6nVfX.js → debug-CYUB-urp.js} +26 -21
  17. package/dist/debug-CYUB-urp.js.map +1 -0
  18. package/dist/{debug-BdcTB7EF.js → debug-Du7qXlug.js} +1 -1
  19. package/dist/{defaults-GbLPuHxj.js → defaults-DgKAzsD1.js} +1 -1
  20. package/dist/{defaults-GbLPuHxj.js.map → defaults-DgKAzsD1.js.map} +1 -1
  21. package/dist/{detection-CSjmal-X.js → detection-D651Eb5k.js} +4 -4
  22. package/dist/detection-D651Eb5k.js.map +1 -0
  23. package/dist/{file-8iNrXHkG.js → file-BKbKreWF.js} +1 -1
  24. package/dist/{file-8iNrXHkG.js.map → file-BKbKreWF.js.map} +1 -1
  25. package/dist/{file-utils-DnTSiTJw.js → file-utils-DPmgn9Vm.js} +1 -1
  26. package/dist/{file-utils-DnTSiTJw.js.map → file-utils-DPmgn9Vm.js.map} +1 -1
  27. package/dist/{package-json-F_7oktsp.js → package-json-DZpnf6vU.js} +8 -10
  28. package/dist/package-json-DZpnf6vU.js.map +1 -0
  29. package/dist/package-json-_4PEss19.js +2 -0
  30. package/dist/{package-manager-CD8RQW-e.js → package-manager-liwrN_aI.js} +2 -2
  31. package/dist/{package-manager-CD8RQW-e.js.map → package-manager-liwrN_aI.js.map} +1 -1
  32. package/dist/{posthog-vm0k9PKS.js → posthog-BbQf_Hzq.js} +1 -1
  33. package/dist/{posthog-vm0k9PKS.js.map → posthog-BbQf_Hzq.js.map} +1 -1
  34. package/dist/posthog-integration-C-FFV5ny.js +1012 -0
  35. package/dist/posthog-integration-C-FFV5ny.js.map +1 -0
  36. package/dist/provisioning-ByWo5KcQ.js +2 -0
  37. package/dist/{provisioning-g9aoVIEd.js → provisioning-C4nHkz-O.js} +3 -3
  38. package/dist/{provisioning-g9aoVIEd.js.map → provisioning-C4nHkz-O.js.map} +1 -1
  39. package/dist/{registry-BaMEaAKd.js → registry-B92uyoWK.js} +5 -5
  40. package/dist/{registry-BaMEaAKd.js.map → registry-B92uyoWK.js.map} +1 -1
  41. package/dist/setup-utils-D5aNKrba.js +2 -0
  42. package/dist/{setup-utils-CNV7FSlY.js → setup-utils-LvtZIY18.js} +77 -107
  43. package/dist/setup-utils-LvtZIY18.js.map +1 -0
  44. package/dist/{AuditChecksViewer-B0J7zcY2.js → slides-yyC_W0RZ.js} +626 -1058
  45. package/dist/slides-yyC_W0RZ.js.map +1 -0
  46. package/dist/smoke-test-ci.sh +4 -4
  47. package/dist/{start-playground-C9GWnVdM.js → start-playground-BhwBUq-a.js} +259 -10
  48. package/dist/start-playground-BhwBUq-a.js.map +1 -0
  49. package/dist/{start-tui-B_zwutLe.js → start-tui-BwQa3kmG.js} +288 -446
  50. package/dist/start-tui-BwQa3kmG.js.map +1 -0
  51. package/dist/{steps-Dawz7k3T.js → steps-CGpfOAcr.js} +7 -7
  52. package/dist/{steps-Dawz7k3T.js.map → steps-CGpfOAcr.js.map} +1 -1
  53. package/dist/{task-stream-CX7Uf6EM.js → task-stream-DUpUZmFQ.js} +8 -8
  54. package/dist/task-stream-DUpUZmFQ.js.map +1 -0
  55. package/dist/telemetry-Fmdx1AYv.js +13 -0
  56. package/dist/telemetry-Fmdx1AYv.js.map +1 -0
  57. package/dist/{wizard-abort-Dl0BkqhT.js → wizard-abort-BTBccRto.js} +1 -1
  58. package/dist/{wizard-abort-CJkNkSjT.js → wizard-abort-D-t5yDkY.js} +3 -3
  59. package/dist/{wizard-abort-CJkNkSjT.js.map → wizard-abort-D-t5yDkY.js.map} +1 -1
  60. package/dist/wizard-session-CPhhll4P.js +2 -0
  61. package/dist/{wizard-session-BcNJTl2I.js → wizard-session-CsI33S4_.js} +6 -3
  62. package/dist/wizard-session-CsI33S4_.js.map +1 -0
  63. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  64. package/npm-shrinkwrap.json +2 -2
  65. package/package.json +3 -2
  66. package/dist/AuditChecksViewer-B0J7zcY2.js.map +0 -1
  67. package/dist/agent-interface-CV0-vtxj.js.map +0 -1
  68. package/dist/agent-runner-LvVQH31D.js.map +0 -1
  69. package/dist/analytics-BH7bEHQR.js +0 -2
  70. package/dist/debug-Cqi6nVfX.js.map +0 -1
  71. package/dist/detection-CSjmal-X.js.map +0 -1
  72. package/dist/package-json-BzVey4Bd.js +0 -2
  73. package/dist/package-json-F_7oktsp.js.map +0 -1
  74. package/dist/posthog-integration-BL21S3T6.js +0 -259
  75. package/dist/posthog-integration-BL21S3T6.js.map +0 -1
  76. package/dist/provisioning-BdQ1ONIg.js +0 -2
  77. package/dist/router-COhhuIW3.js +0 -135
  78. package/dist/router-COhhuIW3.js.map +0 -1
  79. package/dist/setup-utils-CNV7FSlY.js.map +0 -1
  80. package/dist/setup-utils-CU4FIqjB.js +0 -2
  81. package/dist/start-playground-C9GWnVdM.js.map +0 -1
  82. package/dist/start-tui-B_zwutLe.js.map +0 -1
  83. package/dist/task-stream-CX7Uf6EM.js.map +0 -1
  84. package/dist/telemetry-D6bjWA-A.js +0 -13
  85. package/dist/telemetry-D6bjWA-A.js.map +0 -1
  86. package/dist/wizard-session-BQC9vy9Z.js +0 -2
  87. package/dist/wizard-session-BcNJTl2I.js.map +0 -1
package/dist/bin.js CHANGED
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
3
- import { D as POSTHOG_DOCS_URL, G as VERSION, K as red, W as runtimeEnv, c as getUI, l as setUI, s as logToFile, u as LoggingUI, z as WIZARD_USER_AGENT } from "./debug-Cqi6nVfX.js";
4
- import { n as analytics } from "./analytics-VM7laaFx.js";
5
- import { u as handleApiError } from "./setup-utils-CNV7FSlY.js";
6
- import { h as AUDIT_REPORT_FILE, m as AUDIT_CHECKS_KEY, p as AUDIT_CHECKS_FILE } from "./agent-interface-CV0-vtxj.js";
7
- import { n as posthogIntegrationConfig } from "./posthog-integration-BL21S3T6.js";
8
- import { t as IGNORED_DIRS } from "./file-utils-DnTSiTJw.js";
3
+ import { D as POSTHOG_DOCS_URL, G as VERSION, W as runtimeEnv, c as getUI, f as SIGNUP_WIZARD_READINESS_CONFIG, l as setUI, m as getBlockingServiceKeys, p as evaluateWizardReadiness, s as logToFile, u as LoggingUI, z as WIZARD_USER_AGENT } from "./debug-CYUB-urp.js";
4
+ import { n as analytics } from "./analytics-Dmnxu2zE.js";
5
+ import { a as isUsingTypeScript, d as getCloudUrlFromRegion, u as handleApiError } from "./setup-utils-LvtZIY18.js";
6
+ import { g as AUDIT_REPORT_FILE, h as AUDIT_CHECKS_KEY, m as AUDIT_CHECKS_FILE, u as WIZARD_TOOL_NAMES } from "./agent-interface-gP4pkZgS.js";
7
+ import { i as SPINNER_MESSAGE } from "./registry-B92uyoWK.js";
8
+ import { a as LINE_CHART_BLOCK, i as FUNNEL_BLOCK, n as posthogIntegrationConfig, o as PRODUCT_SUITE_BLOCK, s as StatusPeekTrigger } from "./posthog-integration-C-FFV5ny.js";
9
+ import { o as Colors } from "./TextBlock-B3cm43YY.js";
10
+ import { t as IGNORED_DIRS } from "./file-utils-DPmgn9Vm.js";
9
11
  import { satisfies } from "semver";
10
12
  import yargs from "yargs";
11
13
  import { hideBin } from "yargs/helpers";
@@ -15,6 +17,8 @@ import path, { join, relative } from "path";
15
17
  import axios from "axios";
16
18
  import { z } from "zod";
17
19
  import "fast-glob";
20
+ import { Text } from "ink";
21
+ import { jsx, jsxs } from "react/jsx-runtime";
18
22
  //#region src/utils/environment.ts
19
23
  var environment_exports = /* @__PURE__ */ __exportAll({
20
24
  isNonInteractiveEnvironment: () => isNonInteractiveEnvironment,
@@ -29,7 +33,7 @@ function readEnvironment() {
29
33
  return readEnv("POSTHOG_WIZARD");
30
34
  }
31
35
  //#endregion
32
- //#region src/lib/workflows/revenue-analytics/detect.ts
36
+ //#region src/lib/programs/revenue-analytics/detect.ts
33
37
  const POSTHOG_SDKS = [
34
38
  "posthog-js",
35
39
  "posthog-node",
@@ -163,47 +167,85 @@ function detectRevenuePrerequisites(session, setFrameworkContext) {
163
167
  setFrameworkContext("detectedPackagePaths", matches.filter((m) => m.posthogSdks.length > 0 || m.stripeSdks.length > 0).map((m) => m.path));
164
168
  }
165
169
  //#endregion
166
- //#region src/lib/workflows/revenue-analytics/index.ts
167
- const revenueAnalyticsConfig = {
168
- command: "revenue",
169
- description: "Set up PostHog revenue analytics (e.g. Stripe integration)",
170
- flowKey: "revenue-analytics-setup",
171
- steps: [
172
- {
173
- id: "detect",
174
- label: "Detecting prerequisites",
175
- onReady: (ctx) => detectRevenuePrerequisites(ctx.session, ctx.setFrameworkContext)
176
- },
177
- {
178
- id: "intro",
179
- label: "Welcome",
180
- screen: "revenue-intro",
181
- gate: (session) => session.setupConfirmed
182
- },
183
- {
184
- id: "auth",
185
- label: "Authentication",
186
- screen: "auth",
187
- isComplete: (session) => session.credentials !== null
188
- },
170
+ //#region src/lib/programs/revenue-analytics/steps.ts
171
+ const REVENUE_ANALYTICS_PROGRAM = [
172
+ {
173
+ id: "detect",
174
+ label: "Detecting prerequisites",
175
+ onReady: (ctx) => detectRevenuePrerequisites(ctx.session, ctx.setFrameworkContext)
176
+ },
177
+ {
178
+ id: "intro",
179
+ label: "Welcome",
180
+ screenId: "revenue-intro",
181
+ gate: (session) => session.setupConfirmed
182
+ },
183
+ {
184
+ id: "auth",
185
+ label: "Authentication",
186
+ screenId: "auth",
187
+ isComplete: (session) => session.credentials !== null
188
+ },
189
+ {
190
+ id: "run",
191
+ label: "Revenue analytics",
192
+ screenId: "run",
193
+ isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
194
+ },
195
+ {
196
+ id: "outro",
197
+ label: "Done",
198
+ screenId: "outro",
199
+ isComplete: (session) => session.outroDismissed
200
+ },
201
+ {
202
+ id: "skills",
203
+ label: "Skills",
204
+ screenId: "keep-skills"
205
+ }
206
+ ];
207
+ //#endregion
208
+ //#region src/lib/programs/agent-skill/content/index.tsx
209
+ /**
210
+ * Agent-skill learn-deck — the short three-line sequence shown while a
211
+ * skill-based program (audit, revenue-analytics, agent-skill, etc.)
212
+ * runs. Skill programs don't need the full PostHog onboarding narrative.
213
+ */
214
+ const getContentBlocks$1 = (store) => {
215
+ return [
189
216
  {
190
- id: "run",
191
- label: "Revenue analytics",
192
- screen: "run",
193
- isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
217
+ content: "Welcome.",
218
+ pause: 3e3,
219
+ mode: 0,
220
+ animationInterval: 160
194
221
  },
195
222
  {
196
- id: "outro",
197
- label: "Done",
198
- screen: "outro",
199
- isComplete: (session) => session.outroDismissed
223
+ content: "The Wizard is an agent.",
224
+ pause: 4e3
200
225
  },
201
226
  {
202
- id: "skills",
203
- label: "Skills",
204
- screen: "keep-skills"
227
+ pause: 6e4,
228
+ content: /* @__PURE__ */ jsxs(Text, { children: [
229
+ "Running the ",
230
+ /* @__PURE__ */ jsx(Text, {
231
+ color: "cyan",
232
+ children: store?.session.skillId ?? "unknown"
233
+ }),
234
+ " skill..."
235
+ ] })
205
236
  }
206
- ],
237
+ ];
238
+ };
239
+ //#endregion
240
+ //#region src/lib/programs/revenue-analytics/index.ts
241
+ const revenueAnalyticsConfig = {
242
+ command: "revenue",
243
+ description: "Set up PostHog revenue analytics (e.g. Stripe integration)",
244
+ id: "revenue-analytics-setup",
245
+ steps: REVENUE_ANALYTICS_PROGRAM,
246
+ getContentBlocks: getContentBlocks$1,
247
+ allowedTools: ["Agent"],
248
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
207
249
  run: {
208
250
  skillId: "revenue-analytics-setup",
209
251
  integrationLabel: "revenue-analytics-setup",
@@ -218,48 +260,50 @@ const revenueAnalyticsConfig = {
218
260
  requires: ["posthog-integration"]
219
261
  };
220
262
  //#endregion
221
- //#region src/lib/workflows/agent-skill/steps.ts
263
+ //#region src/lib/programs/agent-skill/steps.ts
222
264
  const AGENT_SKILL_STEPS = [
223
265
  {
224
266
  id: "intro",
225
267
  label: "Welcome",
226
- screen: "agent-skill-intro",
268
+ screenId: "agent-skill-intro",
227
269
  gate: (session) => session.setupConfirmed
228
270
  },
229
271
  {
230
272
  id: "auth",
231
273
  label: "Authentication",
232
- screen: "auth",
274
+ screenId: "auth",
233
275
  isComplete: (session) => session.credentials !== null
234
276
  },
235
277
  {
236
278
  id: "run",
237
279
  label: "Running",
238
- screen: "run",
280
+ screenId: "run",
239
281
  isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
240
282
  },
241
283
  {
242
284
  id: "outro",
243
285
  label: "Done",
244
- screen: "outro",
286
+ screenId: "outro",
245
287
  isComplete: (session) => session.outroDismissed
246
288
  },
247
289
  {
248
290
  id: "skills",
249
291
  label: "Skills",
250
- screen: "keep-skills"
292
+ screenId: "keep-skills"
251
293
  }
252
294
  ];
253
295
  //#endregion
254
- //#region src/lib/workflows/agent-skill/index.ts
255
- var agent_skill_exports = /* @__PURE__ */ __exportAll({ createSkillWorkflow: () => createSkillWorkflow });
256
- function createSkillWorkflow(opts) {
296
+ //#region src/lib/programs/agent-skill/index.ts
297
+ var agent_skill_exports = /* @__PURE__ */ __exportAll({ createSkillProgram: () => createSkillProgram });
298
+ function createSkillProgram(opts) {
257
299
  return {
258
300
  command: opts.command,
259
301
  description: opts.description,
260
- flowKey: opts.flowKey,
302
+ id: opts.id,
303
+ skillId: opts.skillId,
261
304
  steps: AGENT_SKILL_STEPS,
262
305
  reportFile: opts.reportFile,
306
+ getContentBlocks: getContentBlocks$1,
263
307
  run: {
264
308
  skillId: opts.skillId,
265
309
  integrationLabel: opts.integrationLabel,
@@ -276,17 +320,17 @@ function createSkillWorkflow(opts) {
276
320
  };
277
321
  }
278
322
  //#endregion
279
- //#region src/lib/workflows/audit/detect.ts
323
+ //#region src/lib/programs/audit/detect.ts
280
324
  /** `[ABORT] <reason>` cases the audit skill can emit. Reason strings are
281
325
  * defined in the skill's `Abort statuses` section. */
282
326
  const AUDIT_ABORT_CASES = [{
283
327
  match: /^no posthog sdk found$/i,
284
328
  message: "No PostHog SDK found",
285
- body: "The audit needs an existing PostHog integration to review. No PostHog SDK appears in this project’s dependency manifests. Run the basic integration workflow to install PostHog first, then re-run the audit.",
329
+ body: "The audit needs an existing PostHog integration to review. No PostHog SDK appears in this project’s dependency manifests. Run the basic integration program to install PostHog first, then re-run the audit.",
286
330
  docsUrl: "https://posthog.com/docs/getting-started/install"
287
331
  }];
288
332
  //#endregion
289
- //#region src/lib/workflows/audit/seed.ts
333
+ //#region src/lib/programs/audit/seed.ts
290
334
  /** The 10 data-integrity checks the audit runs. */
291
335
  const AUDIT_SEED_CHECKS = [
292
336
  {
@@ -359,7 +403,7 @@ function seedAuditLedger(installDir) {
359
403
  logToFile(`seedAuditLedger: wrote ${AUDIT_SEED_CHECKS.length} entries to ${target}`);
360
404
  }
361
405
  //#endregion
362
- //#region src/lib/workflows/audit/index.ts
406
+ //#region src/lib/programs/audit/index.ts
363
407
  /** Audit-specific screens for the shared agent-skill pipeline. */
364
408
  const AUDIT_SCREEN_BY_STEP = {
365
409
  intro: "audit-intro",
@@ -374,17 +418,17 @@ const withAuditScreens = (steps) => steps.map((step) => {
374
418
  const override = AUDIT_SCREEN_BY_STEP[step.id];
375
419
  return override ? {
376
420
  ...step,
377
- screen: override
421
+ screenId: override
378
422
  } : step;
379
423
  });
380
424
  const auditSteps = withAuditScreens(AGENT_SKILL_STEPS);
381
- const baseConfig$1 = createSkillWorkflow({
425
+ const baseConfig$1 = createSkillProgram({
382
426
  skillId: "audit",
383
427
  command: "audit",
384
- flowKey: "audit",
428
+ id: "audit",
385
429
  description: "Audit an existing PostHog integration for correctness and best practices",
386
430
  integrationLabel: "audit",
387
- customPrompt: "Run a comprehensive audit of the existing PostHog integration. Follow the skill workflow steps in order. Do not modify any project files — only create the final audit report.",
431
+ customPrompt: "Run a comprehensive audit of the existing PostHog integration. Follow the skill program steps in order. Do not modify any project files — only create the final audit report.",
388
432
  successMessage: "Audit complete! You can view the audit report at ./posthog-audit-report.md",
389
433
  reportFile: AUDIT_REPORT_FILE,
390
434
  docsUrl: "https://posthog.com/docs/product-analytics/best-practices",
@@ -395,16 +439,148 @@ const baseConfig$1 = createSkillWorkflow({
395
439
  });
396
440
  const auditRun = async (session) => {
397
441
  seedBeforeAuditRun(session);
398
- if (!baseConfig$1.run) throw new Error("Audit workflow has no run configuration.");
442
+ if (!baseConfig$1.run) throw new Error("Audit program has no run configuration.");
399
443
  return typeof baseConfig$1.run === "function" ? baseConfig$1.run(session) : baseConfig$1.run;
400
444
  };
401
445
  const auditConfig = {
402
446
  ...baseConfig$1,
403
447
  steps: auditSteps,
404
- run: auditRun
448
+ run: auditRun,
449
+ allowedTools: ["Agent"],
450
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk]
451
+ };
452
+ //#endregion
453
+ //#region src/lib/programs/events-audit/steps.ts
454
+ function needsSetup(session) {
455
+ const config = session.frameworkConfig;
456
+ if (!config?.metadata.setup?.questions) return false;
457
+ return config.metadata.setup.questions.some((q) => !(q.key in session.frameworkContext));
458
+ }
459
+ function healthCheckReady(session) {
460
+ if (!session.readinessResult) return false;
461
+ if (session.signup) {
462
+ const hardBlocking = getBlockingServiceKeys(session.readinessResult.health, SIGNUP_WIZARD_READINESS_CONFIG);
463
+ const defaultBlocking = getBlockingServiceKeys(session.readinessResult.health);
464
+ if (hardBlocking.length === 0 && defaultBlocking.length === 0) return true;
465
+ return session.outageDismissed;
466
+ }
467
+ if (session.readinessResult.decision === "no") return session.outageDismissed;
468
+ return true;
469
+ }
470
+ const EVENTS_AUDIT_PROGRAM = [
471
+ {
472
+ id: "intro",
473
+ label: "Welcome",
474
+ screenId: "audit-intro",
475
+ gate: (session) => session.setupConfirmed
476
+ },
477
+ {
478
+ id: "health-check",
479
+ label: "Health check",
480
+ screenId: "health-check",
481
+ gate: healthCheckReady,
482
+ onInit: (ctx) => {
483
+ evaluateWizardReadiness().then((readiness) => {
484
+ ctx.setReadinessResult(readiness);
485
+ }).catch(() => {
486
+ ctx.setReadinessResult({
487
+ decision: "yes",
488
+ health: {},
489
+ reasons: []
490
+ });
491
+ });
492
+ }
493
+ },
494
+ {
495
+ id: "setup",
496
+ label: "Setup",
497
+ screenId: "setup",
498
+ show: needsSetup,
499
+ isComplete: (session) => !needsSetup(session)
500
+ },
501
+ {
502
+ id: "auth",
503
+ label: "Authentication",
504
+ screenId: "auth",
505
+ isComplete: (session) => session.credentials !== null
506
+ },
507
+ {
508
+ id: "run",
509
+ label: "Events audit",
510
+ screenId: "audit-run",
511
+ isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
512
+ },
513
+ {
514
+ id: "mcp",
515
+ label: "MCP servers",
516
+ screenId: "mcp",
517
+ isComplete: (session) => session.mcpComplete
518
+ },
519
+ {
520
+ id: "outro",
521
+ label: "Done",
522
+ screenId: "audit-outro",
523
+ isComplete: (session) => session.outroDismissed
524
+ },
525
+ {
526
+ id: "keep-skills",
527
+ label: "Keep Skills",
528
+ screenId: "keep-skills"
529
+ }
530
+ ];
531
+ //#endregion
532
+ //#region src/lib/programs/events-audit/index.ts
533
+ const SETUP_REPORT_FILE = "posthog-events-audit-report.md";
534
+ const DOCS_URL = "https://posthog.com/docs/product-analytics/best-practices";
535
+ const eventsAuditConfig = {
536
+ command: "events-audit",
537
+ description: "Audit PostHog event tracking in this project",
538
+ id: "events-audit",
539
+ skillId: "events-audit",
540
+ steps: EVENTS_AUDIT_PROGRAM,
541
+ reportFile: SETUP_REPORT_FILE,
542
+ allowedTools: ["Agent"],
543
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
544
+ run: (session) => {
545
+ const typeScriptDetected = isUsingTypeScript({ installDir: session.installDir });
546
+ session.typescript = typeScriptDetected;
547
+ seedAuditLedger(session.installDir);
548
+ session.frameworkContext[AUDIT_CHECKS_KEY] = AUDIT_SEED_CHECKS;
549
+ return Promise.resolve({
550
+ skillId: "events-audit",
551
+ integrationLabel: "events-audit",
552
+ spinnerMessage: SPINNER_MESSAGE,
553
+ successMessage: "Events audit complete! You can view the report at ./posthog-events-audit-report.md",
554
+ estimatedDurationMinutes: 5,
555
+ reportFile: SETUP_REPORT_FILE,
556
+ docsUrl: DOCS_URL,
557
+ errorMessage: "Events audit failed",
558
+ additionalFeatureQueue: session.additionalFeatureQueue,
559
+ customPrompt: (ctx) => `Audit PostHog event capture in this project. Do not modify any project files — produce a read-only report only.
560
+
561
+ Project context:
562
+ - PostHog Project ID: ${ctx.projectId}
563
+ - TypeScript: ${typeScriptDetected ? "Yes" : "No"}
564
+ - PostHog public token: ${ctx.projectApiKey}
565
+ - PostHog Host: ${ctx.host}
566
+ `,
567
+ buildOutroData: (sess, _credentials, cloudRegion) => {
568
+ const cloudUrl = cloudRegion ? getCloudUrlFromRegion(cloudRegion) : void 0;
569
+ return {
570
+ kind: "success",
571
+ message: "Your events audit was successful",
572
+ reportFile: SETUP_REPORT_FILE,
573
+ changes: [],
574
+ docsUrl: DOCS_URL,
575
+ continueUrl: sess.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0,
576
+ dashboardUrl: sess.dashboardUrl ?? (cloudUrl ? `${cloudUrl}/dashboard` : void 0)
577
+ };
578
+ }
579
+ });
580
+ }
405
581
  };
406
582
  //#endregion
407
- //#region src/lib/workflows/audit-3000/index.ts
583
+ //#region src/lib/programs/audit-3000/index.ts
408
584
  const AUDIT3000_REPORT_FILE = "posthog-audit-3000-report.md";
409
585
  const AUDIT3000_EXTRA_CHECKS = [
410
586
  {
@@ -573,14 +749,14 @@ const withAudit3000Screens = (steps) => steps.map((step) => {
573
749
  const override = AUDIT3000_SCREEN_BY_STEP[step.id];
574
750
  return override ? {
575
751
  ...step,
576
- screen: override
752
+ screenId: override
577
753
  } : step;
578
754
  });
579
755
  const audit3000Steps = withAudit3000Screens(AGENT_SKILL_STEPS);
580
- const baseConfig = createSkillWorkflow({
756
+ const baseConfig = createSkillProgram({
581
757
  skillId: "audit-3000",
582
758
  command: "audit-3000",
583
- flowKey: "audit-3000",
759
+ id: "audit-3000",
584
760
  description: "Audit an existing PostHog integration (v3000 — adds event quality, stale-flag hygiene, customer enrichment, use-case match)",
585
761
  integrationLabel: "audit-3000",
586
762
  customPrompt: "Run the audit-3000 skill end-to-end. Follow the step chain starting at references/1-version.md. Do not modify any project files — only create the final audit report and (when enrichment is enabled) the enrichment report.",
@@ -594,44 +770,46 @@ const baseConfig = createSkillWorkflow({
594
770
  });
595
771
  const audit3000Run = async (session) => {
596
772
  seedBeforeAudit3000Run(session);
597
- if (!baseConfig.run) throw new Error("audit-3000 workflow has no run configuration.");
773
+ if (!baseConfig.run) throw new Error("audit-3000 program has no run configuration.");
598
774
  return typeof baseConfig.run === "function" ? baseConfig.run(session) : baseConfig.run;
599
775
  };
600
776
  const audit3000Config = {
601
777
  ...baseConfig,
602
778
  steps: audit3000Steps,
603
- run: audit3000Run
779
+ run: audit3000Run,
780
+ allowedTools: ["Agent"],
781
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk]
604
782
  };
605
783
  //#endregion
606
- //#region src/lib/workflows/posthog-doctor/steps.ts
607
- const POSTHOG_DOCTOR_WORKFLOW = [
784
+ //#region src/lib/programs/posthog-doctor/steps.ts
785
+ const POSTHOG_DOCTOR_PROGRAM = [
608
786
  {
609
787
  id: "intro",
610
788
  label: "Welcome",
611
- screen: "doctor-intro",
789
+ screenId: "doctor-intro",
612
790
  gate: (session) => session.setupConfirmed
613
791
  },
614
792
  {
615
793
  id: "auth",
616
794
  label: "Authentication",
617
- screen: "auth",
795
+ screenId: "auth",
618
796
  isComplete: (session) => session.credentials !== null
619
797
  },
620
798
  {
621
799
  id: "report",
622
800
  label: "Doctor report",
623
- screen: "doctor-report",
801
+ screenId: "doctor-report",
624
802
  isComplete: (session) => session.outroData !== null
625
803
  },
626
804
  {
627
805
  id: "outro",
628
806
  label: "Done",
629
- screen: "outro",
807
+ screenId: "outro",
630
808
  isComplete: (session) => session.outroDismissed
631
809
  }
632
810
  ];
633
811
  //#endregion
634
- //#region src/lib/workflows/posthog-doctor/types.ts
812
+ //#region src/lib/programs/posthog-doctor/types.ts
635
813
  const HealthIssueSeveritySchema = z.enum([
636
814
  "critical",
637
815
  "warning",
@@ -655,7 +833,7 @@ const HealthIssueListResponseSchema = z.object({
655
833
  previous: z.string().nullable().optional()
656
834
  });
657
835
  //#endregion
658
- //#region src/lib/workflows/posthog-doctor/fetch.ts
836
+ //#region src/lib/programs/posthog-doctor/fetch.ts
659
837
  async function fetchHealthIssues(accessToken, baseUrl, projectId) {
660
838
  const endpoint = `/api/environments/${projectId}/health_issues/`;
661
839
  const url = `${baseUrl}${endpoint}?status=active&dismissed=false&limit=250`;
@@ -676,7 +854,7 @@ async function fetchHealthIssues(accessToken, baseUrl, projectId) {
676
854
  }
677
855
  }
678
856
  //#endregion
679
- //#region src/lib/workflows/posthog-doctor/kind-metadata.ts
857
+ //#region src/lib/programs/posthog-doctor/kind-metadata.ts
680
858
  const KIND_METADATA = {
681
859
  ingestion_lag: {
682
860
  title: "Ingestion is delayed",
@@ -746,36 +924,649 @@ function getKindMeta(kind) {
746
924
  };
747
925
  }
748
926
  //#endregion
749
- //#region src/lib/workflows/workflow-registry.ts
750
- const WORKFLOW_REGISTRY = [
927
+ //#region src/lib/programs/posthog-doctor/index.ts
928
+ const posthogDoctorConfig = {
929
+ command: "doctor",
930
+ description: "Diagnose your PostHog project for configuration issues and setup warnings",
931
+ id: "posthog-doctor",
932
+ steps: POSTHOG_DOCTOR_PROGRAM,
933
+ allowedTools: ["Agent"],
934
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk]
935
+ };
936
+ //#endregion
937
+ //#region src/lib/programs/migration/steps.ts
938
+ const MIGRATION_PROGRAM = [
939
+ {
940
+ id: "intro",
941
+ label: "Welcome",
942
+ screenId: "migration-intro",
943
+ gate: (session) => session.setupConfirmed
944
+ },
945
+ {
946
+ id: "auth",
947
+ label: "Authentication",
948
+ screenId: "auth",
949
+ isComplete: (session) => session.credentials !== null
950
+ },
951
+ {
952
+ id: "run",
953
+ label: "Migration",
954
+ screenId: "run",
955
+ isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
956
+ },
957
+ {
958
+ id: "outro",
959
+ label: "Done",
960
+ screenId: "outro",
961
+ isComplete: (session) => session.outroDismissed
962
+ },
963
+ {
964
+ id: "skills",
965
+ label: "Skills",
966
+ screenId: "keep-skills"
967
+ }
968
+ ];
969
+ //#endregion
970
+ //#region src/lib/programs/migration/content/vendor-stack.tsx
971
+ /**
972
+ * Vendor cost stack — the multi-tool baseline a typical migration target has
973
+ * before consolidating onto PostHog. Numbers from each vendor's published
974
+ * starter pricing.
975
+ */
976
+ const VENDOR_STACK_BLOCK = {
977
+ type: "lines",
978
+ interval: 600,
979
+ pause: 9e3,
980
+ lines: [
981
+ /* @__PURE__ */ jsx(Text, {
982
+ bold: true,
983
+ children: " Typical pre-migration stack"
984
+ }),
985
+ /* @__PURE__ */ jsx(Text, { children: " " }),
986
+ /* @__PURE__ */ jsxs(Text, { children: [
987
+ /* @__PURE__ */ jsx(Text, {
988
+ color: "gray",
989
+ children: " Sentry"
990
+ }),
991
+ /* @__PURE__ */ jsx(Text, { children: " error tracking " }),
992
+ /* @__PURE__ */ jsx(Text, {
993
+ color: "red",
994
+ children: "$26/mo+"
995
+ })
996
+ ] }),
997
+ /* @__PURE__ */ jsxs(Text, { children: [
998
+ /* @__PURE__ */ jsx(Text, {
999
+ color: "gray",
1000
+ children: " LaunchDarkly"
1001
+ }),
1002
+ /* @__PURE__ */ jsx(Text, { children: " feature flags " }),
1003
+ /* @__PURE__ */ jsx(Text, {
1004
+ color: "red",
1005
+ children: "$8.33/mo+"
1006
+ })
1007
+ ] }),
1008
+ /* @__PURE__ */ jsxs(Text, { children: [
1009
+ /* @__PURE__ */ jsx(Text, {
1010
+ color: "gray",
1011
+ children: " Amplitude"
1012
+ }),
1013
+ /* @__PURE__ */ jsx(Text, { children: " product analytics " }),
1014
+ /* @__PURE__ */ jsx(Text, {
1015
+ color: "red",
1016
+ children: "$49/mo+"
1017
+ })
1018
+ ] }),
1019
+ /* @__PURE__ */ jsxs(Text, { children: [
1020
+ /* @__PURE__ */ jsx(Text, {
1021
+ color: "gray",
1022
+ children: " Braintrust"
1023
+ }),
1024
+ /* @__PURE__ */ jsx(Text, { children: " LLM analytics " }),
1025
+ /* @__PURE__ */ jsx(Text, {
1026
+ color: "red",
1027
+ children: "$50/mo+"
1028
+ })
1029
+ ] }),
1030
+ /* @__PURE__ */ jsx(Text, {
1031
+ color: "gray",
1032
+ children: " ─────────────────────────────────────"
1033
+ }),
1034
+ /* @__PURE__ */ jsxs(Text, { children: [
1035
+ /* @__PURE__ */ jsx(Text, { children: " Total" }),
1036
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1037
+ /* @__PURE__ */ jsx(Text, {
1038
+ bold: true,
1039
+ color: "red",
1040
+ children: "$133/mo+"
1041
+ })
1042
+ ] }),
1043
+ /* @__PURE__ */ jsx(Text, {
1044
+ dimColor: true,
1045
+ children: " plus ~450KB of JavaScript SDKs"
1046
+ })
1047
+ ]
1048
+ };
1049
+ //#endregion
1050
+ //#region src/lib/programs/migration/content/free-tier.tsx
1051
+ /**
1052
+ * PostHog free-tier highlights — the numbers a migrating team gets back when
1053
+ * they consolidate. Sourced from posthog.com/pricing.md.
1054
+ */
1055
+ const FREE_TIER_BLOCK = {
1056
+ type: "lines",
1057
+ interval: 400,
1058
+ pause: 9e3,
1059
+ lines: [
1060
+ /* @__PURE__ */ jsx(Text, {
1061
+ bold: true,
1062
+ children: " Free every month, on every product"
1063
+ }),
1064
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1065
+ /* @__PURE__ */ jsxs(Text, { children: [
1066
+ /* @__PURE__ */ jsx(Text, {
1067
+ color: Colors.accent,
1068
+ children: " 1,000,000 "
1069
+ }),
1070
+ /* @__PURE__ */ jsx(Text, { children: "events " }),
1071
+ /* @__PURE__ */ jsx(Text, {
1072
+ dimColor: true,
1073
+ children: "product analytics"
1074
+ })
1075
+ ] }),
1076
+ /* @__PURE__ */ jsxs(Text, { children: [
1077
+ /* @__PURE__ */ jsx(Text, {
1078
+ color: Colors.accent,
1079
+ children: " 1,000,000 "
1080
+ }),
1081
+ /* @__PURE__ */ jsx(Text, { children: "requests " }),
1082
+ /* @__PURE__ */ jsx(Text, {
1083
+ dimColor: true,
1084
+ children: "feature flags + experiments"
1085
+ })
1086
+ ] }),
1087
+ /* @__PURE__ */ jsxs(Text, { children: [
1088
+ /* @__PURE__ */ jsx(Text, {
1089
+ color: Colors.accent,
1090
+ children: " 5,000 "
1091
+ }),
1092
+ /* @__PURE__ */ jsx(Text, { children: "recordings " }),
1093
+ /* @__PURE__ */ jsx(Text, {
1094
+ dimColor: true,
1095
+ children: "session replay"
1096
+ })
1097
+ ] }),
1098
+ /* @__PURE__ */ jsxs(Text, { children: [
1099
+ /* @__PURE__ */ jsx(Text, {
1100
+ color: Colors.accent,
1101
+ children: " 100,000 "
1102
+ }),
1103
+ /* @__PURE__ */ jsx(Text, { children: "exceptions " }),
1104
+ /* @__PURE__ */ jsx(Text, {
1105
+ dimColor: true,
1106
+ children: "error tracking"
1107
+ })
1108
+ ] }),
1109
+ /* @__PURE__ */ jsxs(Text, { children: [
1110
+ /* @__PURE__ */ jsx(Text, {
1111
+ color: Colors.accent,
1112
+ children: " 100,000 "
1113
+ }),
1114
+ /* @__PURE__ */ jsx(Text, { children: "events " }),
1115
+ /* @__PURE__ */ jsx(Text, {
1116
+ dimColor: true,
1117
+ children: "LLM analytics"
1118
+ })
1119
+ ] }),
1120
+ /* @__PURE__ */ jsxs(Text, { children: [
1121
+ /* @__PURE__ */ jsx(Text, {
1122
+ color: Colors.accent,
1123
+ children: " 50 GB "
1124
+ }),
1125
+ /* @__PURE__ */ jsx(Text, { children: "logs " }),
1126
+ /* @__PURE__ */ jsx(Text, {
1127
+ dimColor: true,
1128
+ children: "logs"
1129
+ })
1130
+ ] }),
1131
+ /* @__PURE__ */ jsxs(Text, { children: [
1132
+ /* @__PURE__ */ jsx(Text, {
1133
+ color: Colors.accent,
1134
+ children: " 1,500 "
1135
+ }),
1136
+ /* @__PURE__ */ jsx(Text, { children: "responses " }),
1137
+ /* @__PURE__ */ jsx(Text, {
1138
+ dimColor: true,
1139
+ children: "surveys"
1140
+ })
1141
+ ] }),
1142
+ /* @__PURE__ */ jsxs(Text, { children: [
1143
+ /* @__PURE__ */ jsx(Text, {
1144
+ color: Colors.accent,
1145
+ children: " 1,000,000 "
1146
+ }),
1147
+ /* @__PURE__ */ jsx(Text, { children: "rows " }),
1148
+ /* @__PURE__ */ jsx(Text, {
1149
+ dimColor: true,
1150
+ children: "data warehouse"
1151
+ })
1152
+ ] })
1153
+ ]
1154
+ };
1155
+ //#endregion
1156
+ //#region src/lib/programs/migration/content/pricing-structure.tsx
1157
+ /**
1158
+ * Pricing structure block — what happens after the free tier.
1159
+ */
1160
+ const PRICING_STRUCTURE_BLOCK = {
1161
+ type: "lines",
1162
+ interval: 500,
1163
+ pause: 8e3,
1164
+ lines: [
1165
+ /* @__PURE__ */ jsx(Text, {
1166
+ bold: true,
1167
+ children: " After the free tier"
1168
+ }),
1169
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1170
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1171
+ color: Colors.accent,
1172
+ children: " $0 "
1173
+ }), /* @__PURE__ */ jsx(Text, { children: "base price · pay only for what you use" })] }),
1174
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1175
+ color: Colors.accent,
1176
+ children: " ◆ "
1177
+ }), /* @__PURE__ */ jsx(Text, { children: "per-event prices decrease with volume" })] }),
1178
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1179
+ color: Colors.accent,
1180
+ children: " ◆ "
1181
+ }), /* @__PURE__ */ jsx(Text, { children: "no per-seat charges — your whole team is included" })] }),
1182
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1183
+ color: Colors.accent,
1184
+ children: " ◆ "
1185
+ }), /* @__PURE__ */ jsx(Text, { children: "web analytics bundled with product analytics" })] }),
1186
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1187
+ color: Colors.accent,
1188
+ children: " ◆ "
1189
+ }), /* @__PURE__ */ jsx(Text, { children: "experiments bundled with feature flags" })] }),
1190
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1191
+ color: Colors.accent,
1192
+ children: " ◆ "
1193
+ }), /* @__PURE__ */ jsx(Text, { children: "revenue analytics bundled with data warehouse" })] })
1194
+ ]
1195
+ };
1196
+ //#endregion
1197
+ //#region src/lib/programs/migration/content/index.tsx
1198
+ /**
1199
+ * Migration learn deck (statsig variant). Statsig is the only `migrate`
1200
+ * variant today, so this deck plays as-is when the wizard runs
1201
+ * `migrate --product=statsig`. Three movements:
1202
+ *
1203
+ * 1. Welcome and reassure.
1204
+ * 2. What to expect — the migration is replacement-only, takes a few
1205
+ * minutes, leaves the build green.
1206
+ * 3. What's a little different — how flags and experiments work in
1207
+ * PostHog, presented as right-way guidance rather than gotchas.
1208
+ *
1209
+ * FF/experiments guidance paraphrased from PostHog public docs:
1210
+ * - posthog.com/docs/feature-flags/best-practices
1211
+ * - posthog.com/docs/feature-flags/common-questions
1212
+ * - posthog.com/docs/experiments/best-practices
1213
+ */
1214
+ const getContentBlocks = (store) => [
1215
+ {
1216
+ content: "Hello.",
1217
+ pause: 3e3,
1218
+ mode: 0,
1219
+ animationInterval: 160
1220
+ },
1221
+ {
1222
+ content: "The Wizard is an agent.",
1223
+ pause: 4e3
1224
+ },
1225
+ {
1226
+ content: "As we speak, it’s making a plan to migrate from Statsig to PostHog.",
1227
+ pause: 6e3
1228
+ },
1229
+ {
1230
+ content: "PostHog covers the cost of running this agent.",
1231
+ pause: 4e3
1232
+ },
1233
+ {
1234
+ type: "clear",
1235
+ pause: 2e3
1236
+ },
1237
+ {
1238
+ pause: 5e3,
1239
+ persist: true,
1240
+ content: /* @__PURE__ */ jsx(StatusPeekTrigger, { store })
1241
+ },
1242
+ {
1243
+ pause: 6e3,
1244
+ persist: true,
1245
+ content: /* @__PURE__ */ jsxs(Text, { children: [
1246
+ "Press",
1247
+ " ",
1248
+ /* @__PURE__ */ jsx(Text, {
1249
+ color: Colors.accent,
1250
+ bold: true,
1251
+ children: "S"
1252
+ }),
1253
+ " ",
1254
+ "to expand or collapse the status."
1255
+ ] })
1256
+ },
1257
+ {
1258
+ type: "clear",
1259
+ pause: 2e3
1260
+ },
1261
+ {
1262
+ content: "Here’s what to expect.",
1263
+ pause: 3e3
1264
+ },
1265
+ {
1266
+ content: "The migration takes about ten minutes.",
1267
+ pause: 3e3
1268
+ },
1269
+ {
1270
+ content: "Every Statsig call gets replaced in place with its PostHog equivalent.",
1271
+ pause: 5500
1272
+ },
1273
+ {
1274
+ content: "Nothing new gets added. No extra captures, no surprise instrumentation.",
1275
+ pause: 5500
1276
+ },
1277
+ {
1278
+ content: "The Statsig package gets removed at the end. We’ll run build and lint to clean up after ourselves.",
1279
+ pause: 6500
1280
+ },
1281
+ {
1282
+ type: "clear",
1283
+ pause: 2e3
1284
+ },
1285
+ {
1286
+ content: "A few things work a little differently in PostHog.",
1287
+ pause: 4500
1288
+ },
1289
+ {
1290
+ content: /* @__PURE__ */ jsxs(Text, { children: [
1291
+ "Flags evaluate against a stable user. Call",
1292
+ " ",
1293
+ /* @__PURE__ */ jsx(Text, {
1294
+ bold: true,
1295
+ color: Colors.accent,
1296
+ children: "identify()"
1297
+ }),
1298
+ " ",
1299
+ "first, then check the flag."
1300
+ ] }),
1301
+ pause: 6e3,
1302
+ persist: true
1303
+ },
1304
+ {
1305
+ content: "For anything in the first paint, evaluate server-side and bootstrap the values into the client.",
1306
+ pause: 6500
1307
+ },
1308
+ {
1309
+ content: /* @__PURE__ */ jsxs(Text, { children: [
1310
+ "In production, route requests through a reverse proxy to avoid ad blockers breaking your flags.",
1311
+ "\n",
1312
+ /* @__PURE__ */ jsx(Text, {
1313
+ dimColor: true,
1314
+ children: "https://posthog.com/docs/advanced/proxy"
1315
+ })
1316
+ ] }),
1317
+ pause: 6500,
1318
+ persist: true
1319
+ },
1320
+ {
1321
+ content: "When a flag reaches 100% rollout, retire it. Flags are signals, not switches.",
1322
+ pause: 5500
1323
+ },
1324
+ {
1325
+ content: /* @__PURE__ */ jsxs(Text, { children: [
1326
+ "Name flags descriptively. No double negatives. Reflect the return type.",
1327
+ " ",
1328
+ /* @__PURE__ */ jsx(Text, {
1329
+ dimColor: true,
1330
+ children: "For example "
1331
+ }),
1332
+ /* @__PURE__ */ jsx(Text, {
1333
+ bold: true,
1334
+ children: "show-new-checkout"
1335
+ }),
1336
+ /* @__PURE__ */ jsx(Text, {
1337
+ dimColor: true,
1338
+ children: "."
1339
+ })
1340
+ ] }),
1341
+ pause: 6500,
1342
+ persist: true
1343
+ },
1344
+ {
1345
+ type: "clear",
1346
+ pause: 1500
1347
+ },
1348
+ {
1349
+ content: /* @__PURE__ */ jsx(Text, {
1350
+ bold: true,
1351
+ color: Colors.accent,
1352
+ children: "Experiments"
1353
+ }),
1354
+ pause: 2500,
1355
+ persist: true
1356
+ },
1357
+ {
1358
+ content: "Change one thing per variant. Multiple changes in one variant blur the result.",
1359
+ pause: 5500
1360
+ },
1361
+ {
1362
+ content: "Decide the running time up front. PostHog includes a sample-size and duration calculator in the setup flow.",
1363
+ pause: 6500
1364
+ },
1365
+ {
1366
+ content: "Roll out to 5–10% first. Watch the metrics. Then increase.",
1367
+ pause: 5e3
1368
+ },
1369
+ {
1370
+ content: "Exclude users who already completed the flow. They can’t be affected by the test.",
1371
+ pause: 5500
1372
+ },
1373
+ {
1374
+ type: "clear",
1375
+ pause: 1500
1376
+ },
1377
+ {
1378
+ content: "Flags and experiments live alongside the rest of your data.",
1379
+ pause: 4500
1380
+ },
1381
+ {
1382
+ content: "Ship behind a flag, watch replays, check analytics for impact.",
1383
+ pause: 4500
1384
+ },
1385
+ {
1386
+ type: "clear",
1387
+ pause: 1500
1388
+ },
1389
+ {
1390
+ content: "PostHog also provides every other analytics and AI tool to build your product.",
1391
+ pause: 4500
1392
+ },
1393
+ PRODUCT_SUITE_BLOCK,
1394
+ {
1395
+ type: "clear",
1396
+ pause: 1500
1397
+ },
1398
+ {
1399
+ content: "And consolidating onto one platform saves real money.",
1400
+ pause: 4500
1401
+ },
1402
+ {
1403
+ content: "Here’s the math.",
1404
+ pause: 1500
1405
+ },
1406
+ VENDOR_STACK_BLOCK,
1407
+ {
1408
+ type: "clear",
1409
+ pause: 1500
1410
+ },
1411
+ {
1412
+ content: "Pricing is usage-based, with a generous free tier.",
1413
+ pause: 4e3
1414
+ },
1415
+ FREE_TIER_BLOCK,
1416
+ {
1417
+ type: "clear",
1418
+ pause: 1500
1419
+ },
1420
+ PRICING_STRUCTURE_BLOCK,
1421
+ {
1422
+ type: "clear",
1423
+ pause: 1500
1424
+ },
1425
+ {
1426
+ content: "Gain clarity and really understand your users.",
1427
+ pause: 4e3
1428
+ },
1429
+ {
1430
+ content: "Use trends to measure growth.",
1431
+ pause: 2500
1432
+ },
1433
+ LINE_CHART_BLOCK,
1434
+ {
1435
+ type: "clear",
1436
+ pause: 500
1437
+ },
1438
+ {
1439
+ content: "Use funnels to reveal bottlenecks.",
1440
+ pause: 2500
1441
+ },
1442
+ FUNNEL_BLOCK
1443
+ ];
1444
+ //#endregion
1445
+ //#region src/lib/programs/migration/index.ts
1446
+ const MIGRATION_REPORT_FILE = "migration-report.md";
1447
+ const MIGRATION_ABORT_CASES = [{
1448
+ match: /^no source-sdk calls found$/i,
1449
+ message: "No source-SDK calls found",
1450
+ body: "The migration needs an existing third-party SDK to migrate from. No calls to the source SDK appear anywhere in this project. If you haven't installed PostHog yet, you don't need this command — run `npx @posthog/wizard@latest` to add PostHog from scratch."
1451
+ }];
1452
+ /**
1453
+ * Map each `--product=<id>` choice to the context-mill skill ID that handles
1454
+ * it. Adding a variant: drop a new row here. The CLI `choices` and the
1455
+ * runtime lookup both read from this map, so the two stay in sync.
1456
+ */
1457
+ const PRODUCT_TO_SKILL_ID = { statsig: "migrate-statsig" };
1458
+ const MIGRATE_PRODUCTS = Object.keys(PRODUCT_TO_SKILL_ID);
1459
+ const migrationConfig = {
1460
+ command: "migrate",
1461
+ description: "Migrate to PostHog from another analytics provider",
1462
+ id: "migration",
1463
+ skillId: PRODUCT_TO_SKILL_ID.statsig,
1464
+ steps: MIGRATION_PROGRAM,
1465
+ reportFile: MIGRATION_REPORT_FILE,
1466
+ getContentBlocks,
1467
+ allowedTools: ["Agent"],
1468
+ disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
1469
+ cliOptions: { product: {
1470
+ describe: "Source SDK to migrate from",
1471
+ type: "string",
1472
+ choices: MIGRATE_PRODUCTS,
1473
+ demandOption: true
1474
+ } },
1475
+ mapCliOptions: (argv) => ({ skillId: PRODUCT_TO_SKILL_ID[argv.product] }),
1476
+ run: {
1477
+ skillId: PRODUCT_TO_SKILL_ID.statsig,
1478
+ integrationLabel: "migration",
1479
+ customPrompt: () => `Migrate this project from its existing third-party analytics, feature-flag, and observability tools to PostHog. Run the \`migrate\` skill end-to-end: follow the step chain starting at references/1-presence.md. Only replace existing source-SDK call sites with PostHog equivalents — make zero unrelated changes and no net-new instrumentation. The final report is written to ./${MIGRATION_REPORT_FILE}.`,
1480
+ successMessage: `Migration complete! View the report at ./${MIGRATION_REPORT_FILE}`,
1481
+ reportFile: MIGRATION_REPORT_FILE,
1482
+ docsUrl: "",
1483
+ spinnerMessage: "Migrating to PostHog...",
1484
+ estimatedDurationMinutes: 8,
1485
+ abortCases: MIGRATION_ABORT_CASES
1486
+ },
1487
+ requires: ["posthog-integration"]
1488
+ };
1489
+ //#endregion
1490
+ //#region src/lib/programs/mcp/index.ts
1491
+ const mcpAddConfig = {
1492
+ id: "mcp-add",
1493
+ description: "Add PostHog MCP server to supported clients",
1494
+ steps: [{
1495
+ id: "mcp-add",
1496
+ label: "Add MCP server",
1497
+ screenId: "mcp-add",
1498
+ isComplete: (s) => s.mcpComplete
1499
+ }]
1500
+ };
1501
+ const mcpRemoveConfig = {
1502
+ id: "mcp-remove",
1503
+ description: "Remove PostHog MCP server from supported clients",
1504
+ steps: [{
1505
+ id: "mcp-remove",
1506
+ label: "Remove MCP server",
1507
+ screenId: "mcp-remove",
1508
+ isComplete: (s) => s.mcpComplete
1509
+ }]
1510
+ };
1511
+ //#endregion
1512
+ //#region src/lib/programs/program-registry.ts
1513
+ const agentSkillConfig = {
1514
+ id: "agent-skill",
1515
+ description: "Run an arbitrary context-mill skill",
1516
+ steps: AGENT_SKILL_STEPS,
1517
+ getContentBlocks: getContentBlocks$1,
1518
+ allowedTools: ["Agent"]
1519
+ };
1520
+ const PROGRAM_REGISTRY = [
751
1521
  posthogIntegrationConfig,
752
1522
  revenueAnalyticsConfig,
753
1523
  auditConfig,
1524
+ eventsAuditConfig,
754
1525
  audit3000Config,
755
- {
756
- command: "doctor",
757
- description: "Diagnose your PostHog project for configuration issues and setup warnings",
758
- flowKey: "posthog-doctor",
759
- steps: POSTHOG_DOCTOR_WORKFLOW
760
- }
1526
+ posthogDoctorConfig,
1527
+ migrationConfig,
1528
+ agentSkillConfig,
1529
+ mcpAddConfig,
1530
+ mcpRemoveConfig
761
1531
  ];
762
- /** Look up a workflow config by its flowKey. */
763
- function getWorkflowConfig(flowKey) {
764
- return WORKFLOW_REGISTRY.find((c) => c.flowKey === flowKey);
1532
+ /**
1533
+ * Typed program names. Values come from each config's `id`, so there's
1534
+ * no parallel string list to keep in sync — adding `Program.Foo` here is
1535
+ * just exposing `fooConfig.id` under a friendly name for call sites.
1536
+ */
1537
+ const Program = {
1538
+ PostHogIntegration: posthogIntegrationConfig.id,
1539
+ RevenueAnalyticsSetup: revenueAnalyticsConfig.id,
1540
+ Migration: migrationConfig.id,
1541
+ Audit: auditConfig.id,
1542
+ EventsAudit: eventsAuditConfig.id,
1543
+ Audit3000: audit3000Config.id,
1544
+ PosthogDoctor: posthogDoctorConfig.id,
1545
+ AgentSkill: agentSkillConfig.id,
1546
+ McpAdd: mcpAddConfig.id,
1547
+ McpRemove: mcpRemoveConfig.id
1548
+ };
1549
+ /**
1550
+ * Look up a program config by its id. `ProgramId` is a union of every
1551
+ * registered id, so the lookup is statically guaranteed to find a match
1552
+ * — the `!` is a load-bearing assertion of that invariant, not a hope.
1553
+ */
1554
+ function getProgramConfig(id) {
1555
+ return PROGRAM_REGISTRY.find((c) => c.id === id);
765
1556
  }
766
- /** All workflow configs that are exposed as CLI subcommands. */
767
- function getSubcommandWorkflows() {
768
- return WORKFLOW_REGISTRY.filter((c) => c.command != null);
1557
+ /** All program configs that are exposed as CLI subcommands. */
1558
+ function getSubcommandPrograms() {
1559
+ return PROGRAM_REGISTRY.filter((c) => c.command != null);
769
1560
  }
770
1561
  //#endregion
771
1562
  //#region bin.ts
772
1563
  const WIZARD_VERSION = VERSION;
773
1564
  const NODE_VERSION_RANGE = ">=18.17.0";
774
1565
  if (!satisfies(process.version, NODE_VERSION_RANGE)) {
775
- red(`PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`);
1566
+ console.log(`PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`);
776
1567
  process.exit(1);
777
1568
  }
778
- /** Shared yargs options for skill-based workflow subcommands. */
1569
+ /** Shared yargs options for skill-based program subcommands. */
779
1570
  const skillSubcommandOptions = {
780
1571
  debug: {
781
1572
  default: false,
@@ -925,12 +1716,24 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
925
1716
  process.exit(1);
926
1717
  return;
927
1718
  }
1719
+ if (options.apiKey) {
1720
+ const apiKeyValue = String(options.apiKey);
1721
+ if (!apiKeyValue.startsWith("phx_")) {
1722
+ setUI(new LoggingUI());
1723
+ getUI().intro("PostHog Wizard");
1724
+ const prefix = apiKeyValue.slice(0, 4);
1725
+ let hint = "";
1726
+ if (prefix === "pha_") hint = " (pha_ is an OAuth access token — CI mode expects a personal API key)";
1727
+ else if (prefix === "phc_") hint = " (phc_ is a project/client key — CI mode expects a personal API key)";
1728
+ getUI().log.warn(`--api-key does not start with "phx_"${hint}. Continuing anyway, but the LLM Gateway may reject it with a 401.`);
1729
+ }
1730
+ }
928
1731
  (async () => {
929
1732
  if (!options.apiKey && options.signup) {
930
1733
  setUI(new LoggingUI());
931
1734
  getUI().intro("PostHog Wizard");
932
1735
  try {
933
- const { provisionNewAccount } = await import("./provisioning-BdQ1ONIg.js");
1736
+ const { provisionNewAccount } = await import("./provisioning-ByWo5KcQ.js");
934
1737
  const signupRegion = options.region.toUpperCase();
935
1738
  getUI().log.info(`Provisioning new PostHog account for ${String(options.email)} in ${signupRegion}...`);
936
1739
  const result = await provisionNewAccount(options.email, options.name ?? "", signupRegion);
@@ -952,11 +1755,11 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
952
1755
  return;
953
1756
  }
954
1757
  }
955
- const { posthogIntegrationConfig } = await import("./posthog-integration-BL21S3T6.js").then((n) => n.r);
956
- const { FRAMEWORK_REGISTRY } = await import("./registry-BaMEaAKd.js").then((n) => n.n);
957
- const { detectFramework, gatherFrameworkContext } = await import("./detection-CSjmal-X.js").then((n) => n.t);
958
- const { analytics } = await import("./analytics-BH7bEHQR.js");
959
- const { wizardAbort } = await import("./wizard-abort-Dl0BkqhT.js");
1758
+ const { posthogIntegrationConfig } = await import("./posthog-integration-C-FFV5ny.js").then((n) => n.r);
1759
+ const { FRAMEWORK_REGISTRY } = await import("./registry-B92uyoWK.js").then((n) => n.n);
1760
+ const { detectFramework, gatherFrameworkContext } = await import("./detection-D651Eb5k.js").then((n) => n.t);
1761
+ const { analytics } = await import("./analytics-tslsXyf9.js");
1762
+ const { wizardAbort } = await import("./wizard-abort-BTBccRto.js");
960
1763
  runWizardCI(posthogIntegrationConfig, options, async (session) => {
961
1764
  const integration = session.integration ?? await detectFramework(session.installDir);
962
1765
  if (!integration) {
@@ -989,16 +1792,16 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
989
1792
  getUI().log.error("This installer requires an interactive terminal (TTY) to run.\nIt appears you are running in a non-interactive environment.\nPlease run the wizard in an interactive terminal.\n\nFor CI/CD environments, use --ci mode:\n npx @posthog/wizard --ci --region us --api-key phx_xxx");
990
1793
  process.exit(1);
991
1794
  } else if (options.playground) (async () => {
992
- const { startPlayground } = await import("./start-playground-C9GWnVdM.js");
1795
+ const { startPlayground } = await import("./start-playground-BhwBUq-a.js");
993
1796
  startPlayground(WIZARD_VERSION);
994
1797
  })();
995
1798
  else if (options.skill) (async () => {
996
- const { createSkillWorkflow } = await Promise.resolve().then(() => agent_skill_exports);
1799
+ const { createSkillProgram } = await Promise.resolve().then(() => agent_skill_exports);
997
1800
  const skillId = options.skill;
998
- runWizard(createSkillWorkflow({
1801
+ runWizard(createSkillProgram({
999
1802
  skillId,
1000
1803
  command: "skill",
1001
- flowKey: "agent-skill",
1804
+ id: "agent-skill",
1002
1805
  description: `Run skill: ${skillId}`,
1003
1806
  integrationLabel: skillId,
1004
1807
  successMessage: `${skillId} completed!`,
@@ -1012,7 +1815,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1012
1815
  });
1013
1816
  })();
1014
1817
  else (async () => {
1015
- const { posthogIntegrationConfig } = await import("./posthog-integration-BL21S3T6.js").then((n) => n.r);
1818
+ const { posthogIntegrationConfig } = await import("./posthog-integration-C-FFV5ny.js").then((n) => n.r);
1016
1819
  runWizard(posthogIntegrationConfig, options);
1017
1820
  })();
1018
1821
  }).command("mcp <command>", "MCP server management commands", (yargs) => {
@@ -1039,10 +1842,9 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1039
1842
  const { readApiKeyFromEnv } = await import("./env-api-key-D5G2PrXW.js");
1040
1843
  const apiKey = options.apiKey || readApiKeyFromEnv();
1041
1844
  try {
1042
- const { startTUI } = await import("./start-tui-B_zwutLe.js");
1043
- const { buildSession } = await import("./wizard-session-BQC9vy9Z.js");
1044
- const { Flow } = await import("./router-COhhuIW3.js").then((n) => n.n);
1045
- const tui = startTUI(WIZARD_VERSION, Flow.McpAdd);
1845
+ const { startTUI } = await import("./start-tui-BwQa3kmG.js");
1846
+ const { buildSession } = await import("./wizard-session-CPhhll4P.js");
1847
+ const tui = startTUI(WIZARD_VERSION, Program.McpAdd);
1046
1848
  const session = buildSession({
1047
1849
  debug: options.debug,
1048
1850
  localMcp: options.local,
@@ -1052,7 +1854,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1052
1854
  tui.store.session = session;
1053
1855
  } catch {
1054
1856
  setUI(new LoggingUI());
1055
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-CUNR00bB.js").then((n) => n.r);
1857
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-BTW9Ey5Z.js").then((n) => n.r);
1056
1858
  await addMCPServerToClientsStep({
1057
1859
  local: options.local,
1058
1860
  features: mcpFeatures,
@@ -1070,10 +1872,9 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1070
1872
  const options = { ...argv };
1071
1873
  (async () => {
1072
1874
  try {
1073
- const { startTUI } = await import("./start-tui-B_zwutLe.js");
1074
- const { buildSession } = await import("./wizard-session-BQC9vy9Z.js");
1075
- const { Flow } = await import("./router-COhhuIW3.js").then((n) => n.n);
1076
- const tui = startTUI(WIZARD_VERSION, Flow.McpRemove);
1875
+ const { startTUI } = await import("./start-tui-BwQa3kmG.js");
1876
+ const { buildSession } = await import("./wizard-session-CPhhll4P.js");
1877
+ const tui = startTUI(WIZARD_VERSION, Program.McpRemove);
1077
1878
  const session = buildSession({
1078
1879
  debug: options.debug,
1079
1880
  localMcp: options.local
@@ -1081,7 +1882,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1081
1882
  tui.store.session = session;
1082
1883
  } catch {
1083
1884
  setUI(new LoggingUI());
1084
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-CUNR00bB.js").then((n) => n.r);
1885
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-BTW9Ey5Z.js").then((n) => n.r);
1085
1886
  await removeMCPServerFromClientsStep({ local: options.local });
1086
1887
  }
1087
1888
  })();
@@ -1117,7 +1918,7 @@ cli.command("provision", "Create a new PostHog account (headless, no TUI)", (yar
1117
1918
  if (!jsonMode) setUI(new LoggingUI());
1118
1919
  (async () => {
1119
1920
  try {
1120
- const { provisionNewAccount } = await import("./provisioning-BdQ1ONIg.js");
1921
+ const { provisionNewAccount } = await import("./provisioning-ByWo5KcQ.js");
1121
1922
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
1122
1923
  const result = await provisionNewAccount(email, name, region);
1123
1924
  if (jsonMode) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -1144,14 +1945,21 @@ cli.command("provision", "Create a new PostHog account (headless, no TUI)", (yar
1144
1945
  }
1145
1946
  })();
1146
1947
  });
1147
- for (const wfConfig of getSubcommandWorkflows()) cli.command(wfConfig.command, wfConfig.description, (y) => y.options(skillSubcommandOptions), (argv) => {
1148
- const options = { ...argv };
1149
- if (options.ci) runWizardCI(wfConfig, options);
1150
- else runWizard(wfConfig, options);
1948
+ for (const programConfig of getSubcommandPrograms()) cli.command(programConfig.command, programConfig.description, (y) => y.options({
1949
+ ...skillSubcommandOptions,
1950
+ ...programConfig.cliOptions ?? {}
1951
+ }), (argv) => {
1952
+ const extras = programConfig.mapCliOptions?.(argv) ?? {};
1953
+ const options = {
1954
+ ...argv,
1955
+ ...extras
1956
+ };
1957
+ if (options.ci) runWizardCI(programConfig, options);
1958
+ else runWizard(programConfig, options);
1151
1959
  });
1152
1960
  cli.help().alias("help", "h").version().alias("version", "v").wrap(process.stdout.isTTY ? cli.terminalWidth() : 80).argv;
1153
1961
  /**
1154
- * Run a full wizard workflow in the TUI. Handles the full lifecycle: start TUI,
1962
+ * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,
1155
1963
  * build session, run detection, wait for intro gate, execute the
1156
1964
  * agent pipeline, wait for outro dismissal, then exit.
1157
1965
  */
@@ -1159,13 +1967,13 @@ function runWizard(config, options) {
1159
1967
  (async () => {
1160
1968
  try {
1161
1969
  const installDir = options.installDir || process.cwd();
1162
- const { startTUI } = await import("./start-tui-B_zwutLe.js");
1163
- const { buildSession } = await import("./wizard-session-BQC9vy9Z.js");
1164
- const { TaskStreamPush } = await import("./task-stream-CX7Uf6EM.js");
1165
- const { FileDestination } = await import("./file-8iNrXHkG.js");
1166
- const { PostHogDestination } = await import("./posthog-vm0k9PKS.js");
1167
- const { analytics } = await import("./analytics-BH7bEHQR.js");
1168
- const tui = startTUI(WIZARD_VERSION, config.flowKey);
1970
+ const { startTUI } = await import("./start-tui-BwQa3kmG.js");
1971
+ const { buildSession } = await import("./wizard-session-CPhhll4P.js");
1972
+ const { TaskStreamPush } = await import("./task-stream-DUpUZmFQ.js");
1973
+ const { FileDestination } = await import("./file-BKbKreWF.js");
1974
+ const { PostHogDestination } = await import("./posthog-BbQf_Hzq.js");
1975
+ const { analytics } = await import("./analytics-tslsXyf9.js");
1976
+ const tui = startTUI(WIZARD_VERSION, config.id);
1169
1977
  const session = buildSession({
1170
1978
  debug: options.debug,
1171
1979
  forceInstall: options.forceInstall,
@@ -1181,12 +1989,13 @@ function runWizard(config, options) {
1181
1989
  benchmark: options.benchmark,
1182
1990
  yaraReport: options.yaraReport
1183
1991
  });
1184
- session.workflowLabel = config.flowKey;
1992
+ session.programLabel = config.id;
1185
1993
  if (options.skillId) session.skillId = options.skillId;
1994
+ else if (config.skillId) session.skillId = config.skillId;
1186
1995
  tui.store.session = session;
1187
1996
  const taskStream = new TaskStreamPush({
1188
1997
  store: tui.store,
1189
- workflowId: config.flowKey,
1998
+ programId: config.id,
1190
1999
  destinations: [new FileDestination(), new PostHogDestination()]
1191
2000
  });
1192
2001
  tui.store.onTasksChanged = () => void taskStream.push();
@@ -1195,7 +2004,7 @@ function runWizard(config, options) {
1195
2004
  await tui.store.getGate("health-check");
1196
2005
  const skipAgent = config.run == null;
1197
2006
  if (skipAgent) {
1198
- const { getOrAskForProjectData } = await import("./setup-utils-CU4FIqjB.js");
2007
+ const { getOrAskForProjectData } = await import("./setup-utils-D5aNKrba.js");
1199
2008
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
1200
2009
  signup: session.signup,
1201
2010
  ci: session.ci,
@@ -1209,7 +2018,7 @@ function runWizard(config, options) {
1209
2018
  projectId
1210
2019
  });
1211
2020
  } else {
1212
- const { runAgent } = await import("./agent-runner-LvVQH31D.js");
2021
+ const { runAgent } = await import("./agent-runner-Bxi71jnp.js");
1213
2022
  await runAgent(config, tui.store.session);
1214
2023
  }
1215
2024
  const isDone = () => skipAgent ? tui.store.session.outroDismissed : tui.store.session.skillsComplete;
@@ -1241,7 +2050,7 @@ function runWizard(config, options) {
1241
2050
  * CI-mode pipeline shared by every non-interactive entry point.
1242
2051
  *
1243
2052
  * Validates flags, builds a `ci:true` session, runs `preRun` (or the
1244
- * workflow's `onReady` hooks by default), executes `runAgent`, and
2053
+ * program's `onReady` hooks by default), executes `runAgent`, and
1245
2054
  * routes any failure through `wizardAbort`. `wizardAbort` owns all
1246
2055
  * exits — never add a raw `process.exit` here.
1247
2056
  */
@@ -1260,11 +2069,11 @@ function runWizardCI(config, options, preRun) {
1260
2069
  }
1261
2070
  (async () => {
1262
2071
  const path = await import("path");
1263
- const { buildSession } = await import("./wizard-session-BQC9vy9Z.js");
2072
+ const { buildSession } = await import("./wizard-session-CPhhll4P.js");
1264
2073
  const { readEnvironment } = await Promise.resolve().then(() => environment_exports);
1265
2074
  const { readApiKeyFromEnv } = await import("./env-api-key-D5G2PrXW.js");
1266
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-BdcTB7EF.js");
1267
- const { wizardAbort, WizardError } = await import("./wizard-abort-Dl0BkqhT.js");
2075
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-Du7qXlug.js");
2076
+ const { wizardAbort, WizardError } = await import("./wizard-abort-BTBccRto.js");
1268
2077
  configureLogFileFromEnvironment();
1269
2078
  const env = readEnvironment();
1270
2079
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -1285,10 +2094,11 @@ function runWizardCI(config, options, preRun) {
1285
2094
  yaraReport: options.yaraReport,
1286
2095
  ...env
1287
2096
  });
1288
- session.workflowLabel = config.flowKey;
2097
+ session.programLabel = config.id;
2098
+ if (config.skillId) session.skillId = config.skillId;
1289
2099
  const runDef = typeof config.run === "object" ? config.run : null;
1290
2100
  getUI().intro("Welcome to the PostHog setup wizard");
1291
- getUI().log.info(`Running ${config.flowKey} in CI mode`);
2101
+ getUI().log.info(`Running ${config.id} in CI mode`);
1292
2102
  try {
1293
2103
  if (preRun) await preRun(session);
1294
2104
  else {
@@ -1307,13 +2117,13 @@ function runWizardCI(config, options, preRun) {
1307
2117
  const detectError = session.frameworkContext.detectError;
1308
2118
  if (detectError) await wizardAbort({
1309
2119
  message: `Prerequisites not met: ${detectError.kind}\n\nSee ${runDef?.docsUrl ?? "https://posthog.com/docs"}`,
1310
- error: new WizardError(`${config.flowKey} prerequisites failed`, {
1311
- integration: config.flowKey,
2120
+ error: new WizardError(`${config.id} prerequisites failed`, {
2121
+ integration: config.id,
1312
2122
  detect_error_kind: detectError.kind
1313
2123
  })
1314
2124
  });
1315
2125
  }
1316
- const { runAgent } = await import("./agent-runner-LvVQH31D.js");
2126
+ const { runAgent } = await import("./agent-runner-Bxi71jnp.js");
1317
2127
  await runAgent(config, session);
1318
2128
  } catch (error) {
1319
2129
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1331,6 +2141,6 @@ function runWizardCI(config, options, preRun) {
1331
2141
  });
1332
2142
  }
1333
2143
  //#endregion
1334
- export { AGENT_SKILL_STEPS as a, fetchHealthIssues as i, getWorkflowConfig as n, POSTHOG_SDKS as o, getKindMeta as r, STRIPE_SDKS as s, WORKFLOW_REGISTRY as t };
2144
+ export { getKindMeta as a, POSTHOG_SDKS as c, getContentBlocks as i, STRIPE_SDKS as l, Program as n, fetchHealthIssues as o, getProgramConfig as r, getContentBlocks$1 as s, PROGRAM_REGISTRY as t };
1335
2145
 
1336
2146
  //# sourceMappingURL=bin.js.map