@posthog/wizard 2.35.0 → 2.37.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 (76) hide show
  1. package/README.md +6 -3
  2. package/dist/{add-mcp-server-to-clients-to65gLPl.js → add-mcp-server-to-clients-CNn9br9l.js} +6 -6
  3. package/dist/{add-mcp-server-to-clients-to65gLPl.js.map → add-mcp-server-to-clients-CNn9br9l.js.map} +1 -1
  4. package/dist/{agent-interface-CXL9i_vX.js → agent-interface-D8jnkEnB.js} +237 -174
  5. package/dist/agent-interface-D8jnkEnB.js.map +1 -0
  6. package/dist/{agent-runner-CCTTG_Rn.js → agent-runner-BxIYcxmA.js} +56 -102
  7. package/dist/agent-runner-BxIYcxmA.js.map +1 -0
  8. package/dist/{analytics-DP_j88IC.js → analytics-Du8Z_3oX.js} +2 -2
  9. package/dist/{analytics-DP_j88IC.js.map → analytics-Du8Z_3oX.js.map} +1 -1
  10. package/dist/{api-Bdxv7mWH.js → api-BqKMQVhj.js} +3 -3
  11. package/dist/{api-Bdxv7mWH.js.map → api-BqKMQVhj.js.map} +1 -1
  12. package/dist/bin.js +285 -59
  13. package/dist/bin.js.map +1 -1
  14. package/dist/{ci-install-BO-KLPLD.js → ci-install-UlWb3u5t.js} +4 -4
  15. package/dist/{ci-install-BO-KLPLD.js.map → ci-install-UlWb3u5t.js.map} +1 -1
  16. package/dist/{debug-Clw8ctxh.js → debug-B4AH8Ahp.js} +1 -1
  17. package/dist/{debug-DXWxKT5f.js → debug-CZwmzyDx.js} +2 -2
  18. package/dist/{debug-DXWxKT5f.js.map → debug-CZwmzyDx.js.map} +1 -1
  19. package/dist/{defaults-4rSse24X.js → defaults-UswXMiTx.js} +1 -1
  20. package/dist/{defaults-4rSse24X.js.map → defaults-UswXMiTx.js.map} +1 -1
  21. package/dist/{env-api-key-B3gE9Un0.js → env-api-key-Db-mNPK2.js} +1 -1
  22. package/dist/{env-api-key-B3gE9Un0.js.map → env-api-key-Db-mNPK2.js.map} +1 -1
  23. package/dist/{environment-C4HyCWTC.js → environment-BRXwshJO.js} +3 -3
  24. package/dist/{environment-C4HyCWTC.js.map → environment-BRXwshJO.js.map} +1 -1
  25. package/dist/{file-utils-CW8XbbZP.js → file-utils-D6CWLaOm.js} +2 -2
  26. package/dist/{file-utils-CW8XbbZP.js.map → file-utils-D6CWLaOm.js.map} +1 -1
  27. package/dist/{headless-ui-BoZYhNpE.js → headless-ui-DvkogF0b.js} +2 -2
  28. package/dist/{headless-ui-BoZYhNpE.js.map → headless-ui-DvkogF0b.js.map} +1 -1
  29. package/dist/{host-resolution-Dw0fS8h5.js → host-resolution-DrOzdKdY.js} +3 -3
  30. package/dist/{host-resolution-Dw0fS8h5.js.map → host-resolution-DrOzdKdY.js.map} +1 -1
  31. package/dist/{interactive-pwrc7QM-.js → interactive-CXL8oJwb.js} +2 -2
  32. package/dist/{interactive-pwrc7QM-.js.map → interactive-CXL8oJwb.js.map} +1 -1
  33. package/dist/{mcp-prompt-streaming-DZjjoeu3.js → mcp-prompt-streaming-Dumivcgi.js} +4 -4
  34. package/dist/{mcp-prompt-streaming-DZjjoeu3.js.map → mcp-prompt-streaming-Dumivcgi.js.map} +1 -1
  35. package/dist/{non-interactive-BW-MZYrP.js → non-interactive-BI5b25U7.js} +2 -2
  36. package/dist/{non-interactive-BW-MZYrP.js.map → non-interactive-BI5b25U7.js.map} +1 -1
  37. package/dist/{package-manager-BgXgJ1Mu.js → package-manager-9nhQBKAy.js} +2 -2
  38. package/dist/{package-manager-BgXgJ1Mu.js.map → package-manager-9nhQBKAy.js.map} +1 -1
  39. package/dist/{playground-xuLBqzJM.js → playground-DDYYs2ub.js} +7 -7
  40. package/dist/{playground-xuLBqzJM.js.map → playground-DDYYs2ub.js.map} +1 -1
  41. package/dist/{posthog-integration-Bj9WmwDq.js → posthog-integration-Cx4RvC7E.js} +29 -14
  42. package/dist/posthog-integration-Cx4RvC7E.js.map +1 -0
  43. package/dist/{provisioning-BF2reo5_.js → provisioning-PosLaOt4.js} +4 -4
  44. package/dist/{provisioning-BF2reo5_.js.map → provisioning-PosLaOt4.js.map} +1 -1
  45. package/dist/{registry-Dj17F0a-.js → registry-B43CNAAx.js} +4 -4
  46. package/dist/{registry-Dj17F0a-.js.map → registry-B43CNAAx.js.map} +1 -1
  47. package/dist/{setup-utils-DyTlaGOV.js → setup-utils-CR8X8Fmf.js} +19 -11
  48. package/dist/setup-utils-CR8X8Fmf.js.map +1 -0
  49. package/dist/{start-tui-S4fBBfmO.js → start-tui-DeewAqJg.js} +374 -24
  50. package/dist/start-tui-DeewAqJg.js.map +1 -0
  51. package/dist/{steps-CHgikk6q.js → steps-CPvI-2Ms.js} +7 -7
  52. package/dist/{steps-CHgikk6q.js.map → steps-CPvI-2Ms.js.map} +1 -1
  53. package/dist/{store-vr5j37CU.js → store-0uzey9Am.js} +55 -4
  54. package/dist/store-0uzey9Am.js.map +1 -0
  55. package/dist/{task-stream-BVF6gi8x.js → task-stream-DkbGqxZv.js} +2 -2
  56. package/dist/{task-stream-BVF6gi8x.js.map → task-stream-DkbGqxZv.js.map} +1 -1
  57. package/dist/{telemetry-CR-ilpWe.js → telemetry-DJNpvkYP.js} +3 -3
  58. package/dist/{telemetry-CR-ilpWe.js.map → telemetry-DJNpvkYP.js.map} +1 -1
  59. package/dist/{terminal-uzjco-wz.js → terminal-Bd6q58zn.js} +13 -13
  60. package/dist/{terminal-uzjco-wz.js.map → terminal-Bd6q58zn.js.map} +1 -1
  61. package/dist/{urls-ChWit8SE.js → urls-B1a2v93j.js} +2 -2
  62. package/dist/{urls-ChWit8SE.js.map → urls-B1a2v93j.js.map} +1 -1
  63. package/dist/{wizard-abort-BE_j8xUt.js → wizard-abort-BG8VNOI9.js} +4 -4
  64. package/dist/{wizard-abort-BE_j8xUt.js.map → wizard-abort-BG8VNOI9.js.map} +1 -1
  65. package/dist/{wizard-abort-CNYxdjJl.js → wizard-abort-DyAGpw-u.js} +1 -1
  66. package/dist/{wizard-session-BHoLQueN.js → wizard-session-CqihOtk3.js} +6 -1
  67. package/dist/wizard-session-CqihOtk3.js.map +1 -0
  68. package/dist/{wizard-session-D0PJ9lsl.js → wizard-session-xzqycI7i.js} +1 -1
  69. package/package.json +1 -1
  70. package/dist/agent-interface-CXL9i_vX.js.map +0 -1
  71. package/dist/agent-runner-CCTTG_Rn.js.map +0 -1
  72. package/dist/posthog-integration-Bj9WmwDq.js.map +0 -1
  73. package/dist/setup-utils-DyTlaGOV.js.map +0 -1
  74. package/dist/start-tui-S4fBBfmO.js.map +0 -1
  75. package/dist/store-vr5j37CU.js.map +0 -1
  76. package/dist/wizard-session-BHoLQueN.js.map +0 -1
