@posthog/wizard 2.78.0 → 2.79.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 (130) hide show
  1. package/README.md +20 -11
  2. package/dist/{add-mcp-server-to-clients-JMv8LP-O.js → add-mcp-server-to-clients-amlJWW7W.js} +5 -5
  3. package/dist/{add-mcp-server-to-clients-JMv8LP-O.js.map → add-mcp-server-to-clients-amlJWW7W.js.map} +1 -1
  4. package/dist/{agent-bCZ3i3fh.js → agent-CNrEC-9v.js} +130 -31
  5. package/dist/agent-CNrEC-9v.js.map +1 -0
  6. package/dist/{agent-interface-BAOIHuXS.js → agent-interface-BXvmAm4c.js} +48 -22
  7. package/dist/agent-interface-BXvmAm4c.js.map +1 -0
  8. package/dist/{agent-prompt-loader-7Pd4CfZO.js → agent-prompt-loader-DiKUbhi_.js} +5 -5
  9. package/dist/{agent-prompt-loader-7Pd4CfZO.js.map → agent-prompt-loader-DiKUbhi_.js.map} +1 -1
  10. package/dist/analytics-DxwRi2Hf.js +2 -0
  11. package/dist/{analytics-CHCZ_qUR.js → analytics-VRYdebXW.js} +4 -4
  12. package/dist/{analytics-CHCZ_qUR.js.map → analytics-VRYdebXW.js.map} +1 -1
  13. package/dist/{api-Diy_2fp8.js → api-DGuJTzjr.js} +3 -3
  14. package/dist/{api-Diy_2fp8.js.map → api-DGuJTzjr.js.map} +1 -1
  15. package/dist/bin.js +56 -53
  16. package/dist/bin.js.map +1 -1
  17. package/dist/{bounded-fs-Bx9zTe6m.js → bounded-fs-Cpn129A4.js} +3 -3
  18. package/dist/{bounded-fs-Bx9zTe6m.js.map → bounded-fs-Cpn129A4.js.map} +1 -1
  19. package/dist/{ci-install-CDdQYsPe.js → ci-install-BPA6gzEq.js} +6 -6
  20. package/dist/ci-install-BPA6gzEq.js.map +1 -0
  21. package/dist/{constants-jFI2SaE1.js → constants-CuJfQEcC.js} +3 -3
  22. package/dist/{constants-jFI2SaE1.js.map → constants-CuJfQEcC.js.map} +1 -1
  23. package/dist/{debug-M2gV2iDq.js → debug-B9k4ideV.js} +1 -1
  24. package/dist/{debug-Ch4BDOtD.js → debug-Cj-8vfXY.js} +2 -2
  25. package/dist/{debug-Ch4BDOtD.js.map → debug-Cj-8vfXY.js.map} +1 -1
  26. package/dist/{endpoints-DCVbM06L.js → endpoints-DnIX0pZH.js} +3 -3
  27. package/dist/{endpoints-DCVbM06L.js.map → endpoints-DnIX0pZH.js.map} +1 -1
  28. package/dist/{env-api-key-Qx8NnYHm.js → env-api-key-BWdKpGEr.js} +2 -2
  29. package/dist/{env-api-key-Qx8NnYHm.js.map → env-api-key-BWdKpGEr.js.map} +1 -1
  30. package/dist/{environment-B07Bmxae.js → environment-DZYUSCpV.js} +4 -4
  31. package/dist/{environment-B07Bmxae.js.map → environment-DZYUSCpV.js.map} +1 -1
  32. package/dist/{errors-CQ9kttJD.js → errors-ddDE6MbA.js} +4 -46
  33. package/dist/errors-ddDE6MbA.js.map +1 -0
  34. package/dist/{file-BcLTjU16.js → file-dEhr-l3n.js} +3 -3
  35. package/dist/file-dEhr-l3n.js.map +1 -0
  36. package/dist/{file-watcher-DWc_bTs6.js → file-watcher-CPM-Nn9L.js} +2 -2
  37. package/dist/{file-watcher-DWc_bTs6.js.map → file-watcher-CPM-Nn9L.js.map} +1 -1
  38. package/dist/{gateway-CjoShdLa.js → gateway-CVU1G0H3.js} +38 -8
  39. package/dist/gateway-CVU1G0H3.js.map +1 -0
  40. package/dist/{headless-ui-BFFmYC4v.js → headless-ui-pY2xB5ug.js} +2 -2
  41. package/dist/{headless-ui-BFFmYC4v.js.map → headless-ui-pY2xB5ug.js.map} +1 -1
  42. package/dist/{interactive-D6zV7brJ.js → interactive-BOGlinZe.js} +2 -2
  43. package/dist/interactive-BOGlinZe.js.map +1 -0
  44. package/dist/{logging-ui-_TwoMNbG.js → logging-ui-CUxNYF2t.js} +4 -4
  45. package/dist/{logging-ui-_TwoMNbG.js.map → logging-ui-CUxNYF2t.js.map} +1 -1
  46. package/dist/{mcp-DAgaoGk5.js → mcp-JcsBBnWv.js} +4 -4
  47. package/dist/{mcp-DAgaoGk5.js.map → mcp-JcsBBnWv.js.map} +1 -1
  48. package/dist/{mcp-prompt-streaming-I2U_X7BC.js → mcp-prompt-streaming-B-p_Pvb2.js} +6 -6
  49. package/dist/mcp-prompt-streaming-B-p_Pvb2.js.map +1 -0
  50. package/dist/{mint-failure-D4nd2XmZ.js → mint-failure-CZFZpHpW.js} +687 -125
  51. package/dist/mint-failure-CZFZpHpW.js.map +1 -0
  52. package/dist/{models-DDdBJKwT.js → models-DnAY67Lg.js} +2 -2
  53. package/dist/{models-DDdBJKwT.js.map → models-DnAY67Lg.js.map} +1 -1
  54. package/dist/{non-interactive-Dzow7YKY.js → non-interactive-DR1CWXY1.js} +3 -3
  55. package/dist/{non-interactive-Dzow7YKY.js.map → non-interactive-DR1CWXY1.js.map} +1 -1
  56. package/dist/{oauth-session-DJ8h6GFa.js → oauth-session-CQTFOk-I.js} +2 -2
  57. package/dist/{oauth-session-DJ8h6GFa.js.map → oauth-session-CQTFOk-I.js.map} +1 -1
  58. package/dist/{orchestrator-tools-szcdscwn.js → orchestrator-tools-CBdt-SXO.js} +3 -3
  59. package/dist/{orchestrator-tools-szcdscwn.js.map → orchestrator-tools-CBdt-SXO.js.map} +1 -1
  60. package/dist/{pi-D3h5Ok0i.js → pi-BtqcLX3y.js} +143 -44
  61. package/dist/pi-BtqcLX3y.js.map +1 -0
  62. package/dist/{playground-5AB4WgNF.js → playground-Dz-ZVjBk.js} +9 -9
  63. package/dist/playground-Dz-ZVjBk.js.map +1 -0
  64. package/dist/{posthog-DNn574nW.js → posthog-6Uqw_Eux.js} +3 -3
  65. package/dist/posthog-6Uqw_Eux.js.map +1 -0
  66. package/dist/{provisioning-B8uSqRZk.js → provisioning-Zf7yPcEs.js} +4 -4
  67. package/dist/{provisioning-B8uSqRZk.js.map → provisioning-Zf7yPcEs.js.map} +1 -1
  68. package/dist/{queue-tools-9OOVx5TE.js → queue-tools-B7_aCyd-.js} +3 -3
  69. package/dist/{queue-tools-9OOVx5TE.js.map → queue-tools-B7_aCyd-.js.map} +1 -1
  70. package/dist/{registry-8YG-kuXk.js → registry-B6iLGorH.js} +49 -49
  71. package/dist/registry-B6iLGorH.js.map +1 -0
  72. package/dist/{run-agent-legacy-d7rWlzQR.js → run-agent-legacy-6WcYMaR9.js} +822 -1020
  73. package/dist/run-agent-legacy-6WcYMaR9.js.map +1 -0
  74. package/dist/{security-Cg_4a7vB.js → security-lkBwWbrK.js} +16 -6
  75. package/dist/security-lkBwWbrK.js.map +1 -0
  76. package/dist/{setup-utils-CmTCTPkX.js → setup-utils-dCViCC6s.js} +11 -11
  77. package/dist/setup-utils-dCViCC6s.js.map +1 -0
  78. package/dist/{start-tui-CB2PZs1x.js → start-tui-oCWMgsDP.js} +26 -26
  79. package/dist/start-tui-oCWMgsDP.js.map +1 -0
  80. package/dist/{steps-BZcXRJNY.js → steps-gx0Pq4I4.js} +7 -7
  81. package/dist/{steps-BZcXRJNY.js.map → steps-gx0Pq4I4.js.map} +1 -1
  82. package/dist/{store-UN7c-ASf.js → store-xYy_6Ruv.js} +10 -10
  83. package/dist/store-xYy_6Ruv.js.map +1 -0
  84. package/dist/{subagent-BofIDK-O.js → subagent-Bfy0sfhU.js} +3 -3
  85. package/dist/{subagent-BofIDK-O.js.map → subagent-Bfy0sfhU.js.map} +1 -1
  86. package/dist/{task-r9t1UhQP.js → task-BOfw7GPc.js} +16 -16
  87. package/dist/{task-r9t1UhQP.js.map → task-BOfw7GPc.js.map} +1 -1
  88. package/dist/{task-stream-CMUilu54.js → task-stream-kYlm9qd0.js} +9 -9
  89. package/dist/task-stream-kYlm9qd0.js.map +1 -0
  90. package/dist/{telemetry-D6ruCtnv.js → telemetry-Bpv-Mh5B.js} +3 -3
  91. package/dist/{telemetry-D6ruCtnv.js.map → telemetry-Bpv-Mh5B.js.map} +1 -1
  92. package/dist/{terminal-DrGyci_a.js → terminal-D07EQ2y0.js} +15 -15
  93. package/dist/terminal-D07EQ2y0.js.map +1 -0
  94. package/dist/{tools-Dyfh9aCD.js → tools-Cc41af5W.js} +8 -8
  95. package/dist/{tools-Dyfh9aCD.js.map → tools-Cc41af5W.js.map} +1 -1
  96. package/dist/{ui-BBVuTM1v.js → ui-CGXtC7Vn.js} +3 -3
  97. package/dist/{ui-BBVuTM1v.js.map → ui-CGXtC7Vn.js.map} +1 -1
  98. package/dist/{version-aXxpgRKx.js → version-Cadof0Z_.js} +2 -2
  99. package/dist/{version-aXxpgRKx.js.map → version-Cadof0Z_.js.map} +1 -1
  100. package/dist/{wizard-abort-BBkiUxfS.js → wizard-abort-HDbP3YcS.js} +6 -6
  101. package/dist/{wizard-abort-BBkiUxfS.js.map → wizard-abort-HDbP3YcS.js.map} +1 -1
  102. package/dist/wizard-abort-Y-Ip2K4z.js +3 -0
  103. package/dist/wizard-session-2w4Ru-Wz.js.map +1 -1
  104. package/dist/yara-hooks-B49RIk5d.js +2 -0
  105. package/dist/{yara-hooks-DCeMDd1o.js → yara-hooks-DCfROpZt.js} +5 -5
  106. package/dist/{yara-hooks-DCeMDd1o.js.map → yara-hooks-DCfROpZt.js.map} +1 -1
  107. package/package.json +2 -1
  108. package/dist/agent-bCZ3i3fh.js.map +0 -1
  109. package/dist/agent-interface-BAOIHuXS.js.map +0 -1
  110. package/dist/analytics-BcV-WCM4.js +0 -2
  111. package/dist/ci-install-CDdQYsPe.js.map +0 -1
  112. package/dist/errors-CQ9kttJD.js.map +0 -1
  113. package/dist/file-BcLTjU16.js.map +0 -1
  114. package/dist/gateway-CjoShdLa.js.map +0 -1
  115. package/dist/interactive-D6zV7brJ.js.map +0 -1
  116. package/dist/mcp-prompt-streaming-I2U_X7BC.js.map +0 -1
  117. package/dist/mint-failure-D4nd2XmZ.js.map +0 -1
  118. package/dist/pi-D3h5Ok0i.js.map +0 -1
  119. package/dist/playground-5AB4WgNF.js.map +0 -1
  120. package/dist/posthog-DNn574nW.js.map +0 -1
  121. package/dist/registry-8YG-kuXk.js.map +0 -1
  122. package/dist/run-agent-legacy-d7rWlzQR.js.map +0 -1
  123. package/dist/security-Cg_4a7vB.js.map +0 -1
  124. package/dist/setup-utils-CmTCTPkX.js.map +0 -1
  125. package/dist/start-tui-CB2PZs1x.js.map +0 -1
  126. package/dist/store-UN7c-ASf.js.map +0 -1
  127. package/dist/task-stream-CMUilu54.js.map +0 -1
  128. package/dist/terminal-DrGyci_a.js.map +0 -1
  129. package/dist/wizard-abort-BU4aLyvh.js +0 -3
  130. package/dist/yara-hooks-DSGuCU9A.js +0 -2
@@ -1,35 +1,433 @@
1
- import { a as AgentSignals, d as ErrorCodes } from "./errors-CQ9kttJD.js";
2
- import { r as debug, s as logToFile, x as regionOption, y as headlessOption } from "./debug-Ch4BDOtD.js";
3
- import { Q as WIZARD_USER_AGENT, U as WIZARD_INTERACTION_EVENT_NAME, f as EVENTS_AUDIT_REPORT_FILE, h as EVENT_PLAN_FILE, k as POSTHOG_DOCS_URL, w as Integration } from "./constants-jFI2SaE1.js";
1
+ import { s as ErrorCodes } from "./errors-ddDE6MbA.js";
2
+ import { r as debug, s as logToFile, x as regionOption, y as headlessOption } from "./debug-Cj-8vfXY.js";
3
+ import { $ as getSkillsBaseUrl, Q as WIZARD_USER_AGENT, U as WIZARD_INTERACTION_EVENT_NAME, f as EVENTS_AUDIT_REPORT_FILE, h as EVENT_PLAN_FILE, k as POSTHOG_DOCS_URL, n as AGENTIC_DETECTION_RETRY_TIMEOUT_MS, t as AGENTIC_DETECTION_FIRST_ATTEMPT_TIMEOUT_MS, u as DETECTION_TIMEOUT_MS, w as Integration } from "./constants-CuJfQEcC.js";
4
4
  import { r as mayReportScanResults } from "./wizard-session-2w4Ru-Wz.js";
5
- import { n as analytics } from "./analytics-CHCZ_qUR.js";
6
- import { i as withUtm, n as openTrackedLink } from "./telemetry-D6ruCtnv.js";
7
- import "./bounded-fs-Bx9zTe6m.js";
8
- import { i as tryGetPackageJson, n as isUsingTypeScript } from "./setup-utils-CmTCTPkX.js";
9
- import { a as getBlockingServiceKeys, i as evaluateWizardReadiness, r as SIGNUP_WIZARD_READINESS_CONFIG } from "./logging-ui-_TwoMNbG.js";
10
- import { t as getUI } from "./ui-BBVuTM1v.js";
11
- import { i as requestDeepLink } from "./provisioning-B8uSqRZk.js";
12
- import { s as handleApiError } from "./api-Diy_2fp8.js";
13
- import { i as wizardAbort } from "./wizard-abort-BBkiUxfS.js";
14
- import { _ as detectProjectsWithAgent, b as detectFramework, d as findPackageJsons, f as WAREHOUSE_ABORT_CASES, g as AgenticDetectionTimeoutError, h as detectWarehouseSources, m as getDetectedWarehouseSources, o as detectPostHogIntegration, p as detectWarehousePrerequisites, r as AUDIT_CHECKS_KEY, t as runProgramAgent, v as resolveProjectDir, x as authenticate, y as gatherFrameworkContext } from "./run-agent-legacy-d7rWlzQR.js";
15
- import { I as WIZARD_TOOL_NAMES, nt as LONGER_ASK_TIMEOUT_MS } from "./agent-interface-BAOIHuXS.js";
16
- import { s as shouldDisableAsk } from "./agent-bCZ3i3fh.js";
17
- import { g as AUDIT_REPORT_FILE, h as AUDIT_CHECKS_FILE } from "./yara-hooks-DCeMDd1o.js";
18
- import { y as writeJsonAtomic } from "./queue-tools-9OOVx5TE.js";
19
- import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-8YG-kuXk.js";
5
+ import { n as analytics } from "./analytics-VRYdebXW.js";
6
+ import { i as withUtm, n as openTrackedLink } from "./telemetry-Bpv-Mh5B.js";
7
+ import { a as safeReadFile, o as walkProjectFiles } from "./bounded-fs-Cpn129A4.js";
8
+ import { i as tryGetPackageJson, n as isUsingTypeScript, p as detectNodePackageManagers } from "./setup-utils-dCViCC6s.js";
9
+ import { a as getBlockingServiceKeys, i as evaluateWizardReadiness, r as SIGNUP_WIZARD_READINESS_CONFIG } from "./logging-ui-CUxNYF2t.js";
10
+ import { t as getUI } from "./ui-CGXtC7Vn.js";
11
+ import { i as requestDeepLink } from "./provisioning-Zf7yPcEs.js";
12
+ import { s as handleApiError } from "./api-DGuJTzjr.js";
13
+ import { i as wizardAbort } from "./wizard-abort-HDbP3YcS.js";
14
+ import { s as AgentSignals } from "./gateway-CVU1G0H3.js";
15
+ import { I as WIZARD_TOOL_NAMES, n as buildRunTags, nt as LONGER_ASK_TIMEOUT_MS } from "./agent-interface-BXvmAm4c.js";
16
+ import { c as shouldDisableAsk, i as resolveScanBindings, n as runAgent } from "./agent-CNrEC-9v.js";
17
+ import { g as AUDIT_REPORT_FILE, h as AUDIT_CHECKS_FILE } from "./yara-hooks-DCfROpZt.js";
18
+ import { y as writeJsonAtomic } from "./queue-tools-B7_aCyd-.js";
19
+ import { a as detectWarehousePrerequisites, c as discoverFeatures, f as authenticate, h as stampAiSdkDetected, i as WAREHOUSE_ABORT_CASES, l as AUDIT_CHECKS_KEY, m as createUiReducer, o as getDetectedWarehouseSources, r as DETECTED_WAREHOUSE_SOURCES_KEY, s as detectWarehouseSources, t as runProgramAgent } from "./run-agent-legacy-6WcYMaR9.js";
20
+ import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-B6iLGorH.js";
21
+ import * as semver from "semver";
20
22
  import { existsSync, readFileSync, readdirSync, statSync } from "fs";
21
- import path, { join } from "path";
23
+ import path, { isAbsolute, join, relative, resolve, sep } from "path";
22
24
  import * as os from "node:os";
23
25
  import * as path$2 from "node:path";
24
26
  import { spawnSync } from "node:child_process";
25
27
  import * as fs$1 from "node:fs";
26
28
  import axios from "axios";
27
29
  import { z } from "zod";
30
+ import { zodToJsonSchema } from "zod-to-json-schema";
28
31
  import { Text } from "ink";
29
32
  import { useEffect, useMemo, useRef, useState } from "react";
30
33
  import { jsx, jsxs } from "react/jsx-runtime";
31
34
  import { access, rm } from "node:fs/promises";