package/dist/bin.js CHANGED
@@ -1,24 +1,25 @@
1
1
  #!/usr/bin/env node
2
- import { $ as getSkillsBaseUrl, I as POSTHOG_DOCS_URL, Z as WIZARD_USER_AGENT, a as getLogFilePath, et as VERSION, h as LoggingUI, m as setUI, p as getUI, r as debug, s as logToFile } from "./debug-DXWxKT5f.js";
3
- import { t as analytics } from "./analytics-DP_j88IC.js";
4
- import { r as setEntryCommand } from "./telemetry-CR-ilpWe.js";
5
- import { n as isUsingTypeScript } from "./setup-utils-DyTlaGOV.js";
6
- import { o as getUiHostFromHost } from "./urls-ChWit8SE.js";
7
- import { t as HostResolution } from "./host-resolution-Dw0fS8h5.js";
8
- import { o as handleApiError } from "./api-Bdxv7mWH.js";
9
- import "./wizard-session-BHoLQueN.js";
10
- import { r as runCleanups } from "./wizard-abort-BE_j8xUt.js";
11
- import { n as isNonInteractiveEnvironment } from "./environment-C4HyCWTC.js";
12
- import { D as AUDIT_CHECKS_KEY, E as AUDIT_CHECKS_FILE, O as AUDIT_REPORT_FILE, f as AgentSignals, l as recoverOrphanedSettingsBackups, v as SETUP_REPORT_FILE, x as fetchSkillMenu, y as WIZARD_TOOL_NAMES } from "./agent-interface-CXL9i_vX.js";
13
- import { i as SPINNER_MESSAGE } from "./registry-Dj17F0a-.js";
14
- import { _ as parseRequirementsTxt, a as StatusPeekTrigger, c as isClearBlock, d as Colors, f as Icons, g as parsePyprojectToml, h as parsePipfile, i as PRODUCT_SUITE_BLOCK, n as FUNNEL_BLOCK, p as HEALTH_CHECK_STEP, r as LINE_CHART_BLOCK, t as posthogIntegrationConfig } from "./posthog-integration-Bj9WmwDq.js";
15
- import { n as safeReadFile, r as walkProjectFiles, t as IGNORED_DIRS } from "./file-utils-CW8XbbZP.js";
16
- import { n as readApiKeyFromEnv } from "./env-api-key-B3gE9Un0.js";
2
+ import { $ as getSkillsBaseUrl, I as POSTHOG_DOCS_URL, Z as WIZARD_USER_AGENT, a as getLogFilePath, et as VERSION, h as LoggingUI, j as Integration, m as setUI, p as getUI, r as debug, s as logToFile } from "./debug-CZwmzyDx.js";
3
+ import { t as analytics } from "./analytics-Du8Z_3oX.js";
4
+ import { r as setEntryCommand } from "./telemetry-DJNpvkYP.js";
5
+ import { n as isUsingTypeScript } from "./setup-utils-CR8X8Fmf.js";
6
+ import { o as getUiHostFromHost } from "./urls-B1a2v93j.js";
7
+ import { t as HostResolution } from "./host-resolution-DrOzdKdY.js";
8
+ import { o as handleApiError } from "./api-BqKMQVhj.js";
9
+ import "./wizard-session-CqihOtk3.js";
10
+ import { r as runCleanups } from "./wizard-abort-BG8VNOI9.js";
11
+ import { n as isNonInteractiveEnvironment } from "./environment-BRXwshJO.js";
12
+ import { D as AUDIT_CHECKS_FILE, O as AUDIT_CHECKS_KEY, f as AgentSignals, k as AUDIT_REPORT_FILE, l as recoverOrphanedSettingsBackups, v as SETUP_REPORT_FILE, x as fetchSkillMenu, y as WIZARD_TOOL_NAMES } from "./agent-interface-D8jnkEnB.js";
13
+ import { n as runAgent, r as authenticate } from "./agent-runner-BxIYcxmA.js";
14
+ import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-B43CNAAx.js";
15
+ import { _ as gatherFrameworkContext, a as LINE_CHART_BLOCK, b as parseRequirementsTxt, g as detectProjectsWithAgent, h as HEALTH_CHECK_STEP, i as FUNNEL_BLOCK, m as Icons, n as integrationRunStep, o as PRODUCT_SUITE_BLOCK, p as Colors, r as posthogIntegrationConfig, s as StatusPeekTrigger, u as isClearBlock, v as parsePipfile, y as parsePyprojectToml } from "./posthog-integration-Cx4RvC7E.js";
16
+ import { n as safeReadFile, r as walkProjectFiles, t as IGNORED_DIRS } from "./file-utils-D6CWLaOm.js";
17
+ import { n as readApiKeyFromEnv } from "./env-api-key-Db-mNPK2.js";
17
18
  import { satisfies } from "semver";