32
- //#region src/lib/detection/project-scope.ts
35
+ //#region src/programs/detection/framework.ts
36
+ /**
37
+ * Framework detection — identify which PostHog-supported framework
38
+ * is present in the project directory.
39
+ *
40
+ * Pure function: takes an install dir, returns the detected integration
41
+ * (or undefined). No store mutations, no UI calls.
42
+ */
43
+ /**
44
+ * Loop through all registered frameworks and return the first one
45
+ * whose `detect()` predicate matches the given directory.
46
+ * Returns undefined if no framework is detected or detection times out.
47
+ */
48
+ async function detectFramework(installDir) {
49
+ for (const integration of Object.values(Integration)) {
50
+ const config = FRAMEWORK_REGISTRY[integration];
51
+ try {
52
+ if (await Promise.race([config.detection.detect({ installDir }), new Promise((resolve) => setTimeout(() => resolve(false), 1e4))])) return integration;
53
+ } catch {}
54
+ }
55
+ }
56
+ //#endregion
57
+ //#region src/programs/detection/context.ts
58
+ /**
59
+ * Framework context gathering — run gatherContext and version checks
60
+ * for a detected framework.
61
+ *
62
+ * Pure functions: take a framework config and options, return results.
63
+ * No store mutations, no UI calls.
64
+ */
65
+ /**
66
+ * Run a framework's `gatherContext()` to collect variant-specific
67
+ * metadata (e.g., router type for Next.js, Expo vs bare for React Native).
68
+ *
69
+ * Returns the gathered context, or an empty object on failure/timeout.
70
+ */
71
+ async function gatherFrameworkContext(config, options) {
72
+ if (!config.metadata.gatherContext) return {};
73
+ try {
74
+ return await Promise.race([config.metadata.gatherContext(options), new Promise((resolve) => setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS))]);
75
+ } catch {
76
+ return {};
77
+ }
78
+ }
79
+ /**
80
+ * Check whether the installed framework version meets the minimum requirement.
81
+ *
82
+ * Returns `{ supported: true }` if the version is fine (or no check is needed).
83
+ * Returns the version details if unsupported.
84
+ */
85
+ async function checkFrameworkVersion(config, options) {
86
+ if (!config.detection.minimumVersion || !config.detection.getInstalledVersion) return { supported: true };
87
+ const version = await config.detection.getInstalledVersion(options);
88
+ if (!version) return { supported: true };
89
+ const coerced = semver.coerce(version);
90
+ if (coerced && semver.lt(coerced, config.detection.minimumVersion)) return { supported: {
91
+ current: version,
92
+ minimum: config.detection.minimumVersion,
93
+ docsUrl: config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl
94
+ } };
95
+ return { supported: true };
96
+ }
97
+ //#endregion
98
+ //#region src/programs/detection/agentic.ts
99
+ /**
100
+ * Agentic project detection.
101
+ *
102
+ * A reusable detection tool that drives an agent over the repo: it finds
103
+ * project roots, resolves monorepo/workspace markers, reads package manifests,
104
+ * classifies each project against a caller-supplied set of targets, and reports
105
+ * which projects already have a PostHog SDK installed.
106
+ *
107
+ * Product-knowledge-free by design — the caller passes the targets to classify
108
+ * into (e.g. source-map skill variants) and maps the result back. Sits next to
109
+ * the other detection tools (framework, features, package-manager) so it's
110
+ * discoverable. Runs AFTER auth: it goes through the same `runAgent` every
111
+ * program uses, which needs credentials.
112
+ */
113
+ var AgenticDetectionTimeoutError = class extends Error {
114
+ constructor(attempt, timeoutMs) {
115
+ super(`Project scan attempt ${attempt} timed out after ${timeoutMs / 1e3}s`);
116
+ this.name = "AgenticDetectionTimeoutError";
117
+ }
118
+ };
119
+ /**
120
+ * Every project-manifest / workspace-marker filename the wizard's frameworks
121
+ * are identified by. One brace-expansion Glob over all of these locates every
122
+ * project root in the repo in a single call, regardless of language.
123
+ *
124
+ * Counterpart: POSTHOG_MANIFESTS in @programs/self-driving/detect (SDK
125
+ * grep); keep the two in sync.
126
+ */
127
+ const PROJECT_MANIFESTS = [
128
+ "package.json",
129
+ "pnpm-workspace.yaml",
130
+ "turbo.json",
131
+ "nx.json",
132
+ "lerna.json",
133
+ "requirements.txt",
134
+ "pyproject.toml",
135
+ "setup.py",
136
+ "Pipfile",
137
+ "manage.py",
138
+ "Gemfile",
139
+ "composer.json",
140
+ "pom.xml",
141
+ "Cargo.toml",
142
+ "mix.exs",
143
+ "go.mod",
144
+ "*.csproj",
145
+ "Package.swift",
146
+ "Podfile",
147
+ "project.yml",
148
+ "project.pbxproj",
149
+ "pubspec.yaml",
150
+ "build.gradle",
151
+ "build.gradle.kts",
152
+ "settings.gradle",
153
+ "settings.gradle.kts",
154
+ "gradle/libs.versions.toml"
155
+ ];
156
+ /** The single brace-expansion glob covering every supported manifest. */
157
+ function manifestGlob() {
158
+ return `**/{${PROJECT_MANIFESTS.join(",")}}`;
159
+ }
160
+ function buildPrompt$1(cwd, targets, purpose, recommend) {
161
+ const targetList = targets.map((t) => `- ${t.id} → ${t.name}`).join("\n");
162
+ const projectShape = `{"path":string,"framework":string,"matchingTargets":string[],"targetId":string|null,"hasPostHog":boolean,"evidence":string${recommend ? ",\"recommended\":boolean" : ""}}`;
163
+ return [
164
+ `You are scanning a code repository to ${purpose}. Be fast and mechanical — do not over-explore. Keep any reasoning to one short sentence, then run the tool calls and output the JSON.`,
165
+ "",
166
+ `Working directory: ${cwd}`,
167
+ "",
168
+ "A \"project\" is a directory containing one or more of the manifest files below. Find projects by their manifests, NOT by walking directories — never report a directory that has no manifest.",
169
+ "",
170
+ "Do exactly this:",
171
+ `1. Run Glob ONCE with this pattern to find every project manifest in the repo in a single call: "${manifestGlob()}". Discard any result whose path contains node_modules/, dist/, build/, .next/, out/, coverage/, vendor/, .venv/, site-packages/, target/, Pods/, Carthage/, or DerivedData/. Group the remaining results by directory — each directory is one project. Three exceptions to "directory = project": a project.pbxproj lives inside a "<Name>.xcodeproj/" wrapper, so the project root is the PARENT of that .xcodeproj directory; a project.yml at a directory root is an XcodeGen-generated Xcode app rooted at that directory; a gradle/libs.versions.toml is a version catalog belonging to the gradle project rooted at the PARENT of that gradle/ directory (read it alongside the build.gradle when deciding hasPostHog), never its own project.`,
172
+ "2. Decide repoType: \"monorepo\" if the root package.json has a \"workspaces\" field OR a pnpm-workspace.yaml / turbo.json / nx.json / lerna.json was found at the root, else \"single\".",
173
+ `3. For EACH project directory, ONE AT A TIME: Read its manifest(s) ONCE, decide the fields below, then IMMEDIATELY — before reading any other project — write that project's verdict as one JSON line of shape ${projectShape}. Never write a verdict from memory of an earlier Read; the manifest you just read is the only source. Decide from its dependency lists:`,
174
+ " - the human-readable framework name (e.g. \"Next.js\", \"Django\", \"Rails\"),",
175
+ " - matchingTargets: EVERY target id from the list below whose technology appears in THIS manifest, in the priority order of the list. An id belongs here only if you can point at the dependency or setting in the manifest you just read — never carry one over from another project,",
176
+ " - targetId: the FIRST entry of matchingTargets (the list is ordered by priority, most specific first). null when matchingTargets is empty,",
177
+ ` - hasPostHog: true if any dependency is a PostHog SDK. This includes: a name containing "posthog" in any ecosystem (e.g. posthog-js, posthog-node, @posthog/*, posthog for pip/gem/hex, a com.posthog:* gradle/maven coordinate, a PostHog NuGet PackageReference); an SPM package named "PostHog" or a repositoryURL of github.com/PostHog/posthog-ios (in Package.swift or a .pbxproj); or a "pod 'PostHog'" line in a Podfile. Else false.`,
178
+ " - evidence: the manifest fact that decided targetId, with the file it came from (e.g. \"rollup in devDependencies of backend/package.json\"). When targetId is null, name the closest fact you saw. One short clause, quoted from the manifest you just read.",
179
+ " Do NOT read any file other than these manifests.",
180
+ ...recommend ? ["4. Pick exactly ONE project as recommended — the main user-facing client application. Prefer a frontend web app or a mobile app over backend servers/APIs, libraries, CLIs, tooling, and example/demo/docs apps. If several client apps exist, pick the primary production app; if no client app exists, pick the primary application project."] : [],
181
+ "",
182
+ "Target ids (id → name), in priority order — most specific first; if several match a project, keep the one listed earliest:",
183
+ targetList,
184
+ "",
185
+ "Output requirements:",
186
+ "- After the last verdict line, respond with ONLY a single JSON object assembling the verdict lines you wrote, copied VERBATIM — same path, framework, targetId and evidence per project. No prose, no markdown code fences.",
187
+ `- Shape: {"repoType":"monorepo"|"single","projects":[${projectShape}]}`,
188
+ "- \"path\" is the project directory relative to the working directory; use \".\" for the repo root.",
189
+ "- \"targetId\" MUST be exactly one of the target ids above when it matches; if several match, use the one listed earliest; otherwise null.",
190
+ "- Include projects whose stack matches no target too (targetId: null).",
191
+ ...recommend ? ["- Exactly one project has \"recommended\": true; every other project has \"recommended\": false."] : [],
192
+ "- If there are no manifests at all, return {\"repoType\":\"single\",\"projects\":[]}."
193
+ ].join("\n");
194
+ }
195
+ /**
196
+ * Build the detection report from the agent's output, or null when it holds
197
+ * neither a project verdict nor a `projects` array. Exported for testing.
198
+ *
199
+ * The verdict lines are far more reliable than the model's final assembly
200
+ * (prose, pretty-printing, per-object fences), so every parseable line
201
+ * contributes: objects with a `path` merge by path (last wins), and a
202
+ * one-line assembly's `projects` merge the same way. `repoType` is
203
+ * approximated from the count — it only feeds telemetry and display.
204
+ */
205
+ function deriveReportJson(text) {
206
+ const byPath = /* @__PURE__ */ new Map();
207
+ let sawReport = false;
208
+ for (const line of text.split("\n")) {
209
+ const start = line.indexOf("{");
210
+ const end = line.lastIndexOf("}");
211
+ if (start === -1 || end <= start) continue;
212
+ let parsed;
213
+ try {
214
+ parsed = JSON.parse(line.slice(start, end + 1));
215
+ } catch {
216
+ continue;
217
+ }
218
+ const obj = parsed ?? {};
219
+ sawReport ||= Array.isArray(obj.projects);
220
+ const candidates = Array.isArray(obj.projects) ? obj.projects : [obj];
221
+ for (const candidate of candidates) {
222
+ const p = candidate ?? {};
223
+ if (typeof p.path === "string") byPath.set(p.path, p);
224
+ }
225
+ }
226
+ if (byPath.size === 0 && !sawReport) return null;
227
+ const projects = [...byPath.values()];
228
+ return {
229
+ repoType: projects.length > 1 ? "monorepo" : "single",
230
+ projects
231
+ };
232
+ }
233
+ /**
234
+ * Clamp an agent-reported project path to a safe repo-relative dir. The path
235
+ * is LLM output: absolute paths or `..` segments could steer later phases
236
+ * (e.g. integrate-run's targetDir) outside the repo, so they clamp to '.'.
237
+ */
238
+ function coercePath(raw) {
239
+ if (typeof raw !== "string" || raw.length === 0) return ".";
240
+ if (isAbsolute(raw) || raw.split(/[\\/]/).includes("..")) return ".";
241
+ return raw;
242
+ }
243
+ /** Resolve an agent-reported path to an absolute dir clamped to the root — the caller-side counterpart of coercePath. */
244
+ function resolveProjectDir(installDir, rel) {
245
+ if (typeof rel !== "string" || rel === ".") return installDir;
246
+ const root = resolve(installDir);
247
+ const dir = resolve(root, rel);
248
+ return dir === root || dir.startsWith(root + sep) ? dir : root;
249
+ }
250
+ /**
251
+ * Validate the agent's raw JSON into a report, clamping each targetId to the
252
+ * supplied set and each path to a repo-relative dir. Exported for testing.
253
+ * `recommended` is stripped unless requested; at most one (the first) survives.
254
+ */
255
+ function coerceAgenticReport(parsed, validTargetIds, options) {
256
+ const recommend = options?.recommend === true;
257
+ const rerankIds = options?.rerankIds ?? [];
258
+ const obj = parsed ?? {};
259
+ const repoType = obj.repoType === "monorepo" ? "monorepo" : "single";
260
+ const rawProjects = Array.isArray(obj.projects) ? obj.projects : [];
261
+ let recommendedSeen = false;
262
+ return {
263
+ repoType,
264
+ projects: rawProjects.map((raw) => {
265
+ const p = raw ?? {};
266
+ const pick = typeof p.targetId === "string" && validTargetIds.includes(p.targetId) ? p.targetId : null;
267
+ const enumerated = Array.isArray(p.matchingTargets) ? validTargetIds.find((id) => p.matchingTargets.includes(id)) ?? null : null;
268
+ const targetId = pick === null ? enumerated : enumerated !== null && rerankIds.includes(enumerated) && rerankIds.includes(pick) ? enumerated : pick;
269
+ const recommended = recommend && !recommendedSeen && p.recommended === true;
270
+ recommendedSeen ||= recommended;
271
+ return {
272
+ path: coercePath(p.path),
273
+ framework: typeof p.framework === "string" ? p.framework : "Unknown",
274
+ targetId,
275
+ hasPostHog: p.hasPostHog === true,
276
+ ...recommend ? { recommended } : {}
277
+ };
278
+ })
279
+ };
280
+ }
281
+ function detectionReportSchema(recommend) {
282
+ return z.object({
283
+ repoType: z.enum(["monorepo", "single"]),
284
+ projects: z.array(z.object({
285
+ path: z.string(),
286
+ framework: z.string(),
287
+ matchingTargets: z.array(z.string()),
288
+ targetId: z.string().nullable(),
289
+ hasPostHog: z.boolean(),
290
+ evidence: z.string(),
291
+ ...recommend ? { recommended: z.boolean() } : {}
292
+ }).strict())
293
+ }).strict();
294
+ }
295
+ /** Read-only scan with a typed result and transcript recovery. */
296
+ function detectionRunDefinition(prompt) {
297
+ return {
298
+ integrationLabel: "agentic-detect",
299
+ readOnly: true,
300
+ prompt: () => prompt,
301
+ collectTranscript: true,
302
+ requestRemark: false,
303
+ detectPackageManager: detectNodePackageManagers,
304
+ spinnerMessage: "Scanning the repo...",
305
+ successMessage: "Detection complete",
306
+ errorMessage: "Detection failed",
307
+ estimatedDurationMinutes: 1,
308
+ reportFile: "",
309
+ docsUrl: POSTHOG_DOCS_URL
310
+ };
311
+ }
312
+ /** What the UI saw before `runAgent`: no run lifecycle, spinner, outro, or setup logs below warn. */
313
+ function reachesUi(event) {
314
+ switch (event.kind) {
315
+ case "lifecycle":
316
+ case "completion":
317
+ case "spinner": return false;
318
+ case "log": return event.level === "warn" || event.level === "error";
319
+ default: return true;
320
+ }
321
+ }
322
+ /** Scan through `runAgent` with the bound triage model, then the SDK fallback. */
323
+ async function detectProjectsWithAgent(session, options) {
324
+ if (!session.credentials) throw new Error("Detection requires authenticated credentials.");
325
+ const { targets, programId, purpose = "set up a PostHog integration", recommend = false, rerankIds, onEvent } = options;
326
+ const wizardMetadata = {
327
+ ...buildRunTags({
328
+ programId,
329
+ integration: "agentic-detect",
330
+ runId: analytics.runId,
331
+ build: analytics.build
332
+ }),
333
+ call_type: "detection"
334
+ };
335
+ const wizardFlags = await analytics.getAllFlagsForWizard();
336
+ const wizardFlagPayloads = analytics.getWizardFlagPayloads();
337
+ const switchboard = {
338
+ program: programId,
339
+ composed: true,
340
+ flags: wizardFlags,
341
+ flagPayloads: wizardFlagPayloads,
342
+ cliHarness: session.harness
343
+ };
344
+ const bindings = resolveScanBindings(switchboard);
345
+ const reportSchema = detectionReportSchema(recommend);
346
+ const schema = zodToJsonSchema(reportSchema);
347
+ const config = {
348
+ programId,
349
+ run: detectionRunDefinition(buildPrompt$1(session.installDir, targets, purpose, recommend)),
350
+ composed: true,
351
+ binding: bindings[0],
352
+ switchboard,
353
+ skillsBaseUrl: getSkillsBaseUrl(),
354
+ wizardFlags,
355
+ wizardFlagPayloads,
356
+ wizardMetadata,
357
+ scanReport: "defer"
358
+ };
359
+ const input = {
360
+ installDir: session.installDir,
361
+ credentials: session.credentials,
362
+ project: null,
363
+ apiUser: null,
364
+ flags: {
365
+ ci: session.ci,
366
+ signup: session.signup,
367
+ debug: session.debug,
368
+ e2eAsk: false,
369
+ localMcp: session.localMcp,
370
+ captureAio: false,
371
+ benchmark: false,
372
+ yaraReport: session.yaraReport
373
+ },
374
+ host: {
375
+ projectId: session.projectId,
376
+ apiKey: session.apiKey
377
+ }
378
+ };
379
+ const reduceUi = createUiReducer(getUI());
380
+ const forward = (event) => {
381
+ if (event.kind === "activity") onEvent?.(event.line);
382
+ if (reachesUi(event)) reduceUi(event);
383
+ };
384
+ for (let attempt = 0; attempt < 2; attempt++) {
385
+ const timeoutMs = attempt === 0 ? AGENTIC_DETECTION_FIRST_ATTEMPT_TIMEOUT_MS : AGENTIC_DETECTION_RETRY_TIMEOUT_MS;
386
+ const result = await runAgent({
387
+ ...config,
388
+ binding: bindings[attempt],
389
+ run: {
390
+ ...config.run,
391
+ structured: {
392
+ schema,
393
+ timeoutMs
394
+ }
395
+ }
396
+ }, input, { onProgress: forward });
397
+ if (result.outcome !== "success" && result.failure.code === ErrorCodes.AgenticDetectionTimeout) {
398
+ if (attempt === 0) {
399
+ onEvent?.("Project scan timed out; retrying...");
400
+ continue;
401
+ }
402
+ throw new AgenticDetectionTimeoutError(attempt + 1, timeoutMs);
403
+ }
404
+ if (result.outcome !== "success") {
405
+ if (result.failure.code === ErrorCodes.AgentInvalidStructuredOutput && attempt === 0) {
406
+ onEvent?.("Project scan returned invalid output; retrying...");
407
+ continue;
408
+ }
409
+ throw result.failure.error ?? new Error(result.failure.message);
410
+ }
411
+ if (result.structuredOutput !== void 0) {
412
+ const structured = reportSchema.safeParse(result.structuredOutput);
413
+ if (structured.success) return coerceAgenticReport(structured.data, targets.map((t) => t.id), {
414
+ recommend,
415
+ rerankIds
416
+ });
417
+ if (attempt === 0) onEvent?.("Project scan returned invalid output; retrying...");
418
+ continue;
419
+ }
420
+ const derived = deriveReportJson(result.snapshot.transcriptTail ?? "");
421
+ if (derived !== null) return coerceAgenticReport(derived, targets.map((t) => t.id), {
422
+ recommend,
423
+ rerankIds
424
+ });
425
+ if (attempt === 0) onEvent?.("Retrying project scan...");
426
+ }
427
+ throw new Error("Agent did not return a JSON object after retry");
428
+ }
429
+ //#endregion
430
+ //#region src/programs/detection/project-scope.ts
33
431
  /** Non-interactive project scoping — scan the repo agentically and pick which project the run integrates. */