18
19
  import yargs from "yargs";
19
20
  import { hideBin } from "yargs/helpers";
20
21
  import fs, { existsSync, readFileSync, readdirSync, statSync } from "fs";
21
- import path, { join, relative } from "path";
22
+ import path, { join, relative, resolve } from "path";
22
23
  import * as os from "node:os";
23
24
  import * as path$1 from "node:path";
24
25
  import { spawnSync } from "node:child_process";
@@ -234,7 +235,7 @@ function runProvision(argv) {
234
235
  }
235
236
  async function provision({ email, region, name, baseUrl, jsonMode }) {
236
237
  try {
237
- const { provisionNewAccount } = await import("./provisioning-BF2reo5_.js").then((n) => n.n);
238
+ const { provisionNewAccount } = await import("./provisioning-PosLaOt4.js").then((n) => n.n);
238
239
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
239
240
  emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode);
240
241
  process.exit(0);
@@ -299,22 +300,22 @@ const basicIntegrationCommand = {
299
300
  setEntryCommand("integrate");
300
301
  (async () => {
301
302
  if (isHeadless(argv)) {
302
- const { runHeadlessInstall } = await import("./ci-install-BO-KLPLD.js");
303
+ const { runHeadlessInstall } = await import("./ci-install-UlWb3u5t.js");
303
304
  return runHeadlessInstall(argv);
304
305
  }
305
306
  if (argv.ci) {
306
- const { runCIInstall } = await import("./ci-install-BO-KLPLD.js");
307
+ const { runCIInstall } = await import("./ci-install-UlWb3u5t.js");
307
308
  return runCIInstall(argv);
308
309
  }
309
310
  if (isNonInteractiveEnvironment()) {
310
- const { failNonInteractive } = await import("./non-interactive-BW-MZYrP.js");
311
+ const { failNonInteractive } = await import("./non-interactive-BI5b25U7.js");
311
312
  return failNonInteractive();
312
313
  }
313
314
  if (argv.playground) {
314
- const { runPlayground } = await import("./playground-xuLBqzJM.js");
315
+ const { runPlayground } = await import("./playground-DDYYs2ub.js");
315
316
  return runPlayground();
316
317
  }
317
- const { runInteractive } = await import("./interactive-pwrc7QM-.js");
318
+ const { runInteractive } = await import("./interactive-CXL8oJwb.js");
318
319
  runInteractive(argv);
319
320
  })();
320
321
  }
@@ -3277,6 +3278,48 @@ const errorTrackingUploadSourceMapsConfig = {
3277
3278
  * PostHog-side flags (`product-autonomy`, `signals-scout`) are unchanged by
3278
3279
  * the wizard-side "self-driving" rename.
3279
3280
  */
3281
+ /** frameworkContext key holding the deterministic PostHog-presence result. */
3282
+ const POSTHOG_PRESENT_KEY = "postHogPresent";
3283
+ /**
3284
+ * frameworkContext key holding the repo-relative path of the project the user
3285
+ * picked on the integration-detect screen ("." for the repo root). The
3286
+ * integrate-run phase scopes its install dir to this so a monorepo integrates
3287
+ * into the chosen sub-app, not the root.
3288
+ */
3289
+ const SELF_DRIVING_INTEGRATE_PATH_KEY = "selfDrivingIntegratePath";
3290
+ const POSTHOG_PACKAGE_RE = /(^|["'\s/=])posthog/im;
3291
+ /**
3292
+ * Deterministic, offline check: does the project already have a PostHog SDK?
3293
+ * Scans the common dependency manifests at the install dir for a `posthog`
3294
+ * package — the same signal the agentic detector reports as `hasPostHog`, but
3295
+ * instant and credential-free. Drives whether self-driving asks to integrate
3296
+ * first ("not found") or proceeds straight to setup ("found").
3297
+ */
3298
+ function detectPostHogPresent(installDir) {
3299
+ const manifests = [
3300
+ "package.json",
3301
+ "requirements.txt",
3302
+ "pyproject.toml",
3303
+ "Pipfile",
3304
+ "Gemfile",
3305
+ "go.mod",
3306
+ "composer.json",
3307
+ "pubspec.yaml"
3308
+ ];
3309
+ for (const dir of [
3310
+ ".",
3311
+ "app",
3312
+ "frontend",
3313
+ "backend"
3314
+ ]) for (const name of manifests) {
3315
+ const path = join(installDir, dir, name);
3316
+ if (!existsSync(path)) continue;
3317
+ try {
3318
+ if (POSTHOG_PACKAGE_RE.test(readFileSync(path, "utf8"))) return true;
3319
+ } catch {}
3320
+ }
3321
+ return false;
3322
+ }
3280
3323
  /**
3281
3324
  * `[ABORT] <reason>` cases the self-driving skill can emit. The
3282
3325
  * reason strings are part of the skill contract — the context-mill
@@ -3337,9 +3380,110 @@ function detectSelfDrivingPrerequisites(session, setFrameworkContext) {
3337
3380
  });
3338
3381
  return;
3339
3382
  }
3383
+ setFrameworkContext(POSTHOG_PRESENT_KEY, detectPostHogPresent(installDir));
3384
+ }
3385
+ //#endregion
3386
+ //#region src/lib/programs/self-driving/detect-agentic.ts
3387
+ /**
3388
+ * Agentic (Haiku) detection for self-driving's integration phase.
3389
+ *
3390
+ * Mirrors source-maps: the integration-detect screen runs `detectSelfDriving-
3391
+ * IntegrationProjects` (the shared Haiku detector with the integration framework
3392
+ * targets), shows a project map, and the user picks one. This file supplies the
3393
+ * targets, maps the result back to `Integration`s, and classifies each project
3394
+ * as instrumentable (a framework the wizard supports that doesn't already have
3395
+ * PostHog). The screen writes the choice to the session; `prepSelfDriving-
3396
+ * Integration` then gathers the chosen project's framework context before the
3397
+ * integration agent runs (the runner scopes the install dir).
3398
+ */
3399
+ /** Integration framework targets for the agentic detector (id → display name). */
3400
+ const INTEGRATION_TARGETS = Object.entries(FRAMEWORK_REGISTRY).map(([id, config]) => ({
3401
+ id,
3402
+ name: config.metadata.name
3403
+ }));
3404
+ const INTEGRATION_IDS = new Set(Object.values(Integration));
3405
+ function classify(integration, hasPostHog) {
3406
+ if (integration == null) return {
3407
+ instrumentable: false,
3408
+ reason: "Not a framework the wizard can set up yet"
3409
+ };
3410
+ if (hasPostHog) return {
3411
+ instrumentable: false,
3412
+ reason: "Already has the PostHog SDK"
3413
+ };
3414
+ return { instrumentable: true };
3415
+ }
3416
+ /** Map a generic detection report into classified integration projects. */
3417
+ function toIntegrationReport(report) {
3418
+ return {
3419
+ repoType: report.repoType,
3420
+ projects: report.projects.map((p) => {
3421
+ const integration = p.targetId && INTEGRATION_IDS.has(p.targetId) ? p.targetId : null;
3422
+ return {
3423
+ path: p.path,
3424
+ framework: p.framework,
3425
+ integration,
3426
+ hasPostHog: p.hasPostHog,
3427
+ ...classify(integration, p.hasPostHog)
3428
+ };
3429
+ })
3430
+ };
3431
+ }
3432
+ /** Run the Haiku detector over the repo and classify projects for integration. */
3433
+ async function detectSelfDrivingIntegrationProjects(session, onEvent) {
3434
+ return toIntegrationReport(await detectProjectsWithAgent(session, {
3435
+ targets: INTEGRATION_TARGETS,
3436
+ purpose: "set up a PostHog SDK integration",
3437
+ onEvent
3438
+ }));
3439
+ }
3440
+ /**
3441
+ * Prepare the integration phase after the user picked a project on the
3442
+ * integration-detect screen (which set `session.integration`, `frameworkConfig`,
3443
+ * and the chosen path). Scopes `installDir` to the chosen project — so a
3444
+ * monorepo integrates into the picked sub-app — and gathers that project's
3445
+ * framework context, mirroring posthog-integration's `ciPreRun`. Used as the
3446
+ * integrate-run step's `onRunPrep`.
3447
+ */
3448
+ async function prepSelfDrivingIntegration(session) {
3449
+ const frameworkConfig = session.frameworkConfig;
3450
+ if (!frameworkConfig) return;
3451
+ const context = await gatherFrameworkContext(frameworkConfig, {
3452
+ installDir: session.installDir,
3453
+ debug: session.debug,
3454
+ default: false,
3455
+ signup: session.signup,
3456
+ localMcp: session.localMcp,
3457
+ ci: session.ci,
3458
+ benchmark: session.benchmark,
3459
+ yaraReport: session.yaraReport
3460
+ });
3461
+ for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) session.frameworkContext[key] = value;
3340
3462
  }
3341
3463
  //#endregion
3342
3464
  //#region src/lib/programs/self-driving/steps.ts
3465
+ /**
3466
+ * Self-driving program step list.
3467
+ *
3468
+ * detect → intro → integration-check → health-check → auth → integrate-detect →
3469
+ * integrate-run → self-driving-handoff → run → outro. A deterministic check in
3470
+ * `detect` decides whether PostHog is already in the project: found → the
3471
+ * integration screens are skipped and the integrate-run phase never shows; not
3472
+ * found → integration-check reports it and the only action sets up PostHog.
3473
+ * After auth, `integrate-detect` runs the Haiku detector and has the user pick
3474
+ * which project to set PostHog up in (a monorepo can have several);
3475
+ * `integrate-run` then runs the real integration program's agent (its own task
3476
+ * list) in that project. `self-driving-handoff` then bridges to Self-driving
3477
+ * ("PostHog is installed — now set up Self-driving") before the Self-driving
3478
+ * run. No keep-skills step: the setup skill is transient, so postRun removes it.
3479
+ */
3480
+ /** True once detection found PostHog already present in the project. */
3481
+ const postHogPresent = (session) => session.frameworkContext[POSTHOG_PRESENT_KEY] === true;
3482
+ /** Absolute dir to integrate into: the picked sub-app, else the repo root. */
3483
+ const integrationDir = (session) => {
3484
+ const rel = session.frameworkContext[SELF_DRIVING_INTEGRATE_PATH_KEY];
3485
+ return typeof rel === "string" && rel !== "." ? resolve(session.installDir, rel) : session.installDir;
3486
+ };
3343
3487
  const SELF_DRIVING_PROGRAM = [
3344
3488
  {
3345
3489
  id: "detect",
@@ -3352,6 +3496,14 @@ const SELF_DRIVING_PROGRAM = [
3352
3496
  screenId: "self-driving-intro",
3353
3497
  gate: (session) => session.setupConfirmed
3354
3498
  },
3499
+ {
3500
+ id: "integration-check",
3501
+ label: "Integration",
3502
+ screenId: "self-driving-integration-check",
3503
+ show: (session) => !postHogPresent(session) && session.integrate === null,
3504
+ isComplete: (session) => postHogPresent(session) || session.integrate !== null,
3505
+ gate: (session) => postHogPresent(session) || session.integrate !== null
3506
+ },
3355
3507
  HEALTH_CHECK_STEP,
3356
3508
  {
3357
3509
  id: "auth",
@@ -3359,6 +3511,28 @@ const SELF_DRIVING_PROGRAM = [
3359
3511
  screenId: "auth",
3360
3512
  isComplete: (session) => session.credentials !== null
3361
3513
  },
3514
+ {
3515
+ id: "integrate-detect",
3516
+ label: "Detecting",
3517
+ screenId: "self-driving-integration-detect",
3518
+ show: (session) => session.integrate === true && session.integration == null,
3519
+ isComplete: (session) => session.integration != null
3520
+ },
3521
+ {
3522
+ ...integrationRunStep,
3523
+ id: "integrate-run",
3524
+ onRunPrep: prepSelfDrivingIntegration,
3525
+ targetDir: integrationDir,
3526
+ show: (session) => session.integrate === true,
3527
+ isComplete: (session) => session.completedRuns.includes("integrate-run")
3528
+ },
3529
+ {
3530
+ id: "self-driving-handoff",
3531
+ label: "Ready",
3532
+ screenId: "self-driving-handoff",
3533
+ show: (session) => session.integrate === true,
3534
+ isComplete: (session) => session.selfDrivingHandoffConfirmed
3535
+ },
3362
3536
  {
3363
3537
  id: "run",
3364
3538
  label: "Self-driving",
@@ -3380,6 +3554,10 @@ const SELF_DRIVING_PROGRAM = [
3380
3554
  * every step (which MCP tools to call, which sources/scouts apply, how
3381
3555
  * to verify); this prompt carries the order, the wizard-specific
3382
3556
  * mechanics (wizard_ask, abort signals), and the project URLs.
3557
+ *
3558
+ * Integration (when the project has no PostHog yet) runs as a separate phase
3559
+ * before this — the real integration program, with its own screens and task
3560
+ * list — so this prompt only covers the Self-driving steps.
3383
3561
  */
3384
3562
  function buildSelfDrivingPrompt(ctx) {
3385
3563
  const uiHost = getUiHostFromHost(ctx.host).replace(/\/$/, "");
@@ -3418,11 +3596,12 @@ tasks, in this order:
3418
3596
  1. Check Self-driving access
3419
3597
  2. Read project and current Self-driving state
3420
3598
  3. Connect GitHub (required)
3599
+ 3b. Enable products (replay, error tracking, support)
3421
3600
  4. Enable signal sources
3422
3601
  5. Offer issue-tracker integrations
3423
3602
  6. Configure the scout troop
3424
- 7. Design custom scouts
3425
- 8. Write report and hand off
3603
+ 6b. Design custom scouts
3604
+ 7. Write report and hand off
3426
3605
  Drive the list with TaskUpdate — mark a task in_progress when you start
3427
3606
  it and completed when done. If a step turns out to be a no-op (e.g.
3428
3607
  GitHub is already connected), still mark its task completed.
@@ -3470,6 +3649,19 @@ STEP 3 — Connect GitHub. REQUIRED. (skill: "Connect GitHub")
3470
3649
  ${AgentSignals.ABORT} github connection declined
3471
3650
  and halt — never finish setup without GitHub.
3472
3651
 
3652
+ STEP 3b — Enable products. (skill: "Enable products")
3653
+ Turn ON the PostHog products Signals reads from — Session Replay,
3654
+ Error Tracking, and Support — so the sources you enable next have data
3655
+ to read. These are server-side enables with conservative defaults
3656
+ (owned by the server, not you). The project-state block above covers
3657
+ only Session Replay and Error Tracking, so you can skip those if they
3658
+ are already ON; it does not show Support, but every enable is idempotent
3659
+ so enabling any of them again is safe regardless. For a web app, also
3660
+ make sure this repo's posthog-js
3661
+ init doesn't disable them; for a pure backend or mobile app the server
3662
+ flip is inert, so just record that for the report and move on. The skill
3663
+ names the exact tool and the per-platform detail.
3664
+
3473
3665
  STEP 4 — Enable signal sources. (skill: "Enable sources")
3474
3666
  Enable the sources that match what this product actually uses, per
3475
3667
  the skill. Never enable a source for a tool the user hasn't
@@ -3489,7 +3681,7 @@ STEP 6 — Configure the scout troop. (skill: "Scouts")
3489
3681
  scout plus the one or two specialists for the products this project
3490
3682
  uses most — and disable the rest, per the skill.
3491
3683
 
3492
- STEP 7 — Design custom scouts for this product. (skill: "Custom scouts")
3684
+ STEP 6b — Design custom scouts for this product. (skill: "Custom scouts")
3493
3685
  You are the only actor that has read this repo — turn that into
3494
3686
  coverage per the skill: a real gap analysis of the project's
3495
3687
  watchable surfaces against what the built-in troop already covers,
@@ -3503,7 +3695,7 @@ STEP 7 — Design custom scouts for this product. (skill: "Custom scouts")
3503
3695
  no gap at all) is a valid outcome, not an abort. Mark the task
3504
3696
  completed either way.
3505
3697
 
3506
- STEP 8 — Write the report and hand off. (skill: "Report")
3698
+ STEP 7 — Write the report and hand off. (skill: "Report")
3507
3699
  Write the report per the skill, including follow-ups for anything
3508
3700
  deferred. Tell the user findings will start appearing in their inbox
3509
3701
  at ${inboxUrl} within about 30 minutes.`;
@@ -3843,13 +4035,13 @@ const mcpAddCommand = {
3843
4035
  function runMcpAdd(argv) {
3844
4036
  const features = parseFeatures(argv.features);
3845
4037
  (async () => {
3846
- const { readApiKeyFromEnv } = await import("./env-api-key-B3gE9Un0.js").then((n) => n.t);
4038
+ const { readApiKeyFromEnv } = await import("./env-api-key-Db-mNPK2.js").then((n) => n.t);
3847
4039
  const apiKey = argv.apiKey || readApiKeyFromEnv();
3848
4040
  const debug = argv.debug;
3849
4041
  const localMcp = argv.local;
3850
4042
  try {
3851
- const { startTUI } = await import("./start-tui-S4fBBfmO.js");
3852
- const { buildSession } = await import("./wizard-session-D0PJ9lsl.js");
4043
+ const { startTUI } = await import("./start-tui-DeewAqJg.js");
4044
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3853
4045
  const tui = startTUI(VERSION, Program.McpAdd);
3854
4046
  tui.store.session = buildSession({
3855
4047
  debug,
@@ -3861,7 +4053,7 @@ function runMcpAdd(argv) {
3861
4053
  } catch (error) {
3862
4054
  if (!isTUIUnavailable(error)) throw error;
3863
4055
  setUI(new LoggingUI());
3864
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-to65gLPl.js").then((n) => n.r);
4056
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-CNn9br9l.js").then((n) => n.r);
3865
4057
  await addMCPServerToClientsStep({
3866
4058
  local: localMcp,
3867
4059
  features,
@@ -3900,8 +4092,8 @@ function runMcpRemove(argv) {
3900
4092
  const debug = argv.debug;
3901
4093
  const localMcp = argv.local;
3902
4094
  try {
3903
- const { startTUI } = await import("./start-tui-S4fBBfmO.js");
3904
- const { buildSession } = await import("./wizard-session-D0PJ9lsl.js");
4095
+ const { startTUI } = await import("./start-tui-DeewAqJg.js");
4096
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3905
4097
  const tui = startTUI(VERSION, Program.McpRemove);
3906
4098
  tui.store.session = buildSession({
3907
4099
  debug,
@@ -3910,7 +4102,7 @@ function runMcpRemove(argv) {
3910
4102
  });
3911
4103
  } catch {
3912
4104
  setUI(new LoggingUI());
3913
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-to65gLPl.js").then((n) => n.r);
4105
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-CNn9br9l.js").then((n) => n.r);
3914
4106
  await removeMCPServerFromClientsStep({ local: localMcp });
3915
4107
  }
3916
4108
  })();
@@ -3932,8 +4124,8 @@ function runMcpTutorial(argv) {
3932
4124
  const debug = argv.debug;
3933
4125
  const localMcp = argv.local;
3934
4126
  try {
3935
- const { startTUI } = await import("./start-tui-S4fBBfmO.js");
3936
- const { buildSession } = await import("./wizard-session-D0PJ9lsl.js");
4127
+ const { startTUI } = await import("./start-tui-DeewAqJg.js");
4128
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3937
4129
  const tui = startTUI(VERSION, Program.McpTutorial);
3938
4130
  tui.store.session = buildSession({
3939
4131
  debug,
@@ -3975,6 +4167,31 @@ function resolveNoTelemetry(options) {
3975
4167
  //#endregion
3976
4168
  //#region src/lib/runners/run-wizard.ts
3977
4169
  const WIZARD_VERSION = VERSION;
4170
+ /** The session a run step's agent runs in: scoped to the step's target dir
4171
+ * (e.g. a monorepo sub-app) with its own framework context, after any prep.
4172
+ * A step without `targetDir` runs in the live session, unchanged. */
4173
+ async function prepareRunSession(step, live) {
4174
+ const session = step.targetDir ? {
4175
+ ...live,
4176
+ installDir: step.targetDir(live),
4177
+ frameworkContext: { ...live.frameworkContext }
4178
+ } : live;
4179
+ if (step.onRunPrep) await step.onRunPrep(session);
4180
+ return session;
4181
+ }
4182
+ /** Advance one step of a composed run to completion: the auth screen
4183
+ * authenticates (every later run reuses it); a step carrying its own `run`
4184
+ * thunk runs that agent in its dir and is recorded in `completedRuns`; the
4185
+ * host program's own run screen runs `config.run`; any other screen waits for
4186
+ * the user to satisfy `isComplete`. */
4187
+ async function advanceStep(step, store, config) {
4188
+ if (step.screenId === "auth") await authenticate(store.session, config.id);
4189
+ else if (step.run) {
4190
+ await step.run(await prepareRunSession(step, store.session));
4191
+ store.completeRunStep(step.id);
4192
+ } else if (step.screenId === "run") await runAgent(config, await prepareRunSession(step, store.session));
4193
+ else if (step.isComplete) await store.waitUntil(step.isComplete);
4194
+ }
3978
4195
  /**
3979
4196
  * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,
3980
4197
  * build session, run detection, wait for intro gate, execute the
@@ -3988,9 +4205,9 @@ function runWizard(config, options) {
3988
4205
  (async () => {
3989
4206
  try {
3990
4207
  const installDir = options.installDir || process.cwd();
3991
- const { startTUI } = await import("./start-tui-S4fBBfmO.js");
3992
- const { buildSession, RunPhase } = await import("./wizard-session-D0PJ9lsl.js");
3993
- const { TaskStreamPush } = await import("./task-stream-BVF6gi8x.js");
4208
+ const { startTUI } = await import("./start-tui-DeewAqJg.js");
4209
+ const { buildSession, RunPhase } = await import("./wizard-session-xzqycI7i.js");
4210
+ const { TaskStreamPush } = await import("./task-stream-DkbGqxZv.js");
3994
4211
  const { PostHogDestination } = await import("./posthog-BrLFkaji.js");
3995
4212
  tui = startTUI(WIZARD_VERSION, config.id);
3996
4213
  const activeTui = tui;
@@ -4006,7 +4223,8 @@ function runWizard(config, options) {
4006
4223
  baseUrl: options.baseUrl,
4007
4224
  benchmark: options.benchmark,
4008
4225
  yaraReport: options.yaraReport,
4009
- noTelemetry: resolveNoTelemetry(options)
4226
+ noTelemetry: resolveNoTelemetry(options),
4227
+ integrate: options.integrate
4010
4228
  });
4011
4229
  session.programLabel = config.id;
4012
4230
  if (options.skillId) session.skillId = options.skillId;
@@ -4042,10 +4260,16 @@ function runWizard(config, options) {
4042
4260
  process.on("SIGTERM", onSignal);
4043
4261
  await activeTui.store.runReadyHooks();
4044
4262
  await activeTui.store.getGate("intro");
4263
+ await activeTui.store.getGate("integration-check");
4045
4264
  await activeTui.store.getGate("health-check");
4046
4265
  const skipAgent = config.run == null;
4047
- if (skipAgent) {
4048
- const { getOrAskForProjectData } = await import("./setup-utils-DyTlaGOV.js").then((n) => n.r);
4266
+ const shown = (s) => !s.show || s.show(activeTui.store.session);
4267
+ if (config.steps.some((s) => s.run)) for (const step of config.steps) {
4268
+ if (step.screenId === "outro") break;
4269
+ if (shown(step)) await advanceStep(step, activeTui.store, config);
4270
+ }
4271
+ else if (skipAgent) {
4272
+ const { getOrAskForProjectData } = await import("./setup-utils-CR8X8Fmf.js").then((n) => n.r);
4049
4273
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
4050
4274
  signup: session.signup,
4051
4275
  ci: session.ci,
@@ -4060,10 +4284,7 @@ function runWizard(config, options) {
4060
4284
  host,
4061
4285
  projectId
4062
4286
  });
4063
- } else {
4064
- const { runAgent } = await import("./agent-runner-CCTTG_Rn.js");
4065
- await runAgent(config, activeTui.store.session);
4066
- }
4287
+ } else await runAgent(config, activeTui.store.session);
4067
4288
  const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
4068
4289
  await new Promise((resolve) => {
4069
4290
  const unsub = activeTui.store.subscribe(() => {
@@ -4150,11 +4371,11 @@ function runNonInteractive(config, options, mode) {
4150
4371
  analytics.setTag("build", mode);
4151
4372
  (async () => {
4152
4373
  const path = await import("path");
4153
- const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-D0PJ9lsl.js");
4154
- const { readEnvironment } = await import("./environment-C4HyCWTC.js").then((n) => n.t);
4155
- const { readApiKeyFromEnv } = await import("./env-api-key-B3gE9Un0.js").then((n) => n.t);
4156
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-Clw8ctxh.js");
4157
- const { wizardAbort, WizardError } = await import("./wizard-abort-CNYxdjJl.js");
4374
+ const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-xzqycI7i.js");
4375
+ const { readEnvironment } = await import("./environment-BRXwshJO.js").then((n) => n.t);
4376
+ const { readApiKeyFromEnv } = await import("./env-api-key-Db-mNPK2.js").then((n) => n.t);
4377
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-B4AH8Ahp.js");
4378
+ const { wizardAbort, WizardError } = await import("./wizard-abort-DyAGpw-u.js");
4158
4379
  configureLogFileFromEnvironment();
4159
4380
  const env = readEnvironment();
4160
4381
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -4182,9 +4403,9 @@ function runNonInteractive(config, options, mode) {
4182
4403
  let store = null;
4183
4404
  let taskStream = null;
4184
4405
  if (mode === "headless") {
4185
- const { WizardStore } = await import("./store-vr5j37CU.js").then((n) => n.n);
4186
- const { HeadlessUI } = await import("./headless-ui-BoZYhNpE.js");
4187
- const { TaskStreamPush, PostHogDestination } = await import("./task-stream-BVF6gi8x.js");
4406
+ const { WizardStore } = await import("./store-0uzey9Am.js").then((n) => n.n);
4407
+ const { HeadlessUI } = await import("./headless-ui-DvkogF0b.js");
4408
+ const { TaskStreamPush, PostHogDestination } = await import("./task-stream-DkbGqxZv.js");
4188
4409
  store = new WizardStore(config.id);
4189
4410
  store.session = session;
4190
4411
  setUI(new HeadlessUI(store));
@@ -4239,7 +4460,7 @@ function runNonInteractive(config, options, mode) {
4239
4460
  });
4240
4461
  }
4241
4462
  }
4242
- const { runAgent } = await import("./agent-runner-CCTTG_Rn.js");
4463
+ const { runAgent } = await import("./agent-runner-BxIYcxmA.js").then((n) => n.t);
4243
4464
  await runAgent(config, session);
4244
4465
  await settleStream(RunPhase.Completed);
4245
4466
  } catch (error) {
@@ -5166,7 +5387,7 @@ async function runDoctorCI(options) {
5166
5387
  getUI().intro("Welcome to the PostHog setup wizard");
5167
5388
  getUI().log.info("Running posthog-doctor in CI mode");
5168
5389
  try {
5169
- const { getOrAskForProjectData } = await import("./setup-utils-DyTlaGOV.js").then((n) => n.r);
5390
+ const { getOrAskForProjectData } = await import("./setup-utils-CR8X8Fmf.js").then((n) => n.r);
5170
5391
  const { host, accessToken, projectId } = await getOrAskForProjectData({
5171
5392
  signup: false,
5172
5393
  ci: true,
@@ -5184,7 +5405,7 @@ async function runDoctorCI(options) {
5184
5405
  for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
5185
5406
  process.exit(1);
5186
5407
  } catch (error) {
5187
- const { ApiError } = await import("./api-Bdxv7mWH.js").then((n) => n.n);
5408
+ const { ApiError } = await import("./api-BqKMQVhj.js").then((n) => n.n);
5188
5409
  const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
5189
5410
  getUI().log.error(`Doctor failed: ${message}`);
5190
5411
  process.exit(1);
@@ -5228,6 +5449,11 @@ const selfDrivingCommand = {
5228
5449
  description: selfDrivingConfig.description,
5229
5450
  options: {
5230
5451
  ...skillProgramOptions,
5452
+ integrate: {
5453
+ describe: "Integrate the PostHog SDK first, then set up Self-driving — skips the \"do you already have PostHog?\" question. Use when the project isn't set up yet.",
5454
+ type: "boolean",
5455
+ default: false
5456
+ },
5231
5457
  ...selfDrivingConfig.cliOptions ?? {}
5232
5458
  },
5233
5459
  check: (argv) => {
@@ -5261,8 +5487,8 @@ function runSlackConnect(argv) {
5261
5487
  (async () => {
5262
5488
  const debug = argv.debug;
5263
5489
  try {
5264
- const { startTUI } = await import("./start-tui-S4fBBfmO.js");
5265
- const { buildSession } = await import("./wizard-session-D0PJ9lsl.js");
5490
+ const { startTUI } = await import("./start-tui-DeewAqJg.js");
5491
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
5266
5492
  const tui = startTUI(VERSION, Program.SlackConnect);
5267
5493
  tui.store.session = buildSession({
5268
5494
  debug,
@@ -5643,6 +5869,6 @@ function resolveInstallDir() {
5643
5869
  }
5644
5870
  Wizard.use(basicIntegrationCommand).use(mcpCommand).use(mcpAnalyticsCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
5645
5871
  //#endregion
5646
- export { fetchHealthIssues as _, ConfirmButton as a, POSTHOG_SDKS as b, runWizardCI as c, Program as d, getProgramConfig as f, getKindMeta as g, SOURCE_MAPS_CONTEXT_KEYS as h, useKeyboardHintsContext as i, runWizard as l, DISPLAY_NAME as m, useKeyBindings as n, PromptLabel as o, AUTOMATABLE_VARIANTS as p, KeyboardHintsProvider as r, runWizardHeadless as s, PickerMenu as t, PROGRAM_REGISTRY as u, getDetectedWarehouseSources as v, STRIPE_SDKS as x, getContentBlocks$2 as y };
5872
+ export { STRIPE_SDKS as C, POSTHOG_SDKS as S, SOURCE_MAPS_CONTEXT_KEYS as _, ConfirmButton as a, getDetectedWarehouseSources as b, runWizardCI as c, Program as d, getProgramConfig as f, DISPLAY_NAME as g, AUTOMATABLE_VARIANTS as h, useKeyboardHintsContext as i, runWizard as l, SELF_DRIVING_INTEGRATE_PATH_KEY as m, useKeyBindings as n, PromptLabel as o, detectSelfDrivingIntegrationProjects as p, KeyboardHintsProvider as r, runWizardHeadless as s, PickerMenu as t, PROGRAM_REGISTRY as u, getKindMeta as v, getContentBlocks$2 as x, fetchHealthIssues as y };
5647
5873
 
5648
5874
  //# sourceMappingURL=bin.js.map