34
432
  /** Integration framework targets for the agentic detector (id → display name). */
35
433
  const INTEGRATION_TARGETS = Object.entries(FRAMEWORK_REGISTRY).map(([id, config]) => ({
@@ -66,13 +464,13 @@ function captureOutcome(outcome, properties = {}) {
66
464
  });
67
465
  }
68
466
  /** Flag-gated non-interactive monorepo phase: scan, auto-choose the recommended project, re-point session.installDir; every failure leaves the session untouched. */
69
- async function scopeInstallDirToProject(session) {
467
+ async function scopeInstallDirToProject(session, runner) {
70
468
  await authenticate(session, "posthog-integration");
71
469
  if ((await analytics.getAllFlagsForWizard())["wizard-basic-integration-agentic-detection"] !== "true") {
72
470
  captureOutcome("flag-off");
73
471
  return;
74
472
  }
75
- getUI().log.info("Scanning the repo for projects...");
473
+ runner.log.info("Scanning the repo for projects...");
76
474
  const startedAt = Date.now();
77
475
  let report;
78
476
  try {
@@ -85,7 +483,7 @@ async function scopeInstallDirToProject(session) {
85
483
  const error = err instanceof Error ? err : new Error(String(err));
86
484
  if (error instanceof AgenticDetectionTimeoutError) {
87
485
  captureOutcome("timeout", { duration_ms: Date.now() - startedAt });
88
- getUI().log.warn(`${error.message}; continuing with the install dir as-is.`);
486
+ runner.log.warn(`${error.message}; continuing with the install dir as-is.`);
89
487
  return;
90
488
  }
91
489
  analytics.captureException(error, { step: "agentic_detection" });
@@ -93,7 +491,7 @@ async function scopeInstallDirToProject(session) {
93
491
  duration_ms: Date.now() - startedAt,
94
492
  error_message: error.message
95
493
  });
96
- getUI().log.warn(`Project scan failed (${error.message}); continuing with the install dir as-is.`);
494
+ runner.log.warn(`Project scan failed (${error.message}); continuing with the install dir as-is.`);
97
495
  return;
98
496
  }
99
497
  const { projects } = report;
@@ -110,7 +508,7 @@ async function scopeInstallDirToProject(session) {
110
508
  const project = chooseIntegrationProject(projects);
111
509
  if (!project) {
112
510
  captureOutcome("no-project", scanProperties);
113
- getUI().log.info("The scan found no supported project; continuing with the install dir as-is.");
511
+ runner.log.info("The scan found no supported project; continuing with the install dir as-is.");
114
512
  return;
115
513
  }
116
514
  session.installDir = resolveProjectDir(session.installDir, project.path);
@@ -119,10 +517,10 @@ async function scopeInstallDirToProject(session) {
119
517
  chosen_framework: project.targetId,
120
518
  chosen_path: project.path
121
519
  });
122
- getUI().log.info(`Continuing with ${project.path} (${project.framework}).`);
520
+ runner.log.info(`Continuing with ${project.path} (${project.framework}).`);
123
521
  }
124
522
  //#endregion
125
- //#region src/lib/programs/shared/health-check-step.ts
523
+ //#region src/programs/shared/health-check-step.ts
126
524
  function healthCheckReady(session) {
127
525
  if (!session.readinessResult) return false;
128
526
  if (session.signup) {
@@ -154,7 +552,180 @@ const HEALTH_CHECK_STEP = {
154
552
  }
155
553
  };
156
554
  //#endregion
157
- //#region src/lib/programs/posthog-integration/steps.ts
555
+ //#region src/programs/shared/package-scanning.ts
556
+ const POSTHOG_SDKS = new Set([
557
+ "posthog-js",
558
+ "posthog-node",
559
+ "posthog-react-native",
560
+ "posthog-android",
561
+ "posthog-ios"
562
+ ]);
563
+ const STRIPE_SDKS = new Set([
564
+ "stripe",
565
+ "@stripe/stripe-js",
566
+ "@stripe/react-stripe-js"
567
+ ]);
568
+ const MAX_PACKAGE_MATCHES = 500;
569
+ /**
570
+ * Find all package.json files under installDir via the shared bounded walk
571
+ * (depth cap, ignored dirs, symlink-loop protection, per-dir entry cap).
572
+ * Returns matches with detected SDKs.
573
+ */
574
+ function findPackageJsons(installDir, maxDepth = 3) {
575
+ const matches = [];
576
+ walkProjectFiles(installDir, (name, fullPath) => {
577
+ if (name !== "package.json" || matches.length >= MAX_PACKAGE_MATCHES) return;
578
+ const content = safeReadFile(fullPath);
579
+ if (content === null) return;
580
+ try {
581
+ const pkg = JSON.parse(content);
582
+ const depNames = [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
583
+ const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.has(d));
584
+ const stripeSdks = depNames.filter((d) => STRIPE_SDKS.has(d));
585
+ matches.push({
586
+ path: relative(installDir, fullPath) || "package.json",
587
+ posthogSdks,
588
+ stripeSdks
589
+ });
590
+ } catch {}
591
+ }, maxDepth);
592
+ return matches;
593
+ }
594
+ //#endregion
595
+ //#region src/programs/posthog-integration/detect.ts
596
+ async function detectPostHogIntegration(ctx) {
597
+ const session = ctx.session;
598
+ const installDir = session.installDir;
599
+ const detectedIntegration = await detectFramework(installDir);
600
+ if (detectedIntegration) {
601
+ const config = FRAMEWORK_REGISTRY[detectedIntegration];
602
+ const sessionOptions = {
603
+ installDir,
604
+ debug: session.debug,
605
+ signup: session.signup,
606
+ ci: session.ci,
607
+ benchmark: session.benchmark,
608
+ yaraReport: session.yaraReport
609
+ };
610
+ const context = await gatherFrameworkContext(config, sessionOptions);
611
+ for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) ctx.setFrameworkContext(key, value);
612
+ ctx.setFrameworkConfig(detectedIntegration, config);
613
+ ctx.setSkillId(detectedIntegration);
614
+ if (!session.detectedFrameworkLabel) ctx.setDetectedFramework(config.metadata.name);
615
+ const versionResult = await checkFrameworkVersion(config, sessionOptions);
616
+ if (versionResult.supported !== true) ctx.setUnsupportedVersion(versionResult.supported);
617
+ }
618
+ for (const feature of discoverFeatures(installDir)) ctx.addDiscoveredFeature(feature);
619
+ detectWarehouseSourcesForSuggestion(ctx, installDir);
620
+ detectExistingPostHog(ctx, installDir);
621
+ ctx.setDetectionComplete();
622
+ }
623
+ /**
624
+ * How the scan went, for the reporter to read later. Three states, and the
625
+ * absent one carries the most weight:
626
+ *
627
+ * absent this program never scanned. Only `posthog-integration` runs the
628
+ * scan below, but every program's intro screen resolves consent
629
+ * through the same store method, so the reporter is reached on runs
630
+ * where no scan ever happened.
631
+ * 'failed' the scan threw. A zero-count row would read as "scanned, found
632
+ * nothing", which is a different fact.
633
+ * 'ok' the scan ran. Zero sources is a real result and gets reported.
634
+ */
635
+ const WAREHOUSE_SCAN_STATE_KEY = "warehouseScanState";
636
+ /**
637
+ * Scan for data warehouse source signals (Postgres, Stripe, Hubspot, …) and,
638
+ * when found, stash them for a `wizard warehouse` suggestion on the outro.
639
+ * Runs unconditionally during `detect`, before the intro screen has asked
640
+ * about sharing. Reporting what this finds is a separate, later concern.
641
+ * See `reportWarehouseSourcesDetected` below.
642
+ *
643
+ * Deliberately a suggestion, not an inline agent run: a second credential-
644
+ * collecting agent run before the outro could `process.exit()` on any of its
645
+ * failure paths and cost the user the success outro on a run where PostHog
646
+ * installed fine.
647
+ *
648
+ * Calls `detectWarehouseSources` (a pure scan) rather than the warehouse
649
+ * program's `detectWarehousePrerequisites`, which writes a `detectError` when
650
+ * it finds nothing — that's right for `wizard warehouse` but here would show a
651
+ * spurious error and trip the CI prerequisites abort. No sources is a no-op.
652
+ *
653
+ * Best-effort: never let a scan failure break the wizard flow.
654
+ */
655
+ function detectWarehouseSourcesForSuggestion(ctx, installDir) {
656
+ try {
657
+ const sources = detectWarehouseSources(installDir);
658
+ ctx.setFrameworkContext(WAREHOUSE_SCAN_STATE_KEY, "ok");
659
+ if (sources.length === 0) return;
660
+ ctx.setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);
661
+ } catch (error) {
662
+ ctx.setFrameworkContext(WAREHOUSE_SCAN_STATE_KEY, "failed");
663
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), { step: "detectWarehouseSourcesForSuggestion" });
664
+ }
665
+ }
666
+ /**
667
+ * Fires the org stamp once per session, right after `authenticate()` succeeds
668
+ * — never from the consent path, since consent on the intro screen resolves
669
+ * before login and `session.apiUser` is unset there. Called right after
670
+ * `authenticate()` from run-wizard.ts's auth step and from bootstrap.ts,
671
+ * whichever completes it first for a given program; a no-op on every call
672
+ * after that. In the `--ci` path, project-scope.ts authenticates first as a
673
+ * prerequisite (no evidence gathered yet, so nothing would stamp there
674
+ * anyway) and this only ever runs from the later, idempotent bootstrap.ts
675
+ * call — still correctly finding no evidence, since CI skips the detect step.
676
+ */
677
+ function maybeStampAiSdkDetected(session) {
678
+ if (session.aiSdkStampReported) return;
679
+ session.aiSdkStampReported = true;
680
+ stampAiSdkDetected({
681
+ apiUser: session.apiUser,
682
+ discoveredFeatures: session.discoveredFeatures,
683
+ warehouseSources: getDetectedWarehouseSources(session),
684
+ mayReportScanResults: mayReportScanResults(session)
685
+ });
686
+ }
687
+ /**
688
+ * The single place scan results become telemetry. Called from
689
+ * `WizardStore.completeSetup()`, the point consent becomes final — the privacy
690
+ * panel's choice is reversible until then, so nothing may report earlier.
691
+ * The org stamp is a separate concern: see `maybeStampAiSdkDetected`, which
692
+ * runs post-auth rather than at consent resolution.
693
+ *
694
+ * Returns true when consent has resolved and the caller should latch
695
+ * `warehouseSourcesReported`, which is not the same as "this sent something":
696
+ * a decline, a failed scan, and a program that never scanned all resolve
697
+ * without sending.
698
+ */
699
+ function reportWarehouseSourcesDetected(session) {
700
+ if (session.warehouseSourcesReported) return false;
701
+ if (session.scanConsent === "undecided") return false;
702
+ if (mayReportScanResults(session)) {
703
+ const sources = getDetectedWarehouseSources(session);
704
+ if (session.frameworkContext[WAREHOUSE_SCAN_STATE_KEY] !== "ok") return true;
705
+ analytics.wizardCapture("warehouse sources detected", {
706
+ warehouse_source_count: sources.length,
707
+ warehouse_source_kinds: sources.map((s) => s.kind),
708
+ warehouse_source_modes: sources.map((s) => s.mode)
709
+ });
710
+ if (sources.length > 0) {
711
+ analytics.setTag("warehouse_source_kinds", sources.map((s) => s.kind).join(","));
712
+ analytics.setTag("warehouse_source_count", sources.length);
713
+ }
714
+ }
715
+ return true;
716
+ }
717
+ /** Dependency-level signal, not a verified install. A failed scan reports false. */
718
+ function detectExistingPostHog(ctx, installDir) {
719
+ try {
720
+ const pkgJsons = findPackageJsons(installDir);
721
+ ctx.setPosthogSdkDetected(pkgJsons.some((p) => p.posthogSdks.length > 0));
722
+ } catch (error) {
723
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), { step: "detectExistingPosthog" });
724
+ ctx.setPosthogSdkDetected(false);
725
+ }
726
+ }
727
+ //#endregion
728
+ //#region src/programs/posthog-integration/steps.ts
158
729
  function needsSetup$1(session) {
159
730
  const config = session.frameworkConfig;
160
731
  if (!config?.metadata.setup?.questions) return false;
@@ -475,7 +1046,7 @@ const StatusPeekTrigger = ({ store, duration = 1e4 }) => {
475
1046
  return /* @__PURE__ */ jsx(Text, { children: "You can view the Wizard's status below." });
476
1047
  };
477
1048
  //#endregion
478
- //#region src/lib/programs/posthog-integration/content/data-flow.tsx
1049
+ //#region src/ui/tui/decks/posthog-integration/data-flow.tsx
479
1050
  /**
480
1051
  * POSTHOG_DATA_FLOW — ASCII diagram of the PostHog event ingestion flow.
481
1052
  */
@@ -644,7 +1215,7 @@ const POSTHOG_DATA_FLOW = {
644
1215
  ]
645
1216
  };
646
1217
  //#endregion
647
- //#region src/lib/programs/posthog-integration/content/product-suite.tsx
1218
+ //#region src/ui/tui/decks/posthog-integration/product-suite.tsx
648
1219
  /**
649
1220
  * PRODUCT_SUITE_BLOCK — Two-column listing of PostHog products.
650
1221
  */
@@ -764,7 +1335,7 @@ const PRODUCT_SUITE_BLOCK = {
764
1335
  ]
765
1336
  };
766
1337
  //#endregion
767
- //#region src/lib/programs/posthog-integration/content/line-chart.tsx
1338
+ //#region src/ui/tui/decks/posthog-integration/line-chart.tsx
768
1339
  /**
769
1340
  * LINE_CHART_BLOCK — ASCII trends chart illustrating an insight.
770
1341
  */
@@ -888,7 +1459,7 @@ const LINE_CHART_BLOCK = {
888
1459
  ]
889
1460
  };
890
1461
  //#endregion
891
- //#region src/lib/programs/posthog-integration/content/funnel.tsx
1462
+ //#region src/ui/tui/decks/posthog-integration/funnel.tsx
892
1463
  /**
893
1464
  * FUNNEL_BLOCK — ASCII funnel illustrating step conversion.
894
1465
  */
@@ -1068,7 +1639,7 @@ const FUNNEL_BLOCK = {
1068
1639
  ]
1069
1640
  };
1070
1641
  //#endregion
1071
- //#region src/lib/programs/posthog-integration/content/index.tsx
1642
+ //#region src/ui/tui/decks/posthog-integration/index.tsx
1072
1643
  /**
1073
1644
  * Integration learn-deck — the narrative script played while the agent
1074
1645
  * runs the PostHog integration flow. Weaves typewriter lines, pauses,
@@ -1257,7 +1828,7 @@ const getContentBlocks$5 = (store) => [
1257
1828
  }
1258
1829
  ];
1259
1830
  //#endregion
1260
- //#region src/lib/programs/posthog-integration/handoff.ts
1831
+ //#region src/programs/posthog-integration/handoff.ts
1261
1832
  /**
1262
1833
  * The one-line prompt the operator pastes into their own coding agent after a
1263
1834
  * run: open the setup-report notebook, work its "Verify before merging"
@@ -1271,7 +1842,7 @@ function buildCodingAgentPrompt(notebookUrl) {
1271
1842
  return `Open ${notebookUrl} (the PostHog setup report) and work through its "Verify before merging" checklist: investigate each item, then list the changes you'd make and get my approval before applying any of them.`;
1272
1843
  }
1273
1844
  //#endregion
1274
- //#region src/lib/programs/posthog-integration/index.ts
1845
+ //#region src/programs/posthog-integration/index.ts
1275
1846
  const DASHBOARD_DEEP_LINK_KEY = "dashboardDeepLink";
1276
1847
  const WAREHOUSE_SOURCES_DOCS_URL = "https://posthog.com/docs/data-warehouse/sources";
1277
1848
  /** Task type of the seeded step below, matched against the drain's result. */
@@ -1428,8 +1999,8 @@ const posthogIntegrationConfig = {
1428
1999
  disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
1429
2000
  seedTasks: warehouseSeedTasks,
1430
2001
  excludedTaskTypes: (flags) => flags["wizard-default-aio-logs"] === "false" ? ["ai-observability", "logs"] : [],
1431
- ciPreRun: async (session) => {
1432
- await scopeInstallDirToProject(session);
2002
+ ciPreRun: async (session, runner) => {
2003
+ await scopeInstallDirToProject(session, runner);
1433
2004
  const integration = await detectFramework(session.installDir);
1434
2005
  if (!integration) {
1435
2006
  await wizardAbort({
@@ -1452,7 +2023,7 @@ const posthogIntegrationConfig = {
1452
2023
  });
1453
2024
  for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) session.frameworkContext[key] = value;
1454
2025
  },
1455
- run: async (session) => {
2026
+ run: async (session, runner) => {
1456
2027
  const config = session.frameworkConfig;
1457
2028
  const typeScriptDetected = isUsingTypeScript({ installDir: session.installDir });
1458
2029
  session.typescript = typeScriptDetected;
@@ -1463,9 +2034,9 @@ const posthogIntegrationConfig = {
1463
2034
  const packageJson = await tryGetPackageJson({ installDir: session.installDir });
1464
2035
  if (packageJson) {
1465
2036
  const { hasDeclaredDependency } = await import("./package-json-DY70kkNp.js").then((n) => n.i);
1466
- if (!hasDeclaredDependency(config.detection.packageName, packageJson)) getUI().log.warn(`${config.detection.packageDisplayName} does not seem to be installed. Continuing anyway — the agent will handle it.`);
2037
+ if (!hasDeclaredDependency(config.detection.packageName, packageJson)) runner.log.warn(`${config.detection.packageDisplayName} does not seem to be installed. Continuing anyway — the agent will handle it.`);
1467
2038
  frameworkVersion = config.detection.getVersion(packageJson);
1468
- } else getUI().log.warn("Could not find package.json. Continuing anyway — the agent will handle it.");
2039
+ } else runner.log.warn("Could not find package.json. Continuing anyway — the agent will handle it.");
1469
2040
  } else frameworkVersion = config.detection.getVersion(null);
1470
2041
  if (frameworkVersion && config.detection.getVersionBucket) {
1471
2042
  const versionBucket = config.detection.getVersionBucket(frameworkVersion);
@@ -1531,7 +2102,7 @@ ${warehouseReportInstruction(session)}
1531
2102
  postRun: async (sess, credentials) => {
1532
2103
  const envVars = config.environment.getEnvVars(credentials.projectApiKey, credentials.host.apiHost);
1533
2104
  if (config.environment.uploadToHosting) {
1534
- const { uploadEnvironmentVariablesStep } = await import("./steps-BZcXRJNY.js");
2105
+ const { uploadEnvironmentVariablesStep } = await import("./steps-gx0Pq4I4.js");
1535
2106
  const uploadedEnvVars = await uploadEnvironmentVariablesStep(envVars, {
1536
2107
  integration: config.metadata.integration,
1537
2108
  session: sess
@@ -1586,7 +2157,7 @@ const integrationRunStep = {
1586
2157
  isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
1587
2158
  };
1588
2159
  //#endregion
1589
- //#region src/lib/programs/revenue-analytics/detect.ts
2160
+ //#region src/programs/revenue-analytics/detect.ts
1590
2161
  /**
1591
2162
  * Revenue analytics prerequisite detection.
1592
2163
  *
@@ -1679,7 +2250,7 @@ function detectRevenuePrerequisites(session, setFrameworkContext) {
1679
2250
  setFrameworkContext("detectedPackagePaths", matches.filter((m) => m.posthogSdks.length > 0 || m.stripeSdks.length > 0).map((m) => m.path));
1680
2251
  }
1681
2252
  //#endregion
1682
- //#region src/lib/programs/revenue-analytics/steps.ts
2253
+ //#region src/programs/revenue-analytics/steps.ts
1683
2254
  const REVENUE_ANALYTICS_PROGRAM = [
1684
2255
  {
1685
2256
  id: "detect",
@@ -1718,7 +2289,7 @@ const REVENUE_ANALYTICS_PROGRAM = [
1718
2289
  }
1719
2290
  ];
1720
2291
  //#endregion
1721
- //#region src/lib/programs/agent-skill/content/index.tsx
2292
+ //#region src/ui/tui/decks/agent-skill/index.tsx
1722
2293
  /**
1723
2294
  * Agent-skill learn-deck — the short three-line sequence shown while a
1724
2295
  * skill-based program (audit, revenue-analytics, agent-skill, etc.)
@@ -1750,7 +2321,7 @@ const getContentBlocks$4 = (store) => {
1750
2321
  ];
1751
2322
  };
1752
2323
  //#endregion
1753
- //#region src/lib/programs/revenue-analytics/index.ts
2324
+ //#region src/programs/revenue-analytics/index.ts
1754
2325
  const revenueAnalyticsConfig = {
1755
2326
  command: "revenue-analytics",
1756
2327
  description: "Set up PostHog for Revenue Analytics",
@@ -1774,7 +2345,7 @@ const revenueAnalyticsConfig = {
1774
2345
  requires: ["posthog-integration"]
1775
2346
  };
1776
2347
  //#endregion
1777
- //#region src/lib/programs/warehouse-source/steps.ts
2348
+ //#region src/programs/warehouse-source/steps.ts
1778
2349
  const WAREHOUSE_SOURCE_PROGRAM = [
1779
2350
  {
1780
2351
  id: "detect",
@@ -1812,7 +2383,7 @@ const WAREHOUSE_SOURCE_PROGRAM = [
1812
2383
  }
1813
2384
  ];
1814
2385
  //#endregion
1815
- //#region src/lib/programs/warehouse-source/index.ts
2386
+ //#region src/programs/warehouse-source/index.ts
1816
2387
  /**
1817
2388
  * Inject the detected sources (and their creation mode) into the prompt so the
1818
2389
  * skill knows what to set up. The *how* — in-CLI creation vs deep-link, field
@@ -1855,7 +2426,7 @@ const warehouseSourceConfig = {
1855
2426
  requires: ["posthog-integration"]
1856
2427
  };
1857
2428
  //#endregion
1858
- //#region src/lib/programs/agent-skill/steps.ts
2429
+ //#region src/programs/agent-skill/steps.ts
1859
2430
  const AGENT_SKILL_STEPS = [
1860
2431
  {
1861
2432
  id: "intro",
@@ -1889,7 +2460,7 @@ const AGENT_SKILL_STEPS = [
1889
2460
  }
1890
2461
  ];
1891
2462
  //#endregion
1892
- //#region src/lib/programs/agent-skill/index.ts
2463
+ //#region src/programs/agent-skill/index.ts
1893
2464
  function createSkillProgram(opts) {
1894
2465
  return {
1895
2466
  command: opts.command,
@@ -1915,7 +2486,7 @@ function createSkillProgram(opts) {
1915
2486
  };
1916
2487
  }
1917
2488
  //#endregion
1918
- //#region src/lib/programs/audit/detect.ts
2489
+ //#region src/programs/audit/detect.ts
1919
2490
  /** `[ABORT] <reason>` cases the audit skill can emit. Reason strings are
1920
2491
  * defined in the skill's `Abort statuses` section. */
1921
2492
  const AUDIT_ABORT_CASES = [{
@@ -1926,7 +2497,7 @@ const AUDIT_ABORT_CASES = [{
1926
2497
  docsUrl: "https://posthog.com/docs/getting-started/install"
1927
2498
  }];
1928
2499
  //#endregion
1929
- //#region src/lib/programs/audit/seed.ts
2500
+ //#region src/programs/audit/seed.ts
1930
2501
  /**
1931
2502
  * The 10 source-tree checks the audit runs, plus one row for the PostHog-side
1932
2503
  * sweep and two workflow rows at the end (so the skill's
@@ -2042,7 +2613,7 @@ function seedAuditLedger(installDir, checks = AUDIT_SEED_CHECKS) {
2042
2613
  logToFile(`seedAuditLedger: wrote ${checks.length} entries to ${target}`);
2043
2614
  }
2044
2615
  //#endregion
2045
- //#region src/lib/programs/audit/index.ts
2616
+ //#region src/programs/audit/index.ts
2046
2617
  /** Audit-specific screens for the shared agent-skill pipeline. */
2047
2618
  const AUDIT_SCREEN_BY_STEP = {
2048
2619
  intro: "audit-intro",
@@ -2076,10 +2647,10 @@ const baseConfig = createSkillProgram({
2076
2647
  requires: ["posthog-integration"],
2077
2648
  abortCases: AUDIT_ABORT_CASES
2078
2649
  });
2079
- const auditRun = async (session) => {
2650
+ const auditRun = async (session, runner) => {
2080
2651
  seedBeforeAuditRun(session);
2081
2652
  if (!baseConfig.run) throw new Error("Audit program has no run configuration.");
2082
- const baseRun = typeof baseConfig.run === "function" ? await baseConfig.run(session) : baseConfig.run;
2653
+ const baseRun = typeof baseConfig.run === "function" ? await baseConfig.run(session, runner) : baseConfig.run;
2083
2654
  return {
2084
2655
  ...baseRun,
2085
2656
  buildOutroData: (sess, credentials) => {
@@ -2115,7 +2686,7 @@ const auditConfig = {
2115
2686
  }
2116
2687
  };
2117
2688
  //#endregion
2118
- //#region src/lib/programs/events-audit/steps.ts
2689
+ //#region src/programs/events-audit/steps.ts
2119
2690
  function needsSetup(session) {
2120
2691
  const config = session.frameworkConfig;
2121
2692
  if (!config?.metadata.setup?.questions) return false;
@@ -2167,7 +2738,7 @@ const EVENTS_AUDIT_PROGRAM = [
2167
2738
  }
2168
2739
  ];
2169
2740
  //#endregion
2170
- //#region src/lib/programs/events-audit/seed.ts
2741
+ //#region src/programs/events-audit/seed.ts
2171
2742
  /**
2172
2743
  * The 7 phases the events-audit skill marches through. One check per area
2173
2744
  * so PendingChecksList renders a clean linear pipeline (area = bold header,
@@ -2223,7 +2794,7 @@ const EVENTS_AUDIT_SEED_CHECKS = [
2223
2794
  }
2224
2795
  ];
2225
2796
  //#endregion
2226
- //#region src/lib/programs/events-audit/index.ts
2797
+ //#region src/programs/events-audit/index.ts
2227
2798
  const DOCS_URL$3 = "https://posthog.com/docs/product-analytics/best-practices";
2228
2799
  /**
2229
2800
  * No CLI word of its own since the audit family took over: `wizard audit
@@ -2284,7 +2855,7 @@ Project context:
2284
2855
  }
2285
2856
  };
2286
2857
  //#endregion
2287
- //#region src/lib/programs/posthog-doctor/steps.ts
2858
+ //#region src/programs/posthog-doctor/steps.ts
2288
2859
  const POSTHOG_DOCTOR_PROGRAM = [
2289
2860
  {
2290
2861
  id: "intro",
@@ -2313,7 +2884,7 @@ const POSTHOG_DOCTOR_PROGRAM = [
2313
2884
  }
2314
2885
  ];
2315
2886
  //#endregion
2316
- //#region src/lib/programs/posthog-doctor/types.ts
2887
+ //#region src/programs/posthog-doctor/types.ts
2317
2888
  const HealthIssueSeveritySchema = z.enum([
2318
2889
  "critical",
2319
2890
  "warning",
@@ -2337,7 +2908,7 @@ const HealthIssueListResponseSchema = z.object({
2337
2908
  previous: z.string().nullable().optional()
2338
2909
  });
2339
2910
  //#endregion
2340
- //#region src/lib/programs/posthog-doctor/fetch.ts
2911
+ //#region src/programs/posthog-doctor/fetch.ts
2341
2912
  async function fetchHealthIssues(accessToken, baseUrl, projectId) {
2342
2913
  const endpoint = `/api/environments/${projectId}/health_issues/`;
2343
2914
  const url = `${baseUrl}${endpoint}?status=active&dismissed=false&limit=250`;
@@ -2358,7 +2929,7 @@ async function fetchHealthIssues(accessToken, baseUrl, projectId) {
2358
2929
  }
2359
2930
  }
2360
2931
  //#endregion
2361
- //#region src/lib/programs/posthog-doctor/kind-metadata.ts
2932
+ //#region src/programs/posthog-doctor/kind-metadata.ts
2362
2933
  const KIND_METADATA = {
2363
2934
  ingestion_lag: {
2364
2935
  title: "Ingestion is delayed",
@@ -2428,7 +2999,7 @@ function getKindMeta(kind) {
2428
2999
  };
2429
3000
  }
2430
3001
  //#endregion
2431
- //#region src/lib/programs/posthog-doctor/index.ts
3002
+ //#region src/programs/posthog-doctor/index.ts
2432
3003
  const posthogDoctorConfig = {
2433
3004
  command: "doctor",
2434
3005
  description: "Diagnose your PostHog project setup",
@@ -2439,7 +3010,7 @@ const posthogDoctorConfig = {
2439
3010
  disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk]
2440
3011
  };
2441
3012
  //#endregion
2442
- //#region src/lib/programs/web-analytics-doctor/detect.ts
3013
+ //#region src/programs/web-analytics-doctor/detect.ts
2443
3014
  const WEB_ANALYTICS_ABORT_CASES = [
2444
3015
  {
2445
3016
  match: /^no web analytics events$/i,
@@ -2506,7 +3077,7 @@ function detectWebAnalyticsPrerequisites(session, setFrameworkContext) {
2506
3077
  setFrameworkContext("detectedPosthogSdks", sdks);
2507
3078
  }
2508
3079
  //#endregion
2509
- //#region src/lib/programs/web-analytics-doctor/steps.ts
3080
+ //#region src/programs/web-analytics-doctor/steps.ts
2510
3081
  const WEB_ANALYTICS_DOCTOR_PROGRAM = [{
2511
3082
  id: "detect",
2512
3083
  label: "Detecting prerequisites",
@@ -2532,7 +3103,7 @@ const webAnalyticsDoctorConfig = {
2532
3103
  parentCommand: "audit"
2533
3104
  };
2534
3105
  //#endregion
2535
- //#region src/lib/programs/migration/steps.ts
3106
+ //#region src/programs/migration/steps.ts
2536
3107
  const MIGRATION_PROGRAM = [
2537
3108
  {
2538
3109
  id: "intro",
@@ -2566,7 +3137,7 @@ const MIGRATION_PROGRAM = [
2566
3137
  }
2567
3138
  ];
2568
3139
  //#endregion
2569
- //#region src/lib/programs/migration/content/vendor-stack.tsx
3140
+ //#region src/ui/tui/decks/migration/vendor-stack.tsx
2570
3141
  /**
2571
3142
  * Vendor cost stack — the multi-tool baseline a typical migration target has
2572
3143
  * before consolidating onto PostHog. Numbers from each vendor's published
@@ -2646,7 +3217,7 @@ const VENDOR_STACK_BLOCK = {
2646
3217
  ]
2647
3218
  };
2648
3219
  //#endregion
2649
- //#region src/lib/programs/migration/content/free-tier.tsx
3220
+ //#region src/ui/tui/decks/migration/free-tier.tsx
2650
3221
  /**
2651
3222
  * PostHog free-tier highlights — the numbers a migrating team gets back when
2652
3223
  * they consolidate. Sourced from posthog.com/pricing.md.
@@ -2752,7 +3323,7 @@ const FREE_TIER_BLOCK = {
2752
3323
  ]
2753
3324
  };
2754
3325
  //#endregion
2755
- //#region src/lib/programs/migration/content/pricing-structure.tsx
3326
+ //#region src/ui/tui/decks/migration/pricing-structure.tsx
2756
3327
  /**
2757
3328
  * Pricing structure block — what happens after the free tier.
2758
3329
  */
@@ -2793,7 +3364,7 @@ const PRICING_STRUCTURE_BLOCK = {
2793
3364
  ]
2794
3365
  };
2795
3366
  //#endregion
2796
- //#region src/lib/programs/migration/content/index.tsx
3367
+ //#region src/ui/tui/decks/migration/index.tsx
2797
3368
  /**
2798
3369
  * Migration learn deck (statsig variant). Statsig is the only `migrate`
2799
3370
  * variant today, so this deck plays as-is when the wizard runs
@@ -3041,7 +3612,7 @@ const getContentBlocks$3 = (store) => [
3041
3612
  FUNNEL_BLOCK
3042
3613
  ];
3043
3614
  //#endregion
3044
- //#region src/lib/programs/migration/index.ts
3615
+ //#region src/programs/migration/index.ts
3045
3616
  const MIGRATION_REPORT_FILE = "migration-report.md";
3046
3617
  const MIGRATION_ABORT_CASES = [{
3047
3618
  match: /^no source-sdk calls found$/i,
@@ -3073,7 +3644,7 @@ const migrationConfig = {
3073
3644
  requires: ["posthog-integration"]
3074
3645
  };
3075
3646
  //#endregion
3076
- //#region src/lib/programs/error-tracking-upload-source-maps/detect.ts
3647
+ //#region src/programs/error-tracking-upload-source-maps/detect.ts
3077
3648
  const DISPLAY_NAME = {
3078
3649
  web: "Web (JavaScript)",
3079
3650
  nextjs: "Next.js",
@@ -3182,7 +3753,7 @@ const SOURCE_MAPS_CONTEXT_KEYS = {
3182
3753
  selectedPath: "sourceMapsSelectedPath"
3183
3754
  };
3184
3755
  //#endregion
3185
- //#region src/lib/programs/error-tracking-upload-source-maps/steps.ts
3756
+ //#region src/programs/error-tracking-upload-source-maps/steps.ts
3186
3757
  function projectSelected(session) {
3187
3758
  return session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.selectedVariant] != null;
3188
3759
  }
@@ -3225,7 +3796,7 @@ const ERROR_TRACKING_UPLOAD_SOURCE_MAPS_PROGRAM = [
3225
3796
  }
3226
3797
  ];
3227
3798
  //#endregion
3228
- //#region src/lib/programs/error-tracking-upload-source-maps/prompt.ts
3799
+ //#region src/programs/error-tracking-upload-source-maps/prompt.ts
3229
3800
  const SOURCE_MAPS_DETECTION_FAILED_PROMPT = `Detection did not pick a source maps skill variant for this project.
3230
3801
  Emit: ${AgentSignals.ABORT} unsupported-platform
3231
3802
  Then halt.`;
@@ -3423,7 +3994,7 @@ STEP 9 — Summarise and hand off. (skill: "Verify and hand off")
3423
3994
  `;
3424
3995
  }
3425
3996
  //#endregion
3426
- //#region src/lib/programs/error-tracking-upload-source-maps/content/index.tsx
3997
+ //#region src/ui/tui/decks/error-tracking-upload-source-maps/index.tsx
3427
3998
  /**
3428
3999
  * Source-maps learn-deck — the narrative played in the run screen's left
3429
4000
  * pane (LearnCard) while the agent wires source-map upload into the build.
@@ -3860,18 +4431,9 @@ function installSteeringSnippet(filePath) {
3860
4431
  };
3861
4432
  }
3862
4433
  //#endregion
3863
- //#region src/lib/programs/shared/posthog-cli-preinstall.ts
3864
- /**
3865
- * Machine-global posthog-cli pre-install, shared by the programs whose symbol
3866
- * upload shells out to it (error-tracking and error-tracking-upload-source-maps).
3867
- *
3868
- * The agent cannot install a global package — warlock blocks `npm install -g`
3869
- * — so the wizard does it in-process, at most once per process. Warn, don't
3870
- * fail: the run still instruments capture, and only the release build's upload
3871
- * needs the CLI.
3872
- */
4434
+ //#region src/programs/shared/posthog-cli-preinstall.ts
3873
4435
  let attempted = false;
3874
- function preinstallPostHogCliOnce(failureEvent, properties) {
4436
+ function preinstallPostHogCliOnce(failureEvent, properties, log) {
3875
4437
  if (attempted) return;
3876
4438
  attempted = true;
3877
4439
  const result = installOrUpdatePostHogCli();
@@ -3880,10 +4442,10 @@ function preinstallPostHogCliOnce(failureEvent, properties) {
3880
4442
  ...properties,
3881
4443
  error: String(result.error).slice(0, 500)
3882
4444
  });
3883
- getUI().log.warn(`Could not pre-install posthog-cli (${result.error}). Your release build will fail to upload debug symbols until it's installed: npm install -g @posthog/cli@latest`);
4445
+ log.warn(`Could not pre-install posthog-cli (${result.error}). Your release build will fail to upload debug symbols until it's installed: npm install -g @posthog/cli@latest`);
3884
4446
  }
3885
4447
  //#endregion
3886
- //#region src/lib/programs/error-tracking-upload-source-maps/index.ts
4448
+ //#region src/programs/error-tracking-upload-source-maps/index.ts
3887
4449
  const REPORT_FILE$1 = "posthog-source-maps-report.md";
3888
4450
  const DOCS_URL$1 = "https://posthog.com/docs/error-tracking/upload-source-maps";
3889
4451
  /**
@@ -3891,8 +4453,8 @@ const DOCS_URL$1 = "https://posthog.com/docs/error-tracking/upload-source-maps";
3891
4453
  * (`VARIANTS_REQUIRING_POSTHOG_CLI`). See `preinstallPostHogCliOnce` for the
3892
4454
  * once-per-process guard and the warn-don't-fail handling.
3893
4455
  */
3894
- function ensurePostHogCli(variant) {
3895
- preinstallPostHogCliOnce("source maps posthog-cli preinstall failed", { variant });
4456
+ function ensurePostHogCli(variant, log) {
4457
+ preinstallPostHogCliOnce("source maps posthog-cli preinstall failed", { variant }, log);
3896
4458
  }
3897
4459
  const errorTrackingUploadSourceMapsConfig = {
3898
4460
  command: "upload-source-maps",
@@ -3903,13 +4465,13 @@ const errorTrackingUploadSourceMapsConfig = {
3903
4465
  reportFile: REPORT_FILE$1,
3904
4466
  getContentBlocks: getContentBlocks$2,
3905
4467
  requires: ["posthog-integration"],
3906
- run: (_session) => {
4468
+ run: (_session, runner) => {
3907
4469
  const readSelection = () => {
3908
- const variant = getUI().getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedVariant);
4470
+ const variant = runner.getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedVariant);
3909
4471
  return {
3910
4472
  variant,
3911
- displayName: getUI().getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedDisplayName),
3912
- projectPath: getUI().getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedPath),
4473
+ displayName: runner.getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedDisplayName),
4474
+ projectPath: runner.getFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.selectedPath),
3913
4475
  skillId: variant ? `error-tracking-upload-source-maps-${variant}` : void 0
3914
4476
  };
3915
4477
  };
@@ -3925,7 +4487,7 @@ const errorTrackingUploadSourceMapsConfig = {
3925
4487
  customPrompt: (ctx) => {
3926
4488
  const { variant, displayName, projectPath, skillId } = readSelection();
3927
4489
  if (!skillId || !variant) return SOURCE_MAPS_DETECTION_FAILED_PROMPT;
3928
- if (VARIANTS_REQUIRING_POSTHOG_CLI.has(variant)) ensurePostHogCli(variant);
4490
+ if (VARIANTS_REQUIRING_POSTHOG_CLI.has(variant)) ensurePostHogCli(variant, runner.log);
3929
4491
  const uiHost = ctx.host.appHost.replace(/\/$/, "");
3930
4492
  return buildSourceMapsUploadPrompt({
3931
4493
  displayName,
@@ -3941,7 +4503,7 @@ const errorTrackingUploadSourceMapsConfig = {
3941
4503
  },
3942
4504
  postRun: () => {
3943
4505
  const { variant } = readSelection();
3944
- if (variant) getUI().setFrameworkContext("sourceMapsCompletedVariant", variant);
4506
+ if (variant) runner.setFrameworkContext("sourceMapsCompletedVariant", variant);
3945
4507
  return Promise.resolve();
3946
4508
  },
3947
4509
  buildOutroData: () => {
@@ -3956,13 +4518,13 @@ const errorTrackingUploadSourceMapsConfig = {
3956
4518
  }
3957
4519
  };
3958
4520
  //#endregion
3959
- //#region src/lib/programs/error-tracking/content/index.tsx
4521
+ //#region src/ui/tui/decks/error-tracking/index.tsx
3960
4522
  const getContentBlocks$1 = (store) => buildSourceMapsDeck(store, {
3961
4523
  intro: "I'm wiring PostHog Error Tracking into your project.",
3962
4524
  wiring: "If your platform ships minified code or stripped binaries, I also hook source-map or debug-symbol upload into your build, tied to each release you ship."
3963
4525
  });
3964
4526
  //#endregion
3965
- //#region src/lib/programs/replay-vision/index.ts
4527
+ //#region src/programs/replay-vision/index.ts
3966
4528
  const REPLAY_VISION_REPORT_FILE = "posthog-replay-vision-report.md";
3967
4529
  /**
3968
4530
  * The platforms session replay can actually record on. Replay vision watches
@@ -4075,8 +4637,8 @@ const replayVisionConfig = {
4075
4637
  }),
4076
4638
  agentFlow: "replay-vision",
4077
4639
  steps: [DETECT_STEP, ...AGENT_SKILL_STEPS],
4078
- ciPreRun: async (session) => {
4079
- await scopeInstallDirToProject(session);
4640
+ ciPreRun: async (session, runner) => {
4641
+ await scopeInstallDirToProject(session, runner);
4080
4642
  const integration = await detectFramework(session.installDir);
4081
4643
  if (!integration) {
4082
4644
  await wizardAbort({
@@ -4106,7 +4668,7 @@ const replayVisionConfig = {
4106
4668
  }
4107
4669
  };
4108
4670
  //#endregion
4109
- //#region src/lib/programs/error-tracking/content/tips.ts
4671
+ //#region src/ui/tui/decks/error-tracking/tips.ts
4110
4672
  const ERROR_TRACKING_TIPS = [
4111
4673
  {
4112
4674
  id: "session-replay",
@@ -4130,7 +4692,7 @@ const ERROR_TRACKING_TIPS = [
4130
4692
  ];
4131
4693
  const getTips$1 = () => ERROR_TRACKING_TIPS;
4132
4694
  //#endregion
4133
- //#region src/lib/programs/error-tracking/detect-agentic.ts
4695
+ //#region src/programs/error-tracking/detect-agentic.ts
4134
4696
  /** frameworkContext key for the picked project's path, relative to the repo root. */
4135
4697
  const ERROR_TRACKING_PROJECT_PATH_KEY = "errorTrackingProjectPath";
4136
4698
  /** KMP skill variants carry no `framework` tag, so orchestrator preflight aborts every KMP run. */
@@ -4175,7 +4737,7 @@ async function gatherErrorTrackingContext(session) {
4175
4737
  for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) session.frameworkContext[key] = value;
4176
4738
  }
4177
4739
  //#endregion
4178
- //#region src/lib/programs/error-tracking/index.ts
4740
+ //#region src/programs/error-tracking/index.ts
4179
4741
  const ERROR_TRACKING_REPORT_FILE = "posthog-error-tracking-report.md";
4180
4742
  const ERROR_TRACKING_DOCS_URL = "https://posthog.com/docs/error-tracking";
4181
4743
  /**
@@ -4207,9 +4769,9 @@ async function abortUnsupportedPlatform(integration) {
4207
4769
  * shell out to it. See `preinstallPostHogCliOnce` for the once-per-process
4208
4770
  * guard and the warn-don't-fail handling.
4209
4771
  */
4210
- function maybePreinstallPostHogCli(integration) {
4772
+ function maybePreinstallPostHogCli(integration, log) {
4211
4773
  if (!integration || !SYMBOL_UPLOAD_CLI_FRAMEWORKS.has(integration)) return;
4212
- preinstallPostHogCliOnce("error tracking posthog-cli preinstall failed", { integration });
4774
+ preinstallPostHogCliOnce("error tracking posthog-cli preinstall failed", { integration }, log);
4213
4775
  }
4214
4776
  /**
4215
4777
  * After login, the scan lists the repo's projects and the user picks one, as in
@@ -4304,12 +4866,12 @@ const errorTrackingConfig = {
4304
4866
  reportFile: ERROR_TRACKING_REPORT_FILE,
4305
4867
  getContentBlocks: getContentBlocks$1,
4306
4868
  getTips: getTips$1,
4307
- run: (session) => {
4308
- maybePreinstallPostHogCli(session.integration);
4869
+ run: (session, runner) => {
4870
+ maybePreinstallPostHogCli(session.integration, runner.log);
4309
4871
  return Promise.resolve(ERROR_TRACKING_RUN);
4310
4872
  },
4311
- ciPreRun: async (session) => {
4312
- await scopeInstallDirToProject(session);
4873
+ ciPreRun: async (session, runner) => {
4874
+ await scopeInstallDirToProject(session, runner);
4313
4875
  const integration = await detectFramework(session.installDir);
4314
4876
  if (!integration) {
4315
4877
  await wizardAbort({
@@ -4330,7 +4892,7 @@ const errorTrackingConfig = {
4330
4892
  }
4331
4893
  };
4332
4894
  //#endregion
4333
- //#region src/lib/programs/self-driving/detect.ts
4895
+ //#region src/programs/self-driving/detect.ts
4334
4896
  /**
4335
4897
  * Self-driving prerequisite detection + abort vocabulary.
4336
4898
  *
@@ -4596,7 +5158,7 @@ function detectConnectedTools(installDir, setFrameworkContext) {
4596
5158
  }
4597
5159
  }
4598
5160
  //#endregion
4599
- //#region src/lib/programs/self-driving/detect-agentic.ts
5161
+ //#region src/programs/self-driving/detect-agentic.ts
4600
5162
  function classify(integration, hasPostHog) {
4601
5163
  if (integration == null) return {
4602
5164
  instrumentable: false,
@@ -4651,7 +5213,7 @@ async function prepSelfDrivingIntegration(session) {
4651
5213
  for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) session.frameworkContext[key] = value;
4652
5214
  }
4653
5215
  //#endregion
4654
- //#region src/lib/programs/self-driving/steps.ts
5216
+ //#region src/programs/self-driving/steps.ts
4655
5217
  /** True once detection found PostHog already present in the project. */
4656
5218
  const postHogPresent = (session) => session.frameworkContext[POSTHOG_PRESENT_KEY] === true;
4657
5219
  /** Absolute dir to integrate into: the picked sub-app (LLM output — the shared resolver clamps escapes), else the repo root. */
@@ -4727,7 +5289,7 @@ const SELF_DRIVING_PROGRAM = [
4727
5289
  }
4728
5290
  ];
4729
5291
  //#endregion
4730
- //#region src/lib/programs/self-driving/prompt.ts
5292
+ //#region src/programs/self-driving/prompt.ts
4731
5293
  /**
4732
5294
  * Render the deterministic codebase-tool scan for the prompt. STEP 4 and
4733
5295
  * STEP 5 read this instead of the agent doing its own flaky "light scan":
@@ -4930,7 +5492,7 @@ STEP 7 — Write the report and hand off. (skill: "Report")
4930
5492
  at ${inboxUrl} within about 30 minutes.`;
4931
5493
  }
4932
5494
  //#endregion
4933
- //#region src/lib/programs/self-driving/step-keys.ts
5495
+ //#region src/programs/self-driving/step-keys.ts
4934
5496
  /**
4935
5497
  * First match wins, so order is the rule. Entity words come before verbs: "Checking GitHub
4936
5498
  * connection" is the GitHub step, not the access-check step, and "Connecting issue trackers" must
@@ -4999,7 +5561,7 @@ const PRICING_LONG = `A report that ships a pull request costs a flat $15. Every
4999
5561
  */
5000
5562
  const NO_DEFAULT_LIMIT = "A paid plan has no monthly cap until you set one. Add a PR limit in your inbox sidebar, and agents pause when they hit it.";
5001
5563
  //#endregion
5002
- //#region src/lib/programs/self-driving/content/tips.ts
5564
+ //#region src/ui/tui/decks/self-driving/tips.ts
5003
5565
  const SELF_DRIVING_TIPS = [
5004
5566
  {
5005
5567
  id: "signal-source",
@@ -5039,7 +5601,7 @@ const SELF_DRIVING_TIPS = [
5039
5601
  ];
5040
5602
  const getTips = () => SELF_DRIVING_TIPS;
5041
5603
  //#endregion
5042
- //#region src/lib/programs/self-driving/content/pipeline-diagram.tsx
5604
+ //#region src/ui/tui/decks/self-driving/pipeline-diagram.tsx
5043
5605
  /**
5044
5606
  * PIPELINE_BLOCK — ASCII diagram of the Self-driving loop: sources feed
5045
5607
  * scouts, scouts raise signals, signals group into reports, reports land
@@ -5127,7 +5689,7 @@ const PIPELINE_BLOCK = {
5127
5689
  ]
5128
5690
  };
5129
5691
  //#endregion
5130
- //#region src/lib/programs/self-driving/content/index.tsx
5692
+ //#region src/ui/tui/decks/self-driving/index.tsx
5131
5693
  /**
5132
5694
  * Self-driving learn-deck — the narrative script played while the agent
5133
5695
  * sets up Self-driving. Teaches the vocabulary ladder (signal source →
@@ -5353,7 +5915,7 @@ const getContentBlocks = (store) => {
5353
5915
  ];
5354
5916
  };
5355
5917
  //#endregion
5356
- //#region src/lib/programs/self-driving/index.ts
5918
+ //#region src/programs/self-driving/index.ts
5357
5919
  const SELF_DRIVING_SKILL_ID = "self-driving-setup";
5358
5920
  const REPORT_FILE = "posthog-self-driving-report.md";
5359
5921
  const DOCS_URL = "https://posthog.com/docs";
@@ -5440,7 +6002,7 @@ const selfDrivingConfig = {
5440
6002
  getContentBlocks
5441
6003
  };
5442
6004
  //#endregion
5443
- //#region src/lib/programs/mcp/index.ts
6005
+ //#region src/programs/mcp/index.ts
5444
6006
  const mcpAddConfig = {
5445
6007
  id: "mcp-add",
5446
6008
  requiresAi: false,
@@ -5521,7 +6083,7 @@ const mcpTutorialConfig = {
5521
6083
  }]
5522
6084
  };
5523
6085
  //#endregion
5524
- //#region src/lib/programs/mcp-analytics/index.ts
6086
+ //#region src/programs/mcp-analytics/index.ts
5525
6087
  const MCP_ANALYTICS_REPORT_FILE = "posthog-mcp-analytics-report.md";
5526
6088
  /**
5527
6089
  * `[ABORT]` reasons the mcp-analytics skill emits when the project can't be
@@ -5575,7 +6137,7 @@ const mcpAnalyticsConfig = createSkillProgram({
5575
6137
  abortCases: MCP_ANALYTICS_ABORT_CASES
5576
6138
  });
5577
6139
  //#endregion
5578
- //#region src/lib/programs/ai-observability/index.ts
6140
+ //#region src/programs/ai-observability/index.ts
5579
6141
  const AI_OBSERVABILITY_STEPS = AGENT_SKILL_STEPS.map((step) => step.id === "intro" ? {
5580
6142
  ...step,
5581
6143
  screenId: "ai-observability-intro"
@@ -5634,7 +6196,7 @@ final report is written to ./${AI_OBSERVABILITY_REPORT_FILE}.`,
5634
6196
  }
5635
6197
  };
5636
6198
  //#endregion
5637
- //#region src/lib/programs/metrics/index.ts
6199
+ //#region src/programs/metrics/index.ts
5638
6200
  const METRICS_STEPS = AGENT_SKILL_STEPS.map((step) => step.id === "intro" ? {
5639
6201
  ...step,
5640
6202
  screenId: "metrics-intro"
@@ -5698,7 +6260,7 @@ is written to ./${METRICS_REPORT_FILE}.`,
5698
6260
  }
5699
6261
  };
5700
6262
  //#endregion
5701
- //#region src/lib/programs/slack/index.ts
6263
+ //#region src/programs/slack/index.ts
5702
6264
  const slackConnectConfig = {
5703
6265
  id: "slack",
5704
6266
  description: "Connect PostHog to your Slack",
@@ -5710,7 +6272,7 @@ const slackConnectConfig = {
5710
6272
  }]
5711
6273
  };
5712
6274
  //#endregion
5713
- //#region src/lib/programs/program-registry.ts
6275
+ //#region src/programs/program-registry.ts
5714
6276
  const agentSkillConfig = {
5715
6277
  id: "agent-skill",
5716
6278
  description: "Run an arbitrary context-mill skill",
@@ -5824,6 +6386,6 @@ function isRunFailure(session) {
5824
6386
  return session.outroData?.kind === "error" && session.credentials !== null;
5825
6387
  }
5826
6388
  //#endregion
5827
- export { wordWrap as $, installOrUpdatePostHogCli as A, webAnalyticsDoctorConfig as B, ERROR_TRACKING_PROJECT_PATH_KEY as C, CLI_STEERING_TARGETS as D, errorTrackingUploadSourceMapsConfig as E, MANUAL_SDK_INSTALL as F, createSkillProgram as G, getKindMeta as H, MANUAL_SDK_VARIANTS as I, getContentBlocks$4 as J, warehouseSourceConfig as K, RUST_SDK_CRATE as L, AUTOMATABLE_VARIANTS as M, DISPLAY_NAME as N, detectTargets as O, GO_SDK_MODULE as P, computeVisibleRange as Q, SOURCE_MAPS_CONTEXT_KEYS as R, errorTrackingConfig as S, replayVisionConfig as T, fetchHealthIssues as U, posthogDoctorConfig as V, auditConfig as W, posthogIntegrationConfig as X, SETUP_REPORT_FILE as Y, TextBlock as Z, PRICING_SHORT as _, PROGRAM_REGISTRY as a, GITHUB_REQUIRED_MESSAGE as b, getCommandPath as c, metricsConfig as d, isClearBlock as et, aiObservabilityConfig as f, PRICING_LONG as g, NO_DEFAULT_LIMIT as h, isRunFailure as i, Icons as it, installSteeringSnippet as j, findTarget as k, getLaunchablePrograms as l, selfDrivingConfig as m, MINT_FAILURE_CONTACT as n, isObjectBlock as nt, Program as o, mcpAnalyticsConfig as p, revenueAnalyticsConfig as q, MINT_FAILURE_MESSAGE as r, Colors as rt, agentSkillConfig as s, MINT_FAILURE_BODY as t, isLinesBlock as tt, getProgramConfig as u, detectSelfDrivingIntegrationProjects as v, detectErrorTrackingProjects as w, SELF_DRIVING_INTEGRATE_PATH_KEY as x, GITHUB_REQUIRED_BODY as y, migrationConfig as z };
6389
+ export { wordWrap as $, installOrUpdatePostHogCli as A, webAnalyticsDoctorConfig as B, ERROR_TRACKING_PROJECT_PATH_KEY as C, CLI_STEERING_TARGETS as D, errorTrackingUploadSourceMapsConfig as E, MANUAL_SDK_INSTALL as F, createSkillProgram as G, getKindMeta as H, MANUAL_SDK_VARIANTS as I, getContentBlocks$4 as J, warehouseSourceConfig as K, RUST_SDK_CRATE as L, AUTOMATABLE_VARIANTS as M, DISPLAY_NAME as N, detectTargets as O, GO_SDK_MODULE as P, computeVisibleRange as Q, SOURCE_MAPS_CONTEXT_KEYS as R, errorTrackingConfig as S, replayVisionConfig as T, fetchHealthIssues as U, posthogDoctorConfig as V, auditConfig as W, posthogIntegrationConfig as X, SETUP_REPORT_FILE as Y, TextBlock as Z, PRICING_SHORT as _, PROGRAM_REGISTRY as a, maybeStampAiSdkDetected as at, GITHUB_REQUIRED_MESSAGE as b, getCommandPath as c, STRIPE_SDKS as ct, metricsConfig as d, isClearBlock as et, aiObservabilityConfig as f, PRICING_LONG as g, NO_DEFAULT_LIMIT as h, isRunFailure as i, Icons as it, installSteeringSnippet as j, findTarget as k, getLaunchablePrograms as l, detectProjectsWithAgent as lt, selfDrivingConfig as m, MINT_FAILURE_CONTACT as n, isObjectBlock as nt, Program as o, reportWarehouseSourcesDetected as ot, mcpAnalyticsConfig as p, revenueAnalyticsConfig as q, MINT_FAILURE_MESSAGE as r, Colors as rt, agentSkillConfig as s, POSTHOG_SDKS as st, MINT_FAILURE_BODY as t, isLinesBlock as tt, getProgramConfig as u, detectSelfDrivingIntegrationProjects as v, detectErrorTrackingProjects as w, SELF_DRIVING_INTEGRATE_PATH_KEY as x, GITHUB_REQUIRED_BODY as y, migrationConfig as z };
5828
6390
 
5829
- //# sourceMappingURL=mint-failure-D4nd2XmZ.js.map
6391
+ //# sourceMappingURL=mint-failure-CZFZpHpW.js.map