@posthog/wizard 2.82.0 → 2.84.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 (149) hide show
  1. package/README.md +1 -29
  2. package/dist/{PickerMenu-BGGeYqd-.js → PickerMenu-BtheKi1o.js} +1 -1
  3. package/dist/{PickerMenu-BGGeYqd-.js.map → PickerMenu-BtheKi1o.js.map} +1 -1
  4. package/dist/_dev-only-stub-B0db0Klc.js +1 -0
  5. package/dist/{agent-interface-3YfIWZmY.js → agent-interface-BNssNetq.js} +86 -32
  6. package/dist/agent-interface-BNssNetq.js.map +1 -0
  7. package/dist/{agent-prompt-loader-hOHONY7u.js → agent-prompt-loader-iV11XVEF.js} +16 -8
  8. package/dist/agent-prompt-loader-iV11XVEF.js.map +1 -0
  9. package/dist/{analytics-B_xFshPY.js → analytics-Drox5LSW.js} +7 -5
  10. package/dist/analytics-Drox5LSW.js.map +1 -0
  11. package/dist/analytics-Ix9HEra3.js +2 -0
  12. package/dist/{api-C_9KsN-7.js → api-Dfu655Qt.js} +2 -2
  13. package/dist/{api-C_9KsN-7.js.map → api-Dfu655Qt.js.map} +1 -1
  14. package/dist/api-H2UaPgjv.js +2 -0
  15. package/dist/{api-key-login-oUJQDmOV.js → api-key-login-BgwfAXfv.js} +5 -5
  16. package/dist/{api-key-login-oUJQDmOV.js.map → api-key-login-BgwfAXfv.js.map} +1 -1
  17. package/dist/api-key-login-Cow3UDAN.js +2 -0
  18. package/dist/bin.js +1 -1
  19. package/dist/{bounded-fs-iRaQcKYL.js → bounded-fs-TRL6IsoU.js} +32 -16
  20. package/dist/bounded-fs-TRL6IsoU.js.map +1 -0
  21. package/dist/{ci-install-BGlijoTo.js → ci-install-nc1IKuX2.js} +6 -6
  22. package/dist/{ci-install-BGlijoTo.js.map → ci-install-nc1IKuX2.js.map} +1 -1
  23. package/dist/{console-log-DJiTqYT2.js → console-log-BMhBoX-o.js} +2 -2
  24. package/dist/{console-log-DJiTqYT2.js.map → console-log-BMhBoX-o.js.map} +1 -1
  25. package/dist/{debug-BvEbemym.js → debug-BfO_Txo8.js} +3 -3
  26. package/dist/debug-BfO_Txo8.js.map +1 -0
  27. package/dist/{defaults-DDVl3tKN.js → defaults-BWLIffh5.js} +1 -1
  28. package/dist/{defaults-DDVl3tKN.js.map → defaults-BWLIffh5.js.map} +1 -1
  29. package/dist/{errors-DhFeR8Sp.js → errors-BXlWujEw.js} +1 -1
  30. package/dist/{errors-DhFeR8Sp.js.map → errors-BXlWujEw.js.map} +1 -1
  31. package/dist/{family-picker-BKs-tTyu.js → family-picker-CAW_VtYf.js} +2 -2
  32. package/dist/{family-picker-BKs-tTyu.js.map → family-picker-CAW_VtYf.js.map} +1 -1
  33. package/dist/{gateway-CWoYlPz7.js → gateway-CLQQb96F.js} +39 -9
  34. package/dist/{gateway-CWoYlPz7.js.map → gateway-CLQQb96F.js.map} +1 -1
  35. package/dist/headless-CHGNEzO3.js +3 -0
  36. package/dist/{headless-Bfi950Qh.js → headless-DMO8N_FD.js} +2 -2
  37. package/dist/{headless-Bfi950Qh.js.map → headless-DMO8N_FD.js.map} +1 -1
  38. package/dist/{host-resolution-BxnNn8Jm.js → host-resolution-DftfSjJD.js} +4 -4
  39. package/dist/{host-resolution-BxnNn8Jm.js.map → host-resolution-DftfSjJD.js.map} +1 -1
  40. package/dist/{install-CDVeUT_5.js → install-C9FPM37m.js} +6 -6
  41. package/dist/{install-CDVeUT_5.js.map → install-C9FPM37m.js.map} +1 -1
  42. package/dist/{install-CX65IxGa.js → install-MWoo1hXL.js} +1 -1
  43. package/dist/{interactive-5-Numwwb.js → interactive-DOnolJHB.js} +3 -3
  44. package/dist/{interactive-5-Numwwb.js.map → interactive-DOnolJHB.js.map} +1 -1
  45. package/dist/{links-Dmj3Wj9X.js → links-CatXPRxH.js} +3 -3
  46. package/dist/{links-Dmj3Wj9X.js.map → links-CatXPRxH.js.map} +1 -1
  47. package/dist/{main-5KNn80Vt.js → main-CINmZtoW.js} +27 -24
  48. package/dist/main-CINmZtoW.js.map +1 -0
  49. package/dist/{mcp-Buf9sfFm.js → mcp-KVV6Z_bq.js} +3 -3
  50. package/dist/{mcp-Buf9sfFm.js.map → mcp-KVV6Z_bq.js.map} +1 -1
  51. package/dist/{mcp-prompt-streaming-DHPxJK-F.js → mcp-prompt-streaming-M6UnLgGX.js} +5 -5
  52. package/dist/{mcp-prompt-streaming-DHPxJK-F.js.map → mcp-prompt-streaming-M6UnLgGX.js.map} +1 -1
  53. package/dist/{mode-label-DB3ol_sj.js → mode-label--bJuXny5.js} +1 -1
  54. package/dist/{mode-label-DB3ol_sj.js.map → mode-label--bJuXny5.js.map} +1 -1
  55. package/dist/{models-C9rjXPZ6.js → models-B0huHItG.js} +6 -2
  56. package/dist/models-B0huHItG.js.map +1 -0
  57. package/dist/{non-interactive-DkldwWDM.js → non-interactive-DiEu4_6l.js} +3 -3
  58. package/dist/{non-interactive-DkldwWDM.js.map → non-interactive-DiEu4_6l.js.map} +1 -1
  59. package/dist/{oauth-session-Bi1MLRCC.js → oauth-session-9EU3ky0v.js} +2 -2
  60. package/dist/{oauth-session-Bi1MLRCC.js.map → oauth-session-9EU3ky0v.js.map} +1 -1
  61. package/dist/{orchestrator-tools-DyKws92o.js → orchestrator-tools-QWyDLu_7.js} +3 -3
  62. package/dist/{orchestrator-tools-DyKws92o.js.map → orchestrator-tools-QWyDLu_7.js.map} +1 -1
  63. package/dist/package-json-BAtJRHSq.js +2 -0
  64. package/dist/{package-json-2UrhE6kP.js → package-json-z1agAYXs.js} +1 -1
  65. package/dist/{package-json-2UrhE6kP.js.map → package-json-z1agAYXs.js.map} +1 -1
  66. package/dist/{package-manager-DpCdmMmB.js → package-manager-B-9I_fAT.js} +4 -4
  67. package/dist/{package-manager-DpCdmMmB.js.map → package-manager-B-9I_fAT.js.map} +1 -1
  68. package/dist/{pi-DTj1hsJe.js → pi-BSnSk6rv.js} +50 -31
  69. package/dist/pi-BSnSk6rv.js.map +1 -0
  70. package/dist/{playground-CiH6zZPb.js → playground-Drz1qszs.js} +4 -4
  71. package/dist/{playground-CiH6zZPb.js.map → playground-Drz1qszs.js.map} +1 -1
  72. package/dist/{posthog-integration-CpinLWNO.js → posthog-integration-mIQGBc1f.js} +883 -2513
  73. package/dist/posthog-integration-mIQGBc1f.js.map +1 -0
  74. package/dist/programs-Bv0_YHzE.js +3 -0
  75. package/dist/{programs-Bq9Ju9xk.js → programs-mxhRXwP-.js} +306 -125
  76. package/dist/programs-mxhRXwP-.js.map +1 -0
  77. package/dist/provisioning-BVsxSNve.js +2 -0
  78. package/dist/{provisioning-D-AM_7DG.js → provisioning-CHUjae9V.js} +4 -4
  79. package/dist/{provisioning-D-AM_7DG.js.map → provisioning-CHUjae9V.js.map} +1 -1
  80. package/dist/{queue-tools-BoIITT7w.js → queue-tools-PFG6H93Q.js} +14 -5
  81. package/dist/queue-tools-PFG6H93Q.js.map +1 -0
  82. package/dist/{results-CDqlHogZ.js → results-5yCKf2cI.js} +2 -2
  83. package/dist/{results-CDqlHogZ.js.map → results-5yCKf2cI.js.map} +1 -1
  84. package/dist/{run-CfMArkpV.js → run-D5TKJuSL.js} +10 -10
  85. package/dist/{run-CfMArkpV.js.map → run-D5TKJuSL.js.map} +1 -1
  86. package/dist/{run-DcaVJSeI.js → run-W03b6jNM.js} +12 -12
  87. package/dist/{run-DcaVJSeI.js.map → run-W03b6jNM.js.map} +1 -1
  88. package/dist/{run-tool-DJZWnnR9.js → run-tool-DTQF8mmI.js} +17 -17
  89. package/dist/{run-tool-DJZWnnR9.js.map → run-tool-DTQF8mmI.js.map} +1 -1
  90. package/dist/run-tool-DjERhu7G.js +2 -0
  91. package/dist/{runners-Cvnk9BcA.js → runners-B_84kPyf.js} +11 -11
  92. package/dist/{runners-Cvnk9BcA.js.map → runners-B_84kPyf.js.map} +1 -1
  93. package/dist/{security-Cz3a-d7r.js → security-pApVawYb.js} +6 -5
  94. package/dist/{security-Cz3a-d7r.js.map → security-pApVawYb.js.map} +1 -1
  95. package/dist/{setup-utils-C7kaDP5X.js → setup-utils-CQY8PHjR.js} +3 -3
  96. package/dist/{setup-utils-C7kaDP5X.js.map → setup-utils-CQY8PHjR.js.map} +1 -1
  97. package/dist/{start-playground-B62_pYfu.js → start-playground-DAw1GbLt.js} +8 -8
  98. package/dist/{start-playground-B62_pYfu.js.map → start-playground-DAw1GbLt.js.map} +1 -1
  99. package/dist/{subagent-BBfETG17.js → subagent-YLGSvgoZ.js} +13 -5
  100. package/dist/subagent-YLGSvgoZ.js.map +1 -0
  101. package/dist/{task-CmNe3xeg.js → task-3hRSovmK.js} +39 -29
  102. package/dist/task-3hRSovmK.js.map +1 -0
  103. package/dist/{tasks-BfJhVky2.js → tasks-C03QbXTx.js} +1 -1
  104. package/dist/{tasks-BfJhVky2.js.map → tasks-C03QbXTx.js.map} +1 -1
  105. package/dist/{telemetry-DKM7VGuJ.js → telemetry-BPBzqsb_.js} +2 -2
  106. package/dist/{telemetry-DKM7VGuJ.js.map → telemetry-BPBzqsb_.js.map} +1 -1
  107. package/dist/{terminal-Bkxwzkhn.js → terminal-DZsYFbm9.js} +471 -81
  108. package/dist/terminal-DZsYFbm9.js.map +1 -0
  109. package/dist/{tools-DZCEvDv9.js → tools-D_AtrhbO.js} +15 -15
  110. package/dist/{tools-DZCEvDv9.js.map → tools-D_AtrhbO.js.map} +1 -1
  111. package/dist/{tools-Bm0FDT6f.js → tools-DyzRi_dQ.js} +8 -8
  112. package/dist/{tools-Bm0FDT6f.js.map → tools-DyzRi_dQ.js.map} +1 -1
  113. package/dist/{tui-B56jvkbi.js → tui-CRp0iCuT.js} +5 -5
  114. package/dist/tui-CRp0iCuT.js.map +1 -0
  115. package/dist/{tui-tKI95MSr.js → tui-UI6ctBQJ.js} +1 -1
  116. package/dist/{upload-step-DqTgn6UB.js → upload-step-DrYXnpzI.js} +3 -3
  117. package/dist/{upload-step-DqTgn6UB.js.map → upload-step-DrYXnpzI.js.map} +1 -1
  118. package/dist/{urls-B82v7gfO.js → urls-WeqfBLP4.js} +2 -2
  119. package/dist/{urls-B82v7gfO.js.map → urls-WeqfBLP4.js.map} +1 -1
  120. package/dist/{wizard-abort-Cd-7sfCw.js → wizard-abort-BwEefm6P.js} +5 -5
  121. package/dist/{wizard-abort-Cd-7sfCw.js.map → wizard-abort-BwEefm6P.js.map} +1 -1
  122. package/dist/yara-hooks-MDtFbuoM.js +2 -0
  123. package/dist/{yara-hooks-BS0n3ekf.js → yara-hooks-aDbdsitJ.js} +41 -5
  124. package/dist/{yara-hooks-BS0n3ekf.js.map → yara-hooks-aDbdsitJ.js.map} +1 -1
  125. package/package.json +9 -7
  126. package/dist/agent-interface-3YfIWZmY.js.map +0 -1
  127. package/dist/agent-prompt-loader-hOHONY7u.js.map +0 -1
  128. package/dist/analytics-B_xFshPY.js.map +0 -1
  129. package/dist/analytics-DGDr6-iD.js +0 -2
  130. package/dist/api-DhLSO3ai.js +0 -2
  131. package/dist/api-key-login-DiRuZ8Lm.js +0 -2
  132. package/dist/bounded-fs-iRaQcKYL.js.map +0 -1
  133. package/dist/debug-BvEbemym.js.map +0 -1
  134. package/dist/headless-Gisv3faN.js +0 -3
  135. package/dist/main-5KNn80Vt.js.map +0 -1
  136. package/dist/models-C9rjXPZ6.js.map +0 -1
  137. package/dist/package-json-Dblip2_X.js +0 -2
  138. package/dist/pi-DTj1hsJe.js.map +0 -1
  139. package/dist/posthog-integration-CpinLWNO.js.map +0 -1
  140. package/dist/programs-Bq9Ju9xk.js.map +0 -1
  141. package/dist/programs-CnOSdQo1.js +0 -3
  142. package/dist/provisioning-D6Cqbc36.js +0 -2
  143. package/dist/queue-tools-BoIITT7w.js.map +0 -1
  144. package/dist/run-tool-zMLQroVh.js +0 -2
  145. package/dist/subagent-BBfETG17.js.map +0 -1
  146. package/dist/task-CmNe3xeg.js.map +0 -1
  147. package/dist/terminal-Bkxwzkhn.js.map +0 -1
  148. package/dist/tui-B56jvkbi.js.map +0 -1
  149. package/dist/yara-hooks-CxksH-GZ.js +0 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-DZsYFbm9.js","names":["getContentBlocks","CHROME_ROWS","fs","getContentBlocks","TUI_PROGRAMS","getContentBlocks","needsSetup","CheckRow","Header","CheckRow","Header","ReportVisual","WriteReportSlide","NotebookVisual","UploadNotebookSlide","WriteReportSlide","UploadNotebookSlide","join","TUI_PROGRAMS","skillDeck","getContentBlocks","getTips","EXIT","MAX_ACTIVITY_LINES","projectLabel","TUI_PROGRAMS","getContentBlocks","getTips","getContentBlocks","MAX_ACTIVITY_LINES","projectLabel","VARIANT_DISPLAY_NAME","join","TUI_PROGRAMS","getContentBlocks","getContentBlocks","getTips","TUI_PROGRAMS","getContentBlocks","getTips","TUI_PROGRAMS","getContentBlocks","getContentBlocks","TUI_PROGRAMS","getContentBlocks","getContentBlocks","TUI_PROGRAMS","getContentBlocks","DetectErrorBody","TUI_PROGRAMS","getContentBlocks","DetectErrorBody","POLL_INTERVAL_MS","TUI_PROGRAMS","TUI_PROGRAMS","getContentBlocks","aiObservability","audit","errorTracking","sourceMaps","featureFlags","metrics","migration","posthogIntegration","revenueAnalytics","selfDriving","warehouseSource","TUI_TOOLS","copyData","runProbe","runSeed","TUI_TOOLS","TUI_TOOLS","doctor","mcp","slack"],"sources":["../src/tui/programs/shared/health-check-step.ts","../src/tui/programs/shared/skill-flow.ts","../src/tui/primitives/text-helpers.ts","../src/tui/primitives/TextBlock.tsx","../src/tui/programs/shared/skill-deck.tsx","../src/tui/primitives/CardLayout.tsx","../src/tui/primitives/SplitView.tsx","../src/tui/primitives/LoadingBox.tsx","../src/tui/primitives/ProgressList.tsx","../src/tui/primitives/GroupedPickerMenu.tsx","../src/tui/primitives/ConfirmationInput.tsx","../src/tui/primitives/Divider.tsx","../src/tui/primitives/ModalOverlay.tsx","../src/tui/primitives/link-helpers.ts","../src/tui/primitives/LinkText.tsx","../src/tui/primitives/LogViewer.tsx","../src/tui/primitives/EventPlanViewer.tsx","../src/tui/components/TitleBar.tsx","../src/tui/token-usage.ts","../src/tui/components/TokenCostHud.tsx","../src/tui/primitives/DissolveTransition.tsx","../src/tui/primitives/KeyboardHintsBar.tsx","../src/tui/primitives/ScreenErrorBoundary.tsx","../src/tui/primitives/ViewportTooSmall.tsx","../src/tui/primitives/ScreenContainer.tsx","../src/tui/primitives/TabContainer.tsx","../src/tui/primitives/HNViewer.tsx","../src/tui/primitives/LinesBlock.tsx","../src/tui/primitives/NodeBlock.tsx","../src/tui/primitives/ContentSequencer.tsx","../src/tui/components/PrivacyPanel.tsx","../src/tui/screens/IntroScreenLayout.tsx","../src/tui/screens/SkillSourceInfo.tsx","../src/tui/programs/shared/screens/AgentSkillIntroScreen.tsx","../src/tui/programs/shared/skill-program.tsx","../src/tui/programs/ai-observability/screens/AiObservabilityIntroScreen.tsx","../src/tui/programs/ai-observability/index.tsx","../src/tui/programs/audit/flow.ts","../src/tui/programs/audit/events-flow.ts","../src/tui/programs/audit/screens/AuditIntroScreen.tsx","../src/tui/programs/audit/screens/AuditChecksViewer/AreaHeaderRow.tsx","../src/tui/programs/audit/severity-style.ts","../src/tui/programs/audit/screens/AuditChecksViewer/layout.ts","../src/tui/programs/audit/screens/AuditChecksViewer/CheckRow.tsx","../src/tui/programs/audit/screens/AuditChecksViewer/DetailRow.tsx","../src/tui/programs/audit/screens/AuditChecksViewer/Legend.tsx","../src/shared/utils/count-noun.ts","../src/tui/programs/audit/screens/AuditChecksViewer/Header.tsx","../src/tui/programs/audit/screens/AuditChecksViewer/Footer.tsx","../src/tui/programs/audit/screens/AuditChecksViewer/sort.ts","../src/tui/programs/audit/screens/AuditChecksViewer/AuditChecksViewer.tsx","../src/tui/programs/audit/screens/slides/shared.tsx","../src/tui/programs/audit/screens/slides/installation.tsx","../src/tui/programs/audit/screens/slides/identification.tsx","../src/tui/programs/audit/screens/slides/eventCapture.tsx","../src/tui/programs/audit/screens/slides/liveData.tsx","../src/tui/programs/audit/screens/slides/writeReport.tsx","../src/tui/programs/audit/screens/slides/uploadNotebook.tsx","../src/tui/programs/audit/screens/slides/index.ts","../src/tui/programs/audit/screens/AuditAreaPane.tsx","../src/tui/programs/audit/screens/slides/events-audit/detectSdk.tsx","../src/tui/programs/audit/screens/slides/events-audit/scanSites.tsx","../src/tui/programs/audit/screens/slides/events-audit/enrichSites.tsx","../src/tui/programs/audit/screens/slides/events-audit/queryVolume.tsx","../src/tui/programs/audit/screens/slides/events-audit/writeReport.tsx","../src/tui/programs/audit/screens/slides/events-audit/createDashboard.tsx","../src/tui/programs/audit/screens/slides/events-audit/uploadNotebook.tsx","../src/tui/programs/audit/screens/slides/events-audit/index.ts","../src/tui/programs/audit/screens/PendingChecksList.tsx","../src/tui/programs/audit/screens/AuditRunScreen.tsx","../src/tui/programs/audit/screens/AuditChecksOutroSection.tsx","../src/tui/hooks/useDismissOnAnyKey.ts","../src/tui/programs/audit/screens/AuditOutroScreen.tsx","../src/tui/programs/audit/index.tsx","../src/tui/programs/error-tracking/flow.ts","../src/tui/components/StatusPeekTrigger.tsx","../src/tui/programs/shared/deck/source-maps.tsx","../src/tui/programs/error-tracking/deck/index.tsx","../src/tui/programs/error-tracking/deck/tips.ts","../src/tui/programs/error-tracking/screens/ErrorTrackingIntroScreen.tsx","../src/tui/agent-progress.ts","../src/tui/programs/error-tracking/screens/ErrorTrackingDetectScreen.tsx","../src/tui/programs/error-tracking/index.tsx","../src/tui/programs/error-tracking-upload-source-maps/flow.ts","../src/tui/programs/error-tracking-upload-source-maps/deck/index.tsx","../src/tui/programs/error-tracking-upload-source-maps/screens/SourceMapsIntroScreen.tsx","../src/tui/programs/error-tracking-upload-source-maps/screens/SourceMapsDetectScreen.tsx","../src/tui/programs/error-tracking-upload-source-maps/screens/SourceMapsOutroScreen.tsx","../src/tui/programs/error-tracking-upload-source-maps/index.tsx","../src/tui/programs/feature-flags/deck/index.tsx","../src/tui/programs/feature-flags/deck/tips.ts","../src/tui/programs/feature-flags/screens/FeatureFlagsIntroScreen.tsx","../src/tui/programs/feature-flags/index.tsx","../src/tui/programs/metrics/screens/MetricsIntroScreen.tsx","../src/tui/programs/metrics/index.tsx","../src/tui/programs/migration/flow.ts","../src/tui/programs/shared/deck/product-suite.tsx","../src/tui/programs/shared/deck/line-chart.tsx","../src/tui/programs/shared/deck/funnel.tsx","../src/tui/programs/migration/deck/vendor-stack.tsx","../src/tui/programs/migration/deck/free-tier.tsx","../src/tui/programs/migration/deck/pricing-structure.tsx","../src/tui/programs/migration/deck/index.tsx","../src/tui/programs/migration/screens/MigrationIntroScreen.tsx","../src/tui/programs/migration/index.tsx","../src/tui/programs/posthog-integration/flow.ts","../src/tui/programs/posthog-integration/deck/data-flow.tsx","../src/tui/programs/posthog-integration/deck/index.tsx","../src/tui/components/sharing-options.ts","../src/tui/programs/posthog-integration/intro-menu.ts","../src/tui/programs/posthog-integration/screens/PostHogIntegrationIntroScreen.tsx","../src/tui/programs/posthog-integration/index.tsx","../src/tui/programs/revenue-analytics/flow.ts","../src/tui/programs/revenue-analytics/screens/RevenueIntroScreen.tsx","../src/tui/programs/revenue-analytics/index.tsx","../src/tui/programs/self-driving/flow.ts","../src/tui/programs/self-driving/deck/pipeline-diagram.tsx","../src/tui/programs/self-driving/deck/index.tsx","../src/tui/programs/self-driving/deck/tips.ts","../src/tui/programs/self-driving/screens/SelfDrivingIntroScreen.tsx","../src/tui/programs/self-driving/screens/SelfDrivingIntegrationCheckScreen.tsx","../src/tui/programs/self-driving/screens/SelfDrivingIntegrationDetectScreen.tsx","../src/tui/programs/self-driving/screens/SelfDrivingHandoffScreen.tsx","../src/tui/programs/self-driving/hooks/useGithubConnection.ts","../src/tui/programs/self-driving/screens/SelfDrivingGitHubScreen.tsx","../src/tui/programs/self-driving/index.tsx","../src/tui/programs/warehouse-source/flow.ts","../src/tui/programs/warehouse-source/screens/WarehouseIntroScreen.tsx","../src/tui/programs/warehouse-source/index.tsx","../src/tui/programs/index.ts","../src/tui/tools/doctor/flow.ts","../src/tui/tools/doctor/screens/DoctorIntroScreen.tsx","../src/tui/tools/doctor/screens/IssueTable.tsx","../src/tui/tools/doctor/screens/DoctorReportScreen.tsx","../src/tui/tools/doctor/index.tsx","../src/tui/screens/McpScreen.tsx","../src/tui/tools/mcp/flow.ts","../src/tui/tools/mcp/services/mcp-role-prompts.copy.ts","../src/tui/tools/mcp/services/mcp-role-prompts.ts","../src/tui/tools/mcp/services/mcp-project-profile.ts","../src/tui/tools/mcp/screens/McpSuggestedPromptsScreen.tsx","../src/tui/abort.ts","../src/tui/auth/oauth.ts","../src/shared/utils/project-resolution.ts","../src/tui/auth/project-data.ts","../src/tui/tools/mcp/services/seed-events.ts","../src/tui/tools/mcp/services/suggested-prompts.ts","../src/tui/tools/mcp/index.tsx","../src/tui/tools/slack/flow.ts","../src/tui/tools/slack/index.ts","../src/tui/tools/index.ts","../src/tui/flow-owner.ts","../src/tui/mint-failure.ts","../src/tui/flow.ts","../src/tui/ai-opt-in-gate.ts","../src/tui/screen-sequences.ts","../src/tui/router.ts","../src/tui/components/ServiceHealthList.tsx","../src/tui/screens/AiOptInRequiredScreen.tsx","../src/tui/components/LearnCard.tsx","../src/tui/hooks/useTick.ts","../src/tui/components/visualizer/palette.ts","../src/tui/components/visualizer/panel.tsx","../src/tui/components/visualizer/MatrixRain.tsx","../src/tui/components/visualizer/grid.ts","../src/tui/components/visualizer/LibraryShelf.tsx","../src/tui/components/visualizer/CrateStack.tsx","../src/tui/components/visualizer/DiffCascade.tsx","../src/tui/components/visualizer/Tumblers.tsx","../src/tui/components/visualizer/DashboardGrid.tsx","../src/tui/components/PhaseVisuals.tsx","../src/tui/components/TipsCard.tsx","../src/tui/services/slack-app-card.ts","../src/tui/screens/SlackConnectScreen.tsx","../src/tui/screens/OutroScreen.tsx","../src/tui/tui-state.ts","../src/tui/store.ts","../src/tui/terminal.ts"],"sourcesContent":["/**\n * Shared health-check step used by every program that runs an agent.\n *\n * Renders the HealthCheckScreen between intro and auth, kicks off the\n * readiness probe in onInit, and gates the screen on either a clean\n * readiness result or an explicit user dismissal of the outage.\n *\n * Programs without this step that hit a blocking outage gridlock the\n * router: the TUI host calls wizardAbort, whose outro awaits its dismissal,\n * but the router can't advance past the still-incomplete auth step to\n * render the OutroScreen.\n */\n\nimport type { FlowStep } from '../../flow.js';\nimport type { TuiView } from '@tui/tui-state';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n SIGNUP_WIZARD_READINESS_CONFIG,\n getBlockingServiceKeys,\n} from '@shared/health-checks/readiness';\nimport { logToFile } from '@utils/debug';\n\nexport function healthCheckReady({\n session,\n outageDismissed,\n}: TuiView): boolean {\n if (!session.readinessResult) return false;\n\n if (session.signup) {\n const hardBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n SIGNUP_WIZARD_READINESS_CONFIG,\n );\n const defaultBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n );\n if (hardBlocking.length === 0 && defaultBlocking.length === 0) return true;\n return outageDismissed;\n }\n\n if (session.readinessResult.decision === WizardReadiness.No) {\n return outageDismissed;\n }\n return true;\n}\n\nexport const HEALTH_CHECK_STEP: FlowStep = {\n id: 'health-check',\n label: 'Health check',\n screenId: 'health-check',\n gate: healthCheckReady,\n onInit: (ctx) => {\n evaluateWizardReadiness()\n .then((readiness) => {\n logToFile(\n `[health-checks] TUI pre-flight complete: decision=${readiness.decision}`,\n );\n ctx.setReadinessResult(readiness);\n })\n .catch((err) => {\n logToFile('[health-checks] TUI pre-flight failed:', err);\n ctx.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n });\n },\n};\n","/**\n * Generic agent skill step list.\n *\n * Minimal flow: intro → health-check → auth → run → outro → skills.\n * No detection, no setup, no MCP.\n */\n\nimport type { FlowStep } from '../../flow.js';\nimport { RunPhase } from '@shared/run-state';\nimport { HEALTH_CHECK_STEP } from './health-check-step.js';\nimport { SkillScreenId } from './screen-ids.js';\n\nexport const AGENT_SKILL_STEPS: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: SkillScreenId.Intro,\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Running',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '@tui/styles';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n /**\n * When `completed === true`, render the text dim. Defaults to `true` —\n * the standard \"completed step\" treatment. Pass `false` to keep the\n * text at full opacity even after the sequencer has moved on.\n */\n dimWhenComplete?: boolean;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n dimWhenComplete = true,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed by default, but can be overridden per-block.\n if (completed) {\n return (\n <Text dimColor={dimWhenComplete}>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n","/**\n * Agent-skill learn-deck — the short three-line sequence shown while a\n * skill-based program (audit, revenue-analytics, agent-skill, etc.)\n * runs. Skill programs don't need the full PostHog onboarding narrative.\n */\n\nimport { Text } from 'ink';\nimport type { WizardStore } from '@tui/store';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => {\n const skillId = store?.session.skillId ?? 'unknown';\n return [\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n { content: 'The Wizard is an agent.', pause: 4000 },\n {\n pause: 60000,\n content: (\n <Text>\n Running the <Text color=\"cyan\">{skillId}</Text> skill...\n </Text>\n ),\n },\n ];\n};\n","/**\n * CardLayout — Aligns a single child within available space.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\nimport { HAlign, VAlign } from '@tui/styles';\n\ninterface CardLayoutProps {\n hAlign?: HAlign;\n vAlign?: VAlign;\n children: ReactNode;\n}\n\nexport const CardLayout = ({\n hAlign = HAlign.Left,\n vAlign = VAlign.Top,\n children,\n}: CardLayoutProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n justifyContent={vAlign}\n alignItems={hAlign}\n >\n {children}\n </Box>\n );\n};\n","/**\n * SplitView — Two-pane horizontal layout: 50/50.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\n\ninterface SplitViewProps {\n left: ReactNode;\n right: ReactNode;\n gap?: number;\n}\n\nexport const SplitView = ({ left, right, gap = 2 }: SplitViewProps) => {\n return (\n <Box flexDirection=\"row\" flexGrow={1} flexShrink={1} gap={gap}>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {left}\n </Box>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {right}\n </Box>\n </Box>\n );\n};\n","/**\n * LoadingBox — Spinner with message.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\n\ninterface LoadingBoxProps {\n message: string;\n}\n\nexport const LoadingBox = ({ message }: LoadingBoxProps) => {\n return (\n <Box gap={1}>\n <Spinner />\n <Text>{message}</Text>\n </Box>\n );\n};\n","/**\n * ProgressList — Reusable task checklist with status icons.\n * Extracted from StatusTab logic.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport { Colors, Icons } from '@tui/styles';\nimport { LoadingBox } from './LoadingBox.js';\n\nexport interface ProgressItem {\n label: string;\n activeForm?: string;\n status: 'pending' | 'in_progress' | 'completed' | 'skipped' | 'failed';\n}\n\ninterface ProgressListProps {\n items: ProgressItem[];\n title?: string;\n}\n\nexport const ProgressList = ({ items, title }: ProgressListProps) => {\n // A task found not needed leaves the list — it was never work to show.\n const visible = items.filter((t) => t.status !== 'skipped');\n const resolved = visible.filter((t) => t.status === 'completed').length;\n const total = visible.length;\n const notRequired = items.length - visible.length;\n\n return (\n <Box flexDirection=\"column\">\n {title && (\n <>\n <Text bold>{title}</Text>\n <Text> </Text>\n </>\n )}\n {visible.length === 0 && <LoadingBox message=\"Analyzing project...\" />}\n {visible.map((item, i) => {\n const icon =\n item.status === 'failed'\n ? Icons.warning\n : item.status === 'completed'\n ? Icons.squareFilled\n : item.status === 'in_progress'\n ? Icons.triangleRight\n : Icons.squareOpen;\n const color =\n item.status === 'failed'\n ? Colors.error\n : item.status === 'completed'\n ? Colors.success\n : item.status === 'in_progress'\n ? Colors.primary\n : Colors.muted;\n const label =\n item.status === 'in_progress' && item.activeForm\n ? item.activeForm\n : item.label;\n\n // One row per task: the pane is half the terminal, so truncate.\n return (\n <Text key={i} wrap=\"truncate\">\n <Text color={color}>{icon}</Text>{' '}\n <Text dimColor={item.status === 'pending'}>{label}</Text>\n </Text>\n );\n })}\n {total > 0 && (\n <Box marginTop={1} gap={1}>\n <Spinner />\n <Text dimColor>\n {resolved < total\n ? `Progress: ${resolved}/${total} completed`\n : 'Cleaning up...'}\n </Text>\n </Box>\n )}\n {notRequired > 0 && (\n <Text dimColor>({notRequired} skipped as not required)</Text>\n )}\n </Box>\n );\n};\n","/**\n * GroupedPickerMenu — Multi-select with category headers.\n *\n * Renders groups of options with bold category labels.\n * Arrow keys navigate selectable items (headers are skipped) and the Confirm\n * button below them; enter toggles the focused option, \"a\" toggles all, and\n * moving onto the Confirm button and pressing enter submits. Space is kept as\n * an undocumented alias for enter. Shares the interaction model with\n * PickerMenu mode=\"multi\".\n *\n * When content exceeds available terminal height, the list scrolls\n * to keep the focused item visible with up/down indicators.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo } from 'react';\nimport { Icons, Colors } from '@tui/styles';\nimport { PromptLabel } from './PromptLabel.js';\nimport { ConfirmButton } from './ConfirmButton.js';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\n\ninterface GroupOption {\n value: string;\n label: string;\n hint?: string;\n}\n\ninterface GroupedPickerMenuProps {\n message?: string;\n groups: Record<string, GroupOption[]>;\n initialSelected?: string[];\n onSelect: (values: string[]) => void;\n}\n\ntype Row =\n | { kind: 'header'; label: string }\n | { kind: 'option'; value: string; label: string; hint?: string };\n\n/** Truncate text with \"\\u2026\" if it exceeds maxWidth. */\nfunction truncateWithEllipsis(text: string, maxWidth: number): string {\n if (text.length <= maxWidth) return text;\n return text.slice(0, maxWidth - 1) + '\\u2026';\n}\n\n/** Rows consumed by chrome outside this component (title bar, screen padding, etc.) */\nconst CHROME_OVERHEAD = 10;\n/**\n * Rows used by the prompt label + marginTop before content (hint text moved to\n * KeyboardHintsBar) plus the Confirm button below the list: marginTop (1) +\n * single border top/bottom (2) + button text (1).\n */\nconst MENU_CHROME = 6;\n/**\n * Max visual rows the list renders regardless of terminal height, so a tall\n * terminal doesn't turn the menu into a full-screen wall. Mirrors\n * PickerMenu's MAX_LIST_ROWS.\n */\nconst MAX_LIST_ROWS = 12;\n\n/** Count the visual rows occupied by rows[start..end), accounting for header margins. */\nfunction countVisualRows(rows: Row[], start: number, end: number): number {\n let count = 0;\n for (let i = start; i < end && i < rows.length; i++) {\n if (rows[i].kind === 'header' && i > start) count += 1; // marginTop gap\n count += 1;\n }\n return count;\n}\n\n/** From scrollOffset, find how many flat rows fit in the visual budget. */\nfunction computeVisibleEnd(\n rows: Row[],\n scrollOffset: number,\n budget: number,\n): number {\n let visualCount = 0;\n let i = scrollOffset;\n while (i < rows.length) {\n const cost = rows[i].kind === 'header' && i > scrollOffset ? 2 : 1;\n if (visualCount + cost > budget) break;\n visualCount += cost;\n i++;\n }\n return i;\n}\n\n/** Adjust scroll offset to keep focusedRowIdx visible within the viewport. */\nfunction adjustScrollOffset(\n currentOffset: number,\n focusedRowIdx: number,\n rows: Row[],\n viewportBudget: number,\n): number {\n const visibleEnd = computeVisibleEnd(rows, currentOffset, viewportBudget);\n\n // Already visible\n if (focusedRowIdx >= currentOffset && focusedRowIdx < visibleEnd) {\n return currentOffset;\n }\n\n // Focus moved above viewport — scroll up, including group header if adjacent\n if (focusedRowIdx < currentOffset) {\n let newOffset = focusedRowIdx;\n if (newOffset > 0 && rows[newOffset - 1]?.kind === 'header') {\n newOffset--;\n }\n return Math.max(0, newOffset);\n }\n\n // Focus moved below viewport — scroll down minimally\n let newOffset = currentOffset + 1;\n while (newOffset < rows.length) {\n const end = computeVisibleEnd(rows, newOffset, viewportBudget);\n if (focusedRowIdx < end) break;\n newOffset++;\n }\n return Math.min(newOffset, Math.max(0, rows.length - 1));\n}\n\nexport const GroupedPickerMenu = ({\n message,\n groups,\n initialSelected,\n onSelect,\n}: GroupedPickerMenuProps) => {\n const [termCols, termRows] = useStdoutDimensions();\n\n // Available width for option labels, after subtracting layout chrome:\n // paddingX(2) + marginLeft(2) + option marginLeft(1) + gap(1) + checkbox(2) = 8\n const labelWidth = Math.max(10, Math.min(termCols, 120) - 8);\n\n // Build a flat row list with headers interleaved\n const rows = useMemo<Row[]>(() => {\n const result: Row[] = [];\n for (const [groupName, options] of Object.entries(groups)) {\n result.push({ kind: 'header', label: groupName });\n for (const opt of options) {\n result.push({ kind: 'option', ...opt });\n }\n }\n return result;\n }, [groups]);\n\n // Indices of selectable (non-header) rows\n const selectableIndices = useMemo(\n () =>\n rows.map((r, i) => (r.kind === 'option' ? i : -1)).filter((i) => i >= 0),\n [rows],\n );\n\n // All option values for toggle-all\n const allValues = useMemo(\n () =>\n rows\n .filter((r): r is Row & { kind: 'option' } => r.kind === 'option')\n .map((r) => r.value),\n [rows],\n );\n\n const [focusedSelectable, setFocusedSelectable] = useState(0);\n // When true, the cursor is on the Confirm button rather than an option.\n const [onButton, setOnButton] = useState(false);\n const [selected, setSelected] = useState<Set<string>>(\n () => new Set(initialSelected ?? allValues),\n );\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const focusedRowIdx = selectableIndices[focusedSelectable] ?? 0;\n\n // Viewport budget: how many visual rows can be shown\n const viewportBudget = Math.max(\n 5,\n Math.min(termRows - CHROME_OVERHEAD - MENU_CHROME, MAX_LIST_ROWS),\n );\n const totalVisual = countVisualRows(rows, 0, rows.length);\n const needsScroll = totalVisual > viewportBudget;\n const effectiveBudget = needsScroll ? viewportBudget - 2 : viewportBudget;\n\n useKeyBindings('grouped-picker', [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const last = selectableIndices.length - 1;\n\n // Move focus onto a selectable option, scrolling it into view.\n const moveTo = (target: number) => {\n setOnButton(false);\n setFocusedSelectable(target);\n if (needsScroll) {\n const rowIdx = selectableIndices[target] ?? 0;\n setScrollOffset((prev) =>\n adjustScrollOffset(prev, rowIdx, rows, effectiveBudget),\n );\n }\n };\n\n if (key.upArrow) {\n if (onButton) {\n moveTo(last); // button → bottom of the list\n } else if (focusedSelectable > 0) {\n moveTo(focusedSelectable - 1);\n } else {\n setOnButton(true); // top of the list → button\n }\n }\n if (key.downArrow) {\n if (onButton) {\n moveTo(0); // button → top of the list\n } else if (focusedSelectable < last) {\n moveTo(focusedSelectable + 1);\n } else {\n setOnButton(true); // bottom of the list → button\n }\n }\n },\n },\n {\n match: [KeyMatch.Space, KeyMatch.Return],\n label: 'enter',\n action: 'select',\n handler: () => {\n if (onButton) {\n onSelect([...selected]);\n return;\n }\n const targetRowIdx = selectableIndices[focusedSelectable] ?? 0;\n const row = rows[targetRowIdx];\n if (row?.kind === 'option') {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(row.value)) {\n next.delete(row.value);\n } else {\n next.add(row.value);\n }\n return next;\n });\n }\n },\n },\n {\n match: 'a',\n label: 'a',\n action: 'toggle all',\n priority: 11,\n handler: () => {\n setSelected((prev) => {\n if (prev.size === allValues.length) {\n return new Set();\n }\n return new Set(allValues);\n });\n },\n },\n ]);\n\n // Determine visible slice\n const visibleStart = needsScroll ? scrollOffset : 0;\n const visibleEnd = needsScroll\n ? computeVisibleEnd(rows, visibleStart, effectiveBudget)\n : rows.length;\n const visibleRows = rows.slice(visibleStart, visibleEnd);\n const hiddenAbove = needsScroll\n ? selectableIndices.filter((s) => s < visibleStart).length\n : 0;\n const hiddenBelow = needsScroll\n ? selectableIndices.filter((s) => s >= visibleEnd).length\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box flexDirection=\"column\" marginTop={message ? 1 : 0} marginLeft={2}>\n {needsScroll && (\n <Text dimColor>\n {hiddenAbove > 0 ? `\\u2191 ${hiddenAbove} more` : ' '}\n </Text>\n )}\n {visibleRows.map((row, relIdx) => {\n const absIdx = visibleStart + relIdx;\n\n if (row.kind === 'header') {\n return (\n <Box\n key={`h-${absIdx}`}\n marginTop={relIdx > 0 && absIdx > 0 ? 1 : 0}\n >\n <Text bold dimColor>\n {row.label}\n </Text>\n </Box>\n );\n }\n\n const isFocused = !onButton && focusedRowIdx === absIdx;\n const isSelected = selected.has(row.value);\n const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;\n const fullLabel = row.hint ? `${row.label} (${row.hint})` : row.label;\n const label = truncateWithEllipsis(fullLabel, labelWidth);\n\n return (\n <Box key={row.value} gap={1} marginLeft={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n wrap=\"truncate\"\n >\n {label}\n </Text>\n </Box>\n </Box>\n );\n })}\n {needsScroll && (\n <Text dimColor>\n {hiddenBelow > 0 ? `\\u2193 ${hiddenBelow} more` : ' '}\n </Text>\n )}\n </Box>\n <Box marginTop={1} marginLeft={2}>\n <ConfirmButton focused={onButton} count={selected.size} />\n </Box>\n </Box>\n );\n};\n","/**\n * ConfirmationInput — Continue/cancel prompt.\n * Enter confirms, escape cancels. Arrow keys toggle focus.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { Icons, Colors } from '@tui/styles';\nimport { PromptLabel } from './PromptLabel.js';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\n\ninterface ConfirmationInputProps {\n message: string;\n onConfirm: () => void;\n onCancel: () => void;\n confirmLabel?: string;\n cancelLabel?: string;\n}\n\nenum FocusTarget {\n Continue = 'continue',\n Cancel = 'cancel',\n}\n\nexport const ConfirmationInput = ({\n message,\n onConfirm,\n onCancel,\n confirmLabel = 'Continue',\n cancelLabel = 'Cancel',\n}: ConfirmationInputProps) => {\n const [focused, setFocused] = useState<FocusTarget>(FocusTarget.Continue);\n\n useKeyBindings('confirmation', [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch',\n handler: () => {\n setFocused((f) =>\n f === FocusTarget.Continue\n ? FocusTarget.Cancel\n : FocusTarget.Continue,\n );\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n if (focused === FocusTarget.Continue) {\n onConfirm();\n } else {\n onCancel();\n }\n },\n },\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: 'cancel',\n handler: () => {\n onCancel();\n },\n },\n ]);\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box gap={2} marginTop={1} marginLeft={2}>\n <Text\n bold={focused === FocusTarget.Continue}\n color={\n focused === FocusTarget.Continue ? Colors.accent : Colors.muted\n }\n >\n {focused === FocusTarget.Continue ? Icons.triangleSmallRight : ' '}{' '}\n {confirmLabel}\n </Text>\n <Text\n bold={focused === FocusTarget.Cancel}\n color={focused === FocusTarget.Cancel ? Colors.accent : Colors.muted}\n >\n {focused === FocusTarget.Cancel ? Icons.triangleSmallRight : ' '}{' '}\n {cancelLabel}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text, measureElement } from 'ink';\nimport { useRef, useState, useEffect } from 'react';\n\ninterface DividerProps {\n dimColor?: boolean;\n char?: string;\n}\n\nexport const Divider = ({ dimColor = true, char = '─' }: DividerProps) => {\n const ref = useRef(null);\n const [width, setWidth] = useState(0);\n\n useEffect(() => {\n if (ref.current) {\n const { width: measured } = measureElement(ref.current);\n setWidth(measured);\n }\n }, []);\n\n return (\n <Box ref={ref} width=\"100%\">\n <Text dimColor={dimColor}>{width > 0 ? char.repeat(width) : ''}</Text>\n </Box>\n );\n};\n","/**\n * ModalOverlay — Reusable centered card for overlay screens.\n *\n * Shared layout for HealthCheckScreen, SettingsOverrideScreen, PortConflictScreen, etc.\n * Provides: centered card with border, title, body, optional feedback, divider, and actions.\n */\n\nimport type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { Divider } from './Divider.js';\n\ninterface ModalOverlayProps {\n /** Card border color */\n borderColor: string;\n /** Title text */\n title: string;\n /** Title text color (defaults to borderColor) */\n titleColor?: string;\n /** Card width (default 68) */\n width?: number;\n /** Body content */\n children: ReactNode;\n /** Optional feedback message (shown in yellow above the divider) */\n feedback?: string | null;\n /** Footer content below the divider (typically ConfirmationInput) */\n footer?: ReactNode;\n}\n\nexport const ModalOverlay = ({\n borderColor,\n title,\n titleColor,\n width = 68,\n children,\n feedback,\n footer,\n}: ModalOverlayProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={borderColor}\n paddingX={3}\n paddingY={1}\n width={width}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color={titleColor ?? borderColor} bold>\n {title}\n </Text>\n </Box>\n\n {children}\n\n {feedback && (\n <Box marginTop={1}>\n <Text color=\"yellow\">{feedback}</Text>\n </Box>\n )}\n\n {footer && (\n <>\n <Box marginY={1}>\n <Divider />\n </Box>\n {footer}\n </>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * Link-rendering helpers for terminal prompts.\n *\n * Terminals that auto-linkify text scan *visual* lines, so a URL the TUI wraps\n * across lines — or pads with box-border characters — gets a wrong click\n * target: the terminal opens half a URL, or one stitched back together with\n * border glyphs and padding.\n *\n * The fix is an explicit OSC 8 hyperlink: the escape carries the exact target\n * out of band, independent of the visible layout, and Ink's wrap re-emits it on\n * every wrapped line — so the click target stays correct even when the URL\n * wraps to fit the overlay. Each standalone URL gets its own line so the escape\n * brackets exactly one URL. Terminals without OSC 8 support ignore the escape\n * and show the visible text.\n */\n\n// OSC 8 hyperlink escape: ESC ] 8 ; ; <url> BEL <label> ESC ] 8 ; ; BEL.\n// Built from char codes so no raw control bytes live in source.\nconst ESC = String.fromCharCode(0x1b);\nconst BEL = String.fromCharCode(0x07);\nconst OSC_8 = `${ESC}]8;;`;\n\nconst ELLIPSIS = '…';\n\n/** Matches an http(s) URL run (no surrounding whitespace). */\nconst URL_RUN = /https?:\\/\\/[^\\s]+/g;\n\n/** Trailing characters that are punctuation around a URL, not part of it. */\nconst TRAILING_PUNCTUATION = /[.,;:!?)\\]}>'\"]+$/;\n\nfunction trimTrailingPunctuation(url: string): string {\n return url.replace(TRAILING_PUNCTUATION, '');\n}\n\n/**\n * Wrap `label` (defaults to the URL) in an OSC 8 hyperlink escape pointing\n * at `url`. Terminals that support OSC 8 make the whole run clickable to the\n * exact `url`; terminals that don't render `label` as plain text.\n */\nexport function osc8Hyperlink(url: string, label: string = url): string {\n return `${OSC_8}${url}${BEL}${label}${OSC_8}${BEL}`;\n}\n\n/**\n * Shorten a URL for *display only*, keeping the trust-relevant head visible.\n *\n * A long authorize URL is mostly query-string noise (`?client_id=…&state=…`).\n * The part a user needs to judge where they're being sent, the scheme and host,\n * sits at the front. So we always keep `scheme://host` intact and collapse the\n * long path/query tail to an ellipsis, never the other way round.\n *\n * This is purely the visible label. Callers pair it with `osc8Hyperlink(url,\n * label)` so the click target, and the copy/open keybinds, stay the full URL.\n * Returns the URL unchanged when it already fits within `maxLength`.\n */\nexport function truncateUrlLabel(url: string, maxLength = 56): string {\n if (url.length <= maxLength) return url;\n\n let head: string;\n let tail: string;\n try {\n const parsed = new URL(url);\n head = `${parsed.protocol}//${parsed.host}`;\n tail = url.slice(head.length);\n } catch {\n // Not parseable as a URL: fall back to a plain head truncation.\n return url.slice(0, Math.max(1, maxLength - ELLIPSIS.length)) + ELLIPSIS;\n }\n\n // The host alone already fills (or overflows) the budget: show it whole (it's\n // the trust signal) and ellipsize only if we're actually hiding a tail.\n if (head.length >= maxLength - ELLIPSIS.length) {\n return tail.length > 0 ? head + ELLIPSIS : head;\n }\n\n // Fill the remaining room with as much of the path/query as fits, then ellipsize.\n const room = maxLength - head.length - ELLIPSIS.length;\n return head + tail.slice(0, room) + ELLIPSIS;\n}\n\n/** Extract every http(s) URL in `text`, trailing punctuation removed. */\nexport function extractUrls(text: string): string[] {\n const matches = text.match(URL_RUN) ?? [];\n return matches.map(trimTrailingPunctuation);\n}\n\nexport type PromptSegment =\n | { type: 'text'; value: string }\n | { type: 'url'; value: string };\n\n/**\n * Split prompt text into renderable segments, breaking *every* URL out onto its\n * own `url` segment — whether it sits alone on a line or inline within prose.\n * Pulling it out matters: `LinkText` renders a `url` segment as a single OSC 8\n * hyperlink, so the click target stays the exact full URL even when it wraps. A\n * URL left inline in a `text` segment is plain text the terminal may auto-detect\n * per *visual* line, which opens a broken half-URL when it wraps.\n *\n * Consecutive URL-free lines stay grouped in one `text` segment (newlines\n * preserved) so paragraph spacing is unchanged. The prose surrounding an inline\n * URL is kept as `text` segments before/after it (trailing URL punctuation stays\n * with the prose), so it reads the same minus the link being on its own line.\n */\nexport function splitPromptIntoSegments(text: string): PromptSegment[] {\n const segments: PromptSegment[] = [];\n let buffer: string[] = [];\n\n const flush = () => {\n if (buffer.length > 0) {\n segments.push({ type: 'text', value: buffer.join('\\n') });\n buffer = [];\n }\n };\n\n for (const line of text.split('\\n')) {\n URL_RUN.lastIndex = 0;\n if (!URL_RUN.test(line)) {\n buffer.push(line);\n continue;\n }\n // The line has at least one URL: emit the buffered prose, then walk the\n // line emitting text/url/text around each URL.\n flush();\n let cursor = 0;\n URL_RUN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = URL_RUN.exec(line)) !== null) {\n const url = trimTrailingPunctuation(match[0]);\n const before = line.slice(cursor, match.index).trim();\n if (before) {\n segments.push({ type: 'text', value: before });\n }\n segments.push({ type: 'url', value: url });\n // Resume after the URL itself — any stripped trailing punctuation stays\n // as prose for the next slice.\n cursor = match.index + url.length;\n URL_RUN.lastIndex = cursor;\n }\n const after = line.slice(cursor).trim();\n if (after) {\n segments.push({ type: 'text', value: after });\n }\n }\n flush();\n return segments;\n}\n","/**\n * LinkText — renders prompt text with URLs as OSC 8 hyperlinks.\n *\n * Every URL (standalone or inline in prose) is pulled onto its own line. Long\n * URLs are truncated for display (`scheme://host` kept, the noisy path/query\n * tail collapsed to an ellipsis) so the overlay stays clean instead of a URL\n * wrapping across several lines. The OSC 8 escape carries the *full* URL as the\n * click target regardless of the shortened label, and `WizardAskScreen` opens\n * (`o`) / copies (`c`) the full URL too, so no path loses the real destination.\n * Prose renders unchanged.\n *\n * Used by the `wizard_ask` overlay only for programs that opt into rich link\n * rendering (see `PendingQuestion.richLinks`). Other flows are untouched.\n */\nimport { Box, Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport {\n osc8Hyperlink,\n truncateUrlLabel,\n splitPromptIntoSegments,\n} from './link-helpers.js';\n\ninterface LinkTextProps {\n text: string;\n}\n\nexport const LinkText = ({ text }: LinkTextProps) => {\n const segments = splitPromptIntoSegments(text);\n return (\n <Box flexDirection=\"column\">\n {segments.map((segment, i) =>\n segment.type === 'url' ? (\n <Text key={i} color={Colors.accent} underline wrap=\"wrap\">\n {osc8Hyperlink(segment.value, truncateUrlLabel(segment.value))}\n </Text>\n ) : (\n <Text key={i}>{segment.value}</Text>\n ),\n )}\n </Box>\n );\n};\n","/**\n * LogViewer — Real-time log tail, pinned to available terminal height.\n * Only renders the last N lines that fit on screen.\n *\n * Reads only the last TAIL_BYTES of the file on each refresh and throttles\n * fs.watch callbacks to one refresh per WATCH_THROTTLE_MS. Without this,\n * fs.readFileSync allocates a string the size of the entire log on every\n * append — during subagent fan-out that's tens of writes per second against\n * a log that grows into the hundreds of MB, producing OOM-grade allocation\n * pressure on V8's heap.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport * as fs from 'fs';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\n\n/** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar +\n * tab bar, with a couple rows of headroom so the tail never crowds the status\n * bar below it. */\nconst CHROME_ROWS = 10;\n\n/** Bytes read from the end of the log per refresh — large enough to contain\n * any practical visible window of lines, small enough to allocate cheaply. */\nconst TAIL_BYTES = 256 * 1024;\n\n/** Minimum gap between watch-triggered refreshes. fs.watch fires on every\n * append */\nconst WATCH_THROTTLE_MS = 250;\n\ninterface LogViewerProps {\n filePath: string;\n /** Fixed visible height. Defaults to terminal rows minus chrome. */\n height?: number;\n}\n\nfunction readTailLines(filePath: string, visibleLines: number): string[] {\n const stat = fs.statSync(filePath);\n if (stat.size === 0) return [];\n const start = Math.max(0, stat.size - TAIL_BYTES);\n const length = stat.size - start;\n const buf = Buffer.alloc(length);\n const fd = fs.openSync(filePath, 'r');\n try {\n fs.readSync(fd, buf, 0, length, start);\n } finally {\n fs.closeSync(fd);\n }\n let text = buf.toString('utf-8');\n if (start > 0) {\n const firstNewline = text.indexOf('\\n');\n if (firstNewline >= 0) text = text.slice(firstNewline + 1);\n }\n return text.split('\\n').slice(-visibleLines);\n}\n\nexport const LogViewer = ({ filePath, height }: LogViewerProps) => {\n const [, rows] = useStdoutDimensions();\n const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);\n\n const [lines, setLines] = useState<string[]>([]);\n\n useEffect(() => {\n let lastReadAt = 0;\n let pendingTimer: ReturnType<typeof setTimeout> | undefined;\n\n const readTail = () => {\n try {\n setLines(readTailLines(filePath, visibleLines));\n } catch {\n setLines(['(No log file found)']);\n }\n };\n\n const scheduleRead = () => {\n const now = Date.now();\n const elapsed = now - lastReadAt;\n if (elapsed >= WATCH_THROTTLE_MS) {\n lastReadAt = now;\n readTail();\n return;\n }\n if (pendingTimer) return;\n pendingTimer = setTimeout(() => {\n pendingTimer = undefined;\n lastReadAt = Date.now();\n readTail();\n }, WATCH_THROTTLE_MS - elapsed);\n };\n\n readTail();\n lastReadAt = Date.now();\n\n let watcher: fs.FSWatcher | undefined;\n try {\n watcher = fs.watch(filePath, () => scheduleRead());\n } catch {\n const interval = setInterval(() => {\n try {\n fs.accessSync(filePath);\n readTail();\n clearInterval(interval);\n watcher = fs.watch(filePath, () => scheduleRead());\n } catch {\n // Still waiting for the file to appear\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n if (pendingTimer) clearTimeout(pendingTimer);\n };\n }\n\n return () => {\n watcher?.close();\n if (pendingTimer) clearTimeout(pendingTimer);\n };\n }, [filePath, visibleLines]);\n\n return (\n <Box flexDirection=\"column\" height={visibleLines}>\n {lines.map((line, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {line}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * EventPlanViewer — Renders a table of planned analytics events.\n */\n\nimport { Box, Text } from 'ink';\nimport type { PlannedEvent } from '@programs/types';\n\ninterface EventPlanViewerProps {\n events: PlannedEvent[];\n}\n\nexport const EventPlanViewer = ({ events }: EventPlanViewerProps) => {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold>Event plan</Text>\n <Box height={1} />\n {events.map((event) => (\n <Box key={event.name}>\n <Text bold>{event.name}</Text>\n <Text dimColor> {event.description}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { Colors } from '@tui/styles';\n\nconst FEEDBACK = 'Feedback: wizard@posthog.com ';\nconst FEEDBACK_SHORT = ' wizard@posthog.com ';\n\ninterface TitleBarProps {\n version: string;\n width: number;\n}\n\nexport const TitleBar = ({ version, width }: TitleBarProps) => {\n const fullTitle = ` PostHog Wizard v${version}`;\n const needShort = width < fullTitle.length + FEEDBACK.length;\n const feedback = needShort ? FEEDBACK_SHORT : FEEDBACK;\n const title =\n needShort && fullTitle.length + feedback.length > width\n ? ` Wizard v${version}`\n : fullTitle;\n const gap = Math.max(0, width - title.length - feedback.length);\n const padding = ' '.repeat(gap);\n\n return (\n <Box width={width} overflow=\"hidden\">\n <Text backgroundColor={Colors.accent} color={Colors.titleColor}>\n {title}\n {padding}\n {feedback}\n </Text>\n </Box>\n );\n};\n","/** The token HUD's running estimate: each assistant turn's usage, reconciled to the run's total at the end. */\nimport type { TokenUsageDelta } from '@agent/types';\nimport { computeTokenCostUsd } from '@shared/token-pricing';\n\nexport interface TokenUsageSnapshot {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n costUsd: number;\n costIsFinal: boolean;\n}\n\nexport const EMPTY_TOKEN_USAGE: TokenUsageSnapshot = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n costUsd: 0,\n costIsFinal: false,\n};\n\n/** Total tokens across all counters, to detect \"no agent turns yet\". */\nexport function totalTokenCount(usage: TokenUsageSnapshot): number {\n return (\n usage.inputTokens +\n usage.outputTokens +\n usage.cacheReadTokens +\n usage.cacheCreationTokens\n );\n}\n\n/** Add one turn's usage; a reconciled total stays as it is. */\nexport function addTokenUsage(\n usage: TokenUsageSnapshot,\n delta: TokenUsageDelta,\n): TokenUsageSnapshot {\n if (usage.costIsFinal) return usage;\n return {\n inputTokens: usage.inputTokens + delta.inputTokens,\n outputTokens: usage.outputTokens + delta.outputTokens,\n cacheReadTokens: usage.cacheReadTokens + delta.cacheReadTokens,\n cacheCreationTokens: usage.cacheCreationTokens + delta.cacheCreationTokens,\n costUsd: usage.costUsd + computeTokenCostUsd(delta),\n costIsFinal: false,\n };\n}\n","/**\n * TokenCostHud — Ctrl+T panel showing the running (then final) LLM\n * token/cost estimate for this wizard run. Toggled from `ScreenContainer`;\n * deliberately not registered via `useKeyBindings`, so the shortcut never\n * shows in the `KeyboardHintsBar` in production. Defaults visible for\n * local/dev/test runs (`WizardStore`'s `$tokenHudVisible` initial value),\n * so contributors see it without needing to know the shortcut; defaults\n * hidden in the published build. Once shown, the panel itself names the\n * shortcut, so it's self-documenting either way.\n *\n * One row when \"Ctrl+T to hide\" fits on the same row as the cost line\n * (right-aligned, with a minimum gap), two when the terminal is too narrow\n * for both — see `tokenCostHudRowCount`, which `ScreenContainer` calls with\n * the same inputs so its height budget always matches what actually renders\n * (plus the blank spacer `ScreenContainer` renders below either way).\n */\nimport { Box, Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport { totalTokenCount, type TokenUsageSnapshot } from '@tui/token-usage';\nimport { formatTokenCount, formatCostUsd } from '@shared/token-pricing';\n\n/** Self-documents the hidden shortcut once the panel is showing. */\nconst HINT_TEXT = 'Ctrl+T to hide';\n/** Minimum blank columns between the cost line and the hint when they\n * share a row, so they never visually run together. */\nconst MIN_GAP = 2;\n\ninterface TokenCostLineParts {\n /** e.g. \"Cost (running): $1.23\" — rendered in the accent color. */\n costPart: string;\n /** e.g. \" · in 12.3K · out 4.5K · cache read 1.0K · cache write 500\", or\n * \" · no agent turns yet\" — rendered dim. */\n breakdownPart: string;\n}\n\nfunction tokenCostLineParts(usage: TokenUsageSnapshot): TokenCostLineParts {\n const label = usage.costIsFinal ? 'Final cost' : 'Cost (running)';\n const costPart = `${label}: ${formatCostUsd(usage.costUsd)}`;\n\n if (totalTokenCount(usage) === 0) {\n return { costPart, breakdownPart: ' · no agent turns yet' };\n }\n return {\n costPart,\n breakdownPart:\n ` · in ${formatTokenCount(usage.inputTokens)}` +\n ` · out ${formatTokenCount(usage.outputTokens)}` +\n ` · cache read ${formatTokenCount(usage.cacheReadTokens)}` +\n ` · cache write ${formatTokenCount(usage.cacheCreationTokens)}`,\n };\n}\n\ninterface TokenCostLineLayout {\n costPart: string;\n breakdownPart: string;\n /** True when \"Ctrl+T to hide\" fits on the cost line's row at `width`\n * columns (with `MIN_GAP` to spare); false when it needs its own row. */\n hintFitsInline: boolean;\n /** Blank columns to pad before the hint when it fits inline. */\n gap: number;\n}\n\n/** Single source of truth for both `tokenCostHudRowCount` (so\n * `ScreenContainer`'s height budget can never disagree with what renders)\n * and the component's own render — computed once per call rather than\n * separately in each. */\nfunction layoutTokenCostLine(\n usage: TokenUsageSnapshot,\n width: number,\n): TokenCostLineLayout {\n const { costPart, breakdownPart } = tokenCostLineParts(usage);\n const lineLength = costPart.length + breakdownPart.length;\n return {\n costPart,\n breakdownPart,\n hintFitsInline: lineLength + MIN_GAP + HINT_TEXT.length <= width,\n gap: Math.max(MIN_GAP, width - lineLength - HINT_TEXT.length),\n };\n}\n\n/**\n * How many rows `TokenCostHud` renders for `usage` at `width` columns of\n * available text space — 1 when the hint fits on the cost line's row, 2\n * when it needs its own row below. `ScreenContainer` calls this with the\n * exact same `usage`/`width` it passes to the component.\n */\nexport function tokenCostHudRowCount(\n usage: TokenUsageSnapshot,\n width: number,\n): 1 | 2 {\n return layoutTokenCostLine(usage, width).hintFitsInline ? 1 : 2;\n}\n\ninterface TokenCostHudProps {\n usage: TokenUsageSnapshot;\n /** Available text width (columns) — decides whether the hint fits on the\n * cost line's row. Pass the content width, not the outer box width (the\n * panel's own `paddingX={1}` is accounted for by the caller). */\n width: number;\n}\n\nexport const TokenCostHud = ({ usage, width }: TokenCostHudProps) => {\n const { costPart, breakdownPart, hintFitsInline, gap } = layoutTokenCostLine(\n usage,\n width,\n );\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text wrap=\"truncate\">\n <Text color={Colors.accent}>{costPart}</Text>\n <Text dimColor>{breakdownPart}</Text>\n {hintFitsInline && <Text>{' '.repeat(gap)}</Text>}\n {hintFitsInline && <Text dimColor>{HINT_TEXT}</Text>}\n </Text>\n {!hintFitsInline && (\n <Text dimColor wrap=\"truncate\">\n {HINT_TEXT}\n </Text>\n )}\n </Box>\n );\n};\n","/**\n * DissolveTransition — Column-sweep inspired by TTE's Sweep effect.\n *\n * Uses a SequenceEaser (in_out_circ) to activate columns with eased pacing.\n * Each activated column cycles through shade characters (░▒▓█) independently.\n *\n * Out phase: columns sweep, building up shade chars until solid █ (covers old content).\n * In phase: columns sweep in reverse, dissolving █ back through shades to empty (reveals new content).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect, useRef, type ReactNode } from 'react';\n\n/** Shade characters in build-up order (light → solid). */\nconst SHADES = ['░', '▒', '▓', '█'] as const;\n/** How many ticks each shade character displays before advancing. */\nconst TICKS_PER_SHADE = 2;\n/** Total ticks a column needs to complete its shade cycle. */\nconst SHADE_CYCLE_TICKS = SHADES.length * TICKS_PER_SHADE;\n\nexport type WipeDirection = 'left' | 'right';\n\ninterface DissolveTransitionProps {\n transitionKey: string;\n width: number;\n height: number;\n children: ReactNode;\n direction?: WipeDirection;\n duration?: number;\n}\n\nfunction easeInOutCirc(t: number): number {\n if (t < 0.5) {\n return (1 - Math.sqrt(1 - 4 * t * t)) / 2;\n }\n return (Math.sqrt(1 - (2 * t - 2) ** 2) + 1) / 2;\n}\n\nenum TransitionPhase {\n Idle = 'idle',\n Out = 'out',\n In = 'in',\n}\n\nexport const DissolveTransition = ({\n transitionKey,\n width,\n height,\n children,\n direction = 'left',\n duration = 2,\n}: DissolveTransitionProps) => {\n const [phase, setPhase] = useState<TransitionPhase>(TransitionPhase.Idle);\n const [tick, setTick] = useState(0);\n const [activeDir, setActiveDir] = useState<WipeDirection>(direction);\n const prevKey = useRef(transitionKey);\n const pendingChildren = useRef<ReactNode>(children);\n const [displayChildren, setDisplayChildren] = useState<ReactNode>(children);\n\n // Track when each column was activated (tick number), -1 means not yet.\n const columnActivationTick = useRef<number[]>([]);\n\n useEffect(() => {\n if (transitionKey !== prevKey.current) {\n prevKey.current = transitionKey;\n pendingChildren.current = children;\n setActiveDir(direction);\n setPhase(TransitionPhase.Out);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else if (phase !== TransitionPhase.Idle) {\n // Terminal resized mid-transition — abort and show new content immediately\n setPhase(TransitionPhase.Idle);\n setDisplayChildren(children);\n } else {\n setDisplayChildren(children);\n }\n }, [transitionKey, children, width, height, phase, direction]);\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n\n const timer = setInterval(() => {\n setTick((prev) => prev + 1);\n }, duration);\n\n return () => clearInterval(timer);\n }, [phase, duration]);\n\n // Easer steps = width: roughly one column activates per tick.\n // This keeps the sweep front tight (only a few columns in-flight at once).\n const easerSteps = width;\n\n // A phase ends when the easer has completed AND all columns have finished their shade cycle.\n const maxTicks = easerSteps + SHADE_CYCLE_TICKS;\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n if (tick >= maxTicks) {\n if (phase === TransitionPhase.Out) {\n setDisplayChildren(pendingChildren.current);\n setPhase(TransitionPhase.In);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else {\n setPhase(TransitionPhase.Idle);\n }\n }\n }, [tick, phase, maxTicks, width]);\n\n if (phase === TransitionPhase.Idle) {\n return <>{displayChildren}</>;\n }\n\n // --- SequenceEaser logic ---\n // Map current tick to easer progress (0..1), apply easing,\n // then determine how many columns should be activated.\n const easerProgress = Math.min(tick / easerSteps, 1);\n const easedValue = easeInOutCirc(easerProgress);\n const activatedCount = Math.floor(easedValue * width);\n\n // Build column order based on direction.\n // \"left\" means sweep moves left-to-right; \"right\" means right-to-left.\n // TTE's COLUMN_RIGHT_TO_LEFT activates rightmost first.\n const columnOrder: number[] = [];\n if (activeDir === 'left') {\n for (let c = width - 1; c >= 0; c--) columnOrder.push(c);\n } else {\n for (let c = 0; c < width; c++) columnOrder.push(c);\n }\n\n // Activate columns that should be active but aren't yet.\n for (let i = 0; i < activatedCount && i < columnOrder.length; i++) {\n const col = columnOrder[i];\n if (columnActivationTick.current[col] === -1) {\n columnActivationTick.current[col] = tick;\n }\n }\n\n // --- Render frame ---\n const rows: string[] = [];\n for (let r = 0; r < height; r++) {\n let row = '';\n for (let c = 0; c < width; c++) {\n const activatedAt = columnActivationTick.current[c];\n\n let char: string;\n if (activatedAt === -1) {\n // Not yet activated\n char = phase === TransitionPhase.Out ? ' ' : '█';\n } else {\n // Column is activated — determine shade based on ticks since activation\n const age = tick - activatedAt;\n const shadeIndex = Math.min(\n Math.floor(age / TICKS_PER_SHADE),\n SHADES.length - 1,\n );\n\n if (phase === TransitionPhase.Out) {\n // Building up: ░ → ▒ → ▓ → █\n char = SHADES[shadeIndex];\n } else {\n // Dissolving: █ → ▓ → ▒ → ░ → space\n if (shadeIndex >= SHADES.length - 1 && age >= SHADE_CYCLE_TICKS) {\n char = ' ';\n } else {\n char = SHADES[SHADES.length - 1 - shadeIndex];\n }\n }\n }\n\n row += char;\n }\n rows.push(row);\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {rows.map((row, i) => (\n <Text key={i} dimColor>\n {row}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * KeyboardHintsBar — Row showing active keyboard shortcuts.\n *\n * Always reserves its row to prevent layout shift, and always renders the\n * active hints (in dimmed grey text) while a screen has registered them.\n */\n\nimport { Box, Text } from 'ink';\nimport { useKeyboardHintsContext } from '@tui/hooks/useKeyboardHints';\nimport { Colors } from '@tui/styles';\n\nexport const KeyboardHintsBar = () => {\n const { hints } = useKeyboardHintsContext();\n\n return (\n <Box height={1} paddingX={1}>\n {hints.map((hint, i) => (\n <Box\n key={`${hint.label}-${hint.action}`}\n marginRight={i < hints.length - 1 ? 2 : 0}\n >\n <Text bold color={Colors.muted}>\n {hint.label}\n </Text>\n <Text dimColor> {hint.action}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * ScreenErrorBoundary — catches React render errors in screens\n * and routes to the outro screen with an error message.\n *\n * Without this, a screen crash silently hangs the TUI.\n */\n\nimport { Box, Text } from 'ink';\nimport { Component, type ReactNode } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { OutroKind } from '@shared/outro';\nimport { RunPhase } from '@shared/run-state';\nimport { logToFile } from '@utils/debug';\n\ninterface Props {\n store: WizardStore;\n children: ReactNode;\n}\n\ninterface State {\n error: Error | null;\n}\n\nexport class ScreenErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error): void {\n const { store } = this.props;\n\n // The console.error below is wiped with the alt screen; this survives.\n logToFile('[screen-error-boundary]', error);\n // eslint-disable-next-line no-console\n console.error('[ScreenErrorBoundary]', error.message, error.stack);\n\n // Set error state — the router will resolve to outro\n store.setOutroData({\n kind: OutroKind.Error,\n message: `A screen crashed: ${error.message}`,\n });\n store.setRunPhase(RunPhase.Error);\n }\n\n render(): ReactNode {\n if (this.state.error) {\n // Fallback while the store transition fires\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n Something went wrong.\n </Text>\n <Text dimColor>{this.state.error.message}</Text>\n </Box>\n );\n }\n\n return this.props.children;\n }\n}\n","/**\n * ViewportTooSmall — The nag shown when the terminal is smaller than the\n * wizard's layout can survive.\n *\n * 80 columns is the width `ScreenContainer` clamps its layout to. 28 rows is\n * measured, not chosen: the framework picker — the tallest screen — overprints\n * its intro lines and silently drops framework options at 27 rows and below,\n * and renders cleanly at 28 (issue #1111). Below either bound the wizard looks\n * broken rather than small, so say so instead of rendering.\n */\n\nimport { Box, Text } from 'ink';\nimport { wordWrap } from './layout-helpers.js';\nimport { Colors } from '@tui/styles';\n\n/** Smallest terminal the wizard will render its screens into. */\nexport const MIN_VIEWPORT_COLUMNS = 80;\nexport const MIN_VIEWPORT_ROWS = 28;\n\nexport const VIEWPORT_TOO_SMALL_MESSAGE =\n 'The Wizard needs more room to display required text. Please make this terminal bigger.';\n\nexport function isViewportTooSmall(columns: number, rows: number): boolean {\n return columns < MIN_VIEWPORT_COLUMNS || rows < MIN_VIEWPORT_ROWS;\n}\n\n/**\n * Pre-wrap the notice rather than letting Ink wrap it: the whole point of this\n * screen is that it renders correctly in a terminal too narrow for everything\n * else. Accounts for the component's own paddingX={1}.\n */\nexport function viewportNoticeLines(text: string, columns: number): string[] {\n return wordWrap(text, Math.max(20, columns - 2));\n}\n\n/** The \"you have this much, you need this much\" line under the message. */\nexport function viewportSizeLine(columns: number, rows: number): string {\n return `Currently ${columns}×${rows}, needs at least ${MIN_VIEWPORT_COLUMNS}×${MIN_VIEWPORT_ROWS}.`;\n}\n\ninterface ViewportTooSmallProps {\n columns: number;\n rows: number;\n}\n\nexport const ViewportTooSmall = ({ columns, rows }: ViewportTooSmallProps) => {\n const message = viewportNoticeLines(VIEWPORT_TOO_SMALL_MESSAGE, columns);\n const size = viewportNoticeLines(viewportSizeLine(columns, rows), columns);\n\n return (\n <Box\n flexDirection=\"column\"\n width={columns}\n height={rows}\n paddingX={1}\n justifyContent=\"center\"\n >\n {message.map((line, i) => (\n <Text key={`m${i}`} color={Colors.error} bold>\n {line}\n </Text>\n ))}\n <Box height={1} />\n {size.map((line, i) => (\n <Text key={`s${i}`} color={Colors.muted}>\n {line}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * ScreenContainer — Renders TitleBar + routes between screens with transitions.\n * Takes a screens map and renders the one matching store.currentScreen.\n * Horizontal wipe plays on push (left) or pop (right).\n *\n * Each screen is wrapped in a ScreenErrorBoundary so that render crashes\n * route to the outro screen with an error message instead of hanging.\n *\n * Provides KeyboardHintsProvider context. The hints bar is rendered below\n * screen content (inside the transition area) so all screens get it.\n */\n\nimport { Box, useInput, useStdout } from 'ink';\nimport { useSyncExternalStore, type ReactNode } from 'react';\nimport { TitleBar } from '@tui/components/TitleBar';\nimport {\n TokenCostHud,\n tokenCostHudRowCount,\n} from '@tui/components/TokenCostHud';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport { KeyboardHintsProvider } from '@tui/hooks/useKeyboardHints';\nimport { DissolveTransition } from './DissolveTransition.js';\nimport { KeyboardHintsBar } from './KeyboardHintsBar.js';\nimport { ScreenErrorBoundary } from './ScreenErrorBoundary.js';\nimport {\n ViewportTooSmall,\n isViewportTooSmall,\n} from './ViewportTooSmall.js';\nimport type { WizardStore } from '@tui/store';\n\nconst MIN_WIDTH = 80;\nexport const MAX_WIDTH = 120;\n\n/** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */\nfunction getContentWidth(terminalColumns: number): number {\n if (terminalColumns < MIN_WIDTH) return terminalColumns;\n return Math.min(MAX_WIDTH, terminalColumns);\n}\n\ninterface ScreenContainerProps {\n store: WizardStore;\n screens: Record<string, ReactNode>;\n}\n\nexport const ScreenContainer = ({ store, screens }: ScreenContainerProps) => {\n const [columns, rows] = useStdoutDimensions();\n const { stdout } = useStdout();\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Hidden shortcut: Ctrl+T toggles the token/cost HUD. Deliberately not\n // wired through useKeyBindings, so it never appears in the hints bar.\n // Mounted here (not on any individual screen) so it works everywhere —\n // ScreenContainer is the one component alive for the whole process.\n useInput((input, key) => {\n if (key.ctrl && input === 't') store.toggleTokenHud();\n });\n\n const terminalWidth = columns;\n const width = getContentWidth(terminalWidth);\n const hudVisible = store.tokenHudVisible;\n // Text width inside TokenCostHud's own paddingX={1} (1 column each side).\n const hudContentWidth = Math.max(1, width - 2);\n // 1 row when the \"Ctrl+T to hide\" hint fits on the cost line's row, 2 when\n // it needs its own row below (see tokenCostHudRowCount) — plus a one-row\n // spacer below the HUD. Budget the exact total so it can never disagree\n // with what TokenCostHud actually renders and push content past the\n // terminal height.\n const hudRows = hudVisible\n ? tokenCostHudRowCount(store.tokenUsage, hudContentWidth) + 1\n : 0;\n const contentHeight = Math.max(5, rows - 3 - hudRows);\n const contentAreaWidth = Math.max(10, width - 2);\n const direction = store.lastNavDirection === 'pop' ? 'right' : 'left';\n const activeScreen = screens[store.currentScreen] ?? null;\n\n // Too small to lay out: hide the screens rather than unmounting them. Yoga\n // drops display:none subtrees from layout entirely, so the hidden tree can't\n // overflow into the notice, and staying mounted keeps a half-typed input\n // alive and — the reason this isn't a plain unmount — stops every screen's\n // mount effects (browser opens, health checks, detection) from re-firing\n // each time someone drags the window edge. The cost is that keypresses\n // still reach the hidden screen; that's how ctrl+c keeps working, and it\n // beats today's behaviour of typing into a garbled one.\n //\n // Only enforced on a real terminal: with stdout piped there are no\n // dimensions to read (useStdoutDimensions substitutes 80×24) and no window\n // for anyone to resize, so nagging would be both wrong and unactionable.\n const tooSmall =\n Boolean(stdout.isTTY) && isViewportTooSmall(columns, rows);\n\n const inner = (\n <Box\n flexDirection=\"column\"\n height={rows}\n width={width}\n display={tooSmall ? 'none' : 'flex'}\n >\n <TitleBar version={store.version} width={width} />\n <Box height={1} />\n {hudVisible && (\n <>\n <TokenCostHud usage={store.tokenUsage} width={hudContentWidth} />\n <Box height={1} />\n </>\n )}\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <DissolveTransition\n transitionKey={store.currentScreen}\n width={contentAreaWidth}\n height={contentHeight}\n direction={direction}\n >\n <ScreenErrorBoundary store={store}>\n <Box flexDirection=\"column\" height={contentHeight}>\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n flexShrink={1}\n overflow=\"hidden\"\n >\n {activeScreen}\n </Box>\n <Box height={1} />\n <KeyboardHintsBar />\n </Box>\n </ScreenErrorBoundary>\n </DissolveTransition>\n </Box>\n </Box>\n );\n\n return (\n <Box\n flexDirection=\"column\"\n height={rows}\n width={terminalWidth}\n alignItems=\"center\"\n justifyContent=\"flex-start\"\n >\n {tooSmall && <ViewportTooSmall columns={columns} rows={rows} />}\n <KeyboardHintsProvider>{inner}</KeyboardHintsProvider>\n </Box>\n );\n};\n","/**\n * TabContainer — Self-contained tabbed interface.\n * Absorbs BottomTabBar + StatusPanel functionality.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar (rendered by ScreenContainer).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo, type ReactNode } from 'react';\nimport { Colors, Icons } from '@tui/styles';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n} from '@tui/hooks/useKeyBindings';\nimport type { WizardStore } from '@tui/store';\nimport { COLLAPSED_COUNT, EXPANDED_COUNT } from '@tui/constants';\n\n// Re-exported so existing importers (e.g. LearnCard) keep their path.\nexport { COLLAPSED_COUNT, EXPANDED_COUNT };\n\nexport interface TabDefinition {\n id: string;\n label: string;\n component: ReactNode;\n}\n\ninterface TabContainerProps {\n tabs: TabDefinition[];\n statusMessage?: string | string[];\n /** Enable expand/collapse on the status box via 's' key */\n expandableStatus?: boolean;\n /** Store reference — required when expandableStatus is true so status state is shared. */\n store?: WizardStore;\n}\n\nexport const TabContainer = ({\n tabs,\n statusMessage,\n expandableStatus = false,\n store,\n}: TabContainerProps) => {\n const [activeTab, setActiveTab] = useState(0);\n // Fallback to local state when no store is provided\n const [localExpanded, setLocalExpanded] = useState(false);\n\n const statusExpanded = store ? store.statusExpanded : localExpanded;\n\n const bindings = useMemo<KeyBinding[]>(() => {\n const b: KeyBinding[] = [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch tab',\n handler: (_input, key) => {\n if (key.leftArrow) {\n setActiveTab((prev) => Math.max(0, prev - 1));\n }\n if (key.rightArrow) {\n setActiveTab((prev) => Math.min(tabs.length - 1, prev + 1));\n }\n },\n },\n ];\n if (expandableStatus) {\n b.push({\n match: 's',\n label: 's',\n action: 'toggle status',\n priority: 12,\n handler: () => {\n if (store) {\n store.toggleStatusExpanded();\n } else {\n setLocalExpanded((prev) => !prev);\n }\n },\n });\n }\n return b;\n }, [tabs.length, expandableStatus, store]);\n\n useKeyBindings('tab-container', bindings);\n\n const current = tabs[activeTab];\n\n const allMessages = statusMessage\n ? Array.isArray(statusMessage)\n ? statusMessage\n : [statusMessage]\n : [];\n const visibleCount =\n expandableStatus && statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT;\n const visibleMessages = allMessages.slice(-visibleCount);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {/* Active tab content — overflow hidden so expanded status eats into this area */}\n <Box flexDirection=\"column\" flexGrow={1} flexShrink={1} overflow=\"hidden\">\n {current?.component}\n </Box>\n\n {/* Status bar */}\n {visibleMessages.length > 0 && (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderTop\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderColor={Colors.muted}\n paddingX={1}\n overflow=\"hidden\"\n >\n {visibleMessages.map((msg, i, arr) => {\n const isCurrent = i === arr.length - 1;\n return (\n <Text key={i} color={Colors.muted} dimColor={!isCurrent}>\n {isCurrent ? Icons.diamond : '\\u250A'} {msg}\n </Text>\n );\n })}\n </Box>\n )}\n\n {/* Tab bar — wraps onto extra rows when there are more tabs than\n fit the terminal width, instead of clipping the overflow. */}\n <Box height={1} />\n <Box gap={1} paddingX={1} flexWrap=\"wrap\" flexShrink={0}>\n {tabs.map((tab, i) => (\n <Text\n key={tab.id}\n inverse={i === activeTab}\n color={i === activeTab ? Colors.accent : Colors.muted}\n bold={i === activeTab}\n >\n {` ${tab.label} `}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","/**\n * HNViewer — Top 10 Hacker News stories.\n *\n * Fetches from the HN Firebase API on mount.\n * Each story has a [1]–[0] numeral; typing it opens the HN comments page.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { Colors } from '@tui/styles';\nimport { useKeyBindings } from '@tui/hooks/useKeyBindings';\n\nconst HN_API = 'https://hacker-news.firebaseio.com/v0';\n\ninterface HNStory {\n id: number;\n title: string;\n by: string;\n time: number;\n score: number;\n}\n\nexport const HNViewer = () => {\n const [stories, setStories] = useState<HNStory[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n void (async () => {\n try {\n const res = await fetch(`${HN_API}/topstories.json`);\n const ids = (await res.json()) as number[];\n const top10 = ids.slice(0, 10);\n\n const items = await Promise.all(\n top10.map(async (id) => {\n const r = await fetch(`${HN_API}/item/${id}.json`);\n return r.json() as Promise<HNStory>;\n }),\n );\n\n setStories(items);\n } catch {\n // Silently fail — tab just stays empty\n }\n setLoading(false);\n })();\n }, []);\n\n useKeyBindings('hn-viewer', [\n {\n match: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],\n label: 'number keys',\n action: 'open story',\n priority: 5,\n handler: (input) => openStory(input, stories),\n },\n ]);\n\n if (loading) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Loading Hacker News...</Text>\n </Box>\n );\n }\n\n if (stories.length === 0) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Could not load Hacker News.</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Hacker News — Top 10\n </Text>\n <Box height={1} />\n {stories.map((story, i) => {\n const key = i === 9 ? '0' : String(i + 1);\n const date = new Date(story.time * 1000);\n const dateStr = date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n });\n\n return (\n <Box key={story.id} flexDirection=\"column\">\n <Box>\n <Text color={Colors.accent} bold>\n [{key}]\n </Text>\n <Text bold> {story.title}</Text>\n </Box>\n <Box marginLeft={4}>\n <Text dimColor>\n {story.score}pts • {story.by}, {dateStr}\n </Text>\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n};\n\nfunction openStory(input: string, stories: HNStory[]): void {\n const num = parseInt(input, 10);\n if (isNaN(num)) return;\n const index = num === 0 ? 9 : num - 1;\n const story = stories[index];\n if (!story) return;\n\n const url = `https://news.ycombinator.com/item?id=${story.id}`;\n void import('child_process').then(({ exec }) => {\n exec(`open \"${url}\" 2>/dev/null || xdg-open \"${url}\" 2>/dev/null`);\n });\n}\n","/**\n * LinesBlock — Reveals ReactNode lines one at a time.\n * Each line can contain colors, bold, ASCII art — any JSX.\n */\n\nimport { Box } from 'ink';\nimport { useState, useEffect, type ReactNode } from 'react';\n\ninterface LinesBlockProps {\n lines: ReactNode[];\n interval: number;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n}\n\nexport const LinesBlock = ({\n lines,\n interval,\n active,\n completed,\n onComplete,\n maxHeight,\n}: LinesBlockProps) => {\n const [revealedCount, setRevealedCount] = useState(0);\n\n // Reveal lines one at a time\n useEffect(() => {\n if (!active || revealedCount >= lines.length) return;\n const timer = setTimeout(\n () => setRevealedCount((c) => c + 1),\n revealedCount === 0 ? 0 : interval,\n );\n return () => clearTimeout(timer);\n }, [active, revealedCount, lines.length, interval]);\n\n // Fire onComplete when all lines revealed\n useEffect(() => {\n if (active && revealedCount >= lines.length) onComplete();\n }, [active, revealedCount, lines.length, onComplete]);\n\n // When maxHeight is set, only show the last maxHeight lines\n const visibleStart =\n maxHeight != null\n ? Math.max(0, (completed ? lines.length : revealedCount) - maxHeight)\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, li) => {\n if (completed) {\n if (li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n }\n if (li >= revealedCount || li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n })}\n </Box>\n );\n};\n","/**\n * NodeBlock — Renders static JSX, fires onComplete immediately.\n * The sequencer's blockInterval handles dwell time.\n */\n\nimport { Text } from 'ink';\nimport { useEffect, type ReactNode } from 'react';\n\ninterface NodeBlockProps {\n content: ReactNode;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n}\n\nexport const NodeBlock = ({\n content,\n active,\n completed,\n onComplete,\n}: NodeBlockProps) => {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n\n if (completed) return <Text dimColor>{content}</Text>;\n return <>{content}</>;\n};\n","/**\n * ContentSequencer — Plays content blocks in order.\n *\n * Each block is a self-animating component that fires onComplete() when done.\n * The sequencer waits blockInterval ms between blocks, then advances.\n *\n * Block types:\n * - string → TextBlock (animated text, sugar for { content: '...' })\n * - { content: str } → TextBlock (animated text with per-block overrides)\n * - { content: JSX } → NodeBlock (static JSX)\n * - { type: 'lines' } → LinesBlock (line-by-line reveal)\n * - { type: 'clear' } → ClearBlock (page break — hides all prior blocks)\n */\n\nimport { Box } from 'ink';\nimport {\n useState,\n useCallback,\n useEffect,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { TextBlock, type TextRevealMode } from './TextBlock.js';\nimport { LinesBlock } from './LinesBlock.js';\nimport { NodeBlock } from './NodeBlock.js';\nimport { computeVisibleRange } from './layout-helpers.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\nexport type {\n ContentBlock,\n ContentObjectBlock,\n ContentLinesBlock,\n ContentClearBlock,\n} from './content-types.js';\nexport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\nimport type { ContentBlock } from './content-types.js';\n\n/** Resolve the pause after a block completes. */\nexport function getBlockPause(\n block: ContentBlock,\n blockInterval: number,\n): number {\n if (typeof block === 'string') return blockInterval;\n return block.pause ?? blockInterval;\n}\n\ninterface ContentSequencerProps {\n blocks: ContentBlock[];\n mode: TextRevealMode;\n /** Row budget for visible content. When set, older blocks are evicted. */\n maxHeight?: number;\n /** Available text width in columns (for height estimation). */\n availableWidth?: number;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval?: number;\n blockInterval?: number;\n /** Delay in ms before the first block appears. */\n startDelay?: number;\n /** Resume from a previously persisted block index. */\n initialBlockIdx?: number;\n /** Called whenever the active block index advances. */\n onBlockChange?: (idx: number) => void;\n /** Called once when the last block completes (after its pause). */\n onSequenceComplete?: () => void;\n}\n\nexport const ContentSequencer = ({\n blocks,\n mode,\n maxHeight,\n availableWidth,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval = 200,\n blockInterval = 3200,\n startDelay = 0,\n initialBlockIdx = 0,\n onBlockChange,\n onSequenceComplete,\n}: ContentSequencerProps) => {\n const resuming = initialBlockIdx > 0;\n const [activeIdx, setActiveIdx] = useState(\n resuming ? initialBlockIdx : startDelay > 0 ? -1 : 0,\n );\n const transitionTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Initial delay before first block (skip when resuming)\n useEffect(() => {\n if (resuming || startDelay <= 0 || activeIdx !== -1) return;\n const timer = setTimeout(() => setActiveIdx(0), startDelay);\n return () => clearTimeout(timer);\n }, [startDelay, activeIdx]);\n\n // Compute visible range reactively (re-evaluates on resize, block advance, etc.)\n const [visibleStart, visibleEnd] = useMemo(() => {\n if (activeIdx < 0) return [0, -1] as [number, number];\n if (maxHeight == null || availableWidth == null) {\n return [0, activeIdx] as [number, number];\n }\n return computeVisibleRange(blocks, activeIdx, availableWidth, maxHeight);\n }, [blocks, activeIdx, maxHeight, availableWidth]);\n\n const handleComplete = useCallback(\n (blockIndex: number) => {\n // Only the active block can trigger advancement\n if (blockIndex !== activeIdx) return;\n // Last block — fire sequence-complete after its pause, don't advance\n if (activeIdx >= blocks.length - 1) {\n if (onSequenceComplete && !transitionTimer.current) {\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n onSequenceComplete();\n }, pause);\n }\n return;\n }\n // Don't double-trigger\n if (transitionTimer.current) return;\n\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n setActiveIdx((i) => {\n const next = i + 1;\n onBlockChange?.(next);\n return next;\n });\n }, pause);\n },\n [activeIdx, blocks, blockInterval, onBlockChange, onSequenceComplete],\n );\n\n // Find the most recent clear block — nothing before it renders.\n // When the active block IS a clear block, immediately hide all prior content\n // so the pause shows a blank screen (not dim prior text).\n const clearFloor = useMemo(() => {\n if (activeIdx >= 0 && isClearBlock(blocks[activeIdx])) return activeIdx;\n for (let i = activeIdx - 1; i >= 0; i--) {\n if (isClearBlock(blocks[i])) return i + 1;\n }\n return 0;\n }, [blocks, activeIdx]);\n\n return (\n <Box flexDirection=\"column\">\n {blocks.map((block, i) => {\n // Not yet reached\n if (i > activeIdx) return null;\n // Hidden by clear block\n if (i < clearFloor) return null;\n // Completed clear blocks don't render (active ones must mount to fire onComplete)\n if (isClearBlock(block) && i < activeIdx) return null;\n // Evicted by viewport\n if (i < visibleStart || i > visibleEnd) return null;\n\n const active = i === activeIdx;\n const completed = i < activeIdx;\n\n // Completed non-text blocks don't persist by default\n if (completed && isObjectBlock(block)) {\n const isText = typeof block.content === 'string';\n const shouldPersist = block.persist ?? isText;\n if (!shouldPersist) return null;\n }\n\n return (\n <Box key={i} flexDirection=\"column\" marginBottom={1}>\n <BlockRenderer\n block={block}\n active={active}\n completed={completed}\n onComplete={() => handleComplete(i)}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n lineInterval={lineInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n </Box>\n );\n })}\n </Box>\n );\n};\n\ninterface BlockRendererProps {\n block: ContentBlock;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval: number;\n maxHeight?: number;\n availableWidth?: number;\n}\n\nconst BlockRenderer = ({\n block,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval,\n maxHeight,\n availableWidth,\n}: BlockRendererProps) => {\n // Clear block — completes immediately, renders nothing\n if (isClearBlock(block)) {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n return null;\n }\n\n // Bare string sugar → TextBlock with sequencer defaults\n if (typeof block === 'string') {\n return (\n <TextBlock\n text={block}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n // Bare string sugar always uses the default — to override, use\n // the object form: { content: '...', dimWhenComplete: false }.\n />\n );\n }\n\n // Lines block\n if (isLinesBlock(block)) {\n return (\n <LinesBlock\n lines={block.lines}\n interval={block.interval ?? lineInterval}\n active={active}\n completed={completed}\n onComplete={onComplete}\n maxHeight={maxHeight}\n />\n );\n }\n\n // Object block — dispatch on content type\n if (typeof block.content === 'string') {\n return (\n <TextBlock\n text={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={block.mode ?? mode}\n bullet={bullet}\n animationInterval={block.animationInterval ?? animationInterval}\n sentenceInterval={block.sentenceInterval ?? sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n dimWhenComplete={block.dimWhenComplete ?? true}\n />\n );\n }\n\n return (\n <NodeBlock\n content={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n />\n );\n};\n","/**\n * PrivacyPanel — Shared disclosure component.\n *\n * Single source of truth for the wizard's privacy disclosure, rendered\n * identically from the intro screen (the `PRIVACY_PANEL_LABEL` menu option)\n * and as an overlay from the auth screen ([I] keystroke).\n *\n * Must fit in a default-sized macOS Terminal (~24 rows). Two condensed\n * paragraphs carry the top-level disclosure; the link footer follows.\n * Users who want the full legal text follow the Terms / Privacy URLs to\n * their browser.\n *\n * The scan paragraph is opt-in per caller. It ends by pointing at a control,\n * so it may only render on a screen that puts one below the panel — three of\n * the four callers show `Back` and nothing else, and would be promising a\n * choice that is not there.\n */\n\nimport { useEffect } from 'react';\nimport { Box, Text } from 'ink';\nimport {\n POSTHOG_ORG_AI_SETTINGS_URL,\n POSTHOG_PRIVACY_URL,\n POSTHOG_TERMS_URL,\n} from '@shared/constants';\nimport { analytics } from '@utils/analytics';\n\n/**\n * The panel's name everywhere it is referenced: intro menu, screen titles, and\n * the auth screen's [I] hint. One constant so the five spellings this replaced\n * cannot come back.\n */\nexport const PRIVACY_PANEL_LABEL = 'Privacy & data';\n\ninterface PrivacyPanelProps {\n /**\n * True only on a screen that renders the sharing choice below the panel.\n * Gates the scan paragraph, whose last sentence sends the reader to a\n * control that exists on one screen.\n */\n canOptOut?: boolean;\n}\n\nexport const PrivacyPanel = ({ canOptOut = false }: PrivacyPanelProps = {}) => {\n // Rendered from the intro menu and the auth-screen [I] overlay; either way,\n // count the impression once per mount.\n useEffect(() => {\n analytics.wizardCapture('privacy panel shown');\n }, []);\n\n return (\n <Box flexDirection=\"column\" width={64} flexShrink={0}>\n <Text>\n We use Anthropic and OpenAI models via the PostHog LLM gateway to read\n your source files as AI context. .env* file contents, secrets, and\n anything matched by the security scanner stay on your machine.\n </Text>\n\n <Box marginTop={1}>\n <Text>\n To use the wizard, AI features must be enabled in your organization's\n settings.\n </Text>\n </Box>\n\n <Box marginTop={1} flexDirection=\"column\">\n <Text>\n Terms: <Text color=\"cyan\">{POSTHOG_TERMS_URL}</Text>\n </Text>\n <Text>\n Privacy: <Text color=\"cyan\">{POSTHOG_PRIVACY_URL}</Text>\n </Text>\n <Text>\n AI settings: <Text color=\"cyan\">{POSTHOG_ORG_AI_SETTINGS_URL}</Text>\n </Text>\n </Box>\n\n {canOptOut && (\n <Box marginTop={1}>\n <Text>\n We also read your file tree, dependency files, templates, and .env\n variable names, never values, to find this project's tools and pick\n the right setup. We share each tool with PostHog to improve our\n products, with the file and name that matched it, and the setup we\n chose, such as the framework. You can opt out of sharing below.\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n","/**\n * IntroScreenLayout ��� Shared visual shell for all program intro screens.\n *\n * Purely presentational — no store subscription. Parent components own\n * the store subscription and pass derived data as props.\n *\n * Slots:\n * body — free-form content below the title bar (copy, spinners, pickers, etc.)\n * children — between detection rows and menu (extra info, warnings)\n * errorView — replaces the entire body for fatal error states\n */\n\nimport path from 'path';\nimport { Box, Text } from 'ink';\nimport { useState, type ReactNode } from 'react';\nimport { PickerMenu, type PickerOption } from '@tui/primitives/index';\nimport {\n PrivacyPanel,\n PRIVACY_PANEL_LABEL,\n} from '@tui/components/PrivacyPanel';\n\nexport interface DetectionRow {\n label: string;\n value: string;\n suffix?: string;\n}\n\ninterface IntroScreenLayoutProps {\n /** Absolute path to the project directory */\n installDir: string;\n\n /** Title text after the colored blocks, e.g. \"PostHog Wizard 🦔\" */\n title?: string;\n\n /** Show the subtitle below the title. Default true. */\n showSubtitle?: boolean;\n\n /**\n * Custom subtitle content, rendered in place of the default\n * \"We'll use AI… / .env*…\" lines when `showSubtitle` is true. Pass the\n * inner <Text> lines — the layout owns the centered, top-margined\n * wrapper. Defaults to the generic subtitle when omitted.\n */\n subtitle?: ReactNode;\n\n /** Free-form content below the title (copy, spinners, pickers, notices) */\n body?: ReactNode;\n\n /** Show the detection block (Directory, detection rows, Program, Skill). Default true. */\n showDetection?: boolean;\n\n /** Extra detection row items rendered as \"Label ✔ value suffix\" */\n detectionRows?: DetectionRow[];\n\n /** Content rendered between detection rows and the menu */\n children?: ReactNode;\n\n /**\n * Menu options, forwarded to PickerMenu as-is — so a screen can mark a row\n * `disabled` (navigation skips it, which is how a blank spacer row works) or\n * give it an `icon`. Pass null to hide the menu entirely.\n */\n menuOptions?: PickerOption<string>[] | null;\n\n /**\n * Menu alignment. 'center' (default) matches the wizard's standard\n * intro menu. 'left' is for views like the privacy panel where the\n * menu should align with the panel content rather than viewport center.\n */\n menuAlign?: 'center' | 'left';\n\n /**\n * Adds the disclosure row to the menu and owns the view behind it, so every\n * program intro offers it at the top level rather than buried under More\n * info. Set false on screens that are not a program intro — the auth\n * overlay renders the panel itself and would otherwise nest inside itself.\n */\n showPrivacy?: boolean;\n\n /**\n * Rows shown above Back on the disclosure view, for a program that lets the\n * user act on what the panel describes. Their selections reach `onSelect`\n * like any other. Passing them also un-gates the panel's scan paragraph,\n * which points the reader at exactly these rows.\n */\n privacyOptions?: PickerOption<string>[];\n\n /** Called when the user picks a menu option */\n onSelect?: (value: string) => void;\n\n /** Program label shown at the bottom */\n programLabel?: string | null;\n\n /** Skill ID shown at the bottom */\n skillId?: string | null;\n\n /** Replaces the entire body (topContent + rows + children + menu) for fatal error views */\n errorView?: ReactNode;\n}\n\n/** Pads to the widest label passed, so every tick lands in one column. */\nexport function detectionLabelWidth(rows?: DetectionRow[]): number {\n return Math.max(\n 'Directory'.length,\n ...(rows ?? []).map((row) => row.label.length),\n );\n}\n\nconst DetectionLine = ({\n label,\n width,\n children,\n}: {\n label: string;\n width: number;\n children: ReactNode;\n}) => (\n <Text>\n {label.padEnd(width)} <Text color=\"green\">{'✔'}</Text>{' '}\n <Text>{children}</Text>\n </Text>\n);\n\nconst WizardTitle = ({ title }: { title: string }) => (\n <Text bold>\n <Text color=\"#1D4AFF\">{'\\u2588'}</Text>\n <Text color=\"#F54E00\">{'\\u2588'}</Text>\n <Text color=\"#F9BD2B\">{'\\u2588'}</Text> {title}\n </Text>\n);\n\n/** Generic subtitle shown when a screen doesn't supply its own. */\nconst DEFAULT_SUBTITLE = (\n <>\n <Text dimColor>\n We'll use AI to analyze your project and complete work.\n </Text>\n <Text dimColor>.env* file contents will not leave your machine.</Text>\n </>\n);\n\n/** Default menu when a screen passes none. */\nconst DEFAULT_MENU: PickerOption<string>[] = [\n { label: 'Continue', value: 'continue' },\n { label: 'Cancel', value: 'cancel' },\n];\n\n/**\n * The menu for the current view. The disclosure row is appended here rather\n * than left to each screen: ten intro screens would otherwise carry the same\n * row, view and back handler, which is how this panel came to answer to five\n * different names and to sit two levels deep on the one screen that had it.\n *\n * Pure and exported so the guarantee is testable without a renderer.\n */\nexport function buildIntroMenu({\n menuOptions,\n showPrivacy = true,\n showingPrivacy = false,\n privacyOptions,\n}: {\n menuOptions?: PickerOption<string>[] | null;\n showPrivacy?: boolean;\n showingPrivacy?: boolean;\n privacyOptions?: PickerOption<string>[];\n}): PickerOption<string>[] | null {\n if (showingPrivacy) {\n // Always supplied here, so a program cannot strand the user by omitting\n // it. A blank glyph keeps its label on the same column as rows above that\n // carry one.\n const back = {\n label: 'Back',\n value: 'privacy-back',\n ...(privacyOptions?.some((o) => o.icon) ? { icon: { glyph: ' ' } } : {}),\n };\n return [...(privacyOptions ?? []), back];\n }\n\n const base = menuOptions === undefined ? DEFAULT_MENU : menuOptions;\n // A screen with no menu at all (a fatal state) gains nothing to select.\n if (base === null || !showPrivacy) return base;\n\n const row = { label: PRIVACY_PANEL_LABEL, value: 'privacy' };\n // Above a trailing Cancel: leaving the wizard stays the last thing offered.\n const insertAt =\n base.at(-1)?.value === 'cancel' ? base.length - 1 : base.length;\n return [...base.slice(0, insertAt), row, ...base.slice(insertAt)];\n}\n\nexport const IntroScreenLayout = ({\n installDir,\n title = 'PostHog Wizard 🦔',\n showSubtitle = true,\n subtitle,\n body,\n showDetection = true,\n detectionRows,\n children,\n menuOptions,\n menuAlign = 'center',\n showPrivacy = true,\n privacyOptions,\n onSelect,\n programLabel,\n skillId,\n errorView,\n}: IntroScreenLayoutProps) => {\n const [showingPrivacy, setShowingPrivacy] = useState(false);\n\n const resolvedMenuOptions = buildIntroMenu({\n menuOptions,\n showPrivacy,\n showingPrivacy,\n privacyOptions,\n });\n\n const labelWidth = detectionLabelWidth(detectionRows);\n\n const handleSelect = (value: string) => {\n if (value === 'privacy') return setShowingPrivacy(true);\n if (value === 'privacy-back') return setShowingPrivacy(false);\n onSelect?.(value);\n };\n\n if (errorView) {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box flexDirection=\"column\" alignItems=\"center\" marginBottom={1}>\n <WizardTitle title={title} />\n </Box>\n {errorView}\n </Box>\n );\n }\n\n return (\n <>\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box flexDirection=\"column\" alignItems=\"center\">\n <WizardTitle title={showingPrivacy ? PRIVACY_PANEL_LABEL : title} />\n\n {showSubtitle && !showingPrivacy && (\n <Box flexDirection=\"column\" alignItems=\"center\" marginTop={1}>\n {subtitle ?? DEFAULT_SUBTITLE}\n </Box>\n )}\n\n {showingPrivacy ? (\n <Box flexDirection=\"column\" alignItems=\"center\" marginTop={1}>\n {/* The paragraph ends by pointing below, so it only renders\n where this screen actually put a choice there. */}\n <PrivacyPanel canOptOut={privacyOptions !== undefined} />\n </Box>\n ) : (\n body && (\n <Box flexDirection=\"column\" alignItems=\"center\" marginTop={1}>\n {body}\n </Box>\n )\n )}\n </Box>\n\n {!showingPrivacy && children}\n\n {showDetection && !showingPrivacy && (\n <Box flexDirection=\"column\" marginTop={1}>\n <DetectionLine label=\"Directory\" width={labelWidth}>\n {'/'}\n {path.basename(installDir)}\n </DetectionLine>\n\n {detectionRows?.map((row) => (\n <DetectionLine\n key={row.label}\n label={row.label}\n width={labelWidth}\n >\n {row.value}\n {row.suffix ? ` ${row.suffix}` : ''}\n </DetectionLine>\n ))}\n\n {programLabel && (\n <DetectionLine label=\"Program\" width={labelWidth}>\n {programLabel}\n </DetectionLine>\n )}\n\n {programLabel === 'agent-skill' && skillId && (\n <DetectionLine label=\"Skill\" width={labelWidth}>\n {skillId}\n </DetectionLine>\n )}\n </Box>\n )}\n\n <Box width={menuAlign === 'left' ? 64 : 24} marginTop={1}>\n {resolvedMenuOptions && onSelect && (\n <Box\n justifyContent={menuAlign === 'left' ? 'flex-start' : 'center'}\n >\n <PickerMenu\n key={resolvedMenuOptions.map((o) => o.value).join(',')}\n options={resolvedMenuOptions}\n onSelect={(value) => {\n const choice = Array.isArray(value) ? value[0] : value;\n handleSelect(choice);\n }}\n />\n </Box>\n )}\n </Box>\n </Box>\n </>\n );\n};\n","/**\n * Shared \"Skill: <id> / URL: <downloadUrl>\" block for intro screens.\n *\n * `useSkillEntry` fetches the entry from the skill menu and re-runs when\n * `skillId` changes — detection sets it after mount. The previous fetch is\n * cancelled so a late result can't overwrite a newer one. Which registry to\n * fetch from is not a screen's business: `getSkillsBaseUrl()` reads the\n * process-wide target.\n *\n * `<SkillSourceInfo>` renders the block, taking the entry as a prop so the\n * caller can reuse the same hook result for additional UI (e.g. showing\n * `skillEntry.name`) without invoking the hook twice.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useState } from 'react';\nimport { fetchSkillMenu, type SkillEntry } from '@shared/skill-menu';\nimport { CONTEXT_MILL_RELEASES_URL, getSkillsBaseUrl } from '@shared/constants';\n\n/**\n * Resolve a session skillId against the skill-menu entries.\n *\n * `session.skillId` is seeded with the raw integration id during\n * detection (e.g. 'python'), but the menu publishes integration skills\n * under prefixed ids ('integration-python'); frameworks with variants\n * publish several ('integration-nextjs-app-router', '-pages-router').\n * Match chain: exact id → `integration-<id>` → unique\n * `integration-<id>-*` prefix → bundle group. Ambiguous variants (≥2 prefix\n * matches) return null — the caller should point at the skills repo instead\n * of guessing the wrong variant.\n */\nexport function resolveSkillEntry(\n entries: SkillEntry[],\n skillId: string,\n): SkillEntry | null {\n const exact = entries.find((s) => s.id === skillId);\n if (exact) return exact;\n\n const prefixed = entries.find((s) => s.id === `integration-${skillId}`);\n if (prefixed) return prefixed;\n\n const variants = entries.filter((s) =>\n s.id.startsWith(`integration-${skillId}-`),\n );\n if (variants.length === 1) return variants[0];\n if (variants.length > 1) return null;\n\n // The menu expands a bundle into per-framework entries that all carry the\n // bundle's group and download URL, so the bundle id matches only by group.\n return entries.find((s) => s.bundle && s.group === skillId) ?? null;\n}\n\nexport function useSkillEntry(skillId: string | null): {\n skillEntry: SkillEntry | null;\n fetchFailed: boolean;\n} {\n const [skillEntry, setSkillEntry] = useState<SkillEntry | null>(null);\n const [fetchFailed, setFetchFailed] = useState(false);\n\n useEffect(() => {\n if (!skillId) {\n setFetchFailed(true);\n return;\n }\n let cancelled = false;\n setSkillEntry(null);\n setFetchFailed(false);\n void fetchSkillMenu(getSkillsBaseUrl()).then((menu) => {\n if (cancelled) return;\n if (!menu) {\n setFetchFailed(true);\n return;\n }\n const match = resolveSkillEntry(\n Object.values(menu.categories).flat(),\n skillId,\n );\n if (match) setSkillEntry(match);\n else setFetchFailed(true);\n });\n return () => {\n cancelled = true;\n };\n }, [skillId]);\n\n return { skillEntry, fetchFailed };\n}\n\ninterface SkillSourceInfoProps {\n skillId: string | null;\n skillEntry: SkillEntry | null;\n fetchFailed: boolean;\n}\n\nexport const SkillSourceInfo = ({\n skillId,\n skillEntry,\n fetchFailed,\n}: SkillSourceInfoProps) => (\n <Box flexDirection=\"column\">\n <Text>\n Skill:{' '}\n <Text italic color=\"cyan\">\n {skillId ?? 'unknown'}\n </Text>\n </Text>\n <Text>\n URL:{' '}\n <Text color=\"cyan\">\n {skillEntry?.downloadUrl ??\n (fetchFailed ? CONTEXT_MILL_RELEASES_URL : 'Loading...')}\n </Text>\n </Text>\n </Box>\n);\n","/**\n * AgentSkillIntroScreen — Default intro for generic agent-skill programs.\n *\n * Programs that need a different intro ship their own screen component\n * (see programs/audit/screens/AuditIntroScreen.tsx).\n */\n\nimport { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface AgentSkillIntroScreenProps {\n store: WizardStore;\n}\n\nexport const AgentSkillIntroScreen = ({\n store,\n}: AgentSkillIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n\n const { session } = store;\n const skillId = session.skillId ?? 'unknown';\n const { skillEntry, fetchFailed } = useSkillEntry(skillId);\n\n let body: ReactNode;\n\n if (showingMoreInfo) {\n body = (\n <Box flexDirection=\"column\" width={56} flexShrink={0}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n <SkillSourceInfo\n skillId={skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n <Box marginTop={1}>\n <Text dimColor>\n {skillEntry?.name ?? (fetchFailed ? skillId : 'Loading...')}\n </Text>\n </Box>\n </Box>\n );\n } else {\n body = (\n <Text>\n Let's run the{' '}\n <Text italic color=\"cyan\">\n {skillId}\n </Text>{' '}\n skill.\n </Text>\n );\n }\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const handleSelect = (value: string) => {\n if (value === 'cancel') store.requestExit(0);\n else if (value === 'more-info') setShowingMoreInfo(true);\n else if (value === 'back') setShowingMoreInfo(false);\n else store.completeSetup();\n };\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n showSubtitle={!showingMoreInfo}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={handleSelect}\n />\n );\n};\n","/** The generic skill program: the TUI for every program without an entry of its own. */\nimport { SkillScreenId } from './screen-ids.js';\nimport type { TuiProgram } from '@tui/programs/types';\nimport { AGENT_SKILL_STEPS } from './skill-flow.js';\nimport { getContentBlocks } from './skill-deck.js';\nimport { AgentSkillIntroScreen } from './screens/AgentSkillIntroScreen.js';\n\nexport const SKILL_PROGRAM: TuiProgram = {\n flow: AGENT_SKILL_STEPS,\n deck: getContentBlocks,\n screens: {\n [SkillScreenId.Intro]: (store) => <AgentSkillIntroScreen store={store} />,\n },\n};\n","import { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface AiObservabilityIntroScreenProps {\n store: WizardStore;\n}\n\nexport const AiObservabilityIntroScreen = ({\n store,\n}: AiObservabilityIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n const { session } = store;\n // ai-observability picks its skill variant at run time (openai-python,\n // anthropic-node, langchain-python, …), so there's no pre-seeded skillId\n // here. Fall back to the group id for the \"more info\" lookup.\n const skillId = session.skillId ?? 'ai-observability';\n const { skillEntry, fetchFailed } = useSkillEntry(skillId);\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56}>\n <Box marginBottom={1}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n\n <Text>\n The{' '}\n <Text color=\"cyan\" italic>\n ai-observability\n </Text>{' '}\n program wraps your LLM SDK calls with PostHog's OpenTelemetry-based\n tracing so every prompt, completion, tool call, token count, and cost\n lands in AI Observability. Supports OpenAI, Anthropic, Google,\n LangChain, Vercel AI, and other SDKs.\n </Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>\n Let's instrument your LLM calls with PostHog AI Observability.\n </Text>\n </Box>\n );\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const handleSelect = (value: string) => {\n if (value === 'cancel') store.requestExit(0);\n else if (value === 'more-info') setShowingMoreInfo(true);\n else if (value === 'back') setShowingMoreInfo(false);\n else store.completeSetup();\n };\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={handleSelect}\n />\n );\n};\n","/** The AI observability TUI: the skill flow and deck behind its own intro. */\nimport type { FlowStep } from '@tui/flow';\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { AGENT_SKILL_STEPS } from '@tui/programs/shared/skill-flow';\nimport { getContentBlocks } from '@tui/programs/shared/skill-deck';\nimport { AiObservabilityScreenId } from './screen-ids.js';\nimport { AiObservabilityIntroScreen } from './screens/AiObservabilityIntroScreen.js';\n\nexport { AiObservabilityScreenId } from './screen-ids.js';\n\nconst AI_OBSERVABILITY_FLOW: FlowStep[] = AGENT_SKILL_STEPS.map((step) =>\n step.id === 'intro'\n ? { ...step, screenId: AiObservabilityScreenId.Intro }\n : step,\n);\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'ai-observability': {\n flow: AI_OBSERVABILITY_FLOW,\n deck: getContentBlocks,\n screens: {\n [AiObservabilityScreenId.Intro]: (store) => (\n <AiObservabilityIntroScreen store={store} />\n ),\n },\n },\n};\n","import type { FlowStep } from '@tui/flow';\nimport { AGENT_SKILL_STEPS } from '@tui/programs/shared/skill-flow';\n\n/** Audit-specific screens for the shared agent-skill pipeline. */\nconst AUDIT_SCREEN_BY_STEP: Record<string, string> = {\n intro: 'audit-intro',\n run: 'audit-run',\n outro: 'audit-outro',\n};\n\nconst withAuditScreens = (steps: FlowStep[]): FlowStep[] =>\n steps.map((step) => {\n const override = AUDIT_SCREEN_BY_STEP[step.id];\n return override ? { ...step, screenId: override } : step;\n });\n\nexport const AUDIT_FLOW: FlowStep[] = withAuditScreens(AGENT_SKILL_STEPS);\n","/**\n * Events-audit program.\n *\n * Mirrors the posthog-integration step list, except:\n * - The initial framework detection step is omitted — the events-audit\n * skill handles detection at agent run time.\n * - The intro step uses the audit intro screen (no framework selection\n * logic) instead of the integration intro.\n */\n\nimport type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\nimport type { WizardSession } from '@programs/types';\n\nfunction needsSetup(session: WizardSession): boolean {\n const config = session.frameworkConfig;\n if (!config?.metadata.setup?.questions) return false;\n\n return config.metadata.setup.questions.some(\n (q: { key: string }) => !(q.key in session.frameworkContext),\n );\n}\n\nexport const EVENTS_AUDIT_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'audit-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'setup',\n label: 'Setup',\n screenId: 'setup',\n show: ({ session }) => needsSetup(session),\n isComplete: ({ session }) => !needsSetup(session),\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Events audit',\n screenId: 'audit-run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'mcp',\n label: 'MCP servers',\n screenId: 'mcp',\n isComplete: (tui) => tui.mcpComplete,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'audit-outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'keep-skills',\n label: 'Keep Skills',\n screenId: 'keep-skills',\n },\n];\n","import { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface AuditIntroScreenProps {\n store: WizardStore;\n}\n\nexport const AuditIntroScreen = ({ store }: AuditIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n const { session } = store;\n // bin.ts seeds session.skillId from ProgramConfig.skillId before render,\n // so audit and events-audit pick up their respective skill metadata here.\n const skillId = session.skillId ?? 'audit';\n const { skillEntry, fetchFailed } = useSkillEntry(skillId);\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56}>\n <Box marginBottom={1}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n\n <Text>\n The{' '}\n <Text color=\"cyan\" italic>\n {skillId}\n </Text>{' '}\n program reviews your project's PostHog integration against best\n practices to help you capture high-quality events and writes a report\n for suggested actions. Nothing in your project will be modified.\n </Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>Let's review your existing PostHog setup for best practices.</Text>\n </Box>\n );\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const handleSelect = (value: string) => {\n if (value === 'cancel') store.requestExit(0);\n else if (value === 'more-info') setShowingMoreInfo(true);\n else if (value === 'back') setShowingMoreInfo(false);\n else store.completeSetup();\n };\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={handleSelect}\n />\n );\n};\n","import { Box, Text } from 'ink';\n\ninterface AreaHeaderRowProps {\n area: string;\n resolved: number;\n total: number;\n}\n\n/** Sub-header row inside the scrollable body — one per area group. */\nexport const AreaHeaderRow = ({\n area,\n resolved,\n total,\n}: AreaHeaderRowProps) => (\n <Box flexShrink={0} marginTop={1}>\n <Text bold color=\"cyan\">\n {area}{' '}\n </Text>\n <Text dimColor>\n ({resolved}/{total})\n </Text>\n </Box>\n);\n","import type { AuditStatus } from '@programs/audit';\n\nexport interface AuditSeverityStyle {\n glyph: string;\n color: string;\n}\n\n/** Single source of truth for status glyph + color across audit views. */\nexport const AUDIT_SEVERITY_STYLE: Record<AuditStatus, AuditSeverityStyle> = {\n pending: { glyph: '◌', color: 'gray' },\n pass: { glyph: '✔', color: 'green' },\n error: { glyph: '✘', color: 'red' },\n warning: { glyph: '⚠', color: 'yellow' },\n suggestion: { glyph: '•', color: 'cyan' },\n};\n","import { MAX_WIDTH } from '@tui/primitives/ScreenContainer';\n\n/** Terminal rows used by chrome outside the viewer\n * (TitleBar, spacer, screen padding, status bar, tab bar). */\nexport const CHROME_ROWS = 10;\n\n/** Rows used by the viewer's own header / footer\n * (title, subtitle, top summary, spacer, column headers, divider,\n * scroll-up marker, scroll-down marker, legend, footer summary). */\nexport const VIEWER_CHROME_BASE = 10;\n\nexport const COL_AREA_WIDTH = 18;\nexport const COL_LABEL_MIN = 28;\nexport const COL_GAP = 2;\n\nexport interface ViewerLayout {\n cols: number;\n visibleHeight: number;\n viewerChrome: number;\n padding: number;\n statusWidth: number;\n areaWidth: number;\n labelWidth: number;\n colGap: number;\n dividerWidth: number;\n detailIndent: number;\n detailWidth: number;\n}\n\n/** ScreenContainer wraps content in paddingX={1} inside a width capped at\n * MAX_WIDTH, so the actual width available to the viewer is\n * min(cols, MAX_WIDTH) - 2. */\nfunction getViewerWidth(rawCols: number): number {\n return Math.min(MAX_WIDTH, rawCols) - 2;\n}\n\nexport function computeLayout(rawCols: number, termRows: number): ViewerLayout {\n const cols = getViewerWidth(rawCols);\n const padding = 2;\n const statusWidth = 2;\n\n // CHECK flexes to consume the rest of the row so long labels stay readable\n // instead of getting truncated.\n const fixedExceptLabel =\n padding + statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP + COL_GAP;\n const labelWidth = Math.max(COL_LABEL_MIN, cols - fixedExceptLabel);\n\n const detailIndent = statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP;\n\n const viewerChrome = VIEWER_CHROME_BASE;\n const visibleHeight = Math.max(5, termRows - CHROME_ROWS - viewerChrome);\n\n return {\n cols,\n visibleHeight,\n viewerChrome,\n padding,\n statusWidth,\n areaWidth: COL_AREA_WIDTH,\n labelWidth,\n colGap: COL_GAP,\n dividerWidth: Math.max(20, cols - padding),\n detailIndent,\n detailWidth: Math.max(20, cols - detailIndent - padding),\n };\n}\n\nexport function truncate(text: string, max: number): string {\n if (max <= 0) return '';\n if (text.length <= max) return text;\n return text.slice(0, Math.max(1, max - 1)) + '…';\n}\n","import { Box, Text } from 'ink';\nimport type { AuditCheck } from '@programs/audit';\nimport { AUDIT_SEVERITY_STYLE } from '../../severity-style.js';\nimport { truncate, type ViewerLayout } from './layout.js';\n\ninterface CheckRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\nexport const CheckRow = ({ item, layout }: CheckRowProps) => {\n const style = AUDIT_SEVERITY_STYLE[item.status];\n return (\n <Box flexShrink={0}>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text color={style.color}>{style.glyph}</Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor>{truncate(item.area, layout.areaWidth)}</Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text\n bold={item.status !== 'pending'}\n dimColor={item.status === 'pending'}\n >\n {truncate(item.label, layout.labelWidth)}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport type { AuditCheck } from '@programs/audit';\nimport type { ViewerLayout } from './layout.js';\n\ninterface DetailRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\n/** Format a `details` string. If it parses as a JSON object, render it as\n * indented key: value lines (skipping huge nested arrays/objects which we\n * truncate). Otherwise return the original text. v3000 emits structured\n * JSON for several event-quality checks — a raw dump is unreadable. */\nfunction formatDetails(raw: string): string[] {\n const trimmed = raw.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return [raw];\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return [raw];\n }\n if (parsed === null || typeof parsed !== 'object') return [raw];\n const lines: string[] = [];\n const renderValue = (v: unknown): string => {\n if (v === null) return 'null';\n if (typeof v === 'string') return v;\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n if (Array.isArray(v)) {\n if (v.length === 0) return '[]';\n const allPrimitive = v.every((e) => e === null || typeof e !== 'object');\n if (allPrimitive) return v.map(renderValue).join(', ');\n return `[${v.length} item${v.length === 1 ? '' : 's'}]`;\n }\n if (typeof v === 'object') {\n const keys = Object.keys(v);\n return `{${keys.length} field${keys.length === 1 ? '' : 's'}}`;\n }\n return String(v);\n };\n for (const [key, value] of Object.entries(parsed)) {\n lines.push(`${key}: ${renderValue(value)}`);\n }\n return lines.length > 0 ? lines : [raw];\n}\n\n/** Indented under the CHECK column; wrap continuation aligns with the prefix. */\nexport const DetailRow = ({ item, layout }: DetailRowProps) => {\n const detailLines = item.details ? formatDetails(item.details) : [];\n return (\n <Box flexShrink={0}>\n <Box width={layout.detailIndent} />\n <Box flexDirection=\"column\" width={layout.detailWidth}>\n {item.file && (\n <Text dimColor wrap=\"wrap\">\n {`↳ File: ${item.file}`}\n </Text>\n )}\n {detailLines.map((line, i) => (\n <Text key={i} dimColor italic wrap=\"wrap\">\n {i === 0 ? `${item.file ? ' ' : '↳ '}${line}` : ` ${line}`}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","import { Text } from 'ink';\n\nexport const Legend = () => (\n <Text>\n <Text color=\"green\">✔ pass</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"red\">✘ error</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"yellow\">⚠ warning</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"cyan\">• suggestion</Text>\n </Text>\n);\n","/** `1 error`, `2 errors`, `0 errors`. Zero stays plural. */\nexport function countNoun(\n n: number,\n noun: string,\n plural = `${noun}s`,\n): string {\n return `${n} ${n === 1 ? noun : plural}`;\n}\n","import { Box, Text } from 'ink';\nimport type { AuditCheck, AuditStatus } from '@programs/audit';\nimport { countNoun } from '@utils/count-noun';\nimport type { ViewerLayout } from './layout.js';\n\ninterface HeaderProps {\n layout: ViewerLayout;\n}\n\ninterface SummaryProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nfunction statusCounts(checks: AuditCheck[]): Record<AuditStatus, number> {\n const out: Record<AuditStatus, number> = {\n pending: 0,\n pass: 0,\n error: 0,\n warning: 0,\n suggestion: 0,\n };\n for (const c of checks) out[c.status] += 1;\n return out;\n}\n\nexport { statusCounts };\n\nexport const Header = ({ layout }: HeaderProps) => (\n <Box>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text dimColor bold>\n {' '}\n </Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor bold>\n AREA\n </Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text dimColor bold>\n CHECK\n </Text>\n </Box>\n </Box>\n);\n\nexport const Summary = ({ total, counts }: SummaryProps) => (\n <Text dimColor>\n {[\n `${total} total`,\n `${counts.pending} pending`,\n countNoun(counts.error, 'error'),\n countNoun(counts.warning, 'warning'),\n countNoun(counts.suggestion, 'suggestion'),\n countNoun(counts.pass, 'pass', 'passes'),\n ].join(' · ')}\n </Text>\n);\n","import { Legend } from './Legend.js';\nimport { Summary } from './Header.js';\nimport type { AuditStatus } from '@programs/audit';\n\ninterface FooterProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nexport const Footer = ({ total, counts }: FooterProps) => (\n <>\n <Legend />\n <Summary total={total} counts={counts} />\n </>\n);\n","import type { AuditCheck, AuditStatus } from '@programs/audit';\n\nconst STATUS_ORDER: Record<AuditStatus, number> = {\n error: 0,\n warning: 1,\n suggestion: 2,\n pass: 3,\n pending: 4,\n};\n\n/** Audit areas in the order they should be displayed. Areas not listed\n * here fall through to alphabetical order at the end. Mirrors the\n * Full audit section grouping in the generated report. */\nconst AREA_ORDER: string[] = [\n 'Installation',\n 'Identification',\n 'Event Capture',\n 'Event Quality',\n 'Feature Flags',\n 'Session Replay',\n 'Session Replay — Optimize',\n 'Use Case: Expansion',\n 'Additional Sections',\n // Findings read back from PostHog rather than from the source tree. Ranked\n // after every source-tree area so the checks the user can act on in their\n // editor come first, and ahead of the trailing workflow rows.\n 'Live Data',\n];\n\nfunction areaRank(area: string): number {\n const idx = AREA_ORDER.indexOf(area);\n return idx === -1 ? AREA_ORDER.length : idx;\n}\n\n/** Issues at the top (error → warning → suggestion), then passes, then pending todos. */\nexport function sortChecks(checks: ReadonlyArray<AuditCheck>): AuditCheck[] {\n return [...checks].sort((a, b) => {\n const da = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];\n if (da !== 0) return da;\n return a.area.localeCompare(b.area);\n });\n}\n\nexport interface AreaGroup {\n area: string;\n checks: AuditCheck[];\n counts: { total: number; resolved: number };\n}\n\n/** Group checks by area, in AREA_ORDER. Within each area, sort by status. */\nexport function groupChecksByArea(\n checks: ReadonlyArray<AuditCheck>,\n): AreaGroup[] {\n const byArea = new Map<string, AuditCheck[]>();\n for (const c of checks) {\n const list = byArea.get(c.area);\n if (list) list.push(c);\n else byArea.set(c.area, [c]);\n }\n const groups: AreaGroup[] = [];\n for (const [area, areaChecks] of byArea) {\n const sorted = [...areaChecks].sort(\n (a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status],\n );\n const resolved = sorted.filter((c) => c.status !== 'pending').length;\n groups.push({\n area,\n checks: sorted,\n counts: { total: sorted.length, resolved },\n });\n }\n groups.sort((a, b) => {\n const dr = areaRank(a.area) - areaRank(b.area);\n if (dr !== 0) return dr;\n return a.area.localeCompare(b.area);\n });\n return groups;\n}\n","/**\n * AuditChecksViewer — \"Audit plan\" tab.\n *\n * Renders the full audit ledger as a scrollable, area-grouped list that\n * mirrors the structure of the final report. Each area gets a sub-header\n * with a resolved/total count; checks within an area are sorted by\n * severity (error → warning → suggestion → pass → pending).\n *\n * Two interactions, both registered via `useKeyBindings`:\n * - `e` — toggle detail rows (file:line + agent's `details` text)\n * - `↑` / `↓` — scroll one row at a time, clamped to content bounds\n *\n * Auto-expands on first mount when the ledger contains any issue, since\n * the AuditAreaPane's `[→] View issues` hint sends users here precisely\n * to read those details.\n */\n\nimport { Box, Text } from 'ink';\nimport { Fragment, useMemo, useState, type ReactNode } from 'react';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport {\n KeyMatch,\n useKeyBindings,\n type KeyBinding,\n} from '@tui/hooks/useKeyBindings';\nimport type { AuditCheck } from '@programs/audit';\nimport { AreaHeaderRow } from './AreaHeaderRow.js';\nimport { CheckRow } from './CheckRow.js';\nimport { DetailRow } from './DetailRow.js';\nimport { Footer } from './Footer.js';\nimport { Header, Summary, statusCounts } from './Header.js';\nimport { computeLayout } from './layout.js';\nimport { groupChecksByArea } from './sort.js';\n\ninterface AuditChecksViewerProps {\n checks: AuditCheck[];\n}\n\nexport const AuditChecksViewer = ({ checks }: AuditChecksViewerProps) => {\n // ── Layout ─────────────────────────────────────────────────────────\n const [rawCols, termRows] = useStdoutDimensions();\n const layout = computeLayout(rawCols, termRows);\n const totalHeight = layout.visibleHeight + layout.viewerChrome;\n\n // ── Group by area ──────────────────────────────────────────────────\n const groups = useMemo(() => groupChecksByArea(checks), [checks]);\n const counts = useMemo(() => statusCounts(checks), [checks]);\n\n // ── Expand state ───────────────────────────────────────────────────\n const hasExpandable = checks.some((c) => Boolean(c.details || c.file));\n const hasIssues = checks.some(\n (c) =>\n c.status === 'error' ||\n c.status === 'warning' ||\n c.status === 'suggestion',\n );\n const [expanded, setExpanded] = useState(hasIssues && hasExpandable);\n\n // ── Flat row list ──────────────────────────────────────────────────\n // One ReactNode per visible terminal row so scroll math stays simple.\n // Sub-header + check rows + (optional) detail rows interleave here.\n const allRows = useMemo<ReactNode[]>(() => {\n const rows: ReactNode[] = [];\n for (const group of groups) {\n rows.push(\n <AreaHeaderRow\n key={`header-${group.area}`}\n area={group.area}\n resolved={group.counts.resolved}\n total={group.counts.total}\n />,\n );\n for (const item of group.checks) {\n rows.push(<CheckRow key={item.id} item={item} layout={layout} />);\n if (expanded && (item.details || item.file)) {\n rows.push(\n <DetailRow key={`${item.id}-detail`} item={item} layout={layout} />,\n );\n }\n }\n }\n return rows;\n }, [groups, expanded, layout]);\n\n // ── Scroll viewport ────────────────────────────────────────────────\n const [offset, setOffset] = useState(0);\n const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);\n const clampedOffset = Math.min(offset, maxOffset);\n const hiddenAbove = clampedOffset;\n const hiddenBelow = Math.max(\n 0,\n allRows.length - clampedOffset - layout.visibleHeight,\n );\n\n // ── Key bindings ───────────────────────────────────────────────────\n const bindings: KeyBinding[] = [];\n if (hasExpandable) {\n bindings.push({\n match: 'e',\n label: 'e',\n action: expanded ? 'collapse details' : 'expand details',\n handler: () => setExpanded((prev) => !prev),\n });\n }\n bindings.push({\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '↑↓',\n action: 'scroll',\n handler: (_input, key) => {\n if (key.upArrow) setOffset((o) => Math.max(0, o - 1));\n else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));\n },\n });\n useKeyBindings('audit-checks-viewer', bindings);\n\n // ── Render ─────────────────────────────────────────────────────────\n const visibleRows = allRows.slice(\n clampedOffset,\n clampedOffset + layout.visibleHeight,\n );\n\n // Dynamic subtitle — lists the actual areas in the ledger.\n const subtitle =\n groups.length === 0\n ? 'No checks yet.'\n : `Review across ${groups.length} ${\n groups.length === 1 ? 'area' : 'areas'\n } — mirrors the final report.`;\n\n return (\n <Box flexDirection=\"column\" paddingX={1} height={totalHeight}>\n {/* Title + dynamic subtitle */}\n <Text bold>Audit plan</Text>\n <Text dimColor>{subtitle}</Text>\n\n {/* Top summary — same as Footer summary, promoted here for at-a-glance */}\n <Summary total={checks.length} counts={counts} />\n <Box height={1} />\n\n {/* Column headers + divider */}\n <Header layout={layout} />\n <Text dimColor>{'─'.repeat(layout.dividerWidth)}</Text>\n\n {/* Scroll-up marker */}\n <Text dimColor>{hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : ' '}</Text>\n\n {/* Scrollable body */}\n <Box\n flexDirection=\"column\"\n height={layout.visibleHeight}\n overflow=\"hidden\"\n >\n {visibleRows.map((node, i) => (\n <Fragment key={`row-${clampedOffset + i}`}>{node}</Fragment>\n ))}\n </Box>\n\n {/* Scroll-down marker */}\n <Text dimColor>{hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : ' '}</Text>\n\n {/* Legend (counts already shown at the top) */}\n <Footer total={checks.length} counts={counts} />\n </Box>\n );\n};\n","import { Box } from 'ink';\nimport type { ReactNode } from 'react';\nimport { Colors } from '@tui/styles';\n\n/** Slide shape consumed by `AuditAreaPane`. One per `AuditCheck.area` value. */\nexport interface AreaSlide {\n area: string;\n /** One element per paragraph — rendered as separate `<Text>` blocks. */\n intro: string[];\n visual?: ReactNode;\n docsUrl: string;\n}\n\n/** Narrow bordered box for the small ASCII illustrations in baseline slides. */\nexport const VisualBox = ({ children }: { children: ReactNode }) => (\n <Box\n borderStyle=\"single\"\n borderColor={Colors.muted}\n paddingX={1}\n flexDirection=\"column\"\n marginBottom={1}\n >\n {children}\n </Box>\n);\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst InstallationVisual = () => (\n <VisualBox>\n <Text dimColor>app boot</Text>\n <Text>\n <Text dimColor>{' ▼ '}</Text>\n <Text color=\"green\">posthog.init(...)</Text>\n <Text dimColor>{' once'}</Text>\n </Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ▼ '}</Text>\n <Text color=\"cyan\">posthog.capture('pageview')</Text>\n </Text>\n <Text>\n <Text dimColor>{' '}</Text>\n <Text color=\"cyan\">posthog.capture('signup')</Text>\n </Text>\n <Text>\n <Text dimColor>{' '}</Text>\n <Text color=\"cyan\">posthog.capture('purchase')</Text>\n </Text>\n </VisualBox>\n);\n\nexport const InstallationSlide: AreaSlide = {\n area: 'Installation',\n intro: [\n \"PostHog releases frequent SDK updates to fix bugs and add new features. We're checking your project's SDK version and making sure it's up to date.\",\n \"We're also checking that your SDK is initialized correctly and in the right part of your app's lifecycle.\",\n \"This ensures you won't miss any autocaptured events.\",\n ],\n visual: <InstallationVisual />,\n docsUrl: 'https://posthog.com/docs/getting-started/install',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst IdentificationVisual = () => (\n <VisualBox>\n <Text>\n <Text bold>{'browser '}</Text>\n <Text dimColor>capture</Text>\n <Text>{' ('}</Text>\n <Text color=\"cyan\">u_42</Text>\n <Text>{', \"click\")'}</Text>\n </Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ▼ '}</Text>\n <Text color=\"green\">same distinct_id</Text>\n </Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text bold>{'server '}</Text>\n <Text dimColor>capture</Text>\n <Text>{' ('}</Text>\n <Text color=\"cyan\">u_42</Text>\n <Text>{', \"charged\")'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const IdentificationSlide: AreaSlide = {\n area: 'Identification',\n intro: [\n 'For events to be useful, they need to be reliably attributed to a user.',\n \"We're checking your project's `identify()` calls to make sure they're correctly and consistently implemented.\",\n \"We're also checking that your `distinct_id`s are correctly passed between your client and server runtimes if applicable.\",\n ],\n visual: <IdentificationVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/identify',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst CaptureVisual = () => (\n <VisualBox>\n <Text>\n <Text color=\"cyan\">{'pageview '}</Text>\n <Text color=\"green\">{'████████████'}</Text>\n <Text dimColor>{' 1000'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'signup '}</Text>\n <Text color=\"green\">{'████████'}</Text>\n <Text dimColor>{' 640'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'activated '}</Text>\n <Text color=\"green\">{'█████'}</Text>\n <Text dimColor>{' 410'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'purchased '}</Text>\n <Text color=\"green\">{'██'}</Text>\n <Text dimColor>{' 120'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const EventCaptureSlide: AreaSlide = {\n area: 'Event Capture',\n intro: [\n 'Everything you do in PostHog starts with event captures. Every dashboard, insight, funnel, cohort, and replay is built on top of events.',\n \"We're checking that your project's event capture calls cover key user actions and use sensible event names, so you can build high-quality insights and reports.\",\n \"We're also checking that you use a reverse proxy so your events are not blocked by ad blockers or tracking blockers.\",\n ],\n visual: <CaptureVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/capture-events',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst LiveDataVisual = () => (\n <VisualBox>\n <Text dimColor>your PostHog project</Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ├ '}</Text>\n <Text color=\"yellow\">⚠</Text>\n <Text dimColor> source maps not uploaded</Text>\n </Text>\n <Text>\n <Text dimColor>{' └ '}</Text>\n <Text color=\"cyan\">•</Text>\n <Text dimColor> error alerts not wired</Text>\n </Text>\n </VisualBox>\n);\n\nexport const LiveDataSlide: AreaSlide = {\n area: 'Live Data',\n intro: [\n 'Everything so far came from reading your code. This part comes from your data.',\n 'PostHog runs its own checks on what your project actually sends — whether stack traces resolve to your original source, whether a warehouse sync keeps failing, whether anyone is alerted when a new error appears. None of that is visible in a file.',\n 'We pull the open ones in so this report covers both halves.',\n ],\n visual: <LiveDataVisual />,\n docsUrl: 'https://posthog.com/docs/error-tracking/upload-source-maps',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst ReportVisual = () => (\n <VisualBox>\n <Text dimColor>posthog-audit-report.md</Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Summary</Text>\n </Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Recommended actions</Text>\n </Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Full audit</Text>\n </Text>\n </VisualBox>\n);\n\nexport const WriteReportSlide: AreaSlide = {\n area: 'Write report',\n intro: [\n 'Now we write an audit report at ./posthog-audit-report.md that summarizes our findings.',\n 'The report leads with a summary, then a prioritized list of fixes with file:line citations, then every check we ran grouped by area so nothing is hidden.',\n 'We will upload the report into a PostHog notebook in the next step.',\n ],\n visual: <ReportVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/best-practices',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from './shared.js';\n\nconst NotebookVisual = () => (\n <VisualBox>\n <Text dimColor>posthog-audit-report.md</Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ▼ '}</Text>\n <Text color=\"cyan\">PostHog notebook</Text>\n </Text>\n <Text dimColor>{' # Summary'}</Text>\n <Text dimColor>{' # Recommended actions'}</Text>\n <Text dimColor>{' # Full audit'}</Text>\n </VisualBox>\n);\n\nexport const UploadNotebookSlide: AreaSlide = {\n area: 'Upload notebook',\n intro: [\n 'Next we upload the report into a PostHog notebook so you can share it with your team as a URL.',\n 'Hang tight.',\n 'The markdown file on disk is still there for you to read locally.',\n ],\n visual: <NotebookVisual />,\n docsUrl: 'https://posthog.com/docs/notebooks',\n};\n","/**\n * Slide registry for `AuditAreaPane`. Each entry is a stand-alone module\n * keyed by `AuditCheck.area`. To add a new area, drop a `<area>.tsx` file\n * exporting an `AreaSlide` and append it here.\n */\n\nimport type { AreaSlide } from './shared.js';\nimport { InstallationSlide } from './installation.js';\nimport { IdentificationSlide } from './identification.js';\nimport { EventCaptureSlide } from './eventCapture.js';\nimport { LiveDataSlide } from './liveData.js';\nimport { WriteReportSlide } from './writeReport.js';\nimport { UploadNotebookSlide } from './uploadNotebook.js';\n\nexport type { AreaSlide };\n\nexport const AUDIT_AREA_SLIDES: AreaSlide[] = [\n InstallationSlide,\n IdentificationSlide,\n EventCaptureSlide,\n LiveDataSlide,\n WriteReportSlide,\n UploadNotebookSlide,\n];\n","/**\n * AuditAreaPane — left-pane slide that follows whatever area the agent is\n * currently checking, plus a wrap-up state once every check is resolved\n * and the agent has moved on to writing the report.\n *\n * Three states, gated top-down on the ledger:\n * 1. firstPending defined → render the slide for that area\n * 2. checks empty → blank (the seed hook fires before\n * this screen mounts in practice;\n * this is just defensive)\n * 3. all checks non-pending → \"writing report\" wrap-up\n *\n * Pressing `O` opens the active slide's docs URL.\n */\n\nimport { Fragment } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { spawn } from 'node:child_process';\nimport { Colors } from '@tui/styles';\nimport { type AuditCheck } from '@programs/audit';\nimport { AUDIT_AREA_SLIDES, type AreaSlide } from './slides/index.js';\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nconst FINDING_STATUSES: AuditCheck['status'][] = [\n 'error',\n 'warning',\n 'suggestion',\n];\n\nconst isFinding = (c: AuditCheck) => FINDING_STATUSES.includes(c.status);\n\nconst fallbackSlide = (area: string): AreaSlide => ({\n area,\n intro: [`Verifying ${area.toLowerCase()}…`],\n docsUrl: '',\n});\n\nconst openLink = (url: string) => {\n const cmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'cmd'\n : 'xdg-open';\n const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];\n spawn(cmd, args, { detached: true, stdio: 'ignore' }).unref();\n};\n\n// ── Component ────────────────────────────────────────────────────────\n\ninterface AuditAreaPaneProps {\n checks: AuditCheck[];\n reportPath: string;\n /** Slide registry to look the active area up in. Defaults to the doctor\n * (`audit` program) slides; events-audit passes its own 6-phase set. */\n slides?: AreaSlide[];\n /** Dashboard URL once the agent emits `[DASHBOARD_URL]`. Shown as a sticky\n * footer so the user can grab the link while later phases still run. */\n dashboardUrl?: string | null;\n /** Notebook URL once the agent emits `[NOTEBOOK_URL]`. Same sticky-footer\n * treatment as the dashboard URL. */\n notebookUrl?: string | null;\n}\n\nexport const AuditAreaPane = ({\n checks,\n reportPath,\n slides = AUDIT_AREA_SLIDES,\n dashboardUrl,\n notebookUrl,\n}: AuditAreaPaneProps) => {\n const pendingChecks = checks.filter((c) => c.status === 'pending');\n const activeArea = pendingChecks[0]?.area;\n const slide = activeArea\n ? slides.find((s) => s.area === activeArea) ?? fallbackSlide(activeArea)\n : null;\n\n useInput((input) => {\n if (input.toLowerCase() === 'o' && slide?.docsUrl) {\n openLink(slide.docsUrl);\n }\n });\n\n const urlsFooter =\n dashboardUrl || notebookUrl ? (\n <UrlsFooter dashboardUrl={dashboardUrl} notebookUrl={notebookUrl} />\n ) : null;\n\n // Active area — agent is still resolving checks for this slide's area.\n if (slide) {\n const hasFindings = checks.some(isFinding);\n return (\n <Box flexDirection=\"column\">\n <ActiveSlide slide={slide} hasFindings={hasFindings} />\n {urlsFooter}\n </Box>\n );\n }\n\n // Ledger empty — the seed hook fires synchronously at intro `onReady`,\n // so this only happens if the seed file write failed. Render nothing\n // rather than misleading the user with a \"wrapped up\" message.\n if (checks.length === 0) {\n return null;\n }\n\n // Every check is resolved and the agent is composing the report.\n return (\n <Box flexDirection=\"column\">\n <WritingReport reportPath={reportPath} />\n {urlsFooter}\n </Box>\n );\n};\n\n// ── States ───────────────────────────────────────────────────────────\n\nconst ActiveSlide = ({\n slide,\n hasFindings,\n}: {\n slide: AreaSlide;\n hasFindings: boolean;\n}) => (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Verifying {slide.area.toLowerCase()}\n </Text>\n <Box height={1} />\n\n {slide.visual}\n {slide.intro.map((paragraph, i) => (\n <Fragment key={i}>\n {i > 0 && <Box height={1} />}\n <Text>{paragraph}</Text>\n </Fragment>\n ))}\n\n <Box marginTop={1}>\n <Text dimColor>\n {slide.docsUrl && (\n <>\n [<Text color={Colors.accent}>O</Text>] Learn more\n </>\n )}\n {hasFindings && (\n <>\n {slide.docsUrl && ' '}[<Text color={Colors.accent}>→</Text>] View\n issues\n </>\n )}\n </Text>\n </Box>\n </Box>\n);\n\nconst UrlsFooter = ({\n dashboardUrl,\n notebookUrl,\n}: {\n dashboardUrl?: string | null;\n notebookUrl?: string | null;\n}) => (\n <Box flexDirection=\"column\" paddingX={1} marginTop={1}>\n <Text dimColor>{'─'.repeat(40)}</Text>\n {dashboardUrl && (\n <Text>\n Dashboard: <Text color=\"cyan\">{dashboardUrl}</Text>\n </Text>\n )}\n {notebookUrl && (\n <Text>\n Notebook: <Text color=\"cyan\">{notebookUrl}</Text>\n </Text>\n )}\n </Box>\n);\n\nconst WritingReport = ({ reportPath }: { reportPath: string }) => (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n We've wrapped up the review.\n </Text>\n <Box height={1} />\n <Text>\n To help you get the most out of your PostHog integration, we're preparing\n a report for you at <Text color=\"cyan\">{reportPath}</Text>.\n </Text>\n <Box height={1} />\n <Text>\n We'll cover what we checked and suggest where we can improve the existing\n integration.\n </Text>\n <Box height={1} />\n <Text dimColor>Hang tight!</Text>\n </Box>\n);\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst DetectVisual = () => (\n <VisualBox>\n <Text dimColor>package.json</Text>\n <Text>\n <Text dimColor>{' └─ '}</Text>\n <Text color=\"green\">posthog-js</Text>\n <Text dimColor>{' ^1.200.0'}</Text>\n </Text>\n <Text dimColor>requirements.txt</Text>\n <Text>\n <Text dimColor>{' └─ '}</Text>\n <Text color=\"green\">posthog</Text>\n <Text dimColor>{' ==4.0.1'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const DetectSdkSlide: AreaSlide = {\n area: 'Detect SDK',\n intro: [\n 'First we find which PostHog SDKs your project uses. The audit needs to know the right languages and frameworks before it looks at any code.',\n 'Only dependency manifests get read here: package.json, requirements.txt, go.mod, and similar files. Source files come in a later step.',\n 'If your project is a monorepo with more than one SDK, we handle each one.',\n ],\n visual: <DetectVisual />,\n docsUrl: 'https://posthog.com/docs/libraries',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst ScanVisual = () => (\n <VisualBox>\n <Text dimColor>grep -rn 'posthog\\.(capture|identify|group)'</Text>\n <Text>\n <Text color=\"cyan\">src/checkout/Checkout.tsx:88</Text>\n <Text dimColor>{' posthog.capture(...)'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">src/auth/login.ts:42</Text>\n <Text dimColor>{' posthog.identify(...)'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">src/onboarding/step.tsx:17</Text>\n <Text dimColor>{' posthog.capture(...)'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const ScanSitesSlide: AreaSlide = {\n area: 'Scan capture sites',\n intro: [\n 'Next we map every place your code captures PostHog events. This is the inventory the rest of the audit builds on.',\n 'We search your project for PostHog SDK calls: capture, identify, group, and more. No source files are opened yet, that comes in the next step.',\n \"Test files are excluded so they don't pollute the inventory.\",\n ],\n visual: <ScanVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/capture-events',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst EnrichVisual = () => (\n <VisualBox>\n <Text dimColor>orchestrator</Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ├─ '}</Text>\n <Text color=\"cyan\">subagent 1</Text>\n <Text dimColor>{' → part-1.json'}</Text>\n </Text>\n <Text>\n <Text dimColor>{' ├─ '}</Text>\n <Text color=\"cyan\">subagent 2</Text>\n <Text dimColor>{' → part-2.json'}</Text>\n </Text>\n <Text>\n <Text dimColor>{' └─ '}</Text>\n <Text color=\"cyan\">subagent N</Text>\n <Text dimColor>{' → part-N.json'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const EnrichSitesSlide: AreaSlide = {\n area: 'Enrich',\n intro: [\n 'Now we look inside each file that captures events. The goal is to know not just that an event fires, but what it is, where it lives, and what data goes with it.',\n 'For every capture site we pull out the event name, the properties, the area of your codebase it sits in, and the surrounding function or component.',\n 'This is the only step that opens source files. Large codebases run in parallel so it finishes in one pass.',\n ],\n visual: <EnrichVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/best-practices',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst QueryVisual = () => (\n <VisualBox>\n <Text dimColor>{'SELECT event, count() AS volume_30d'}</Text>\n <Text dimColor>\n {'FROM events WHERE timestamp > now() - INTERVAL 30 DAY'}\n </Text>\n <Text dimColor>{'GROUP BY event ORDER BY volume_30d DESC'}</Text>\n <Text> </Text>\n <Text>\n <Text color=\"cyan\">{'pageview '}</Text>\n <Text color=\"green\">{'12,430'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'signup_completed '}</Text>\n <Text color=\"green\">{' 840'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const QueryVolumeSlide: AreaSlide = {\n area: 'Query PostHog',\n intro: [\n 'We ask PostHog how often each event in the inventory has fired in the last 30 days.',\n \"Events your code captures but PostHog has never seen are flagged as phantoms. Phantoms usually mean a typo, a dead code path, or instrumentation that hasn't shipped yet. Worth cleaning up.\",\n \"If PostHog isn't reachable the audit still finishes. The report just notes where volume numbers would have gone.\",\n ],\n visual: <QueryVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/sql',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst ReportVisual = () => (\n <VisualBox>\n <Text dimColor>posthog-events-audit-report.md</Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Identity &amp; segmentation</Text>\n </Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Coverage map</Text>\n </Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Data quality</Text>\n </Text>\n <Text>\n <Text dimColor>{' # '}</Text>\n <Text>Events by file &amp; area</Text>\n </Text>\n </VisualBox>\n);\n\nexport const WriteReportSlide: AreaSlide = {\n area: 'Write report',\n intro: [\n 'We package everything we found into one report at ./posthog-events-audit-report.md. This is what you hand to the team.',\n 'The report covers how users get identified, which parts of your codebase capture which events, data quality issues like duplicates and phantoms, and a volume map of every event your code captures.',\n 'Nothing in your project is modified. The report is the only file you keep.',\n ],\n visual: <ReportVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/best-practices',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst DashboardVisual = () => (\n <VisualBox>\n <Text dimColor>events audit dashboard</Text>\n <Text>\n <Text color=\"cyan\">{'pageview '}</Text>\n <Text color=\"green\">{'████████████'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'signup '}</Text>\n <Text color=\"green\">{'████████'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'activated '}</Text>\n <Text color=\"green\">{'█████'}</Text>\n </Text>\n <Text>\n <Text color=\"cyan\">{'purchased '}</Text>\n <Text color=\"green\">{'██'}</Text>\n </Text>\n </VisualBox>\n);\n\nexport const CreateDashboardSlide: AreaSlide = {\n area: 'Create dashboard',\n intro: [\n 'Finally we build a live PostHog dashboard for the events your code captures. Use it to watch volume over time, spot new phantoms, and see how traffic shifts as you ship changes.',\n 'Open the dashboard from the wrap-up screen when the audit completes.',\n ],\n visual: <DashboardVisual />,\n docsUrl: 'https://posthog.com/docs/product-analytics/dashboards',\n};\n","import { Text } from 'ink';\nimport { VisualBox, type AreaSlide } from '../shared.js';\n\nconst NotebookVisual = () => (\n <VisualBox>\n <Text dimColor>posthog-events-audit-report.md</Text>\n <Text dimColor>{' │'}</Text>\n <Text>\n <Text dimColor>{' ▼ '}</Text>\n <Text color=\"cyan\">PostHog notebook</Text>\n </Text>\n <Text dimColor>{' # Identity & segmentation'}</Text>\n <Text dimColor>{' # Coverage map'}</Text>\n <Text dimColor>{' # Events by file & area'}</Text>\n </VisualBox>\n);\n\nexport const UploadNotebookSlide: AreaSlide = {\n area: 'Upload notebook',\n intro: [\n 'Next we upload the report into a PostHog notebook so you can share it with your team as a URL.',\n 'Hang tight.',\n 'The markdown file on disk is still there for you to read locally.',\n ],\n visual: <NotebookVisual />,\n docsUrl: 'https://posthog.com/docs/notebooks',\n};\n","/**\n * Slide registry for the events-audit program. Each entry is keyed by\n * `AuditCheck.area` and corresponds to one phase of the 6-phase pipeline.\n *\n * `AuditAreaPane` looks up the active phase's slide here when the active\n * program is events-audit.\n */\n\nimport type { AreaSlide } from '../shared.js';\nimport { DetectSdkSlide } from './detectSdk.js';\nimport { ScanSitesSlide } from './scanSites.js';\nimport { EnrichSitesSlide } from './enrichSites.js';\nimport { QueryVolumeSlide } from './queryVolume.js';\nimport { WriteReportSlide } from './writeReport.js';\nimport { CreateDashboardSlide } from './createDashboard.js';\nimport { UploadNotebookSlide } from './uploadNotebook.js';\n\nexport const EVENTS_AUDIT_AREA_SLIDES: AreaSlide[] = [\n DetectSdkSlide,\n ScanSitesSlide,\n EnrichSitesSlide,\n QueryVolumeSlide,\n WriteReportSlide,\n CreateDashboardSlide,\n UploadNotebookSlide,\n];\n","import { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport type { AuditCheck } from '@programs/audit';\nimport { AUDIT_SEVERITY_STYLE } from '../severity-style.js';\nimport { Colors, Icons } from '@tui/styles';\nimport { LoadingBox } from '@tui/primitives/index';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\n\ninterface PendingChecksListProps {\n checks: AuditCheck[];\n}\n\ninterface Group {\n area: string;\n checks: AuditCheck[];\n}\n\nfunction groupByArea(checks: AuditCheck[]): Group[] {\n const order: string[] = [];\n const map = new Map<string, AuditCheck[]>();\n for (const c of checks) {\n if (!map.has(c.area)) {\n map.set(c.area, []);\n order.push(c.area);\n }\n map.get(c.area)!.push(c);\n }\n return order.map((area) => ({ area, checks: map.get(area)! }));\n}\n\nfunction groupIcon(group: Group): { icon: string; color: string } {\n const total = group.checks.length;\n const complete = group.checks.filter((c) => c.status !== 'pending').length;\n if (complete === 0) return { icon: Icons.squareOpen, color: Colors.muted };\n if (complete === total)\n return { icon: Icons.squareFilled, color: Colors.success };\n return { icon: Icons.triangleRight, color: Colors.primary };\n}\n\nconst GroupHeader = ({\n group,\n showIcon,\n isActive,\n}: {\n group: Group;\n showIcon: boolean;\n isActive: boolean;\n}) => {\n const complete = group.checks.filter((c) => c.status !== 'pending').length;\n const total = group.checks.length;\n const { icon, color } = groupIcon(group);\n return (\n <Box>\n {isActive ? (\n <Box marginRight={1}>\n <Spinner />\n </Box>\n ) : showIcon ? (\n <Text>\n <Text color={color}>{icon}</Text>{' '}\n </Text>\n ) : null}\n <Text>\n <Text bold>{group.area}</Text>{' '}\n <Text dimColor>\n ({complete}/{total})\n </Text>\n </Text>\n </Box>\n );\n};\n\nconst CheckRow = ({ check }: { check: AuditCheck }) => {\n const { glyph, color } = AUDIT_SEVERITY_STYLE[check.status];\n return (\n <Text>\n <Text color={color}>{glyph}</Text>\n <Text dimColor={check.status === 'pending'}> {check.label}</Text>\n </Text>\n );\n};\n\nconst COLLAPSE_BELOW_ROWS = 24;\n\nexport const PendingChecksList = ({ checks }: PendingChecksListProps) => {\n const [, termRows] = useStdoutDimensions();\n\n if (checks.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text bold>Checks</Text>\n <Text> </Text>\n <LoadingBox message=\"Seeding audit checklist...\" />\n </Box>\n );\n }\n\n const groups = groupByArea(checks);\n const activeIndex = groups.findIndex((g) =>\n g.checks.some((c) => c.status === 'pending'),\n );\n const collapsed = termRows < COLLAPSE_BELOW_ROWS;\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>Checks</Text>\n <Text> </Text>\n {collapsed\n ? groups.map((group, i) => (\n <GroupHeader\n key={group.area}\n group={group}\n showIcon\n isActive={i === activeIndex}\n />\n ))\n : groups.map((group, i) => (\n <Box\n key={group.area}\n flexDirection=\"column\"\n marginTop={i === 0 ? 0 : 1}\n >\n <GroupHeader\n group={group}\n showIcon={false}\n isActive={i === activeIndex}\n />\n {group.checks.map((c) => (\n <CheckRow key={c.id} check={c} />\n ))}\n </Box>\n ))}\n </Box>\n );\n};\n","import { useSyncExternalStore } from 'react';\nimport { Box } from 'ink';\nimport type { WizardStore } from '@tui/store';\nimport {\n TabContainer,\n SplitView,\n LogViewer,\n HNViewer,\n} from '@tui/primitives/index';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport { AuditChecksViewer } from './AuditChecksViewer/AuditChecksViewer.js';\nimport { AuditAreaPane } from './AuditAreaPane.js';\nimport { AUDIT_AREA_SLIDES } from './slides/index.js';\nimport { EVENTS_AUDIT_AREA_SLIDES } from './slides/events-audit/index.js';\nimport { PendingChecksList } from './PendingChecksList.js';\nimport { AUDIT_REPORT_FILE, getAuditChecks } from '@programs/audit';\nimport { getProgramConfig } from '@programs';\nimport { getLogFilePath } from '@utils/debug';\n\ninterface AuditRunScreenProps {\n store: WizardStore;\n}\n\nexport const AuditRunScreen = ({ store }: AuditRunScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // The ledger reaches the store through `AuditLedgerWatcher`, which runs for\n // headless runs too. This screen only renders what the store holds.\n const statuses =\n store.statusMessages.length > 0 ? store.statusMessages : undefined;\n\n const [columns] = useStdoutDimensions();\n const checks = getAuditChecks(store.session);\n const reportFile =\n getProgramConfig(store.router.activeProgram).reportFile ??\n AUDIT_REPORT_FILE;\n const reportPath = `./${reportFile}`;\n const pendingChecksList = <PendingChecksList checks={checks} />;\n const slides =\n store.session.skillId === 'audit-events'\n ? EVENTS_AUDIT_AREA_SLIDES\n : AUDIT_AREA_SLIDES;\n const areaPane = (\n <AuditAreaPane\n checks={checks}\n reportPath={reportPath}\n slides={slides}\n dashboardUrl={store.session.dashboardUrl}\n notebookUrl={store.session.notebookUrl}\n />\n );\n\n // Narrow terminals: drop the area pane.\n const statusComponent =\n columns < 80 ? (\n <Box flexDirection=\"column\" flexGrow={1}>\n {pendingChecksList}\n </Box>\n ) : (\n <SplitView left={areaPane} right={pendingChecksList} />\n );\n\n const tabs = [\n { id: 'status', label: 'Status', component: statusComponent },\n {\n id: 'audit-checks',\n label: 'Audit plan',\n component: <AuditChecksViewer checks={checks} />,\n },\n {\n id: 'logs',\n label: 'Tail logs',\n component: <LogViewer filePath={getLogFilePath()} />,\n },\n { id: 'hn', label: 'HN', component: <HNViewer /> },\n ];\n\n return (\n <TabContainer\n tabs={tabs}\n statusMessage={statuses}\n expandableStatus\n store={store}\n />\n );\n};\n","import { Box, Text } from 'ink';\nimport type { AuditCheck } from '@programs/audit';\nimport { AUDIT_SEVERITY_STYLE } from '../severity-style.js';\nimport { relativeToInstallDir } from '@utils/paths';\nimport { countNoun } from '@utils/count-noun';\n\ninterface AuditChecksOutroSectionProps {\n checks: AuditCheck[];\n installDir: string;\n}\n\nconst MAX_VISIBLE = 6;\n\nexport const AuditChecksOutroSection = ({\n checks,\n installDir,\n}: AuditChecksOutroSectionProps) => {\n if (checks.length === 0) return null;\n\n const errors = checks.filter((c) => c.status === 'error');\n const warnings = checks.filter((c) => c.status === 'warning');\n const suggestions = checks.filter((c) => c.status === 'suggestion');\n const problematic = [...errors, ...warnings, ...suggestions];\n\n const visible = problematic.slice(0, MAX_VISIBLE);\n const hidden = problematic.length - visible.length;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"cyan\" bold>\n Items audited:\n </Text>\n <Text dimColor>\n {[\n countNoun(checks.length, 'check'),\n countNoun(errors.length, 'error'),\n countNoun(warnings.length, 'warning'),\n countNoun(suggestions.length, 'suggestion'),\n ].join(' · ')}\n </Text>\n {problematic.length === 0 ? (\n <Text color=\"green\">{'•'} No issues found.</Text>\n ) : (\n <>\n {visible.map((item) => {\n const style = AUDIT_SEVERITY_STYLE[item.status];\n return (\n <Box key={item.id} flexDirection=\"column\" marginTop={1}>\n <Text>\n <Text color={style.color}>{style.glyph}</Text>{' '}\n <Text bold>{item.label}</Text>{' '}\n <Text dimColor>({item.area})</Text>\n </Text>\n {item.file && (\n <Text dimColor>\n {' '}\n {relativeToInstallDir(item.file, installDir)}\n </Text>\n )}\n </Box>\n );\n })}\n {hidden > 0 && (\n <Text dimColor>\n … and {hidden} more. See the report for details.\n </Text>\n )}\n </>\n )}\n </Box>\n );\n};\n","/**\n * useDismissOnAnyKey — \"press any key to continue/exit\" screens.\n *\n * Wraps `useInput` for the recurring \"any key dismisses/exits this screen\"\n * pattern (outro screens, terminal error/timeout screens, etc.), ignoring\n * modifier-combo keypresses (Ctrl/Meta) so a global hidden shortcut — e.g.\n * Ctrl+T toggling the token/cost HUD — can't also dismiss the screen\n * underneath it. Ink calls every mounted `useInput` callback for a given\n * keypress with no `stopPropagation`, so a bare `useInput(() => handler())`\n * would otherwise fire on every registered shortcut too, not just an\n * ordinary keypress.\n *\n * Use this instead of raw `useInput` for any screen where any ordinary\n * keypress should proceed, but a modifier combo shouldn't be able to.\n */\nimport { useInput, type Key } from 'ink';\n\n/**\n * True for a keypress that should NOT count as \"any key\" for a dismiss\n * handler — currently just modifier combos. Extracted as a pure predicate\n * so it's unit-testable without rendering through Ink.\n */\nexport function isIgnoredForDismiss(key: Pick<Key, 'ctrl' | 'meta'>): boolean {\n return key.ctrl || key.meta;\n}\n\nexport function useDismissOnAnyKey(handler: () => void): void {\n useInput((_input, key) => {\n if (isIgnoredForDismiss(key)) return;\n handler();\n });\n}\n","/**\n * AuditOutroScreen — Audit-specific post-run summary. Renders the standard\n * success / error / cancel views with the audit checks summary inlined into\n * the success body. The report path shown in the success headline comes from\n * the program's `successMessage`, so this screen is program-agnostic.\n */\n\nimport { join } from 'node:path';\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { OutroKind } from '@shared/outro';\nimport { Colors } from '@tui/styles';\nimport { getAuditChecks } from '@programs/audit';\nimport { AuditChecksOutroSection } from './AuditChecksOutroSection.js';\nimport { useDismissOnAnyKey } from '@tui/hooks/useDismissOnAnyKey';\n\ninterface AuditOutroScreenProps {\n store: WizardStore;\n}\n\nexport const AuditOutroScreen = ({ store }: AuditOutroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n useDismissOnAnyKey(() => store.setOutroDismissed());\n\n const outroData = store.session.outroData;\n\n if (!outroData) {\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text dimColor>Finishing up...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {outroData.kind === OutroKind.Success && (\n <Box flexDirection=\"column\">\n <Text color=\"green\" bold>\n ✔ {outroData.message || 'Audit complete!'}\n </Text>\n\n {outroData.dashboardUrl && (\n <Box marginTop={1}>\n <Text>\n Dashboard: <Text color=\"cyan\">{outroData.dashboardUrl}</Text>\n </Text>\n </Box>\n )}\n\n {outroData.notebookUrl && (\n <Box marginTop={1}>\n <Text>\n Notebook: <Text color=\"cyan\">{outroData.notebookUrl}</Text>\n </Text>\n </Box>\n )}\n\n {outroData.reportFile && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"cyan\" bold>\n Report saved to:\n </Text>\n <Text>\n {join(store.session.installDir, outroData.reportFile)}\n </Text>\n <Text dimColor>\n A markdown file in your project folder. Open it in any editor to\n read the full audit.\n </Text>\n </Box>\n )}\n\n <AuditChecksOutroSection\n checks={getAuditChecks(store.session)}\n installDir={store.session.installDir}\n />\n\n {outroData.docsUrl && (\n <Box marginTop={1}>\n <Text>\n Learn more: <Text color=\"cyan\">{outroData.docsUrl}</Text>\n </Text>\n </Box>\n )}\n </Box>\n )}\n\n {outroData.kind === OutroKind.Error && (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✘ {outroData.message || 'An error occurred'}\n </Text>\n {outroData.body && (\n <Box marginTop={1}>\n <Text dimColor>{outroData.body}</Text>\n </Box>\n )}\n </Box>\n )}\n\n {outroData.kind === OutroKind.Cancel && (\n <Text color=\"yellow\">■ {outroData.message || 'Cancelled'}</Text>\n )}\n\n <Box marginTop={1}>\n <Text color={Colors.muted}>Press any key to continue</Text>\n </Box>\n </Box>\n );\n};\n","/** The audit programs' TUI: the audit family and the events audit share one set of screens. */\nimport type { TuiProgram, TuiPrograms } from '@tui/programs/types';\nimport { getContentBlocks as skillDeck } from '@tui/programs/shared/skill-deck';\nimport { AUDIT_FLOW } from './flow.js';\nimport { EVENTS_AUDIT_FLOW } from './events-flow.js';\nimport { AuditScreenId } from './screen-ids.js';\nimport { AuditIntroScreen } from './screens/AuditIntroScreen.js';\nimport { AuditRunScreen } from './screens/AuditRunScreen.js';\nimport { AuditOutroScreen } from './screens/AuditOutroScreen.js';\n\nexport { AuditScreenId } from './screen-ids.js';\n\nconst screens: TuiProgram['screens'] = {\n [AuditScreenId.Intro]: (store) => <AuditIntroScreen store={store} />,\n [AuditScreenId.Run]: (store) => <AuditRunScreen store={store} />,\n [AuditScreenId.Outro]: (store) => <AuditOutroScreen store={store} />,\n};\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n audit: { flow: AUDIT_FLOW, deck: skillDeck, screens },\n 'events-audit': { flow: EVENTS_AUDIT_FLOW, screens },\n};\n","import type { FlowStep } from '@tui/flow';\nimport { AGENT_SKILL_STEPS } from '@tui/programs/shared/skill-flow';\n\n/**\n * After login, the scan lists the repo's projects and the user picks one, as in\n * the legacy upload-source-maps program. The pick sets the framework preflight\n * resolves task skills against, and the project path the run is scoped to.\n */\nconst PICK_PROJECT_STEP: FlowStep = {\n id: 'detect',\n label: 'Detecting projects',\n screenId: 'error-tracking-detect',\n isComplete: ({ session }) => session.integration != null,\n};\n\nexport const ERROR_TRACKING_FLOW: FlowStep[] = AGENT_SKILL_STEPS.flatMap(\n (step): FlowStep[] => {\n if (step.id === 'intro') {\n return [{ ...step, screenId: 'error-tracking-intro' }];\n }\n if (step.id === 'auth') return [step, PICK_PROJECT_STEP];\n return [step];\n },\n);\n","/**\n * StatusPeekTrigger — Fires the status-bar expansion once, renders a hint.\n *\n * Module-level `peekedOnce` guards against re-mounts (resize, tab switch)\n * so the peek only happens a single time per process.\n */\n\nimport { Text } from 'ink';\nimport { useEffect } from 'react';\nimport type { WizardStore } from '@tui/store';\n\nlet peekedOnce = false;\n\ninterface StatusPeekTriggerProps {\n store?: WizardStore;\n /** How long the status bar stays expanded, in ms. */\n duration?: number;\n}\n\nexport const StatusPeekTrigger = ({\n store,\n duration = 10000,\n}: StatusPeekTriggerProps) => {\n useEffect(() => {\n if (peekedOnce) return;\n peekedOnce = true;\n store?.setStatusExpanded(true);\n // No cleanup — the store call is safe after unmount and the component\n // may be evicted before the timer fires (non-persist NodeBlock).\n setTimeout(() => {\n store?.setStatusExpanded(false);\n }, duration);\n }, [store, duration]);\n\n return <Text>You can view the Wizard&apos;s status below.</Text>;\n};\n","/**\n * Source-maps learn-deck — the narrative played in the run screen's left\n * pane (LearnCard) while the agent wires source-map upload into the build.\n *\n * It educates the user on what source maps are and why uploading them\n * matters, built around a before/after stack-trace contrast: a minified\n * production trace nobody can read, then the same trace resolved back to\n * real source. Shared by the source-maps and error-tracking decks, which\n * each supply their own copy.\n *\n * Lines stay narrow (~36 cols) because this renders in the left half of a\n * split pane — see LearnCard's paneWidth math.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { WizardStore } from '@tui/store';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport { isClearBlock, type ContentBlock } from '@tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@tui/components/StatusPeekTrigger';\n\n/**\n * Per-slide dwell multiplier. Each block stays on screen for `pause * SLIDE_PACE`\n * ms after it finishes animating, before the deck advances. Bump this single\n * knob to give every slide more reading time. Clear (page-break) blocks are\n * left untouched so the blank gap between slides stays snappy.\n */\nconst SLIDE_PACE = 1.5;\n\nconst withPace = (block: ContentBlock): ContentBlock => {\n if (typeof block === 'string' || isClearBlock(block) || block.pause == null) {\n return block;\n }\n return { ...block, pause: Math.round(block.pause * SLIDE_PACE) };\n};\n\n/** Apply the dwell multiplier to every block in a deck. */\nconst pace = (blocks: ContentBlock[]): ContentBlock[] => blocks.map(withPace);\n\n/**\n * A minified production stack trace — the problem source maps solve. Framed as\n * a labelled, muted example (no error-red ✘) so a glance reads it as\n * illustrative content, not as the wizard itself having errored mid-run.\n */\nconst MINIFIED_TRACE: ContentBlock = {\n type: 'lines',\n interval: 400,\n pause: 7000,\n lines: [\n <Text dimColor>{'example — minified production trace'}</Text>,\n <Text color={Colors.muted}>{' TypeError: cart is undefined'}</Text>,\n <Text dimColor>{' at t.min.js:1:48213'}</Text>,\n <Text dimColor>{' at t.min.js:1:9402'}</Text>,\n <Text dimColor>{' at t.min.js:1:71150'}</Text>,\n ],\n};\n\n/** The same trace, resolved through uploaded source maps. */\nconst RESOLVED_TRACE: ContentBlock = {\n type: 'lines',\n interval: 400,\n pause: 8000,\n lines: [\n <Text dimColor>{'example — resolved with source maps'}</Text>,\n <Text color={Colors.success}>{' ✔ TypeError: cart is undefined'}</Text>,\n <Text>\n <Text dimColor>{' at '}</Text>\n <Text color=\"cyan\">Cart.tsx:42</Text>\n <Text dimColor>{' loadCart'}</Text>\n </Text>,\n <Text>\n <Text dimColor>{' at '}</Text>\n <Text color=\"cyan\">App.tsx:88</Text>\n <Text dimColor>{' render'}</Text>\n </Text>,\n <Text>\n <Text dimColor>{' at '}</Text>\n <Text color=\"cyan\">index.tsx:5</Text>\n <Text dimColor>{' main'}</Text>\n </Text>,\n ],\n};\n\n/**\n * How a bundle is tied to its map: PostHog injects a chunk-ID marker into the\n * built JS and stamps the matching source map with the same ID.\n */\nconst CHUNK_ID_LINK: ContentBlock = {\n type: 'lines',\n interval: 450,\n pause: 7500,\n lines: [\n <Text dimColor>app.min.js</Text>,\n <Text dimColor>{' …minified code…'}</Text>,\n <Text>\n <Text color=\"cyan\">{' //# chunkId=a1b2c3d4'}</Text>\n <Text dimColor>{' ← injected'}</Text>\n </Text>,\n <Text dimColor>{' ↕ matched by id'}</Text>,\n <Text>\n <Text dimColor>app.min.js.map</Text>\n <Text dimColor>{' ← uploaded'}</Text>\n </Text>,\n ],\n};\n\n/** Many similar exceptions collapse into a single issue. */\nconst GROUPING: ContentBlock = {\n type: 'lines',\n interval: 450,\n pause: 7000,\n lines: [\n <Text dimColor>{'exception ─┐'}</Text>,\n <Text>\n <Text dimColor>{'exception ─┼──→ '}</Text>\n <Text color={Colors.accent} bold>\n 1 issue\n </Text>\n </Text>,\n <Text dimColor>{'exception ─┘'}</Text>,\n ],\n};\n\n/** The two lines that say what the run wires. The rest of the deck is shared. */\nexport type SourceMapsDeckCopy = { intro: string; wiring: string };\n\n/** The source-maps narrative. The error-tracking program reuses it with its own copy. */\nexport const buildSourceMapsDeck = (\n store: WizardStore | undefined,\n copy: SourceMapsDeckCopy,\n): ContentBlock[] =>\n pace([\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n {\n content: copy.intro,\n pause: 5000,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'When you ship to production, your code gets minified.',\n pause: 5000,\n },\n {\n content: 'Thousands of readable lines collapse into one dense bundle.',\n pause: 5000,\n },\n {\n content: 'So a thrown error gives you a stack trace like this:',\n pause: 2000,\n },\n\n MINIFIED_TRACE,\n\n { content: 'Just offsets into a file no human can read.', pause: 5000 },\n\n { type: 'clear', pause: 1500 },\n\n { content: 'Source maps are the key.', pause: 3500 },\n {\n content:\n 'They map every position in that bundle back to your original source — the real file, line, and function.',\n pause: 6000,\n },\n {\n content: copy.wiring,\n pause: 6000,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'But how does PostHog know which map belongs to which build?',\n pause: 4500,\n },\n {\n content:\n 'During the build, it injects a unique chunk ID into each bundle:',\n pause: 2500,\n },\n\n CHUNK_ID_LINK,\n\n {\n content:\n 'The matching source map is stamped with that same ID before it ships to PostHog.',\n pause: 6000,\n },\n {\n content:\n 'When an error comes in, PostHog reads the chunk ID off the bundle, finds the map with the exact same ID, and uses it to map each frame back to your source — even for a release you shipped weeks ago.',\n pause: 8000,\n },\n\n { type: 'clear', pause: 1500 },\n\n { content: 'So that same error becomes:', pause: 2000 },\n\n RESOLVED_TRACE,\n\n {\n content: 'Readable stack traces, straight from production.',\n pause: 5000,\n },\n {\n content: 'You debug a live error like it happened on your own machine.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1500 },\n\n { content: 'Zooming out — this is how Error Tracking works.', pause: 4000 },\n {\n content: 'Every error your app throws is captured as an exception.',\n pause: 5000,\n },\n {\n content: 'PostHog groups similar exceptions into a single issue:',\n pause: 2500,\n },\n\n GROUPING,\n\n {\n content:\n 'So a bug that fires ten thousand times is one issue to triage — not ten thousand alerts.',\n pause: 6500,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'And this is where source maps earn their keep again.',\n pause: 4500,\n },\n {\n content:\n 'Grouping reads the stack trace. Minified frames all look alike — so unrelated crashes get merged, and one real bug scatters across many issues.',\n pause: 8000,\n },\n {\n content:\n 'With source maps, PostHog groups on your real frames — so each distinct bug lands as one clean issue.',\n pause: 7000,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n {\n pause: 90000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to follow along — or sit tight, I'll let you know when it's done.\n </Text>\n ),\n },\n ]);\n","/** Error-tracking learn-deck: the source-maps narrative, worded to also fit platforms that upload nothing. */\n\nimport type { WizardStore } from '@tui/store';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { buildSourceMapsDeck } from '@tui/programs/shared/deck/source-maps';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] =>\n buildSourceMapsDeck(store, {\n intro: \"I'm wiring PostHog Error Tracking into your project.\",\n wiring:\n '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. On Python, Ruby and PHP, I link each production deploy to its release instead.',\n });\n","/** Sidebar tips for the error-tracking run: product features the learn deck does not cover. */\n\nimport type { Tip } from '@tui/components/TipsCard';\nimport { REPLAY_VISION_SUPPORTED } from '@shared/constants';\n\nexport const ERROR_TRACKING_TIPS: Tip[] = [\n {\n id: 'session-replay',\n title: 'Watch the crash happen',\n description:\n 'An exception from a recorded session links to its replay. See the clicks that led to the error, not only the stack trace.',\n // Replay records only on platforms with a client SDK.\n visible: (store) => {\n const integration = store.session.integration;\n return integration != null && REPLAY_VISION_SUPPORTED.has(integration);\n },\n },\n {\n id: 'alerts',\n title: 'Know when a bug comes back from the dead',\n description:\n 'Set alerts for new issues, issues that return after you resolve them, and sudden spikes. Hear about them before your users do.',\n },\n {\n id: 'external-issues',\n title: 'From crash to ticket in one click',\n description:\n 'Create a GitHub, GitLab, Jira or Linear issue straight from an error.',\n },\n];\n\nexport const getTips = (): Tip[] => ERROR_TRACKING_TIPS;\n","import { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface ErrorTrackingIntroScreenProps {\n store: WizardStore;\n}\n\nexport const ErrorTrackingIntroScreen = ({\n store,\n}: ErrorTrackingIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n const { session } = store;\n // The flow resolves its skills per framework after the project pick. Point\n // \"more info\" at the capture step, the one skill every run of this flow installs.\n const skillId = 'integration-v2-error-tracking-step';\n const { skillEntry, fetchFailed } = useSkillEntry(skillId);\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56}>\n <Box marginBottom={1}>\n <Text>\n The Wizard is an agent, it's here to help you setup PostHog. Its code\n is open source:{' '}\n <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n\n <Text>\n The{' '}\n <Text color=\"cyan\" italic>\n error-tracking\n </Text>{' '}\n program makes uncaught errors reach PostHog with readable stack traces.\n It installs and initializes the PostHog, wires up exception capture, and\n sets up source-map uploading or release linking in your deploys when\n necessary. In PostHog, you can analyze these errors and have agents\n proactively suggest fixes in self-driving.\n </Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>\n Let's make uncaught errors reach PostHog with readable stack traces.\n </Text>\n </Box>\n );\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const handleSelect = (value: string) => {\n if (value === 'cancel') store.requestExit(0);\n else if (value === 'more-info') setShowingMoreInfo(true);\n else if (value === 'back') setShowingMoreInfo(false);\n else store.completeSetup();\n };\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={handleSelect}\n />\n );\n};\n","import type { AgentProgress } from '@agent/types';\nimport type { ProgramProgress } from '@programs/types';\nimport { applyAgentProgress } from '@programs';\nimport type { WizardStore } from './store.js';\n\n// ── Progress → the store, one write per event ─────────────────────────\n\n/**\n * A scan's progress on the store: one event, one write, synchronous, in\n * emission order. For a scan a screen runs itself; a `runProgram` run already\n * writes its run state to the session store, so its progress goes through\n * `displayProgress`.\n */\nexport function scanProgress(\n store: WizardStore,\n): (event: AgentProgress) => void {\n const show = displayProgress(store);\n return (event) => {\n // The success line is shown and set as the fallback outro without escape codes.\n const clean =\n event.kind === 'lifecycle' && event.phase === 'completed'\n ? { ...event, message: stripAnsi(event.message) }\n : event;\n show({ runId: 'scan', event: clean });\n applyAgentProgress(store.sessions, clean);\n };\n}\n\n/** A `runProgram` run's progress on what only the TUI shows; the run state is already in the session store. */\nexport function displayProgress(\n store: WizardStore,\n): (progress: ProgramProgress) => void {\n return ({ event }) => {\n switch (event.kind) {\n case 'lifecycle':\n if (event.phase === 'completed')\n store.pushStatus(stripAnsi(event.message));\n return;\n case 'spinner':\n case 'log':\n case 'stage':\n case 'usage':\n case 'finalCost':\n case 'authError':\n showDisplayEvent(store, event);\n return;\n // Run state runProgram records, or nothing to show.\n case 'status':\n case 'tasks':\n case 'url':\n case 'handoff':\n case 'completion':\n case 'activity':\n case 'binding':\n return;\n default: {\n const unhandled: never = event;\n throw new Error(\n `Unhandled agent progress: ${JSON.stringify(unhandled)}`,\n );\n }\n }\n };\n}\n\ntype DisplayEvent = Extract<\n AgentProgress,\n { kind: 'spinner' | 'log' | 'stage' | 'usage' | 'finalCost' | 'authError' }\n>;\n\n/** The events both feeds show the same way: lines on the status feed, the stage, the token HUD, the auth overlay. */\nfunction showDisplayEvent(store: WizardStore, event: DisplayEvent): void {\n switch (event.kind) {\n case 'spinner':\n if (event.message) store.pushStatus(event.message);\n return;\n case 'log':\n store.pushStatus(event.message);\n return;\n case 'stage':\n store.setCurrentStage(event.stage);\n return;\n case 'usage':\n store.addTokenUsage(event.delta);\n return;\n case 'finalCost':\n store.setFinalTokenCostUsd(event.usd);\n return;\n case 'authError':\n store.showAuthError(event.detail);\n return;\n }\n}\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g;\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, '');\n}\n","/**\n * ErrorTrackingDetectScreen — after login, runs the detection agent over the\n * repo, streams its progress, and lets the user pick the project to set error\n * tracking up in. Mirrors the legacy SourceMapsDetectScreen.\n */\n\nimport { scanProgress } from '@tui/agent-progress';\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { LoadingBox, PickerMenu } from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\nimport { FRAMEWORK_REGISTRY } from '@programs';\nimport {\n detectErrorTrackingProjects,\n ERROR_TRACKING_PROJECT_PATH_KEY,\n type ErrorTrackingDetectionReport,\n type ErrorTrackingProject,\n} from '@programs/error-tracking';\n\ninterface ErrorTrackingDetectScreenProps {\n store: WizardStore;\n}\n\ntype DetectState =\n | { kind: 'loading' }\n | { kind: 'ready'; report: ErrorTrackingDetectionReport }\n | { kind: 'error'; message: string };\n\nconst EXIT = '__exit';\nconst MAX_ACTIVITY_LINES = 8;\n\nfunction projectLabel(p: ErrorTrackingProject): string {\n const where = p.path === '.' ? 'repo root' : p.path;\n return `${p.framework} ${Icons.bullet} ${where}`;\n}\n\nexport const ErrorTrackingDetectScreen = ({\n store,\n}: ErrorTrackingDetectScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { credentials } = store.session;\n const accessToken = credentials?.accessToken;\n\n const [state, setState] = useState<DetectState>({ kind: 'loading' });\n const [activity, setActivity] = useState<string[]>([]);\n const started = useRef(false);\n\n useEffect(() => {\n if (!accessToken || started.current) return;\n started.current = true;\n let cancelled = false;\n void (async () => {\n try {\n const report = await detectErrorTrackingProjects(\n store.session,\n (line) => {\n if (!cancelled) {\n setActivity((prev) => [...prev, line].slice(-MAX_ACTIVITY_LINES));\n }\n },\n scanProgress(store),\n );\n if (!cancelled) setState({ kind: 'ready', report });\n } catch (err) {\n if (!cancelled) {\n setState({\n kind: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [accessToken, store]);\n\n if (!credentials) {\n return <LoadingBox message=\"Waiting for authentication...\" />;\n }\n\n if (state.kind === 'loading') {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Detecting your project...\n </Text>\n <Box marginY={1}>\n <LoadingBox message=\"Scanning the repo for frameworks and PostHog SDKs...\" />\n </Box>\n <Box flexDirection=\"column\">\n {activity.length === 0 ? (\n <Text dimColor>{' '}Starting up the detection agent…</Text>\n ) : (\n activity.map((line, i) => (\n <Text\n key={`${i}-${line}`}\n dimColor={i < activity.length - 1}\n color={i === activity.length - 1 ? Colors.primary : undefined}\n >\n {' '}\n {Icons.triangleSmallRight} {line}\n </Text>\n ))\n )}\n </Box>\n </Box>\n );\n }\n\n if (state.kind === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginY={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Detection failed\n </Text>\n <Text dimColor>{state.message}</Text>\n </Box>\n <PickerMenu\n options={[{ label: 'Exit', value: EXIT }]}\n onSelect={() => store.requestExit(1)}\n />\n </Box>\n );\n }\n\n const { report } = state;\n const instrumentable = report.projects.filter((p) => p.instrumentable);\n const unsupported = report.projects.length - instrumentable.length;\n\n if (instrumentable.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Nothing to set up here\n </Text>\n <Text dimColor>\n None of the {report.projects.length} projects found uses a framework\n the wizard can set up error tracking for.\n </Text>\n </Box>\n <PickerMenu\n options={[{ label: 'Exit', value: EXIT }]}\n onSelect={() => store.requestExit(0)}\n />\n </Box>\n );\n }\n\n const options = [\n ...instrumentable.map((p) => ({\n label: projectLabel(p),\n value: p.path,\n })),\n { label: 'Cancel', value: EXIT },\n ];\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n {Icons.check} Found{' '}\n {report.repoType === 'monorepo' ? 'a monorepo' : 'your project'}\n </Text>\n </Box>\n\n <PickerMenu\n message=\"Which project would you like to set up error tracking for?\"\n options={options}\n onSelect={(value) => {\n const path = Array.isArray(value) ? value[0] : value;\n if (path === EXIT) {\n store.requestExit(0);\n return;\n }\n const chosen = instrumentable.find((p) => p.path === path);\n if (!chosen?.integration) return;\n store.setFrameworkContext(\n ERROR_TRACKING_PROJECT_PATH_KEY,\n chosen.path,\n );\n store.setFrameworkConfig(\n chosen.integration,\n FRAMEWORK_REGISTRY[chosen.integration],\n );\n }}\n />\n\n {unsupported > 0 && (\n <Box marginTop={1}>\n <Text dimColor>\n (… {unsupported} other project{unsupported === 1 ? '' : 's'} not\n supported)\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n","/** The error-tracking TUI: its flow, deck, tips and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { ERROR_TRACKING_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { getTips } from './deck/tips.js';\nimport { ErrorTrackingScreenId } from './screen-ids.js';\nimport { ErrorTrackingIntroScreen } from './screens/ErrorTrackingIntroScreen.js';\nimport { ErrorTrackingDetectScreen } from './screens/ErrorTrackingDetectScreen.js';\n\nexport { ErrorTrackingScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'error-tracking': {\n flow: ERROR_TRACKING_FLOW,\n deck: getContentBlocks,\n tips: getTips,\n screens: {\n [ErrorTrackingScreenId.Intro]: (store) => (\n <ErrorTrackingIntroScreen store={store} />\n ),\n [ErrorTrackingScreenId.Detect]: (store) => (\n <ErrorTrackingDetectScreen store={store} />\n ),\n },\n },\n};\n","/**\n * Error tracking source maps upload program step list.\n *\n * Flow: a static intro (no detection yet) → login → an agentic detect+pick\n * screen that scans the repo on Haiku and lets the user choose a project →\n * agent run → outro. Detection runs after auth because the detection agent\n * needs credentials.\n */\n\nimport type { FlowStep } from '@tui/flow';\nimport type { TuiView } from '@tui/tui-state';\nimport { RunPhase } from '@shared/run-state';\nimport { SOURCE_MAPS_CONTEXT_KEYS } from '@programs/error-tracking-upload-source-maps';\n\nfunction projectSelected({ session }: TuiView): boolean {\n return (\n session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.selectedVariant] != null\n );\n}\n\nexport const ERROR_TRACKING_UPLOAD_SOURCE_MAPS_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'source-maps-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'detect',\n label: 'Detecting projects',\n // The Haiku agent scans the repo, surfaces an instrumentable / not-yet map,\n // and the user picks the project to wire up. Advances once a project is\n // chosen (its variant is written to frameworkContext). The gate lets the\n // agent runner park after auth until the pick lands, so the run prompt sees\n // the chosen variant.\n screenId: 'source-maps-detect',\n isComplete: projectSelected,\n gate: projectSelected,\n },\n {\n id: 'run',\n label: 'Upload source maps',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'source-maps-outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screenId: 'keep-skills',\n },\n];\n","/** Source-maps learn-deck: the shared source-maps narrative, worded for the upload program. */\n\nimport type { WizardStore } from '@tui/store';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { buildSourceMapsDeck } from '@tui/programs/shared/deck/source-maps';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] =>\n buildSourceMapsDeck(store, {\n intro: \"I'm wiring PostHog Error Tracking into your build.\",\n wiring:\n \"Right now I'm hooking source-map generation and upload into your build, tied to each release you ship.\",\n });\n","/**\n * SourceMapsIntroScreen — Welcome screen for the source-maps upload flow.\n *\n * Static intro: detection now runs after login (on the source-maps-detect\n * screen), so this screen no longer shows a detected platform. Continue takes\n * the user straight to authentication.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\n\ntype View = 'default' | 'more-info';\n\ninterface SourceMapsIntroScreenProps {\n store: WizardStore;\n}\n\nexport const SourceMapsIntroScreen = ({\n store,\n}: SourceMapsIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [view, setView] = useState<View>('default');\n\n const { session } = store;\n\n const body =\n view === 'more-info' ? (\n <Box flexDirection=\"column\" width={56} flexShrink={0}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>.\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The{' '}\n <Text italic color=\"cyan\">\n {store.programLabel}\n </Text>{' '}\n program sets up your project to upload source maps to PostHog, so\n Error Tracking shows production stack traces in your original source\n instead of minified bundles. It will:\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={4}>\n <Text>{'•'} Detect the framework(s) in your repo</Text>\n <Text>{'•'} Download the relevant docs for your stack</Text>\n <Text>{'•'} Wire map generation + upload into your build</Text>\n <Text>{'•'} Wire CI for deploys and offer a local test run</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Maps upload to PostHog during the production build and never need to\n be served publicly.\n </Text>\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" width={60}>\n <Text>\n The Wizard will run an agent to detect your project's framework(s),\n download the relevant docs, and implement source-map uploads for you.\n </Text>\n <Box marginTop={1}>\n <Text>Ready?</Text>\n </Box>\n </Box>\n );\n\n // No privacy row here: IntroScreenLayout appends it to every intro menu.\n const menuOptions =\n view === 'more-info'\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const title = 'PostHog Wizard 🦔';\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n title={title}\n showSubtitle={view === 'default'}\n body={body}\n showDetection={view === 'default'}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={(value) => {\n if (value === 'cancel') {\n store.requestExit(0);\n } else if (value === 'more-info') {\n setView('more-info');\n } else if (value === 'back') {\n setView('default');\n } else {\n store.completeSetup();\n }\n }}\n />\n );\n};\n","/**\n * SourceMapsDetectScreen — runs the Haiku detection agent over the repo, shows\n * streaming progress, then renders a structured map of which projects can have\n * source-map upload wired up and which cannot. The user picks one project; the\n * choice is written to frameworkContext and the run step instruments it.\n *\n * Runs after auth — the detection agent needs credentials.\n */\n\nimport { scanProgress } from '@tui/agent-progress';\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { LoadingBox, PickerMenu } from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\nimport {\n SOURCE_MAPS_CONTEXT_KEYS,\n VARIANT_DISPLAY_NAME,\n MANUAL_SDK_VARIANTS,\n} from '@programs/error-tracking-upload-source-maps';\nimport {\n detectSourceMapsProjects,\n type DetectedProject,\n type DetectionReport,\n} from '@programs/error-tracking-upload-source-maps';\n\ninterface SourceMapsDetectScreenProps {\n store: WizardStore;\n}\n\ntype DetectState =\n | { kind: 'loading' }\n | { kind: 'ready'; report: DetectionReport }\n | { kind: 'error'; message: string };\n\nconst EXIT = '__exit';\nconst MAX_ACTIVITY_LINES = 8;\n\nfunction projectLabel(p: DetectedProject): string {\n const name = p.variant ? VARIANT_DISPLAY_NAME[p.variant] : p.framework;\n const where = p.path === '.' ? 'repo root' : p.path;\n return `${name} ${Icons.bullet} ${where}`;\n}\n\nexport const SourceMapsDetectScreen = ({\n store,\n}: SourceMapsDetectScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { credentials } = store.session;\n const accessToken = credentials?.accessToken;\n\n const [state, setState] = useState<DetectState>({ kind: 'loading' });\n const [activity, setActivity] = useState<string[]>([]);\n const started = useRef(false);\n\n useEffect(() => {\n if (!accessToken || started.current) return;\n started.current = true;\n let cancelled = false;\n void (async () => {\n try {\n const report = await detectSourceMapsProjects(\n store.session,\n (line) => {\n if (!cancelled) {\n setActivity((prev) => [...prev, line].slice(-MAX_ACTIVITY_LINES));\n }\n },\n scanProgress(store),\n );\n if (!cancelled) setState({ kind: 'ready', report });\n } catch (err) {\n if (!cancelled) {\n setState({\n kind: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [accessToken, store]);\n\n if (!credentials) {\n return <LoadingBox message=\"Waiting for authentication...\" />;\n }\n\n if (state.kind === 'loading') {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Detecting your project...\n </Text>\n <Box marginY={1}>\n <LoadingBox message=\"Scanning the repo for frameworks and PostHog SDKs...\" />\n </Box>\n <Box flexDirection=\"column\">\n {activity.length === 0 ? (\n <Text dimColor>{' '}Starting up the detection agent…</Text>\n ) : (\n activity.map((line, i) => (\n <Text\n key={`${i}-${line}`}\n dimColor={i < activity.length - 1}\n color={i === activity.length - 1 ? Colors.primary : undefined}\n >\n {' '}\n {Icons.triangleSmallRight} {line}\n </Text>\n ))\n )}\n </Box>\n </Box>\n );\n }\n\n if (state.kind === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginY={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Detection failed\n </Text>\n <Text dimColor>{state.message}</Text>\n </Box>\n <PickerMenu\n options={[{ label: 'Exit', value: EXIT }]}\n onSelect={() => store.requestExit(1)}\n />\n </Box>\n );\n }\n\n const { report } = state;\n const instrumentable = report.projects.filter((p) => p.instrumentable);\n const blocked = report.projects.filter((p) => !p.instrumentable);\n\n if (instrumentable.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Nothing to instrument yet\n </Text>\n <Text dimColor>\n None of the {report.projects.length} projects found can have\n source-map upload set up.\n </Text>\n </Box>\n <BlockedSummary blocked={blocked} />\n <Box marginTop={1}>\n <PickerMenu\n options={[{ label: 'Exit', value: EXIT }]}\n onSelect={() => store.requestExit(0)}\n />\n </Box>\n </Box>\n );\n }\n\n const options = [\n ...instrumentable.map((p) => ({\n label: projectLabel(p),\n value: p.path,\n })),\n { label: 'Cancel', value: EXIT },\n ];\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n {Icons.check} Found{' '}\n {report.repoType === 'monorepo' ? 'a monorepo' : 'your project'}\n </Text>\n </Box>\n\n <PickerMenu\n message=\"Which project would you like to set up source map uploads for?\"\n options={options}\n onSelect={(value) => {\n const path = Array.isArray(value) ? value[0] : value;\n if (path === EXIT) {\n store.requestExit(0);\n return;\n }\n const chosen = instrumentable.find((p) => p.path === path);\n if (!chosen || !chosen.variant) return;\n store.setFrameworkContext(\n SOURCE_MAPS_CONTEXT_KEYS.selectedVariant,\n chosen.variant,\n );\n store.setFrameworkContext(\n SOURCE_MAPS_CONTEXT_KEYS.selectedDisplayName,\n VARIANT_DISPLAY_NAME[chosen.variant],\n );\n store.setFrameworkContext(\n SOURCE_MAPS_CONTEXT_KEYS.selectedPath,\n chosen.path,\n );\n }}\n />\n\n <Box marginTop={1}>\n <BlockedSummary blocked={blocked} />\n </Box>\n </Box>\n );\n};\n\n/**\n * Collapses the non-instrumentable projects into a short count line (or two)\n * instead of listing every one — a monorepo can have dozens.\n */\nconst BlockedSummary = ({ blocked }: { blocked: DetectedProject[] }) => {\n const unsupported = blocked.filter((p) => p.variant == null).length;\n // The wizard can't install the Go/Rust SDKs, so their missing-SDK\n // remediation is a manual install, not `npx @posthog/wizard`.\n const manualSdk = blocked.filter(\n (p) => p.variant != null && MANUAL_SDK_VARIANTS.includes(p.variant),\n ).length;\n const missingSdk = blocked.length - unsupported - manualSdk;\n if (blocked.length === 0) return null;\n return (\n <Box flexDirection=\"column\">\n {unsupported > 0 && (\n <Text dimColor>\n (… {unsupported} other project{unsupported === 1 ? '' : 's'} not\n supported)\n </Text>\n )}\n {missingSdk > 0 && (\n <Text dimColor>\n (… {missingSdk} supported but missing the PostHog SDK — install it\n first with `npx @posthog/wizard`)\n </Text>\n )}\n {manualSdk > 0 && (\n <Text dimColor>\n (… {manualSdk} supported but missing the PostHog SDK — add it to the\n project first (posthog-go / posthog-rs), then re-run)\n </Text>\n )}\n </Box>\n );\n};\n","/**\n * SourceMapsOutroScreen — post-run summary for the source-maps upload flow.\n *\n * Unlike the generic OutroScreen, this spells out the operational facts a user\n * needs to actually get de-minified stack traces: that packages were installed\n * and upload credentials written to .env, plus the three gotchas (builds\n * upload, run the build, give CI the same credentials). All static guidance —\n * driven only by the program's `buildOutroData` (kind / message / report /\n * docs), no per-run data.\n */\n\nimport { join } from 'node:path';\nimport type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { OutroKind } from '@shared/outro';\nimport { Colors } from '@tui/styles';\nimport { useDismissOnAnyKey } from '@tui/hooks/useDismissOnAnyKey';\n\ninterface SourceMapsOutroScreenProps {\n store: WizardStore;\n}\n\nexport const SourceMapsOutroScreen = ({\n store,\n}: SourceMapsOutroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n useDismissOnAnyKey(() => store.setOutroDismissed());\n\n const outroData = store.session.outroData;\n\n if (!outroData) {\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text dimColor>Finishing up...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {outroData.kind === OutroKind.Success && (\n <Box flexDirection=\"column\">\n <Text color={Colors.success} bold>\n ✔ {outroData.message || 'Source maps wired up!'}\n </Text>\n\n <Section title=\"What the wizard did\">\n <Text>• Installed the packages needed for source map upload.</Text>\n <Text>\n • Wrote the PostHog upload credentials to your{' '}\n <Text bold>.env</Text> file.\n </Text>\n </Section>\n\n <Section title=\"How uploads work now\">\n <Text>\n • Every <Text bold>build</Text> now uploads source maps to PostHog\n automatically — no extra command to remember.\n </Text>\n <Text>\n • Run your app from the <Text bold>built output</Text>. Source\n maps only resolve for errors thrown by the build that was\n uploaded.\n </Text>\n <Text>\n • In <Text bold>CI</Text>, the build job needs the same upload\n credentials. If the wizard wired your pipeline, add the referenced\n secrets to your CI provider (e.g. GitHub repo secrets) before your\n next deploy.\n </Text>\n </Section>\n\n {outroData.reportFile && (\n <Box marginTop={1}>\n <Text>\n Details in{' '}\n <Text bold>\n {join(store.session.installDir, outroData.reportFile)}\n </Text>\n </Text>\n </Box>\n )}\n\n {outroData.docsUrl && (\n <Box marginTop={1}>\n <Text>\n Learn more:{' '}\n <Text color={Colors.primary}>{outroData.docsUrl}</Text>\n </Text>\n </Box>\n )}\n\n <Box marginTop={1}>\n <Text dimColor>\n Note: This wizard uses an LLM agent to analyze and modify your\n project. Please review the changes made.\n </Text>\n </Box>\n <Text dimColor>\n How did this work for you? Drop us a line: wizard@posthog.com\n </Text>\n </Box>\n )}\n\n {outroData.kind === OutroKind.Error && (\n <Box flexDirection=\"column\">\n <Text color={Colors.error} bold>\n ✘ {outroData.message || 'An error occurred'}\n </Text>\n {outroData.body && (\n <Box marginTop={1}>\n <Text dimColor>{outroData.body}</Text>\n </Box>\n )}\n {outroData.docsUrl && (\n <Box marginTop={1}>\n <Text>\n Docs: <Text color={Colors.primary}>{outroData.docsUrl}</Text>\n </Text>\n </Box>\n )}\n </Box>\n )}\n\n {outroData.kind === OutroKind.Cancel && (\n <Text color=\"yellow\">■ {outroData.message || 'Cancelled'}</Text>\n )}\n\n <Box marginTop={1}>\n <Text color={Colors.muted}>Press any key to continue</Text>\n </Box>\n </Box>\n );\n};\n\nconst Section = ({\n title,\n children,\n}: {\n title: string;\n children: ReactNode;\n}) => (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={Colors.primary} bold>\n {title}:\n </Text>\n {children}\n </Box>\n);\n","/** The source-maps upload TUI: its flow, deck and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { ERROR_TRACKING_UPLOAD_SOURCE_MAPS_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { SourceMapsScreenId } from './screen-ids.js';\nimport { SourceMapsIntroScreen } from './screens/SourceMapsIntroScreen.js';\nimport { SourceMapsDetectScreen } from './screens/SourceMapsDetectScreen.js';\nimport { SourceMapsOutroScreen } from './screens/SourceMapsOutroScreen.js';\n\nexport { SourceMapsScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'error-tracking-upload-source-maps': {\n flow: ERROR_TRACKING_UPLOAD_SOURCE_MAPS_FLOW,\n deck: getContentBlocks,\n screens: {\n [SourceMapsScreenId.Intro]: (store) => (\n <SourceMapsIntroScreen store={store} />\n ),\n [SourceMapsScreenId.Detect]: (store) => (\n <SourceMapsDetectScreen store={store} />\n ),\n [SourceMapsScreenId.Outro]: (store) => (\n <SourceMapsOutroScreen store={store} />\n ),\n },\n },\n};\n","import { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { WizardStore } from '@tui/store';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@tui/components/StatusPeekTrigger';\n\nconst GATED_CODE: ContentBlock = {\n type: 'lines',\n interval: 400,\n pause: 7000,\n lines: [\n <Text> </Text>,\n <Text dimColor>{'example — a flag around new code'}</Text>,\n <Text>\n <Text color=\"cyan\">{'if'}</Text>\n <Text>{\" (flags.isEnabled('new-checkout')) {\"}</Text>\n </Text>,\n <Text>{' showNewCheckout()'}</Text>,\n <Text>{'}'}</Text>,\n ],\n};\n\nconst GRADUAL_ROLLOUT: ContentBlock = {\n type: 'lines',\n interval: 700,\n pause: 7000,\n lines: [\n <Text> </Text>,\n <Text dimColor>{'example — new-checkout rollout'}</Text>,\n <Text>\n <Text color={Colors.accent}>{'▓'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n <Text>{' 5% internal team'}</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{'▓▓▓▓▓'}</Text>\n <Text dimColor>{'░░░░░'}</Text>\n <Text>{' 50% half of users'}</Text>\n </Text>,\n <Text>\n <Text color={Colors.success}>{'▓▓▓▓▓▓▓▓▓▓'}</Text>\n <Text>{' 100% everyone'}</Text>\n </Text>,\n ],\n};\n\nconst RUN_PLAN: ContentBlock = {\n type: 'lines',\n interval: 600,\n pause: 8000,\n lines: [\n <Text>\n <Text color=\"cyan\">{'1 '}</Text>\n <Text>{'Create example flags, off at 0%'}</Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{'2 '}</Text>\n <Text>{'Evaluate the backend flag on the server'}</Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{'3 '}</Text>\n <Text>{'Evaluate the frontend flag in the UI'}</Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{'4 '}</Text>\n <Text>{'Publish a report to a PostHog notebook'}</Text>\n </Text>,\n ],\n};\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => [\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: \"It's setting up feature flags for this project.\",\n pause: 5000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content:\n 'A feature flag is a switch in your code that you flip from PostHog, with no deploy.',\n pause: 6000,\n },\n GATED_CODE,\n {\n content: 'Ship new code turned off, then turn it on when you are ready.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1500 },\n\n { content: 'Roll out gradually instead of all at once:', pause: 2500 },\n GRADUAL_ROLLOUT,\n {\n content:\n 'Target who sees it: your team, a beta cohort, a plan, or a country.',\n pause: 6000,\n },\n {\n content:\n 'Something breaks? Turn the flag off in seconds. No rollback, no redeploy.',\n pause: 7000,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content:\n 'Each evaluation is reported to PostHog, so you can see who got which value.',\n pause: 6500,\n },\n {\n content:\n 'The same flags run experiments: split users between variants and measure the result.',\n pause: 7000,\n },\n\n { type: 'clear', pause: 1500 },\n\n { content: \"Here's what it's doing now:\", pause: 2000 },\n RUN_PLAN,\n {\n content: 'Each side gets a flag only when your app has code there.',\n pause: 6000,\n },\n];\n","import type { Tip } from '@tui/components/TipsCard';\n\nexport const FEATURE_FLAGS_TIPS: Tip[] = [\n {\n id: 'payloads',\n title: 'Ship settings, not just on and off',\n description:\n 'Attach a JSON payload to a flag to change copy, limits, or config without a deploy.',\n },\n {\n id: 'local-evaluation',\n title: 'Check flags without a network call',\n description:\n 'Server SDKs can download your flag definitions and evaluate them locally, so a check adds no round trip.',\n },\n {\n id: 'experiments',\n title: 'Turn a flag into an experiment',\n description:\n 'Give a flag variants and PostHog measures which one wins on the metrics you pick.',\n },\n];\n\nexport const getTips = (): Tip[] => FEATURE_FLAGS_TIPS;\n","import { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport {\n FEATURE_FLAGS_STEP_SKILL_ID,\n FEATURE_FLAGS_UNSUPPORTED,\n} from '@programs/feature-flags';\nimport { LoadingBox } from '@tui/primitives/index';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface FeatureFlagsIntroScreenProps {\n store: WizardStore;\n}\n\nconst CANCEL_ONLY_MENU = [{ label: 'Cancel', value: 'cancel' }];\n\nexport const FeatureFlagsIntroScreen = ({\n store,\n}: FeatureFlagsIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n const { session } = store;\n const { skillEntry, fetchFailed } = useSkillEntry(\n FEATURE_FLAGS_STEP_SKILL_ID,\n );\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56}>\n <Box marginBottom={1}>\n <Text>\n The Wizard is an agent, it's here to help you set up PostHog. Its code\n is open source:{' '}\n <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n\n <Box marginBottom={1}>\n <Text>\n Feature flags let you ship code turned off, roll it out to a\n percentage of users or a chosen group, and switch it off in seconds\n without a deploy. The same flags run your experiments.\n </Text>\n </Box>\n\n <Text>\n The{' '}\n <Text color=\"cyan\" italic>\n feature-flags\n </Text>{' '}\n program creates example flags in PostHog, off at 0% rollout: one for\n your backend and one for your frontend, for each side your app has. It\n installs and initializes the PostHog SDKs if needed, evaluates each flag\n once in your code, and writes a report on how to turn them on.\n </Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={FEATURE_FLAGS_STEP_SKILL_ID}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>\n Let's add your first feature flag, so you can ship safely and control\n rollouts.\n </Text>\n </Box>\n );\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const menuActions: Record<string, () => void> = {\n cancel: () => store.requestExit(0),\n 'more-info': () => setShowingMoreInfo(true),\n back: () => setShowingMoreInfo(false),\n continue: () => store.completeSetup(),\n };\n\n const selectMenuAction = (value: string) => menuActions[value]?.();\n const blockedBody = bodyThatBlocksContinue(session);\n\n if (blockedBody) {\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={blockedBody}\n showDetection={false}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={CANCEL_ONLY_MENU}\n onSelect={selectMenuAction}\n />\n );\n }\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={selectMenuAction}\n />\n );\n};\n\nfunction bodyThatBlocksContinue(\n session: WizardStore['session'],\n): ReactNode | null {\n if (!session.detectionComplete) return DETECTING_FRAMEWORK_BODY;\n if (session.integration === null) return UNDETECTED_FRAMEWORK_BODY;\n if (FEATURE_FLAGS_UNSUPPORTED.has(session.integration)) {\n return UNSUPPORTED_FRAMEWORK_BODY;\n }\n if (!session.unsupportedVersion) return null;\n const { current, minimum, docsUrl } = session.unsupportedVersion;\n return (\n <Box flexDirection=\"column\" alignItems=\"center\" width={64}>\n <Text color=\"#DC9300\">\n Version {current} is not supported by the wizard. Please upgrade to{' '}\n {minimum} or later.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>Manual setup guide: {docsUrl}</Text>\n </Box>\n </Box>\n );\n}\n\nconst DETECTING_FRAMEWORK_BODY: ReactNode = (\n <Box marginY={1}>\n <LoadingBox message=\"Detecting project framework...\" />\n </Box>\n);\n\nconst UNDETECTED_FRAMEWORK_BODY: ReactNode = (\n <Box flexDirection=\"column\" alignItems=\"center\" width={64}>\n <Text>Could not detect your project's framework.</Text>\n <Box marginTop={1}>\n <Text dimColor>\n The feature-flags program needs a supported framework. Run the wizard\n from your app's root directory.\n </Text>\n </Box>\n </Box>\n);\n\nconst UNSUPPORTED_FRAMEWORK_BODY: ReactNode = (\n <Box flexDirection=\"column\" alignItems=\"center\" width={64}>\n <Text>The wizard cannot set up feature flags for this framework yet.</Text>\n <Box marginTop={1}>\n <Text dimColor>\n Manual setup guide: https://posthog.com/docs/feature-flags\n </Text>\n </Box>\n </Box>\n);\n","/** The feature-flags TUI: the skill flow, deck and tips behind its own intro. */\nimport type { FlowStep } from '@tui/flow';\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { AGENT_SKILL_STEPS } from '@tui/programs/shared/skill-flow';\nimport { getContentBlocks } from './deck/index.js';\nimport { getTips } from './deck/tips.js';\nimport { FeatureFlagsScreenId } from './screen-ids.js';\nimport { FeatureFlagsIntroScreen } from './screens/FeatureFlagsIntroScreen.js';\n\nexport { FeatureFlagsScreenId } from './screen-ids.js';\n\nconst FEATURE_FLAGS_FLOW: FlowStep[] = AGENT_SKILL_STEPS.map((step) =>\n step.id === 'intro'\n ? { ...step, screenId: FeatureFlagsScreenId.Intro }\n : step,\n);\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'feature-flags': {\n flow: FEATURE_FLAGS_FLOW,\n deck: getContentBlocks,\n tips: getTips,\n screens: {\n [FeatureFlagsScreenId.Intro]: (store) => (\n <FeatureFlagsIntroScreen store={store} />\n ),\n },\n },\n};\n","import { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\n\ninterface MetricsIntroScreenProps {\n store: WizardStore;\n}\n\nexport const MetricsIntroScreen = ({ store }: MetricsIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n const { session } = store;\n // metrics picks its skill variant at run time (python, nodejs, javascript,\n // kubernetes, other), so there's no pre-seeded skillId here. Fall back to\n // the group id for the \"more info\" lookup.\n const skillId = session.skillId ?? 'metrics';\n const { skillEntry, fetchFailed } = useSkillEntry(skillId);\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56}>\n <Box marginBottom={1}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n </Box>\n\n <Text>\n The{' '}\n <Text color=\"cyan\" italic>\n metrics\n </Text>{' '}\n program instruments your service with PostHog application metrics —\n counters, gauges, and histograms via{' '}\n <Text color=\"cyan\">posthog.metrics</Text> — at operational choke points:\n request middleware, background jobs, external calls, and business commit\n sites. Supports Python, Node.js, web JavaScript, Kubernetes, and any\n other language via OTLP.\n </Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>\n Let's instrument your service with PostHog application metrics.\n </Text>\n </Box>\n );\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n const handleSelect = (value: string) => {\n if (value === 'cancel') store.requestExit(0);\n else if (value === 'more-info') setShowingMoreInfo(true);\n else if (value === 'back') setShowingMoreInfo(false);\n else store.completeSetup();\n };\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={handleSelect}\n />\n );\n};\n","/** The metrics TUI: the skill flow and deck behind its own intro. */\nimport type { FlowStep } from '@tui/flow';\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { AGENT_SKILL_STEPS } from '@tui/programs/shared/skill-flow';\nimport { getContentBlocks } from '@tui/programs/shared/skill-deck';\nimport { MetricsScreenId } from './screen-ids.js';\nimport { MetricsIntroScreen } from './screens/MetricsIntroScreen.js';\n\nexport { MetricsScreenId } from './screen-ids.js';\n\nconst METRICS_FLOW: FlowStep[] = AGENT_SKILL_STEPS.map((step) =>\n step.id === 'intro' ? { ...step, screenId: MetricsScreenId.Intro } : step,\n);\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n metrics: {\n flow: METRICS_FLOW,\n deck: getContentBlocks,\n screens: {\n [MetricsScreenId.Intro]: (store) => <MetricsIntroScreen store={store} />,\n },\n },\n};\n","import type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\n\nexport const MIGRATION_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'migration-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Migration',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * PRODUCT_SUITE_BLOCK — Two-column listing of PostHog products.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const PRODUCT_SUITE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 1000,\n pause: 15000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Error Tracking'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Web Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Feature Flags '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Pipelines'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Experiments '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Warehouse'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'AI Observability '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Surveys'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Workflows '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Tours '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Support'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Revenue Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Endpoints'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Customer Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'PostHog Desktop'}\n </Text>,\n ],\n};\n","/**\n * LINE_CHART_BLOCK — ASCII trends chart illustrating an insight.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const LINE_CHART_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 6000,\n lines: [\n <Text bold>{' Trends · user signups (monthly)'}</Text>,\n <Text> </Text>,\n // 10k\n <Text>\n <Text color=\"gray\">{' 10k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──'}</Text>\n <Text dimColor>{' 9,575'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n // 7.5k\n <Text>\n <Text color=\"gray\">{' 7.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n // 5k\n <Text>\n <Text color=\"gray\">{' 5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──╯'}</Text>\n </Text>,\n // 2.5k\n <Text>\n <Text color=\"gray\">{' 2.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭───╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──────╯'}</Text>\n </Text>,\n // 0\n <Text>\n <Text color=\"gray\">{' 0 ┤'}</Text>\n <Text color=\"cyan\">{'──────╯'}</Text>\n </Text>,\n // X-axis\n <Text color=\"gray\">{' └┬─────┬─────┬─────┬─────┬──'}</Text>,\n <Text dimColor>{' May Aug Nov Feb May'}</Text>,\n ],\n};\n","/**\n * FUNNEL_BLOCK — ASCII funnel illustrating step conversion.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const FUNNEL_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 200,\n pause: 8000,\n lines: [\n <Text bold>{' Funnel · ride conversion'}</Text>,\n <Text> </Text>,\n // Step 1\n <Text>\n {' '}\n <Text bold>1</Text>\n {' app_launched'}\n {' '}\n <Text bold color=\"green\">\n 100.00%\n </Text>\n </Text>,\n <Text color=\"cyan\">{' ██████████████████████████████'}</Text>,\n <Text dimColor>{' → 1,200 users'}</Text>,\n <Text> </Text>,\n // Step 2\n <Text>\n {' '}\n <Text bold>2</Text>\n {' ride_requested'}\n {' '}\n <Text dimColor>{'avg 2m 30s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 72.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 864 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 336 (28%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 3\n <Text>\n {' '}\n <Text bold>3</Text>\n {' ride_accepted'}\n {' '}\n <Text dimColor>{'avg 5m 12s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 51.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 612 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 252 (29%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 4\n <Text>\n {' '}\n <Text bold>4</Text>\n {' ride_started'}\n {' '}\n <Text dimColor>{'avg 1m 45s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 38.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'█████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 456 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 156 (25%)'}</Text>\n </Text>,\n ],\n};\n","/**\n * Vendor cost stack — the multi-tool baseline a typical migration target has\n * before consolidating onto PostHog. Numbers from each vendor's published\n * starter pricing.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const VENDOR_STACK_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 600,\n pause: 9000,\n lines: [\n <Text bold>{' Typical pre-migration stack'}</Text>,\n <Text> </Text>,\n <Text>\n <Text color=\"gray\">{' Sentry'}</Text>\n <Text>{' error tracking '}</Text>\n <Text color=\"red\">{'$26/mo+'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' LaunchDarkly'}</Text>\n <Text>{' feature flags '}</Text>\n <Text color=\"red\">{'$8.33/mo+'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' Amplitude'}</Text>\n <Text>{' product analytics '}</Text>\n <Text color=\"red\">{'$49/mo+'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' Braintrust'}</Text>\n <Text>{' AI observability '}</Text>\n <Text color=\"red\">{'$50/mo+'}</Text>\n </Text>,\n <Text color=\"gray\">{' ─────────────────────────────────────'}</Text>,\n <Text>\n <Text>{' Total'}</Text>\n <Text>{' '}</Text>\n <Text bold color=\"red\">\n {'$133/mo+'}\n </Text>\n </Text>,\n <Text dimColor>{' plus ~450KB of JavaScript SDKs'}</Text>,\n ],\n};\n","/**\n * PostHog free-tier highlights — the numbers a migrating team gets back when\n * they consolidate. Sourced from posthog.com/pricing.md.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const FREE_TIER_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 400,\n pause: 9000,\n lines: [\n <Text bold>{' Free every month, on every product'}</Text>,\n <Text> </Text>,\n <Text>\n <Text color={Colors.accent}>{' 1,000,000 '}</Text>\n <Text>events </Text>\n <Text dimColor>product analytics</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 1,000,000 '}</Text>\n <Text>requests </Text>\n <Text dimColor>feature flags + experiments</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 5,000 '}</Text>\n <Text>recordings </Text>\n <Text dimColor>session replay</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 100,000 '}</Text>\n <Text>exceptions </Text>\n <Text dimColor>error tracking</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 100,000 '}</Text>\n <Text>events </Text>\n <Text dimColor>AI observability</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 50 GB '}</Text>\n <Text>logs </Text>\n <Text dimColor>logs</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 1,500 '}</Text>\n <Text>responses </Text>\n <Text dimColor>surveys</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' 1,000,000 '}</Text>\n <Text>rows </Text>\n <Text dimColor>data warehouse</Text>\n </Text>,\n ],\n};\n","/**\n * Pricing structure block — what happens after the free tier.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const PRICING_STRUCTURE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n lines: [\n <Text bold>{' After the free tier'}</Text>,\n <Text> </Text>,\n <Text>\n <Text color={Colors.accent}>{' $0 '}</Text>\n <Text>base price · pay only for what you use</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' ◆ '}</Text>\n <Text>per-event prices decrease with volume</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' ◆ '}</Text>\n <Text>no per-seat charges — your whole team is included</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' ◆ '}</Text>\n <Text>web analytics bundled with product analytics</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' ◆ '}</Text>\n <Text>experiments bundled with feature flags</Text>\n </Text>,\n <Text>\n <Text color={Colors.accent}>{' ◆ '}</Text>\n <Text>revenue analytics bundled with data warehouse</Text>\n </Text>,\n ],\n};\n","/**\n * Migration learn deck (statsig variant). Statsig is the only `migrate`\n * variant today, so this deck plays as-is when the wizard runs\n * `migrate --product=statsig`. Three movements:\n *\n * 1. Welcome and reassure.\n * 2. What to expect — the migration is replacement-only, takes a few\n * minutes, leaves the build green.\n * 3. What's a little different — how flags and experiments work in\n * PostHog, presented as right-way guidance rather than gotchas.\n *\n * FF/experiments guidance paraphrased from PostHog public docs:\n * - posthog.com/docs/feature-flags/best-practices\n * - posthog.com/docs/feature-flags/common-questions\n * - posthog.com/docs/experiments/best-practices\n */\n\nimport { Text } from 'ink';\nimport type { WizardStore } from '@tui/store';\nimport { Colors } from '@tui/styles';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@tui/components/StatusPeekTrigger';\nimport { PRODUCT_SUITE_BLOCK } from '@tui/programs/shared/deck/product-suite';\nimport { LINE_CHART_BLOCK } from '@tui/programs/shared/deck/line-chart';\nimport { FUNNEL_BLOCK } from '@tui/programs/shared/deck/funnel';\nimport { VENDOR_STACK_BLOCK } from './vendor-stack.js';\nimport { FREE_TIER_BLOCK } from './free-tier.js';\nimport { PRICING_STRUCTURE_BLOCK } from './pricing-structure.js';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => [\n // ── Welcome ────────────────────────────────────────────────────────────\n {\n content: 'Hello.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content:\n 'As we speak, it’s making a plan to migrate from Statsig to PostHog.',\n pause: 6000,\n },\n\n {\n content: 'PostHog covers the cost of running this agent.',\n pause: 4000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n persist: true,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n // ── What to expect ─────────────────────────────────────────────────────\n { content: 'Here’s what to expect.', pause: 3000 },\n\n { content: 'The migration takes about ten minutes.', pause: 3000 },\n\n {\n content:\n 'Every Statsig call gets replaced in place with its PostHog equivalent.',\n pause: 5500,\n },\n\n {\n content:\n 'Nothing new gets added. No extra captures, no surprise instrumentation.',\n pause: 5500,\n },\n\n {\n content:\n 'The Statsig package gets removed at the end. We’ll run build and lint to clean up after ourselves.',\n pause: 6500,\n },\n\n { type: 'clear', pause: 2000 },\n\n // ── What's a little different ─────────────────────────────────────────\n {\n content: 'A few things work a little differently in PostHog.',\n pause: 4500,\n },\n\n {\n content: (\n <Text>\n Flags evaluate against a stable user. Call{' '}\n <Text bold color={Colors.accent}>\n identify()\n </Text>{' '}\n first, then check the flag.\n </Text>\n ),\n pause: 6000,\n persist: true,\n },\n\n {\n content:\n 'For anything in the first paint, evaluate server-side and bootstrap the values into the client.',\n pause: 6500,\n },\n\n {\n content: (\n <Text>\n In production, route requests through a reverse proxy to avoid ad\n blockers breaking your flags.{'\\n'}\n <Text dimColor>https://posthog.com/docs/advanced/proxy</Text>\n </Text>\n ),\n pause: 6500,\n persist: true,\n },\n\n {\n content:\n 'When a flag reaches 100% rollout, retire it. Flags are signals, not switches.',\n pause: 5500,\n },\n\n {\n content: (\n <Text>\n Name flags descriptively. No double negatives. Reflect the return type.{' '}\n <Text dimColor>For example </Text>\n <Text bold>show-new-checkout</Text>\n <Text dimColor>.</Text>\n </Text>\n ),\n pause: 6500,\n persist: true,\n },\n\n { type: 'clear', pause: 1500 },\n\n // ── Experiments ────────────────────────────────────────────────────────\n {\n content: (\n <Text bold color={Colors.accent}>\n Experiments\n </Text>\n ),\n pause: 2500,\n persist: true,\n },\n\n {\n content:\n 'Change one thing per variant. Multiple changes in one variant blur the result.',\n pause: 5500,\n },\n\n {\n content:\n 'Decide the running time up front. PostHog includes a sample-size and duration calculator in the setup flow.',\n pause: 6500,\n },\n\n {\n content: 'Roll out to 5–10% first. Watch the metrics. Then increase.',\n pause: 5000,\n },\n\n {\n content:\n 'Exclude users who already completed the flow. They can’t be affected by the test.',\n pause: 5500,\n },\n\n { type: 'clear', pause: 1500 },\n\n // ── Close ──────────────────────────────────────────────────────────────\n {\n content: 'Flags and experiments live alongside the rest of your data.',\n pause: 4500,\n },\n\n {\n content: 'Ship behind a flag, watch replays, check analytics for impact.',\n pause: 4500,\n },\n\n { type: 'clear', pause: 1500 },\n\n {\n content:\n 'PostHog also provides every other analytics and AI tool to build your product.',\n pause: 4500,\n },\n\n PRODUCT_SUITE_BLOCK,\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'And consolidating onto one platform saves real money.',\n pause: 4500,\n },\n\n { content: 'Here’s the math.', pause: 1500 },\n\n VENDOR_STACK_BLOCK,\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'Pricing is usage-based, with a generous free tier.',\n pause: 4000,\n },\n\n FREE_TIER_BLOCK,\n\n { type: 'clear', pause: 1500 },\n\n PRICING_STRUCTURE_BLOCK,\n\n { type: 'clear', pause: 1500 },\n\n {\n content: 'Gain clarity and really understand your users.',\n pause: 4000,\n },\n\n { content: 'Use trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Use funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n];\n","import { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\n\ninterface MigrationIntroScreenProps {\n store: WizardStore;\n}\n\nexport const MigrationIntroScreen = ({ store }: MigrationIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { session } = store;\n\n const body = (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>Let's migrate this project to PostHog.</Text>\n </Box>\n );\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n body={body}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={[\n { label: 'Continue', value: 'continue' },\n { label: 'Cancel', value: 'cancel' },\n ]}\n onSelect={(value) => {\n if (value === 'cancel') {\n store.requestExit(0);\n } else {\n store.completeSetup();\n }\n }}\n />\n );\n};\n","/** The migration TUI: its flow, deck and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { MIGRATION_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { MigrationScreenId } from './screen-ids.js';\nimport { MigrationIntroScreen } from './screens/MigrationIntroScreen.js';\n\nexport { MigrationScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n migration: {\n flow: MIGRATION_FLOW,\n deck: getContentBlocks,\n screens: {\n [MigrationScreenId.Intro]: (store) => (\n <MigrationIntroScreen store={store} />\n ),\n },\n },\n};\n","/**\n * PostHog integration program — the default wizard flow.\n *\n * Steps define their own gate predicates and onInit callbacks.\n * The store derives gate promises and fires init work from these\n * definitions — no hardcoded per-flow logic in the store.\n */\n\nimport type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\nimport type { WizardSession } from '@programs/types';\n\nfunction needsSetup(session: WizardSession): boolean {\n const config = session.frameworkConfig;\n if (!config?.metadata.setup?.questions) return false;\n\n return config.metadata.setup.questions.some(\n (q: { key: string }) => !(q.key in session.frameworkContext),\n );\n}\n\nexport const POSTHOG_INTEGRATION_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'intro',\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'setup',\n label: 'Setup',\n screenId: 'setup',\n show: ({ session }) => needsSetup(session),\n isComplete: ({ session }) => !needsSetup(session),\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Integration',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'mcp',\n label: 'MCP servers',\n screenId: 'mcp',\n isComplete: (tui) => tui.mcpComplete,\n },\n {\n id: 'keep-skills',\n label: 'Keep Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * POSTHOG_DATA_FLOW — ASCII diagram of the PostHog event ingestion flow.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const POSTHOG_DATA_FLOW: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n // Box is 30 chars wide between │ borders.\n // Labels: 1-char indent. Arrows: \" ↓ \" (5). Sub-items: \" │ \" (7).\n lines: [\n <Text color=\"gray\">{' ┌──────────────────────────────┐'}</Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"cyan\">\n Your App\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text>posthog.capture()</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom events</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom properties</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>person profiles</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text dimColor>groups</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog SDK\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>HTTP</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog Cloud\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>query + visualize</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"green\">\n Dashboards & Insights\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text color=\"gray\">{' └──────────────────────────────┘'}</Text>,\n ],\n};\n","/**\n * Integration learn-deck — the narrative script played while the agent\n * runs the PostHog integration flow. Weaves typewriter lines, pauses,\n * `clear` markers, and the diagram blocks into one sequence.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { WizardStore } from '@tui/store';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@tui/components/StatusPeekTrigger';\nimport { POSTHOG_DATA_FLOW } from './data-flow.js';\nimport { PRODUCT_SUITE_BLOCK } from '@tui/programs/shared/deck/product-suite';\nimport { LINE_CHART_BLOCK } from '@tui/programs/shared/deck/line-chart';\nimport { FUNNEL_BLOCK } from '@tui/programs/shared/deck/funnel';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => [\n {\n // Name comes from the login profile; falls back when absent (CI keys).\n content: store?.session.apiUser?.first_name\n ? `Welcome, ${store.session.apiUser.first_name}.`\n : 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: 'It handles the entire PostHog setup process on your behalf.',\n pause: 5000,\n },\n\n {\n content:\n \"As we speak, it's building a plan to set up PostHog in your project.\",\n pause: 6000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'It takes about eight minutes.',\n pause: 2000,\n },\n\n {\n content: 'So grab some coffee ☕️.',\n pause: 2000,\n },\n\n {\n content: 'Or stick around and learn about PostHog.',\n pause: 5000,\n },\n\n { type: 'clear', pause: 3000 },\n\n {\n content: 'Events are the foundation of the PostHog platform.',\n pause: 4000,\n },\n\n {\n content:\n 'Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.',\n pause: 6000,\n },\n\n {\n content: 'Events are sent to PostHog and joined with other product data.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1000 },\n\n { content: \"Here's the flow.\", pause: 1000 },\n\n POSTHOG_DATA_FLOW,\n\n { type: 'clear', pause: 2000 },\n\n {\n content:\n 'With enough event data, you can answer powerful questions about your product.',\n pause: 4000,\n },\n\n { content: 'And create insights.', pause: 4000 },\n\n { type: 'clear', pause: 500 },\n\n { content: 'Like trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Or funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n\n { type: 'clear', pause: 1000 },\n\n {\n content: 'Use those signals to decide what to build next.',\n pause: 4000,\n },\n\n { content: 'PostHog has all the dev tools you need.', pause: 3000 },\n\n PRODUCT_SUITE_BLOCK,\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'The wizard is wiring up your PostHog stack with...',\n pause: 2500,\n },\n\n {\n type: 'lines',\n interval: 1000,\n pause: 12000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Web Analytics'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Error Tracking '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'AI Observability '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Data Warehouse sources'}\n </Text>,\n ],\n },\n];\n","/**\n * The sharing choice a program intro offers on its privacy view. Every program\n * that scans the codebase (`scansCodebase`) shows the same rows, so consent\n * reads and behaves the same wherever it is asked.\n */\n\nimport { ScanConsent } from '@shared/run-state';\nimport type { PickerOption } from '@tui/primitives/index';\nimport type { WizardStore } from '@tui/store';\nimport { Icons } from '@tui/styles';\n\n/**\n * A blank, unselectable row. Navigation skips disabled options, so this is a\n * margin the menu can hold rather than one the layout has to special-case.\n */\nconst MENU_SPACER: PickerOption<string> = {\n label: '',\n value: 'spacer',\n disabled: true,\n};\n\n/**\n * The sharing choice, as two explicit rows rather than one toggle. A toggle\n * label has to describe either the current state or the next action, and a\n * reader cannot tell which; two rows with the filled diamond on the live one\n * say both at once. The trailing spacer separates them from the Back that\n * IntroScreenLayout appends, since leaving the screen is a different kind of\n * act from changing something on it.\n */\nexport function sharingOptions(sharing: boolean): PickerOption<string>[] {\n const mark = (on: boolean) => ({\n glyph: on ? Icons.diamond : Icons.diamondOpen,\n });\n return [\n { label: 'Share tools', value: 'share', icon: mark(sharing) },\n { label: \"Don't share tools\", value: 'no-share', icon: mark(!sharing) },\n MENU_SPACER,\n ];\n}\n\ntype SharingStore = Pick<\n WizardStore,\n 'session' | 'grantSharing' | 'declineSharing'\n>;\n\n/** Sharing is on by default, so only an explicit decline turns it off. */\nexport function isSharing(store: SharingStore): boolean {\n return store.session.scanConsent !== ScanConsent.Declined;\n}\n\n/** Apply a sharing row the user picked. Returns false for any other value. */\nexport function applySharingChoice(\n store: SharingStore,\n value: string,\n): boolean {\n if (value === 'share') store.grantSharing();\n else if (value === 'no-share') store.declineSharing();\n else return false;\n return true;\n}\n\n/** Continue with no choice made means sharing, the default. A choice already made stands. */\nexport function resolveSharingOnContinue(store: SharingStore): void {\n if (store.session.scanConsent === ScanConsent.Undecided) store.grantSharing();\n}\n","import { getCommandPath, getSubcommandPrograms } from '@programs';\nimport { getTool } from '@tools';\nimport type { PickerOption } from '@tui/primitives/index';\n\nexport type IntroMenuView = 'default' | 'more-info' | 'commands';\n\nexport const CONTINUE_LABEL = 'Continue';\nexport const CONTINUE_ANYWAY_LABEL = 'Continue anyway';\n\nexport const DEFAULT_HEADLINE = \"Let's do two hours of work in eight minutes.\";\nexport const DETECTED_HEADLINE = [\n 'It looks like PostHog is already installed. The Wizard has many tricks ' +\n 'up its sleeve, like auditing, uploading source maps, or making your ' +\n 'product self-drive.',\n 'You can still rerun the installation, but it might overwrite some of your work.',\n];\n\nexport function introHeadline(posthogSdkDetected: boolean): string[] {\n return posthogSdkDetected ? DETECTED_HEADLINE : [DEFAULT_HEADLINE];\n}\n\n/** What the spell book offers, in order: programs and tools. Curated: no config field ranks these. */\nconst INTRO_ENTRIES = [\n 'self-driving',\n 'error-tracking-upload-source-maps',\n 'warehouse-source',\n 'audit',\n 'posthog-doctor',\n 'mcp-analytics',\n 'replay-vision',\n 'ai-observability',\n 'metrics',\n 'revenue-analytics-setup',\n];\n\n/** One spell book row: the id the intro hands off to, the words that run it, and its help line. */\nexport type IntroEntry = { id: string; command: string; description: string };\n\n/** The programs and tools the intro can hand off to, in the order it lists them. */\nexport function introEntries(): IntroEntry[] {\n const programs = new Map(getSubcommandPrograms().map((c) => [c.id, c]));\n return INTRO_ENTRIES.flatMap((id) => {\n const entry = programs.get(id) ?? getTool(id);\n return entry\n ? [{ id, command: getCommandPath(entry), description: entry.description }]\n : [];\n });\n}\n\nexport function introMenuOptions({\n view,\n showContinue,\n posthogSdkDetected,\n}: {\n view: IntroMenuView;\n showContinue: boolean;\n posthogSdkDetected: boolean;\n}): PickerOption<string>[] | null {\n // Its body is a picker, and a second menu here would move both cursors.\n if (view === 'commands') return null;\n\n if (view === 'more-info') {\n return [{ label: 'Back', value: 'back' }];\n }\n\n if (showContinue) {\n return [\n ...(posthogSdkDetected\n ? [{ label: 'Explore spell book', value: 'commands' }]\n : []),\n {\n label: posthogSdkDetected ? CONTINUE_ANYWAY_LABEL : CONTINUE_LABEL,\n value: 'continue',\n },\n { label: 'Change framework', value: 'framework' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n }\n\n return null;\n}\n","/**\n * PostHogIntegrationIntroScreen — Intro screen for the core PostHog integration.\n *\n * Composes IntroScreenLayout with framework-detection-specific state:\n * 1. Detecting: spinner while detection runs\n * 2. Detection failed: framework picker\n * 3. Unsupported version: upgrade prompt\n * 4. Detection succeeded: continue/change-framework/cancel\n */\n\nimport { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { Integration } from '@shared/constants';\nimport { PickerMenu, LoadingBox } from '@tui/primitives/index';\nimport {\n IntroScreenLayout,\n type DetectionRow,\n} from '@tui/screens/IntroScreenLayout';\nimport { SkillSourceInfo, useSkillEntry } from '@tui/screens/SkillSourceInfo';\nimport { KeyMatch, useKeyBindings } from '@tui/hooks/useKeyBindings';\nimport { analytics } from '@utils/analytics';\nimport { PRIVACY_PANEL_LABEL } from '@tui/components/PrivacyPanel';\nimport {\n applySharingChoice,\n isSharing,\n resolveSharingOnContinue,\n sharingOptions,\n} from '@tui/components/sharing-options';\nimport type { IntroMenuView } from '@tui/programs/posthog-integration/intro-menu';\nimport {\n introEntries,\n introHeadline,\n introMenuOptions,\n} from '@tui/programs/posthog-integration/intro-menu';\n\n/**\n * Replaces IntroScreenLayout's DEFAULT_SUBTITLE for this screen only. The\n * shared default (\".env* file contents will not leave your machine\") is true\n * of values and false of variable names, which this screen reads and reports.\n * Two lines carry the fact and name the screen that holds the detail, so the\n * disclosure reaches people who never open it.\n */\nconst SUBTITLE = (\n <>\n <Text dimColor>\n We'll use AI to analyze your project and complete work.\n </Text>\n <Text dimColor>Review what data is shared in \"{PRIVACY_PANEL_LABEL}.\"</Text>\n <Text dimColor>.env* values stay on your machine.</Text>\n </>\n);\n\n/** Framework picker shown when auto-detection fails. */\nconst FrameworkPicker = ({\n store,\n onComplete,\n}: {\n store: WizardStore;\n onComplete?: () => void;\n}) => {\n const options = Object.values(Integration).map((value) => ({\n label: value,\n value,\n }));\n\n return (\n <PickerMenu<Integration>\n centered\n columns={2}\n message=\"Select your framework\"\n options={options}\n onSelect={(value) => {\n const integration = Array.isArray(value) ? value[0] : value;\n void import('@programs').then(({ FRAMEWORK_REGISTRY }) => {\n const config = FRAMEWORK_REGISTRY[integration];\n store.setFrameworkConfig(integration, config);\n store.setDetectedFramework(config.metadata.name);\n onComplete?.();\n });\n }}\n />\n );\n};\n\ninterface PostHogIntegrationIntroScreenProps {\n store: WizardStore;\n}\n\nexport const PostHogIntegrationIntroScreen = ({\n store,\n}: PostHogIntegrationIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [pickingFramework, setPickingFramework] = useState(false);\n const [manuallySelected, setManuallySelected] = useState(false);\n const [view, setView] = useState<IntroMenuView>('default');\n\n const { session } = store;\n const sharing = isSharing(store);\n const config = session.frameworkConfig;\n const frameworkLabel =\n session.detectedFrameworkLabel ?? config?.metadata.name;\n const { skillEntry, fetchFailed } = useSkillEntry(session.skillId);\n const detecting = !session.detectionComplete;\n const needsFrameworkPick =\n session.detectionComplete && !session.frameworkConfig;\n const unsupported = session.unsupportedVersion;\n const showContinue =\n session.frameworkConfig !== null &&\n !detecting &&\n !pickingFramework &&\n view === 'default' &&\n !unsupported;\n\n // The only view with no menu to carry a Back row, so Esc is its way out.\n useKeyBindings(\n 'posthog-integration-intro',\n view === 'commands'\n ? [\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: 'back',\n handler: () => setView('default'),\n },\n ]\n : [],\n );\n\n // ── Title ──────────────────────────────────────────────────────────\n\n const title = detecting ? 'PostHog Wizard starting up' : 'PostHog Wizard 🦔';\n\n // ── Description ────────────────────────────────────────────────────\n\n let body: ReactNode = null;\n\n if (detecting) {\n body = (\n <Box marginY={1}>\n <LoadingBox message=\"Detecting project framework...\" />\n </Box>\n );\n } else if (needsFrameworkPick && !pickingFramework) {\n body = (\n <>\n <Box marginY={1}>\n <Text dimColor>Could not auto-detect your framework.</Text>\n </Box>\n <FrameworkPicker\n store={store}\n onComplete={() => setPickingFramework(false)}\n />\n </>\n );\n } else if (pickingFramework) {\n body = (\n <FrameworkPicker\n store={store}\n onComplete={() => setPickingFramework(false)}\n />\n );\n } else if (view === 'more-info') {\n body = (\n <Box flexDirection=\"column\" width={64} flexShrink={0}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The{' '}\n <Text italic color=\"cyan\">\n {store.programLabel}\n </Text>{' '}\n program installs the PostHog SDKs, instruments event tracking, and\n integrates the following dev tools for your application:\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={4}>\n <Text>{`•`} Product Analytics</Text>\n <Text>{`•`} Web Analytics</Text>\n <Text>{`•`} Session Replay</Text>\n <Text>{`•`} Error Tracking</Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>If you prefer your own AI setup, download the skill:</Text>\n <Box marginTop={1}>\n <SkillSourceInfo\n skillId={session.skillId}\n skillEntry={skillEntry}\n fetchFailed={fetchFailed}\n />\n </Box>\n </Box>\n </Box>\n );\n } else if (view === 'commands') {\n body = (\n <PickerMenu\n message=\"The Wizard can do more than integrate with your project:\"\n options={introEntries().map((entry) => ({\n label: `${entry.command.padEnd(21)}${entry.description}`,\n value: entry.id,\n }))}\n onSelect={(value) => {\n const id = Array.isArray(value) ? value[0] : value;\n analytics.wizardCapture('intro menu selected', { value: id, view });\n store.switchProgram(id);\n }}\n />\n );\n } else if (showContinue) {\n const paragraphs = introHeadline(session.posthogSdkDetected);\n body = (\n <Box\n flexDirection=\"column\"\n width={64}\n flexShrink={0}\n // A wrapped block reads as ragged centered; one line always centered.\n alignItems={paragraphs.length > 1 ? undefined : 'center'}\n >\n {paragraphs.map((paragraph, i) => (\n <Box key={paragraph} marginTop={i === 0 ? 0 : 1}>\n <Text>{paragraph}</Text>\n </Box>\n ))}\n </Box>\n );\n }\n\n // ── Detection rows ─────────────────────────────────────────────────\n\n const detectionRows: DetectionRow[] = [];\n if (frameworkLabel) {\n const suffixParts: string[] = [];\n if (!manuallySelected) suffixParts.push('(detected)');\n // Dead path today — every framework went GA. Kept for re-activation\n // when the next beta framework lands (set `beta: true` on its config).\n if (config?.metadata.beta) suffixParts.push('[BETA]');\n\n detectionRows.push({\n label: 'Framework',\n value: frameworkLabel,\n suffix: suffixParts.join(' ') || undefined,\n });\n }\n\n if (session.posthogSdkDetected) {\n detectionRows.push({\n label: 'PostHog',\n value: 'detected in package.json',\n });\n }\n\n // ── Children (between rows and menu) ───────────────────────────────\n\n let bodyChildren: ReactNode = null;\n\n if (config?.metadata.preRunNotice) {\n bodyChildren = <Text color=\"yellow\">{config.metadata.preRunNotice}</Text>;\n }\n\n if (unsupported) {\n bodyChildren = (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"#DC9300\">\n Version {unsupported.current} is not supported by the wizard. Please\n upgrade to {unsupported.minimum} or later.\n </Text>\n <Text dimColor>Manual setup guide: {unsupported.docsUrl}</Text>\n <Box marginTop={1}>\n <Text dimColor>\n Did we get this wrong? You can also select another framework.\n </Text>\n </Box>\n <PickerMenu\n options={[\n { label: 'Select another framework', value: 'framework' },\n { label: 'Exit', value: 'exit' },\n ]}\n onSelect={(value) => {\n const choice = Array.isArray(value) ? value[0] : value;\n if (choice === 'framework') {\n setPickingFramework(true);\n setManuallySelected(true);\n } else {\n store.requestExit(0);\n }\n }}\n />\n </Box>\n );\n }\n\n // ── Menu ───────────────────────────────────────────────────────────\n\n const menuOptions = introMenuOptions({\n view,\n showContinue,\n posthogSdkDetected: session.posthogSdkDetected,\n });\n\n const handleSelect = (value: string) => {\n analytics.wizardCapture('intro menu selected', { value, view });\n if (value === 'cancel') {\n store.requestExit(0);\n } else if (value === 'framework') {\n setPickingFramework(true);\n setManuallySelected(true);\n } else if (value === 'more-info') {\n setView('more-info');\n } else if (value === 'commands') {\n setView('commands');\n } else if (value === 'back') {\n setView('default');\n } else if (applySharingChoice(store, value)) {\n return;\n } else if (value === 'continue') {\n resolveSharingOnContinue(store);\n store.completeSetup();\n }\n };\n\n // ── Render ─────────────────────────────────────────────────────────\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n title={title}\n showSubtitle={view === 'default'}\n subtitle={SUBTITLE}\n body={body}\n showDetection={showContinue}\n detectionRows={detectionRows}\n menuOptions={unsupported ? null : menuOptions}\n menuAlign=\"center\"\n // The one program whose disclosure view can be acted on.\n privacyOptions={sharingOptions(sharing)}\n onSelect={handleSelect}\n programLabel={store.programLabel}\n skillId={session.skillId}\n >\n {bodyChildren}\n </IntroScreenLayout>\n );\n};\n","/** The integration program's TUI: its flow, deck and intro. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { POSTHOG_INTEGRATION_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { PostHogIntegrationScreenId } from './screen-ids.js';\nimport { PostHogIntegrationIntroScreen } from './screens/PostHogIntegrationIntroScreen.js';\n\nexport { PostHogIntegrationScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'posthog-integration': {\n flow: POSTHOG_INTEGRATION_FLOW,\n deck: getContentBlocks,\n screens: {\n [PostHogIntegrationScreenId.Intro]: (store) => (\n <PostHogIntegrationIntroScreen store={store} />\n ),\n },\n },\n};\n","/** Revenue analytics program step list. The skill install and agent run happen in `runProgram`. */\n\nimport type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\n\nexport const REVENUE_ANALYTICS_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'revenue-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Revenue analytics',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * RevenueIntroScreen — Welcome screen for the revenue analytics flow.\n *\n * Composes IntroScreenLayout with SDK-detection-specific state:\n * - Detection succeeded: shows detected PostHog + Stripe SDKs, continue/cancel\n * - Detection failed: shows the error via errorView + exit prompt\n *\n * Reads `frameworkContext.detectError` and `frameworkContext.detectedPosthogSdks`\n * / `detectedStripeSdks` set by detectRevenuePrerequisites().\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { PickerMenu } from '@tui/primitives/index';\nimport {\n IntroScreenLayout,\n type DetectionRow,\n} from '@tui/screens/IntroScreenLayout';\nimport {\n POSTHOG_SDKS,\n STRIPE_SDKS,\n type RevenueDetectError,\n} from '@programs/revenue-analytics';\n\ninterface RevenueIntroScreenProps {\n store: WizardStore;\n}\n\nexport const RevenueIntroScreen = ({ store }: RevenueIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n\n const { session } = store;\n const detectError = session.frameworkContext.detectError as\n | RevenueDetectError\n | undefined;\n const detectedPosthogSdks =\n (session.frameworkContext.detectedPosthogSdks as string[] | undefined) ??\n [];\n const detectedStripeSdks =\n (session.frameworkContext.detectedStripeSdks as string[] | undefined) ?? [];\n const detectedPackagePaths =\n (session.frameworkContext.detectedPackagePaths as string[] | undefined) ??\n [];\n\n // ── Detection rows ─────────────────────────────────────────────────\n\n const detectionRows: DetectionRow[] = [];\n if (detectedPosthogSdks.length > 0) {\n detectionRows.push({\n label: 'PostHog SDK',\n value: detectedPosthogSdks.join(', '),\n });\n }\n if (detectedStripeSdks.length > 0) {\n detectionRows.push({\n label: 'Stripe SDK',\n value: detectedStripeSdks.join(', '),\n });\n }\n\n // ── Body ────────────────────────────────────────────────────────────\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56} flexShrink={0}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>.\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The{' '}\n <Text italic color=\"cyan\">\n {store.programLabel}\n </Text>{' '}\n program links Stripe customers and purchases to PostHog product data\n and persons. It unlocks insights like:\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={4}>\n <Text>{'\\u2022'} Revenue per user</Text>\n <Text>{'\\u2022'} Lifetime value</Text>\n <Text>{'\\u2022'} MRR / churn tracking</Text>\n </Box>\n </Box>\n ) : (\n <>\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>Let's create revenue analytics with Stripe and PostHog.</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>Link purchases to product data.</Text>\n </Box>\n </Box>\n\n {detectedPackagePaths.length > 1 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text dimColor>Found in {detectedPackagePaths.length} packages:</Text>\n {detectedPackagePaths.map((p) => (\n <Text key={p} dimColor>\n {' '}\n {'\\u2022'} {p}\n </Text>\n ))}\n </Box>\n )}\n </>\n );\n\n // ── Error view ─────────────────────────────────────────────────────\n\n const errorView = detectError ? (\n <>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"red\" bold>\n {'\\u2718'} Cannot set up revenue analytics\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <DetectErrorBody error={detectError} />\n </Box>\n </Box>\n\n <PickerMenu\n options={[{ label: 'Exit', value: 'exit' }]}\n onSelect={() => store.requestExit(1)}\n />\n </>\n ) : undefined;\n\n // ── Menu ───────────────────────────────────────────────────────────\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n // ── Render ─────────────────────────────────────────────────────────\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n showSubtitle={!showingMoreInfo}\n body={body}\n showDetection={!showingMoreInfo}\n detectionRows={detectionRows}\n errorView={errorView}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n onSelect={(value) => {\n if (value === 'cancel') {\n store.requestExit(0);\n } else if (value === 'more-info') {\n setShowingMoreInfo(true);\n } else if (value === 'back') {\n setShowingMoreInfo(false);\n } else {\n store.completeSetup();\n }\n }}\n />\n );\n};\n\nconst DetectErrorBody = ({ error }: { error: RevenueDetectError }) => {\n switch (error.kind) {\n case 'bad-directory': {\n const reasonText = {\n missing: 'does not exist',\n 'not-dir': 'is not a directory',\n unreadable: 'could not be accessed',\n }[error.reason];\n return (\n <>\n <Text>This path {reasonText}:</Text>\n <Text dimColor>\n {' '}\n {error.path}\n </Text>\n </>\n );\n }\n\n case 'no-package-json':\n return (\n <>\n <Text>No package.json found in this directory.</Text>\n <Text dimColor>\n Revenue analytics currently supports Node.js / TypeScript projects.\n </Text>\n <Text dimColor>Run this command from your project root.</Text>\n </>\n );\n\n case 'no-sdks':\n return (\n <>\n <Text>\n Neither PostHog nor Stripe SDKs detected (scanned{' '}\n {error.scannedCount} package.json file\n {error.scannedCount === 1 ? '' : 's'}).\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text>Revenue analytics requires:</Text>\n <Text dimColor>\n {' \\u2022'} A PostHog SDK (\n {[...POSTHOG_SDKS].slice(0, 3).join(', ')}, …)\n </Text>\n <Text dimColor>\n {' \\u2022'} A Stripe SDK ({[...STRIPE_SDKS].join(', ')})\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Install Stripe and run <Text bold>npx @posthog/wizard</Text> to\n set up PostHog.\n </Text>\n </Box>\n </>\n );\n\n case 'missing-posthog':\n return (\n <>\n <Text>\n Found Stripe ({error.foundStripe.join(', ')}) but no PostHog SDK.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>\n Run <Text bold>npx @posthog/wizard</Text> first to set up the base\n PostHog integration.\n </Text>\n </Box>\n </>\n );\n\n case 'missing-stripe':\n return (\n <>\n <Text>\n Found PostHog ({error.foundPosthog.join(', ')}) but no Stripe SDK.\n </Text>\n <Text dimColor>\n Revenue analytics currently supports Stripe only.\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>Install one of:</Text>\n {[...STRIPE_SDKS].map((sdk) => (\n <Text key={sdk} dimColor>\n {' \\u2022'} {sdk}\n </Text>\n ))}\n </Box>\n </>\n );\n }\n};\n","/** The revenue-analytics TUI: its flow, deck and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { REVENUE_ANALYTICS_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { RevenueAnalyticsScreenId } from './screen-ids.js';\nimport { RevenueIntroScreen } from './screens/RevenueIntroScreen.js';\n\nexport { RevenueAnalyticsScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'revenue-analytics-setup': {\n flow: REVENUE_ANALYTICS_FLOW,\n deck: getContentBlocks,\n screens: {\n [RevenueAnalyticsScreenId.Intro]: (store) => (\n <RevenueIntroScreen store={store} />\n ),\n },\n },\n};\n","/**\n * Self-driving program step list.\n *\n * detect → intro → integration-check → health-check → auth → integrate-detect →\n * integrate-run → self-driving-handoff → self-driving-github → run → outro. A deterministic check in\n * `detect` decides whether PostHog is already in the project: found → the\n * integration screens are skipped and the integrate-run phase never shows; not\n * found → integration-check reports it and the only action sets up PostHog.\n * After auth, `integrate-detect` runs the Haiku detector and has the user pick\n * which project to set PostHog up in (a monorepo can have several);\n * `integrate-run` then runs the real integration program's agent (its own task\n * list) in that project. `self-driving-handoff` then bridges to Self-driving\n * (\"PostHog is installed — now set up Self-driving\"), then `self-driving-github`\n * gates on the GitHub App connection the run cannot proceed without. No keep-skills step: the setup skill is transient, so postRun removes it.\n */\n\nimport type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\nimport type { WizardSession } from '@programs/types';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\nimport { POSTHOG_PRESENT_KEY } from '@programs/self-driving';\n\n/** True once detection found PostHog already present in the project. */\nconst postHogPresent = (session: WizardSession): boolean =>\n session.frameworkContext[POSTHOG_PRESENT_KEY] === true;\n\nexport const SELF_DRIVING_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'self-driving-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n {\n // Shown only when PostHog wasn't detected and the decision is still open:\n // \"Set up PostHog first?\". On \"yes\" the integrate-run phase runs the\n // integration. When PostHog is already present (or `--integrate` pre-set\n // it), this is skipped. The gate lets run-wizard settle the decision —\n // resolved immediately when no question is needed.\n id: 'integration-check',\n label: 'Integration',\n screenId: 'self-driving-integration-check',\n show: (tui) => !postHogPresent(tui.session) && tui.integrate === null,\n isComplete: (tui) => postHogPresent(tui.session) || tui.integrate !== null,\n gate: (tui) => postHogPresent(tui.session) || tui.integrate !== null,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n // After auth, before the integration runs: the detector scans the repo and\n // the user picks which project to set PostHog up in — a single project or\n // the repo root is still a one-item confirm. The pick writes the framework +\n // path to the session. Shown only while integrating and undecided; complete\n // once a project is picked (the orchestrator waits on this live).\n id: 'integrate-detect',\n label: 'Detecting',\n screenId: 'self-driving-integration-detect',\n show: (tui) => tui.integrate === true && tui.session.integration == null,\n // Complete on a picked project OR \"continue with existing\"\n // (integrate=false); without the latter the orchestrator's waitUntil hangs.\n isComplete: (tui) =>\n tui.session.integration != null || tui.integrate === false,\n },\n {\n // The integration agent (its prompt, tools, task list) runs composed in\n // the picked project's dir; the program's `config.runSteps` owns that run.\n // Shown only when integrating. Completion is tracked via `completedRuns`,\n // separate from the Self-driving run's `runPhase`.\n id: 'integrate-run',\n label: 'Integration',\n screenId: 'run',\n show: (tui) => tui.integrate === true,\n isComplete: (tui) => tui.completedRuns.includes('integrate-run'),\n },\n {\n // Handoff after the integration run: \"PostHog is installed — now set up\n // Self-driving\". Only in the integrate path; the already-has-PostHog path\n // skips it. Complete once acknowledged (the orchestrator waits on this).\n id: 'self-driving-handoff',\n label: 'Ready',\n screenId: 'self-driving-handoff',\n show: (tui) => tui.integrate === true,\n isComplete: (tui) => tui.selfDrivingHandoffConfirmed,\n },\n {\n // Hard gate before the agent starts: Self-driving cannot research findings\n // or open fixes without repo access. Asking here rather than mid-run means\n // a user who steps away isn't read as declining, and a user who won't\n // connect hasn't paid for an agent start. Complete once GitHub is\n // connected, or once the user says they can't — which hides `run` below.\n id: 'self-driving-github',\n label: 'GitHub',\n screenId: 'self-driving-github',\n isComplete: (tui) => tui.githubConnected === true || tui.githubDeclined,\n gate: (tui) => tui.githubConnected === true || tui.githubDeclined,\n },\n {\n id: 'run',\n label: 'Self-driving',\n screenId: 'run',\n show: (tui) => !tui.githubDeclined,\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n];\n","/**\n * PIPELINE_BLOCK — ASCII diagram of the Self-driving loop: sources feed\n * scouts, scouts raise signals, signals group into reports, reports land\n * in the inbox, shipped fixes get measured, and misses loop back as new\n * signals. Kept under ~38 chars wide so it fits the LearnCard pane at an\n * 80-column terminal.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { ContentBlock } from '@tui/primitives/content-types';\n\nexport const PIPELINE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 8000,\n lines: [\n <Text>\n {' '}\n <Text bold color=\"cyan\">\n signal sources\n </Text>\n </Text>,\n <Text dimColor>{' errors · replays · support'}</Text>,\n <Text>\n <Text color=\"gray\">{' ↓ '}</Text>\n <Text bold color={Colors.accent}>\n scouts\n </Text>\n </Text>,\n <Text dimColor>{' watching on a schedule'}</Text>,\n <Text>\n <Text color=\"gray\">{' ↓ '}</Text>\n <Text bold color={Colors.accent}>\n signals\n </Text>\n </Text>,\n <Text dimColor>{' finding + evidence + action'}</Text>,\n <Text>\n <Text color=\"gray\">{' ↓ '}</Text>\n <Text bold color={Colors.accent}>\n reports\n </Text>\n </Text>,\n <Text dimColor>{' grouped and prioritized'}</Text>,\n <Text>\n <Text color=\"gray\">{' ↓ '}</Text>\n <Text bold color=\"green\">\n your inbox\n </Text>\n </Text>,\n <Text dimColor>{' investigate · tag · ship a PR'}</Text>,\n <Text>\n <Text color=\"gray\">{' ↓ '}</Text>\n <Text bold color={Colors.accent}>\n measured\n </Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ↺ '}</Text>\n <Text dimColor>didn't fix it? a new signal</Text>\n </Text>,\n ],\n};\n","import { NO_DEFAULT_LIMIT, PRICING_LONG } from '@programs/self-driving';\n/**\n * Self-driving learn-deck — the narrative script played while the agent\n * sets up Self-driving. Teaches the vocabulary ladder (signal source →\n * scout → signal → report → action → measured loop) before the agent's\n * questions use those nouns, and explains why GitHub is required before\n * the connect ask lands.\n *\n * One deck for every self-driving run. On the integrate path it plays\n * during the install run (the pane belongs to whichever run screen shows\n * first), so it doubles as the wait-time read.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { WizardStore } from '@tui/store';\nimport { TextRevealMode } from '@tui/primitives/TextBlock';\nimport type { ContentBlock } from '@tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@tui/components/StatusPeekTrigger';\nimport { PIPELINE_BLOCK } from './pipeline-diagram.js';\n\nconst CLEAR: ContentBlock = { type: 'clear', pause: 2000 };\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => {\n return [\n // Scene 1 — orient\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: \"It's setting up PostHog Self-driving for this project.\",\n pause: 5000,\n },\n\n {\n content: \"We'll occasionally need your input. Stick around.\",\n pause: 6000,\n },\n\n CLEAR,\n\n // Scene 2 — controls\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n CLEAR,\n\n // Scene 3 — platform story\n {\n content: 'Your PostHog tools all share one data layer.',\n pause: 4000,\n },\n\n {\n content:\n 'Analytics, replays, errors, flags: they all share the same users, mapped across every tool.',\n pause: 6000,\n },\n\n {\n content: 'Together, they show how people really use your product.',\n pause: 5000,\n },\n\n {\n content:\n \"Piecing that together used to be manual work. That's what Self-driving automates.\",\n pause: 6000,\n },\n\n CLEAR,\n\n // Scene 4 — the differentiator, and why GitHub\n {\n content:\n 'A coding agent sees your code, but not how your product is used.',\n pause: 5000,\n },\n\n { content: 'PostHog knows what your users actually do.', pause: 4000 },\n\n { content: 'Self-driving puts an agent in the loop.', pause: 5000 },\n\n {\n content:\n \"That's why setup will ask to connect GitHub: so Self-driving can access your code and your context, together.\",\n pause: 6000,\n },\n\n CLEAR,\n\n // Scene 5 — signal sources\n {\n content: 'Each PostHog tool you enable is a signal source.',\n pause: 4000,\n },\n\n {\n content:\n \"Errors, replays, support tickets, GitHub or Linear issues: they're all streams of product usage.\",\n pause: 6000,\n },\n\n CLEAR,\n\n // Scene 6 — scouts\n {\n content: 'Scouts are agents that watch those sources on a schedule.',\n pause: 5000,\n },\n\n {\n content:\n 'They look for anomalies and patterns: a spike in errors or a funnel quietly dropping.',\n pause: 6000,\n },\n\n { content: 'Setup tunes your scouts to fit your product.', pause: 4000 },\n\n CLEAR,\n\n // Scene 7 — signals and reports\n {\n content:\n \"When a scout finds something worth your attention, that's a signal.\",\n pause: 5000,\n },\n\n {\n content:\n 'Each signal carries the finding, the evidence, and a suggested action.',\n pause: 5000,\n },\n\n {\n content: 'Related signals group into reports, sorted by priority.',\n pause: 4000,\n },\n\n CLEAR,\n\n { content: \"Here's the whole loop.\", pause: 1000 },\n\n PIPELINE_BLOCK,\n\n CLEAR,\n\n // Scene 8 — payoff: the inbox\n { content: 'Reports land in your Self-driving inbox.', pause: 4000 },\n\n {\n content: 'Investigate with the agent, tag teammates, or kick off a PR.',\n pause: 6000,\n },\n\n {\n // No lead-in: PRICING_LONG already names the PR as what's charged, and the\n // pane only fits ~148 chars per beat.\n content: PRICING_LONG,\n pause: 5000,\n },\n\n {\n content: NO_DEFAULT_LIMIT,\n pause: 5000,\n },\n\n CLEAR,\n\n // Scene 9 — the loop kicker\n {\n content: 'And after the PR ships, PostHog measures the result.',\n pause: 5000,\n },\n\n { content: 'Did the fix actually address the pattern?', pause: 4000 },\n\n {\n content: 'If not, a new signal surfaces, and the loop keeps working.',\n pause: 6000,\n },\n\n CLEAR,\n\n // Scene 10 — surfaces + closer\n {\n content: 'Work with Self-driving wherever you already are:',\n pause: 2000,\n },\n\n {\n type: 'lines',\n interval: 800,\n pause: 6000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n <Text bold>Inbox</Text>\n <Text dimColor>{' the PostHog web app'}</Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n <Text bold>Slack</Text>\n <Text dimColor>{' tag @PostHog'}</Text>\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n <Text bold>MCP</Text>\n <Text dimColor>{' your agents and editors'}</Text>\n </Text>,\n ],\n },\n\n {\n content: 'Product usage data becomes real, shippable change.',\n pause: 5000,\n },\n\n { content: 'Your product drives itself.', pause: 10000 },\n ];\n};\n","import { NO_DEFAULT_LIMIT, PRICING_LONG } from '@programs/self-driving';\n\n/**\n * Sidebar tips for the self-driving run — short footnotes on the\n * vocabulary ladder (signal source → scout → signal → report → measured\n * loop). The learn deck (`./index.tsx`) carries the teaching; these stay\n * one to two lines each so the pane never overflows.\n *\n * Product knowledge lives here in the program, not in the generic\n * `TipsCard`. Wired onto the program's `getTips`.\n */\n\nimport type { Tip } from '@tui/components/TipsCard';\n\nexport const SELF_DRIVING_TIPS: Tip[] = [\n {\n id: 'signal-source',\n title: 'Signal source',\n description:\n 'A stream PostHog watches: errors, replays, support, GitHub or Linear issues.',\n },\n {\n id: 'scout',\n title: 'Scout',\n description:\n 'An agent on a schedule, watching your sources for anomalies and patterns. Your project gets up to 100 scout runs a day by default.',\n },\n {\n id: 'scanner',\n title: 'Scanner',\n description:\n 'Where a scout reads your data, a scanner watches session recordings — an LLM spotting what broke on screen. It spends Replay Vision quota, so it stays scoped to your key flows.',\n },\n {\n id: 'signal-report',\n title: 'Signal → report',\n description:\n 'One finding with evidence and a suggested action. Signals group into prioritized reports in your inbox.',\n },\n {\n id: 'the-loop',\n title: 'The loop',\n description:\n 'After a fix ships, PostHog measures the result. If the pattern persists, a new signal reopens the work.',\n },\n {\n id: 'pricing',\n title: 'What it costs',\n description: `${PRICING_LONG} ${NO_DEFAULT_LIMIT}`,\n },\n {\n id: 'work-anywhere',\n title: 'Work anywhere',\n description:\n 'Your inbox is in the PostHog app, Slack (tag @PostHog), and MCP. You can work from anywhere.',\n },\n];\n\nexport const getTips = (): Tip[] => SELF_DRIVING_TIPS;\n","/**\n * SelfDrivingIntroScreen — Welcome screen for the self-driving flow.\n *\n * Composes IntroScreenLayout with prerequisite-detection state:\n * - Detection succeeded: explains what Self-driving turns on, continue/cancel\n * - Detection failed: shows the error via errorView + exit prompt\n *\n * Reads `frameworkContext.detectError` set by\n * detectSelfDrivingPrerequisites().\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { PickerMenu } from '@tui/primitives/index';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport {\n applySharingChoice,\n isSharing,\n resolveSharingOnContinue,\n sharingOptions,\n} from '@tui/components/sharing-options';\nimport {\n NO_DEFAULT_LIMIT,\n PRICING_LONG,\n PRICING_SHORT,\n} from '@programs/self-driving';\nimport type { SelfDrivingDetectError } from '@programs/self-driving';\n\ninterface SelfDrivingIntroScreenProps {\n store: WizardStore;\n}\n\nexport const SelfDrivingIntroScreen = ({\n store,\n}: SelfDrivingIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n\n const { session } = store;\n const detectError = session.frameworkContext.detectError as\n | SelfDrivingDetectError\n | undefined;\n\n const subtitle = (\n <>\n <Text dimColor>\n We'll use AI to analyze your project and set up PostHog Self-driving.\n </Text>\n <Text dimColor>.env* file contents will not leave your machine.</Text>\n </>\n );\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56} flexShrink={0}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>.\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The{' '}\n <Text italic color=\"cyan\">\n {store.programLabel}\n </Text>{' '}\n program turns on PostHog Self-driving for this project:\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={4}>\n <Text>\n {'•'} Watches your signal sources: errors, replays, connected tools\n </Text>\n <Text>{'•'} Runs scouts – scheduled agents that scan for issues</Text>\n <Text>{'•'} Groups signals into prioritized reports in your inbox</Text>\n <Text>{'•'} Researches findings in your code via GitHub</Text>\n <Text>\n {'•'} Measures shipped fixes, and reopens the loop if the pattern\n persists\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>{PRICING_LONG}</Text>\n <Text>{NO_DEFAULT_LIMIT}</Text>\n </Box>\n </Box>\n ) : (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>Let's set up PostHog Self-driving.</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n PostHog watches how people really use your product, finds issues, and\n proposes fixes.\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1} alignItems=\"center\">\n <Text dimColor>\n An agent will connect GitHub, enable signal sources, and tune your\n scouts.\n </Text>\n <Text dimColor>\n About 10 minutes, with a few questions along the way.\n </Text>\n <Text dimColor>{PRICING_SHORT}</Text>\n </Box>\n </Box>\n );\n\n const errorView = detectError ? (\n <>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"red\" bold>\n {'✘'} Cannot set up PostHog Self-driving\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <DetectErrorBody error={detectError} />\n </Box>\n </Box>\n\n <PickerMenu\n options={[{ label: 'Exit', value: 'exit' }]}\n onSelect={() => store.requestExit(1)}\n />\n </>\n ) : undefined;\n\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n showSubtitle={!showingMoreInfo}\n subtitle={subtitle}\n body={body}\n showDetection={!showingMoreInfo}\n errorView={errorView}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n privacyOptions={sharingOptions(isSharing(store))}\n onSelect={(value) => {\n if (applySharingChoice(store, value)) return;\n if (value === 'cancel') {\n store.requestExit(0);\n } else if (value === 'more-info') {\n setShowingMoreInfo(true);\n } else if (value === 'back') {\n setShowingMoreInfo(false);\n } else {\n resolveSharingOnContinue(store);\n store.completeSetup();\n }\n }}\n />\n );\n};\n\nconst DetectErrorBody = ({ error }: { error: SelfDrivingDetectError }) => {\n switch (error.kind) {\n case 'bad-directory': {\n const reasonText = {\n missing: 'does not exist',\n 'not-dir': 'is not a directory',\n unreadable: 'could not be accessed',\n }[error.reason];\n return (\n <>\n <Text>This path {reasonText}:</Text>\n <Text dimColor>\n {' '}\n {error.path}\n </Text>\n </>\n );\n }\n\n default:\n // Defensive fallback so a future SelfDrivingDetectError kind still\n // renders something useful instead of a blank screen.\n return (\n <Text>\n Self-driving could not start in this directory. Try again, or reach\n out to wizard@posthog.com.\n </Text>\n );\n }\n};\n","/**\n * SelfDrivingIntegrationCheckScreen — shown only when detection found no\n * PostHog in the project. Self-driving needs a PostHog SDK, so we always\n * integrate first; but a project with no SDK is often a project with no PostHog\n * account either, so this screen first asks whether the user already has one:\n *\n * - \"Yes — log me in\" → setIntegrate(true); auth runs the OAuth login.\n * - \"No — create one for me\" → collect email + region, then\n * chooseProvisionAccount(): auth provisions a new\n * account (and emails a login link) instead.\n *\n * Both answers integrate the SDK; they only differ in how auth gets credentials.\n * Skipped entirely when PostHog is already present (or under `--integrate`,\n * which forces integration + the default OAuth login).\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { TextInput } from '@inkjs/ui';\nimport { useState, useSyncExternalStore } from 'react';\n\nimport type { WizardStore } from '@tui/store';\nimport type { CloudRegion } from '@utils/types';\nimport { PickerMenu } from '@tui/primitives/index';\nimport {\n PrivacyPanel,\n PRIVACY_PANEL_LABEL,\n} from '@tui/components/PrivacyPanel';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport { POSTHOG_PRIVACY_URL, POSTHOG_TERMS_URL } from '@shared/constants';\nimport { Colors } from '@tui/styles';\n\ninterface SelfDrivingIntegrationCheckScreenProps {\n store: WizardStore;\n}\n\n/** Multi-step screen state: pick account status → email → region. */\ntype Stage = 'ask' | 'email' | 'region';\n\nconst EMAIL_RE = /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/;\n\nexport const SelfDrivingIntegrationCheckScreen = ({\n store,\n}: SelfDrivingIntegrationCheckScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [stage, setStage] = useState<Stage>('ask');\n // Pre-fill from `--email` when it was passed; tracked across stages so\n // the region step can hand both to the store in one commit.\n const [email, setEmail] = useState(store.session.email ?? '');\n const [emailError, setEmailError] = useState<string | null>(null);\n const [showPrivacy, setShowPrivacy] = useState(false);\n\n useInput((input, key) => {\n // While the privacy overlay is open, only Esc closes it; the overlay's own\n // Back menu handles the rest.\n if (showPrivacy) {\n if (key.escape) setShowPrivacy(false);\n return;\n }\n\n // [I] opens the full privacy panel. Skipped on the email stage so the\n // keystroke reaches the text field instead.\n if ((input === 'i' || input === 'I') && stage !== 'email') {\n setShowPrivacy(true);\n return;\n }\n\n // Esc steps back toward the account question (the picker owns input on 'ask').\n if (key.escape && stage !== 'ask') {\n setEmailError(null);\n setStage(stage === 'region' ? 'email' : 'ask');\n }\n });\n\n if (showPrivacy) {\n return (\n <IntroScreenLayout\n installDir={store.session.installDir}\n title={PRIVACY_PANEL_LABEL}\n showSubtitle={false}\n showDetection={false}\n body={<PrivacyPanel />}\n showPrivacy={false}\n menuOptions={[{ label: 'Back', value: 'back' }]}\n menuAlign=\"left\"\n onSelect={() => setShowPrivacy(false)}\n />\n );\n }\n\n if (stage === 'region') {\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Where should we create your account?\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>\n We&apos;ll create your PostHog account for {email} in this region.\n </Text>\n </Box>\n <Box marginTop={1}>\n <PickerMenu\n message=\"Pick your cloud region\"\n options={[\n { label: 'US', value: 'us', hint: 'us.posthog.com' },\n { label: 'EU', value: 'eu', hint: 'eu.posthog.com' },\n ]}\n onSelect={(value) => {\n const region = (\n Array.isArray(value) ? value[0] : value\n ) as CloudRegion;\n store.chooseProvisionAccount(email.trim(), region);\n }}\n />\n </Box>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>By creating an account you agree to our terms.</Text>\n <Text dimColor>\n Terms: <Text color=\"cyan\">{POSTHOG_TERMS_URL}</Text>\n </Text>\n <Text dimColor>\n Privacy: <Text color=\"cyan\">{POSTHOG_PRIVACY_URL}</Text>\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n <Text color={Colors.accent}>[Esc]</Text> back{' · '}\n <Text color={Colors.accent}>[I]</Text> {PRIVACY_PANEL_LABEL}\n </Text>\n </Box>\n </Box>\n );\n }\n\n if (stage === 'email') {\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Create your PostHog account\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>\n We&apos;ll create your account and email you a login link. What\n email should we use?\n </Text>\n </Box>\n <Box marginTop={1} width=\"100%\">\n <TextInput\n placeholder=\"you@company.com\"\n defaultValue={email}\n onChange={setEmail}\n onSubmit={(value) => {\n const trimmed = value.trim();\n if (!EMAIL_RE.test(trimmed)) {\n setEmailError('Please enter a valid email address.');\n return;\n }\n setEmail(trimmed);\n setEmailError(null);\n setStage('region');\n }}\n />\n </Box>\n {emailError && (\n <Box marginTop={1}>\n <Text color=\"yellow\">{emailError}</Text>\n </Box>\n )}\n <Box marginTop={1}>\n <Text dimColor>\n <Text color={Colors.accent}>[Enter]</Text> continue{' · '}\n <Text color={Colors.accent}>[Esc]</Text> back\n </Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n No PostHog integration found\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>\n This will kick off an agent to explore your project and find existing\n PostHog integrations. Self-driving reads PostHog data, so we&apos;ll\n set that up first: it gives your signal sources something to watch. To\n do that we need to connect to PostHog — do you already have an\n account?\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <PickerMenu\n options={[\n {\n label: 'Yes, log me in',\n value: 'login',\n hint: 'opens PostHog to authorize',\n },\n {\n label: 'No, create one for me',\n value: 'provision',\n hint: \"we'll email you a login link\",\n },\n ]}\n onSelect={(value) => {\n const choice = Array.isArray(value) ? value[0] : value;\n if (choice === 'login') {\n store.setIntegrate(true);\n } else {\n setStage('email');\n }\n }}\n />\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>\n <Text color={Colors.accent}>[I]</Text> {PRIVACY_PANEL_LABEL}\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * SelfDrivingIntegrationDetectScreen — runs the Haiku detector over the repo,\n * streams progress, then renders a picker of projects. Two kinds are offered:\n * set-up-here (supported framework, no SDK yet; writes framework + path for\n * the integrate-run phase) and continue-with-existing (already has PostHog;\n * sets integrate=false and skips straight to Self-driving). On a detection\n * error, falls back to a manual framework picker.\n *\n * Runs after auth — the detector needs credentials.\n */\n\nimport { scanProgress } from '@tui/agent-progress';\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { LoadingBox, PickerMenu } from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\nimport { Integration } from '@shared/constants';\nimport { FRAMEWORK_REGISTRY } from '@programs';\nimport { SELF_DRIVING_INTEGRATE_PATH_KEY } from '@programs/self-driving';\nimport {\n detectSelfDrivingIntegrationProjects,\n type IntegrationProject,\n type IntegrationDetectionReport,\n} from '@programs/self-driving';\n\ninterface SelfDrivingIntegrationDetectScreenProps {\n store: WizardStore;\n}\n\ntype DetectState =\n | { kind: 'loading' }\n | { kind: 'ready'; report: IntegrationDetectionReport }\n | { kind: 'error'; message: string };\n\nconst CANCEL = '__cancel';\nconst MAX_ACTIVITY_LINES = 8;\n\nfunction projectLabel(p: IntegrationProject): string {\n const where = p.path === '.' ? 'repo root' : p.path;\n return `${p.framework} ${Icons.bullet} ${where}`;\n}\n\nexport const SelfDrivingIntegrationDetectScreen = ({\n store,\n}: SelfDrivingIntegrationDetectScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { credentials } = store.session;\n const accessToken = credentials?.accessToken;\n\n const [state, setState] = useState<DetectState>({ kind: 'loading' });\n const [activity, setActivity] = useState<string[]>([]);\n const started = useRef(false);\n\n // Commit a chosen project to integrate: framework + path → session. The run\n // phase reads both (path scopes the install dir to the sub-app).\n const choose = (p: IntegrationProject) => {\n if (!p.integration) return;\n store.setFrameworkContext(SELF_DRIVING_INTEGRATE_PATH_KEY, p.path);\n store.setFrameworkConfig(p.integration, FRAMEWORK_REGISTRY[p.integration]);\n };\n\n // PostHog already installed here: integrate=false completes integrate-detect\n // and drops the integrate-run / handoff steps from the walk.\n const continueWithExisting = (p: IntegrationProject) => {\n store.setFrameworkContext(SELF_DRIVING_INTEGRATE_PATH_KEY, p.path);\n store.setIntegrate(false, {\n via: 'existing-integration-detected',\n path: p.path,\n });\n };\n\n // Run the detector once, after auth.\n useEffect(() => {\n if (!accessToken || started.current) return;\n started.current = true;\n let cancelled = false;\n void (async () => {\n try {\n const report = await detectSelfDrivingIntegrationProjects(\n store.session,\n (line) => {\n if (!cancelled) {\n setActivity((prev) => [...prev, line].slice(-MAX_ACTIVITY_LINES));\n }\n },\n scanProgress(store),\n );\n if (!cancelled) setState({ kind: 'ready', report });\n } catch (err) {\n if (!cancelled) {\n setState({\n kind: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [accessToken, store]);\n\n if (!credentials) {\n return <LoadingBox message=\"Waiting for authentication...\" />;\n }\n\n if (state.kind === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Detection failed\n </Text>\n <Text dimColor>{state.message}</Text>\n <Text dimColor>\n Pick your framework and we&apos;ll set PostHog up here.\n </Text>\n </Box>\n <PickerMenu<Integration>\n centered\n columns={2}\n message=\"Select your framework\"\n options={Object.values(Integration).map((v) => ({\n label: v,\n value: v,\n }))}\n onSelect={(value) => {\n const integration = Array.isArray(value) ? value[0] : value;\n store.setFrameworkContext(SELF_DRIVING_INTEGRATE_PATH_KEY, '.');\n store.setFrameworkConfig(\n integration,\n FRAMEWORK_REGISTRY[integration],\n );\n }}\n />\n </Box>\n );\n }\n\n if (state.kind === 'loading') {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Detecting your project. Stick around, this will take a few seconds...\n </Text>\n <Box marginY={1}>\n <LoadingBox message=\"Scanning the repo for frameworks and PostHog SDKs...\" />\n </Box>\n <Box flexDirection=\"column\">\n {activity.length === 0 ? (\n <Text dimColor>{' '}Starting up the detection agent…</Text>\n ) : (\n activity.map((line, i) => (\n <Text\n key={`${i}-${line}`}\n dimColor={i < activity.length - 1}\n color={i === activity.length - 1 ? Colors.primary : undefined}\n >\n {' '}\n {Icons.triangleSmallRight} {line}\n </Text>\n ))\n )}\n </Box>\n </Box>\n );\n }\n\n const { report } = state;\n const instrumentable = report.projects.filter((p) => p.instrumentable);\n // Already has PostHog → offer \"continue with existing\" instead of hiding it.\n const existing = report.projects.filter((p) => p.continuable);\n const unsupported = report.projects.filter(\n (p) => !p.instrumentable && !p.continuable,\n );\n\n // Values are prefixed so one picker can mix new: and existing: entries.\n const NEW = 'new:';\n const EXISTING = 'existing:';\n const dispatch = (value: string | string[]) => {\n const v = Array.isArray(value) ? value[0] : value;\n if (v === CANCEL) {\n store.requestExit(0);\n return;\n }\n if (v.startsWith(EXISTING)) {\n const p = existing.find((x) => x.path === v.slice(EXISTING.length));\n if (p) continueWithExisting(p);\n return;\n }\n const p = instrumentable.find((x) => x.path === v.slice(NEW.length));\n if (p) choose(p);\n };\n\n // Nothing to instrument, nothing already installed: a genuine dead end.\n if (instrumentable.length === 0 && existing.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Nothing to set up here\n </Text>\n <Text dimColor>\n None of the {report.projects.length} projects found can have PostHog\n set up.\n </Text>\n </Box>\n <UnsupportedSummary unsupported={unsupported} />\n <Box marginTop={1}>\n <PickerMenu\n options={[{ label: 'Exit', value: CANCEL }]}\n onSelect={() => store.requestExit(0)}\n />\n </Box>\n </Box>\n );\n }\n\n // Only already-installed projects: continue straight to Self-driving.\n if (instrumentable.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n {Icons.check} PostHog is already set up\n </Text>\n <Text dimColor>Continue straight to Self-driving.</Text>\n </Box>\n <PickerMenu\n message={\n existing.length === 1\n ? 'Continue with your existing PostHog install?'\n : 'Which project should Self-driving use?'\n }\n options={[\n ...existing.map((p) => ({\n label: projectLabel(p),\n value: `${EXISTING}${p.path}`,\n })),\n { label: 'Exit', value: CANCEL },\n ]}\n onSelect={dispatch}\n />\n <Box marginTop={1}>\n <UnsupportedSummary unsupported={unsupported} />\n </Box>\n </Box>\n );\n }\n\n const single = instrumentable.length === 1;\n // Disabled rows act as section headings + spacers — navigation skips them.\n const HEAD = 'head:';\n const spacer = (id: string) => ({\n label: ' ',\n value: `${HEAD}${id}`,\n disabled: true,\n });\n const heading = (id: string, label: string) => ({\n label,\n value: `${HEAD}${id}`,\n disabled: true,\n header: true,\n });\n const options = [\n heading('new', 'New PostHog integration:'),\n ...instrumentable.map((p) => ({\n label: projectLabel(p),\n value: `${NEW}${p.path}`,\n indent: true,\n })),\n ...(existing.length > 0\n ? [\n spacer('gap1'),\n heading('existing', 'Existing integrations:'),\n ...existing.map((p) => ({\n label: projectLabel(p),\n value: `${EXISTING}${p.path}`,\n indent: true,\n })),\n ]\n : []),\n spacer('gap2'),\n { label: 'Cancel', value: CANCEL },\n ];\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n {Icons.check} Found{' '}\n {report.repoType === 'monorepo' ? 'a monorepo' : 'your project'}\n </Text>\n </Box>\n\n <PickerMenu\n message={\n single && existing.length === 0\n ? 'Set up PostHog here? Confirm to continue.'\n : undefined\n }\n options={options}\n onSelect={dispatch}\n />\n\n <Box marginTop={1}>\n <UnsupportedSummary unsupported={unsupported} />\n </Box>\n </Box>\n );\n};\n\n/**\n * Collapses unsupported-stack projects into a count line (already-has-PostHog\n * projects are real picker options, not summarised).\n */\nconst UnsupportedSummary = ({\n unsupported,\n}: {\n unsupported: IntegrationProject[];\n}) => {\n if (unsupported.length === 0) return null;\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>\n (… {unsupported.length} project{unsupported.length === 1 ? '' : 's'} not\n supported yet)\n </Text>\n </Box>\n );\n};\n","/**\n * SelfDrivingHandoffScreen — the bridge between the integration run and the\n * Self-driving run. Shown only in the integrate path (PostHog wasn't present, so\n * the wizard set it up first); the already-has-PostHog path skips straight to\n * Self-driving with no note. Confirms the SDK is in, then hands off to the\n * Self-driving run.\n */\n\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\n\nimport type { WizardStore } from '@tui/store';\nimport { PickerMenu } from '@tui/primitives/index';\nimport { Colors } from '@tui/styles';\nimport { SETUP_REPORT_FILE } from '@shared/constants';\nimport { SELF_DRIVING_INTEGRATE_PATH_KEY } from '@programs/self-driving';\n\ninterface SelfDrivingHandoffScreenProps {\n store: WizardStore;\n}\n\nexport const SelfDrivingHandoffScreen = ({\n store,\n}: SelfDrivingHandoffScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // The integration ran in the picked project (a monorepo sub-app, or the\n // root), so the report sits under that path.\n const rel = store.session.frameworkContext[SELF_DRIVING_INTEGRATE_PATH_KEY];\n const dir = typeof rel === 'string' && rel !== '.' ? `${rel}/` : '';\n const reportPath = `./${dir}${SETUP_REPORT_FILE}`;\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n ✔ PostHog is installed\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n <Text>Now let&apos;s make your product self-driving.</Text>\n <Box marginTop={1}>\n <Text dimColor>\n Next, the agent connects GitHub, turns on signal sources, and tunes\n the scouts that watch your product data.\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n About 10 more minutes, and it needs your input a few times. Keep\n this terminal open.\n </Text>\n </Box>\n </Box>\n\n <Box marginTop={1}>\n <PickerMenu\n options={[{ label: 'Set up Self-driving [Enter]', value: 'go' }]}\n onSelect={() => store.confirmSelfDrivingHandoff()}\n />\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>\n You can find your PostHog integration report at{' '}\n <Text bold>{reportPath}</Text>\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * Polls `/integrations/` until the PostHog GitHub App shows up, writing the\n * result to the session so the Self-driving GitHub gate can advance.\n *\n * Installing the App is a manual browser step, so polling is what flips the\n * gate once the user comes back. The first tick also resolves the session's\n * unknown (`null`) state.\n *\n * Each tick reads the token through the login's OAuth session, since the gate\n * can open, or sit, past the token's 1-hour life. A stale token 401s every\n * tick, and the gate then asks for an install the project already has.\n */\n\nimport { useEffect } from 'react';\nimport axios from 'axios';\n\nimport type { WizardStore } from '@tui/store';\nimport type { WizardSession } from '@programs/types';\nimport { fetchGithubConnected, type Credentials } from '@shared/api';\nimport {\n currentCredentials,\n rotateAfterUnauthorized,\n} from '@shared/oauth-session';\nimport { requestDeepLink } from '@utils/provisioning';\nimport { analytics } from '@utils/analytics';\n\nconst POLL_INTERVAL_MS = 3000;\n\n// Provisioned signups have no browser session for the install link; deep link when the partner tier grants one, else the login page.\nexport async function fetchLoginUrl(\n session: WizardSession,\n): Promise<string | null> {\n if (!session.signup || !session.credentials) return null;\n const deepLink = await requestDeepLink(\n session.credentials.accessToken,\n session.credentials.host,\n );\n return deepLink ?? `${session.credentials.host.appHost}/login`;\n}\n\nconst isUnauthorized = (err: unknown): boolean =>\n axios.isAxiosError(err) && err.response?.status === 401;\n\n/** One check. A 401 rotates the token once and retries before it counts as a failure. */\nexport async function checkGithubConnected(\n store: WizardStore,\n signal: AbortSignal,\n): Promise<boolean> {\n const held = store.session.credentials;\n if (!held) return false;\n const check = (credentials: Credentials): Promise<boolean> =>\n fetchGithubConnected(\n credentials.accessToken,\n credentials.projectId,\n credentials.host.apiHost,\n signal,\n );\n const credentials = await currentCredentials(held);\n try {\n return await check(credentials);\n } catch (err) {\n if (!isUnauthorized(err)) throw err;\n const recovery = await rotateAfterUnauthorized(credentials, {\n requireRefreshToken: true,\n });\n if (recovery.kind !== 'rotated') throw err;\n return check(recovery.credentials);\n }\n}\n\nexport function useGithubConnection(store: WizardStore): void {\n // Keyed on being logged in, not on the token: a rotation lands a new token\n // in the session mid-check, and restarting would abort the retry.\n const loggedIn = store.session.credentials !== null;\n const connected = store.githubConnected === true;\n\n useEffect(() => {\n if (!loggedIn || connected) return;\n\n const controller = new AbortController();\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let errorReported = false;\n\n /** A check that came back \"not connected\" — including a failed one. */\n const settleUnknown = (): void => {\n if (store.githubConnected === null) {\n store.setGithubConnected(false);\n }\n };\n\n const wait = (): Promise<void> =>\n new Promise((resolve) => {\n timer = setTimeout(resolve, POLL_INTERVAL_MS);\n });\n\n void (async () => {\n while (!stopped) {\n try {\n const isConnected = await checkGithubConnected(\n store,\n controller.signal,\n );\n if (stopped) return;\n if (isConnected) {\n // Only a false→true flip means the user installed during this\n // screen; true on the first check means they arrived connected.\n if (store.githubConnected === false) {\n analytics.wizardCapture('github connect completed');\n }\n store.setGithubConnected(true);\n return;\n }\n settleUnknown();\n } catch (err) {\n if (stopped) return;\n // Report once, then keep polling. Unlike Slack's nudge, this gate\n // can't degrade to a skip — the run cannot proceed until it\n // resolves — so a transient API blip must not strand the user.\n if (!errorReported) {\n errorReported = true;\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'github_connected_check' },\n );\n }\n settleUnknown();\n }\n await wait();\n }\n })();\n\n return () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n controller.abort();\n };\n }, [loggedIn, connected, store]);\n}\n","/**\n * SelfDrivingGitHubScreen — the \"Connect GitHub\" gate, shown after the handoff\n * and before the Self-driving run.\n *\n * Self-driving cannot research findings or open fixes without code access, so\n * the GitHub App is a hard requirement. The agent used to ask for it mid-run\n * via `wizard_ask` and abort when the answer came back declined — but a\n * `wizard_ask` timeout resolves to the same cancelled value as a real decline,\n * so a user who stepped away had their run killed as if they had refused.\n * Gating here instead makes the requirement cheap (no agent has started),\n * unambiguous (declining is an explicit pick), and un-timeoutable (the screen\n * waits as long as the browser install takes).\n *\n * Unlike SlackConnectScreen this is not skippable: declining ends the run on\n * the outro rather than continuing without it. The connection poll lives in\n * {@link useGithubConnection}.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\n\nimport type { WizardStore } from '@tui/store';\nimport { Colors, Icons } from '@tui/styles';\nimport { PickerMenu, LoadingBox } from '@tui/primitives/index';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\nimport {\n useGithubConnection,\n fetchLoginUrl,\n} from '../hooks/useGithubConnection.js';\nimport { OutroKind } from '@shared/outro';\nimport {\n GITHUB_REQUIRED_BODY,\n GITHUB_REQUIRED_MESSAGE,\n} from '@programs/self-driving';\nimport { analytics } from '@utils/analytics';\nimport { openTrackedLink } from '@utils/links';\nimport { getIntegrationAuthorizeUrl } from '@utils/urls';\n\ninterface SelfDrivingGitHubScreenProps {\n store: WizardStore;\n}\n\nenum ChoiceValue {\n Open = 'open',\n Decline = 'decline',\n}\n\nexport const SelfDrivingGitHubScreen = ({\n store,\n}: SelfDrivingGitHubScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const credentials = store.session.credentials;\n const connectedState = store.githubConnected;\n const connected = connectedState === true;\n\n const authorizeUrl = credentials\n ? getIntegrationAuthorizeUrl(\n credentials.host.appHost,\n credentials.projectId,\n 'github',\n )\n : null;\n\n useGithubConnection(store);\n\n // Once the install link has been opened, re-offering it as the headline CTA\n // is confusing — the poll flips the screen on its own when the install lands.\n const [installOpened, setInstallOpened] = useState(false);\n\n // One-time login link for browsers without a PostHog session (fresh provisioned accounts).\n const [loginUrl, setLoginUrl] = useState<string | null>(null);\n const loginUrlRequested = useRef(false);\n useEffect(() => {\n if (loginUrlRequested.current) return;\n loginUrlRequested.current = true;\n void fetchLoginUrl(store.session).then(setLoginUrl);\n }, [store]);\n\n // Impression fires once the connected state is known, so `already_connected`\n // is real: users who arrive connected segment apart from users who connect\n // during the screen.\n const impressionFired = useRef(false);\n useEffect(() => {\n if (connectedState === null || impressionFired.current) return;\n impressionFired.current = true;\n analytics.wizardCapture('github connect shown', {\n already_connected: connected,\n });\n }, [connectedState, connected]);\n\n const openInstall = (): void => {\n if (!authorizeUrl) return;\n analytics.wizardCapture('github connect opened');\n openTrackedLink(authorizeUrl, 'self-driving-github-connect');\n setInstallOpened(true);\n };\n\n // Declining ends the run here, before the agent starts. The outro carries the\n // same copy the abort case renders, so both paths read identically.\n const decline = (): void => {\n analytics.wizardCapture('github connect declined', {\n install_opened: installOpened,\n });\n store.declineGithub({\n kind: OutroKind.Cancel,\n message: GITHUB_REQUIRED_MESSAGE,\n body: GITHUB_REQUIRED_BODY,\n });\n };\n\n const handleSelect = (value: ChoiceValue | ChoiceValue[]): void => {\n const choice = Array.isArray(value) ? value[0] : value;\n if (choice === ChoiceValue.Open) openInstall();\n else decline();\n };\n\n useKeyBindings('self-driving-github', [\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: connected ? 'continue' : 'end setup',\n handler: () => {\n if (!connected) decline();\n },\n },\n ]);\n\n if (credentials && connectedState === null) {\n return (\n <Box flexDirection=\"column\" flexGrow={1} marginTop={1}>\n <LoadingBox message=\"Checking for an existing GitHub connection...\" />\n </Box>\n );\n }\n\n if (connected) {\n return (\n <Box flexDirection=\"column\" flexGrow={1} marginTop={1}>\n <Text bold color={Colors.success}>\n {Icons.check} GitHub connected\n </Text>\n <Box marginTop={1}>\n <Text>\n Self-driving can research findings in your code and open fixes.\n </Text>\n </Box>\n <Box marginTop={1}>\n <LoadingBox message=\"Starting Self-driving setup...\" />\n </Box>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box marginTop={1} flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n {installOpened ? 'Finish connecting GitHub' : 'Connect GitHub'}\n </Text>\n\n <Box marginTop={1}>\n <Text>\n {installOpened\n ? \"We've opened the PostHog GitHub App install in your browser. Approve access there — we'll detect it automatically and continue.\"\n : 'Self-driving needs GitHub access to research findings in your code and open fixes, so setup cannot finish without it.'}\n </Text>\n </Box>\n\n {!installOpened && (\n <Box marginTop={1}>\n <Text>\n <Text color=\"cyan\">{Icons.diamond} </Text>\n Grant it the repos you want Self-driving to work with — include\n this project&apos;s repo so it can also watch its issues.\n </Text>\n </Box>\n )}\n\n {loginUrl && (\n <Box marginTop={1}>\n <Text dimColor>\n {'Log in to your new account first: '}\n <Text color=\"cyan\">{loginUrl}</Text>\n </Text>\n </Box>\n )}\n\n {authorizeUrl && (\n <Box marginTop={1}>\n <Text dimColor>\n {installOpened ? 'Install page: ' : 'Install it: '}\n <Text color=\"cyan\">{authorizeUrl}</Text>\n </Text>\n </Box>\n )}\n\n <Box marginTop={1}>\n <PickerMenu\n options={[\n {\n label: installOpened\n ? 'Re-open GitHub App install'\n : 'Open GitHub App install',\n value: ChoiceValue.Open,\n },\n {\n label: \"I can't connect right now\",\n value: ChoiceValue.Decline,\n },\n ]}\n onSelect={handleSelect}\n />\n </Box>\n </Box>\n </Box>\n );\n};\n","/** Self-driving's TUI: its flow, deck, tips and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { SELF_DRIVING_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { getTips } from './deck/tips.js';\nimport { SelfDrivingScreenId } from './screen-ids.js';\nimport { SelfDrivingIntroScreen } from './screens/SelfDrivingIntroScreen.js';\nimport { SelfDrivingIntegrationCheckScreen } from './screens/SelfDrivingIntegrationCheckScreen.js';\nimport { SelfDrivingIntegrationDetectScreen } from './screens/SelfDrivingIntegrationDetectScreen.js';\nimport { SelfDrivingHandoffScreen } from './screens/SelfDrivingHandoffScreen.js';\nimport { SelfDrivingGitHubScreen } from './screens/SelfDrivingGitHubScreen.js';\n\nexport { SelfDrivingScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'self-driving': {\n flow: SELF_DRIVING_FLOW,\n deck: getContentBlocks,\n tips: getTips,\n screens: {\n [SelfDrivingScreenId.Intro]: (store) => (\n <SelfDrivingIntroScreen store={store} />\n ),\n [SelfDrivingScreenId.IntegrationCheck]: (store) => (\n <SelfDrivingIntegrationCheckScreen store={store} />\n ),\n [SelfDrivingScreenId.IntegrationDetect]: (store) => (\n <SelfDrivingIntegrationDetectScreen store={store} />\n ),\n [SelfDrivingScreenId.Handoff]: (store) => (\n <SelfDrivingHandoffScreen store={store} />\n ),\n [SelfDrivingScreenId.Github]: (store) => (\n <SelfDrivingGitHubScreen store={store} />\n ),\n },\n },\n};\n","/**\n * Warehouse-source program step list. The skill install and agent run happen\n * in `runProgram`. The skill drives both in-CLI source creation and deep-link\n * emission per detected source.\n */\n\nimport type { FlowStep } from '@tui/flow';\nimport { RunPhase } from '@shared/run-state';\n\nexport const WAREHOUSE_SOURCE_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'warehouse-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Data warehouse',\n screenId: 'run',\n isComplete: ({ session }) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * WarehouseIntroScreen — Welcome screen for the data warehouse source flow.\n *\n * Composes IntroScreenLayout with detection-specific state:\n * - Detection succeeded: lists detected sources (grouped by creation mode),\n * continue/cancel.\n * - Detection failed: shows the error via errorView + exit prompt.\n *\n * Reads `frameworkContext.detectError` and `frameworkContext.detectedWarehouseSources`\n * set by detectWarehousePrerequisites().\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { PickerMenu } from '@tui/primitives/index';\nimport { IntroScreenLayout } from '@tui/screens/IntroScreenLayout';\nimport {\n applySharingChoice,\n isSharing,\n resolveSharingOnContinue,\n sharingOptions,\n} from '@tui/components/sharing-options';\nimport {\n getDetectedWarehouseSources,\n type WarehouseDetectError,\n} from '@programs/warehouse-source';\n\ninterface WarehouseIntroScreenProps {\n store: WizardStore;\n}\n\nexport const WarehouseIntroScreen = ({ store }: WarehouseIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [showingMoreInfo, setShowingMoreInfo] = useState(false);\n\n const { session } = store;\n const detectError = session.frameworkContext.detectError as\n | WarehouseDetectError\n | undefined;\n const detected = getDetectedWarehouseSources(session);\n\n // ── Body ────────────────────────────────────────────────────────────\n\n const body = showingMoreInfo ? (\n <Box flexDirection=\"column\" width={56} flexShrink={0}>\n <Text>\n The wizard is an agent that executes PostHog tasks. Its code is open\n source: <Text color=\"cyan\">https://github.com/PostHog/wizard</Text>.\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>\n The{' '}\n <Text italic color=\"cyan\">\n {store.programLabel}\n </Text>{' '}\n program connects your existing data sources to PostHog's data\n warehouse, so you can query them alongside product data.\n </Text>\n </Box>\n </Box>\n ) : (\n <>\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text>Let's connect your data to PostHog's data warehouse.</Text>\n </Box>\n\n {detected.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text dimColor>Detected warehouse sources:</Text>\n {detected.map((s) => (\n <Text key={s.kind} dimColor>\n {' •'} {s.label}\n </Text>\n ))}\n </Box>\n )}\n </>\n );\n\n // ── Error view ─────────────────────────────────────────────────────\n\n const errorView = detectError ? (\n <>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"red\" bold>\n {'✘'}{' '}\n {detectError.kind === 'bad-directory'\n ? 'Invalid project directory'\n : 'No data warehouse source detected'}\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n <DetectErrorBody error={detectError} />\n </Box>\n </Box>\n\n <PickerMenu\n options={[{ label: 'Exit', value: 'exit' }]}\n onSelect={() => store.requestExit(0)}\n />\n </>\n ) : undefined;\n\n // ── Menu ───────────────────────────────────────────────────────────\n const menuOptions = showingMoreInfo\n ? [{ label: 'Back', value: 'back' }]\n : [\n { label: 'Continue', value: 'continue' },\n { label: 'More info', value: 'more-info' },\n { label: 'Cancel', value: 'cancel' },\n ];\n\n // ── Render ─────────────────────────────────────────────────────────\n\n return (\n <IntroScreenLayout\n installDir={session.installDir}\n showSubtitle={!showingMoreInfo}\n body={body}\n showDetection={!showingMoreInfo}\n programLabel={store.programLabel}\n skillId={session.skillId}\n menuOptions={menuOptions}\n privacyOptions={sharingOptions(isSharing(store))}\n errorView={errorView}\n onSelect={(value) => {\n if (applySharingChoice(store, value)) return;\n if (value === 'cancel') {\n store.requestExit(0);\n } else if (value === 'more-info') {\n setShowingMoreInfo(true);\n } else if (value === 'back') {\n setShowingMoreInfo(false);\n } else {\n resolveSharingOnContinue(store);\n store.completeSetup();\n }\n }}\n />\n );\n};\n\nconst DetectErrorBody = ({ error }: { error: WarehouseDetectError }) => {\n switch (error.kind) {\n case 'bad-directory': {\n const reasonText = {\n missing: 'does not exist',\n 'not-dir': 'is not a directory',\n unreadable: 'could not be accessed',\n }[error.reason];\n return (\n <>\n <Text>This path {reasonText}:</Text>\n <Text dimColor>\n {' '}\n {error.path}\n </Text>\n </>\n );\n }\n\n case 'no-sources':\n return (\n <>\n <Text>No supported data source was detected in this project.</Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>\n The wizard looks for databases (Postgres, MySQL, MongoDB, …) and\n API-key sources like Stripe in your dependencies and .env keys.\n </Text>\n <Text dimColor>\n Run this command from your project root, or set a source up\n directly at{' '}\n <Text color=\"cyan\">https://posthog.com/docs/data-warehouse</Text>.\n </Text>\n </Box>\n </>\n );\n }\n};\n","/** The warehouse-source TUI: its flow, deck and screens. */\nimport type { TuiPrograms } from '@tui/programs/types';\nimport { WAREHOUSE_SOURCE_FLOW } from './flow.js';\nimport { getContentBlocks } from './deck/index.js';\nimport { WarehouseSourceScreenId } from './screen-ids.js';\nimport { WarehouseIntroScreen } from './screens/WarehouseIntroScreen.js';\n\nexport { WarehouseSourceScreenId } from './screen-ids.js';\n\nexport const TUI_PROGRAMS: TuiPrograms = {\n 'warehouse-source': {\n flow: WAREHOUSE_SOURCE_FLOW,\n deck: getContentBlocks,\n screens: {\n [WarehouseSourceScreenId.Intro]: (store) => (\n <WarehouseIntroScreen store={store} />\n ),\n },\n },\n};\n","/**\n * The TUI program registry: each program's UI, gathered from its folder's\n * entry (`programs/<id>/index.ts`). A program without an entry runs the\n * generic skill program. Program logic stays on its `ProgramConfig`.\n *\n * The core reaches this module only through `getTuiProgram` and\n * `listTuiPrograms` (flows through `flowOwner`), and names no program; a\n * program folder never imports it. A tool's screens live in `../tools`.\n */\n\nimport type { TuiProgram, TuiPrograms } from './types.js';\nimport { SKILL_PROGRAM } from './shared/skill-program.js';\nimport { TUI_PROGRAMS as aiObservability } from '@tui/programs/ai-observability';\nimport { TUI_PROGRAMS as audit } from '@tui/programs/audit';\nimport { TUI_PROGRAMS as errorTracking } from '@tui/programs/error-tracking';\nimport { TUI_PROGRAMS as sourceMaps } from '@tui/programs/error-tracking-upload-source-maps';\nimport { TUI_PROGRAMS as featureFlags } from '@tui/programs/feature-flags';\nimport { TUI_PROGRAMS as metrics } from '@tui/programs/metrics';\nimport { TUI_PROGRAMS as migration } from '@tui/programs/migration';\nimport { TUI_PROGRAMS as posthogIntegration } from '@tui/programs/posthog-integration';\nimport { TUI_PROGRAMS as revenueAnalytics } from '@tui/programs/revenue-analytics';\nimport { TUI_PROGRAMS as selfDriving } from '@tui/programs/self-driving';\nimport { TUI_PROGRAMS as warehouseSource } from '@tui/programs/warehouse-source';\n\nexport type { TuiProgram };\n\nconst TUI_PROGRAMS: TuiPrograms = {\n ...aiObservability,\n ...audit,\n ...errorTracking,\n ...sourceMaps,\n ...featureFlags,\n ...metrics,\n ...migration,\n ...posthogIntegration,\n ...revenueAnalytics,\n ...selfDriving,\n ...warehouseSource,\n};\n\nexport function getTuiProgram(programId: string): TuiProgram {\n return TUI_PROGRAMS[programId] ?? SKILL_PROGRAM;\n}\n\n/** Every TUI program, the generic skill program first. */\nexport function listTuiPrograms(): readonly TuiProgram[] {\n const programs = Object.values(TUI_PROGRAMS).filter(\n (p): p is TuiProgram => p !== undefined,\n );\n return [SKILL_PROGRAM, ...programs];\n}\n","import type { FlowStep } from '@tui/flow';\nimport { HEALTH_CHECK_STEP } from '@tui/programs/shared/health-check-step';\n\nexport const POSTHOG_DOCTOR_FLOW: FlowStep[] = [\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'doctor-intro',\n gate: (tui) => tui.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: ({ session }) => session.credentials !== null,\n },\n {\n id: 'report',\n label: 'Doctor report',\n screenId: 'doctor-report',\n isComplete: ({ session }) => session.outroData !== null,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (tui) => tui.outroDismissed,\n },\n];\n","import { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { PickerMenu } from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\n\ninterface DoctorIntroScreenProps {\n store: WizardStore;\n}\n\nexport const DoctorIntroScreen = ({ store }: DoctorIntroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n PostHog Doctor\n </Text>\n <Text dimColor>\n Scan your project configuration for issues that may need attention.\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text>The wizard will:</Text>\n <Box paddingLeft={2} flexDirection=\"column\">\n <Text>{Icons.bullet} Sign you in to PostHog</Text>\n <Text>\n {Icons.bullet} Fetch active health issues for your project\n </Text>\n <Text>\n {Icons.bullet} Show you what needs to be resolved, with docs links\n </Text>\n </Box>\n </Box>\n\n <PickerMenu\n options={[\n { label: 'Continue', value: 'continue' },\n { label: 'Cancel', value: 'cancel' },\n ]}\n onSelect={(value) => {\n if (value === 'cancel') {\n store.requestExit(0);\n } else {\n store.completeSetup();\n }\n }}\n />\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport { Colors, Icons } from '@tui/styles';\nimport {\n getKindMeta,\n type HealthIssue,\n type HealthIssueSeverity,\n} from '@tools';\n\nexport const SEVERITY_ORDER: HealthIssueSeverity[] = [\n 'critical',\n 'warning',\n 'info',\n];\n\nconst SEVERITY_COLOR: Record<HealthIssueSeverity, string> = {\n critical: Colors.error,\n warning: Colors.accent,\n info: Colors.primary,\n};\n\nexport const SEVERITY_LABEL: Record<HealthIssueSeverity, string> = {\n critical: 'Critical',\n warning: 'Warning',\n info: 'Info',\n};\n\nconst ICON_COL = 2;\nconst ROW_GAP = 2;\nconst NARROW_TERM_THRESHOLD = 90;\nconst MAX_DOCS_WIDTH = 50;\nconst MIN_DOCS_WIDTH = 20;\n\nfunction computeDocsWidth(termCols: number): number {\n if (termCols < NARROW_TERM_THRESHOLD) return 0;\n const inner = termCols - 12;\n return Math.min(\n MAX_DOCS_WIDTH,\n Math.max(MIN_DOCS_WIDTH, Math.floor(inner * 0.45)),\n );\n}\n\ninterface IssueTableProps {\n issues: HealthIssue[];\n}\n\nexport const IssueTable = ({ issues }: IssueTableProps) => {\n const [termCols] = useStdoutDimensions();\n const docsWidth = computeDocsWidth(termCols);\n\n const grouped: Partial<Record<HealthIssueSeverity, HealthIssue[]>> = {};\n for (const issue of issues) {\n (grouped[issue.severity] ??= []).push(issue);\n }\n\n return (\n <Box flexDirection=\"column\">\n {SEVERITY_ORDER.map((sev) => {\n const list = grouped[sev];\n if (!list || list.length === 0) return null;\n return (\n <Box key={sev} flexDirection=\"column\" marginTop={1}>\n <Text bold color={SEVERITY_COLOR[sev]}>\n {SEVERITY_LABEL[sev]} ({list.length})\n </Text>\n {list.map((issue) => (\n <IssueRow key={issue.id} issue={issue} docsWidth={docsWidth} />\n ))}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nconst IssueRow = ({\n issue,\n docsWidth,\n}: {\n issue: HealthIssue;\n docsWidth: number;\n}) => {\n const meta = getKindMeta(issue.kind);\n const sevColor = SEVERITY_COLOR[issue.severity];\n\n if (docsWidth === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n </Box>\n <Box paddingLeft={ICON_COL}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\" marginRight={ROW_GAP}>\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n <Box width={docsWidth} flexShrink={0}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { LoadingBox, PickerMenu } from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\nimport { fetchHealthIssues, type HealthIssue } from '@tools';\nimport { OutroKind } from '@shared/outro';\nimport { ApiError } from '@shared/api';\nimport { POSTHOG_DOCS_URL } from '@shared/constants';\nimport { IssueTable, SEVERITY_LABEL, SEVERITY_ORDER } from './IssueTable.js';\n\ninterface DoctorReportScreenProps {\n store: WizardStore;\n}\n\ntype FetchState =\n | { kind: 'loading' }\n | { kind: 'ready'; issues: HealthIssue[] }\n | { kind: 'error'; message: string };\n\nexport const DoctorReportScreen = ({ store }: DoctorReportScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { credentials } = store.session;\n const accessToken = credentials?.accessToken;\n const apiHost = credentials?.host.apiHost;\n const projectId = credentials?.projectId;\n\n const [state, setState] = useState<FetchState>({ kind: 'loading' });\n\n useEffect(() => {\n if (!accessToken || !apiHost || projectId == null) return;\n let cancelled = false;\n void (async () => {\n try {\n const issues = await fetchHealthIssues(accessToken, apiHost, projectId);\n if (!cancelled) {\n setState({ kind: 'ready', issues });\n }\n } catch (err) {\n if (!cancelled) {\n const message =\n err instanceof ApiError && err.statusCode === 401\n ? 'Your PostHog session has expired. Re-run the wizard to sign in again.'\n : err instanceof Error\n ? err.message\n : String(err);\n setState({ kind: 'error', message });\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [accessToken, apiHost, projectId]);\n\n if (!credentials) {\n return <LoadingBox message=\"Waiting for authentication...\" />;\n }\n\n if (state.kind === 'loading') {\n return (\n <Box flexDirection=\"column\">\n <Header\n host={credentials.host.apiHost}\n projectId={credentials.projectId}\n />\n <LoadingBox message=\"Fetching health issues...\" />\n </Box>\n );\n }\n\n const healthUrl = `${credentials.host.appHost}/project/${credentials.projectId}/health`;\n\n if (state.kind === 'error') {\n return (\n <Box flexDirection=\"column\">\n <Header\n host={credentials.host.apiHost}\n projectId={credentials.projectId}\n />\n <Box flexDirection=\"column\" marginY={1}>\n <Text color={Colors.error} bold>\n {Icons.squareFilled} Failed to fetch health issues\n </Text>\n <Text dimColor>{state.message}</Text>\n </Box>\n <PickerMenu\n options={[{ label: 'Continue', value: 'continue' }]}\n onSelect={() => {\n store.setOutroData({\n kind: OutroKind.Error,\n message: 'Failed to fetch health issues',\n body: state.message,\n docsUrl: POSTHOG_DOCS_URL,\n });\n }}\n />\n </Box>\n );\n }\n\n const { issues } = state;\n\n if (issues.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Header\n host={credentials.host.apiHost}\n projectId={credentials.projectId}\n />\n <Box marginY={1}>\n <Text color={Colors.success} bold>\n {Icons.check} No active issues — you're all set!\n </Text>\n </Box>\n <PickerMenu\n options={[{ label: 'Continue', value: 'continue' }]}\n onSelect={() => {\n store.setOutroData({\n kind: OutroKind.Success,\n message: 'No active issues — your project looks healthy.',\n docsUrl: POSTHOG_DOCS_URL,\n continueUrl: healthUrl,\n });\n }}\n />\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Header\n host={credentials.host.apiHost}\n projectId={credentials.projectId}\n />\n <Box marginTop={1}>\n <Text>{formatSummaryLine(issues)}</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <IssueTable issues={issues} />\n </Box>\n\n <PickerMenu\n options={[{ label: 'Continue', value: 'continue' }]}\n onSelect={() => {\n store.setOutroData({\n kind: OutroKind.Success,\n message: `Found ${issues.length} active issue${\n issues.length === 1 ? '' : 's'\n }.`,\n body: 'Open the dashboard in PostHog to dismiss or resolve issues.',\n docsUrl: POSTHOG_DOCS_URL,\n continueUrl: healthUrl,\n });\n }}\n />\n </Box>\n );\n};\n\nconst Header = ({ host, projectId }: { host: string; projectId: number }) => (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n PostHog Doctor Report\n </Text>\n <Text dimColor>\n Project {projectId} {Icons.bullet} {host}\n </Text>\n </Box>\n);\n\nfunction formatSummaryLine(issues: HealthIssue[]): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const n = issues.filter((i) => i.severity === sev).length;\n if (n > 0) parts.push(`${n} ${SEVERITY_LABEL[sev].toLowerCase()}`);\n }\n const suffix = parts.length > 0 ? `: ${parts.join(', ')}` : '';\n return `${issues.length} active issue${\n issues.length === 1 ? '' : 's'\n }${suffix}`;\n}\n","/** The doctor TUI: its flow, its screens, and the login its report waits on. */\nimport type { TuiTools } from '@tui/tools/types';\nimport { POSTHOG_DOCTOR_FLOW } from './flow.js';\nimport { PosthogDoctorScreenId } from './screen-ids.js';\nimport { DoctorIntroScreen } from './screens/DoctorIntroScreen.js';\nimport { DoctorReportScreen } from './screens/DoctorReportScreen.js';\n\nexport { PosthogDoctorScreenId } from './screen-ids.js';\n\nexport const TUI_TOOLS: TuiTools = {\n 'posthog-doctor': {\n flow: POSTHOG_DOCTOR_FLOW,\n screens: {\n [PosthogDoctorScreenId.Intro]: (store) => (\n <DoctorIntroScreen store={store} />\n ),\n [PosthogDoctorScreenId.Report]: (store) => (\n <DoctorReportScreen store={store} />\n ),\n },\n // The auth screen shows the login once the intro and the health check pass.\n start: async ({ store, logIn }) => {\n await store.getGate('intro');\n await store.getGate('health-check');\n await logIn();\n },\n },\n};\n","/**\n * McpScreen — MCP server install/remove flow.\n *\n * Uses an McpInstaller service (passed via props) instead of\n * importing business logic directly. Testable, no dynamic imports.\n *\n * Supports two modes via the `mode` prop:\n * - 'install': detect clients → pick clients (esc cancels) → pick features → install\n * - 'remove': detect installed clients → confirm → remove\n *\n * A successful install ends on one screen: results, any login commands, sample\n * prompts and the tutorial command. When done, calls store.setMcpComplete().\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport { useState, useEffect, useRef } from 'react';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { McpOutcome } from '@shared/run-state';\nimport {\n ConfirmationInput,\n GroupedPickerMenu,\n PickerMenu,\n} from '@tui/primitives/index';\nimport { Colors, Icons } from '@tui/styles';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\nimport type {\n McpInstaller,\n McpClientInfo,\n McpClientResult,\n} from '@tui/services/mcp-installer';\nimport {\n McpClientStatus,\n namesWithStatus,\n isOk,\n summarizeFailure,\n} from '@shared/mcp-clients/results';\nimport {\n AVAILABLE_FEATURES,\n ALL_FEATURE_VALUES,\n isAllFeaturesSelected,\n} from '@shared/mcp-clients/defaults';\n\nexport type McpMode = 'install' | 'remove';\n\ninterface McpScreenProps {\n store: WizardStore;\n installer: McpInstaller;\n mode?: McpMode;\n /** Prompts to suggest once installed; the MCP tool passes its role-tuned kit. */\n samplePrompts?: string[];\n}\n\nenum Phase {\n Detecting = 'detecting',\n Ask = 'ask',\n FeatureSelect = 'feature-select',\n Pick = 'pick',\n Connector = 'connector',\n Working = 'working',\n Done = 'done',\n None = 'none',\n}\n\nconst markDone = (\n store: WizardStore,\n outcome: McpOutcome,\n clients: string[] = [],\n featuresSelected?: 'all' | string[],\n loginCommands: string[] = [],\n) => {\n store.setMcpComplete(outcome, clients, featuresSelected, loginCommands);\n};\n\n/** Report the outcome as the results show, and complete the step on Enter. */\nconst doneOnEnter = (\n store: WizardStore,\n outcome: McpOutcome,\n clients: string[] = [],\n featuresSelected?: 'all' | string[],\n loginCommands: string[] = [],\n): (() => void) => {\n store.reportMcpOutcome(outcome, clients, featuresSelected);\n return () =>\n markDone(store, outcome, clients, featuresSelected, loginCommands);\n};\n\n/**\n * The editor-owned login commands still to run after this install: fresh\n * config entries use the client's own server name, plugin-provided servers\n * their `plugin:` name. One entry per client.\n */\nconst pendingLoginCommands = (\n clients: McpClientInfo[],\n mcpResult: McpClientResult[],\n pluginResult: McpClientResult[],\n): string[] => {\n const commands = new Map<string, string>();\n for (const r of pluginResult) {\n const command = clients.find((c) => c.name === r.name)?.pluginLoginCommand;\n if (isOk(r) && command) commands.set(r.name, command);\n }\n for (const r of mcpResult) {\n const command = clients.find((c) => c.name === r.name)?.loginCommand;\n if (r.status === McpClientStatus.Changed && command)\n commands.set(r.name, command);\n }\n return [...commands.values()];\n};\n\nconst reportFeatures = (features: string[]): 'all' | string[] =>\n isAllFeaturesSelected(features) ? 'all' : features;\n\nconst errorText = (err: unknown): string =>\n summarizeFailure(err instanceof Error ? err.message : String(err)) ??\n 'unknown error';\n\n/**\n * One \"✔ <title>\" / \"✖ <title>\" block with a bullet per client, plus an optional\n * dim explanation underneath. Rendered only when it has something to say.\n */\nconst ResultGroup = ({\n title,\n items,\n color,\n icon,\n note,\n}: {\n title: string;\n items: string[];\n color: string;\n icon: string;\n note?: string;\n}) => {\n if (items.length === 0) return null;\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color={color} bold>\n {icon} {title}\n </Text>\n {items.map((item, i) => (\n <Text key={`${title}-${i}`}>\n {' '}\n {'•'} {item}\n </Text>\n ))}\n {note && <Text dimColor> {note}</Text>}\n </Box>\n );\n};\n\n/**\n * Connector step prompt — Enter continues (opens the connector page). There's\n * no skip: picking the connector commits to opening it.\n */\nconst ConnectorContinue = ({ onContinue }: { onContinue: () => void }) => {\n useInput((_input, key) => {\n if (key.return) {\n onContinue();\n }\n });\n return (\n <Text color={Colors.primary}>\n Press enter to continue {Icons.triangleRight}\n </Text>\n );\n};\n\n/**\n * Done-phase prompt — Enter dismisses the results screen and moves the flow on.\n * Explicit acknowledgement instead of a timeout: the previous 2s auto-dismiss\n * whipped past too fast to read on a normal install, especially when several\n * result groups were stacked.\n */\nconst DoneContinue = ({ onContinue }: { onContinue: () => void }) => {\n useInput((_input, key) => {\n if (key.return) {\n onContinue();\n }\n });\n return (\n <Box marginTop={1}>\n <Text color={Colors.primary}>\n Press enter to continue {Icons.triangleRight}\n </Text>\n </Box>\n );\n};\n\nexport const McpScreen = ({\n store,\n installer,\n mode = 'install',\n samplePrompts = [],\n}: McpScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Keep stdin active from mount so Windows cmd.exe doesn't drop\n // the first keypress when ConfirmationInput appears after detection.\n useInput(() => undefined);\n\n const isRemove = mode === 'remove';\n\n const [phase, setPhase] = useState<Phase>(Phase.Detecting);\n const [clients, setClients] = useState<McpClientInfo[]>([]);\n const [selectedClientNames, setSelectedClientNames] = useState<string[]>([]);\n const [mcpResults, setMcpResults] = useState<McpClientResult[]>([]);\n const [pluginResults, setPluginResults] = useState<McpClientResult[]>([]);\n // Detection and the install/remove call can both blow up. Keep the reason so\n // a crash reads as a crash instead of as \"you have nothing installed\" or\n // \"you selected nothing\".\n const [detectError, setDetectError] = useState<string | null>(null);\n const [flowError, setFlowError] = useState<string | null>(null);\n const [loginCommands, setLoginCommands] = useState<string[]>([]);\n // The action that finishes the screen once the user has read the results.\n // Held in a ref so the useInput handler inside DoneContinue can invoke the\n // freshest closure without re-registering listeners on every render.\n const finishFlow = useRef<null | (() => void)>(null);\n\n useEffect(() => {\n void (async () => {\n try {\n const detected = await installer.detectClients();\n if (detected.length === 0) {\n setPhase(Phase.None);\n setTimeout(() => markDone(store, McpOutcome.NoClients), 1500);\n } else {\n setClients(detected);\n setPhase(isRemove ? Phase.Ask : Phase.Pick);\n }\n } catch (err) {\n setDetectError(errorText(err));\n // Long error text — wait for enter instead of a 3s auto-dismiss the\n // user can't finish reading.\n finishFlow.current = doneOnEnter(store, McpOutcome.Failed);\n setPhase(Phase.None);\n }\n })();\n }, [installer]); // eslint-disable-line\n\n // An api-key install bakes the key into the client config — no OAuth ever\n // runs, so those flows keep the feature menus and never get a login command.\n // OAuth flows ask nothing: access is chosen on the OAuth consent screen.\n const oauthFlow = !store.session.apiKey;\n\n const proceedAfterClientPick = (clientNames: string[]) => {\n setSelectedClientNames(clientNames);\n\n // Browser connectors just open their connector page — no extra screen.\n const isConnector = clientNames.some(\n (name) => clients.find((c) => c.name === name)?.finish,\n );\n if (isConnector) {\n setPhase(Phase.Connector);\n return;\n }\n if (oauthFlow) {\n void doInstall(clientNames);\n return;\n }\n if (store.mcpFeatures) {\n void doInstall(clientNames, store.mcpFeatures);\n return;\n }\n setPhase(Phase.FeatureSelect);\n };\n\n const handleSkip = () => {\n markDone(store, McpOutcome.Skipped);\n };\n\n // The picker has no escape binding of its own; esc declines the install.\n useKeyBindings(\n 'mcp-skip',\n phase === Phase.Pick\n ? [\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: 'cancel',\n handler: handleSkip,\n },\n ]\n : [],\n );\n\n const doInstall = async (names: string[], features?: string[]) => {\n setPhase(Phase.Working);\n let mcpResult: McpClientResult[] = [];\n let pluginResult: McpClientResult[] = [];\n\n const pluginCapableSet = new Set(\n clients.filter((c) => c.supportsPlugin).map((c) => c.name),\n );\n // A direct entry for everyone whose plugin doesn't already ship the MCP\n // server (codex's plugin is skills-only; claude's bundles the server).\n const bundledSet = new Set(\n clients.filter((c) => c.pluginBundlesMcp).map((c) => c.name),\n );\n const pluginCapableNames = names.filter((n) => pluginCapableSet.has(n));\n const directNames = names.filter((n) => !bundledSet.has(n));\n\n // OAuth: plugin-capable clients get the plugin (which bundles MCP), the\n // rest get a direct MCP config write. Api-key installs write key-authed\n // direct entries only — the plugin's server never carries the key.\n try {\n mcpResult = await installer.install(\n oauthFlow ? directNames : names,\n features,\n store.session.apiKey,\n );\n } catch (err) {\n setFlowError(errorText(err));\n }\n if (oauthFlow) {\n try {\n pluginResult = await installer.installPlugins(pluginCapableNames);\n } catch (err) {\n // Best-effort, but still say so rather than showing an empty screen.\n setFlowError(errorText(err));\n }\n }\n\n setMcpResults(mcpResult);\n setPluginResults(pluginResult);\n // Already-installed counts as installed: the user ends up with a working\n // MCP either way.\n const ready = [...mcpResult, ...pluginResult].filter(isOk);\n const outcome = ready.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n const featuresReport = reportFeatures(features ?? [...ALL_FEATURE_VALUES]);\n const logins = oauthFlow\n ? pendingLoginCommands(clients, mcpResult, pluginResult)\n : [];\n setLoginCommands(logins);\n finishFlow.current = doneOnEnter(\n store,\n outcome,\n ready.map((r) => r.name),\n featuresReport,\n logins,\n );\n setPhase(Phase.Done);\n };\n\n const doRemove = async () => {\n setPhase(Phase.Working);\n let result: McpClientResult[] = [];\n try {\n result = await installer.remove(store.session.localMcp);\n } catch (err) {\n setFlowError(errorText(err));\n }\n setMcpResults(result);\n const removed = result.filter(isOk);\n const outcome =\n removed.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n finishFlow.current = doneOnEnter(\n store,\n outcome,\n removed.map((r) => r.name),\n );\n setPhase(Phase.Done);\n };\n\n // The \"what you get\" preview shown above the editor picker —\n // installed users have no idea what \"MCP\" means; lead with the value.\n const installValueLines = [\n 'Ask your agent: \"List my feature flags\" — and it does.',\n 'Run SQL, build dashboards, ship flags, all from your IDE.',\n ];\n\n // Clients connected via a browser page (e.g. Claude Desktop/Web) aren't truly\n // \"installed\" — the user finishes in the browser. Split them out of the\n // \"installed for\" list and render the finish instructions separately.\n const okMcpNames = mcpResults.filter(isOk).map((r) => r.name);\n const finishNotes = clients.flatMap((c) =>\n c.finish && okMcpNames.includes(c.name)\n ? [{ name: c.name, url: c.finish.url, instruction: c.finish.instruction }]\n : [],\n );\n const isConnectorName = (name: string) =>\n finishNotes.some((n) => n.name === name);\n\n const installedNow = namesWithStatus(\n mcpResults,\n McpClientStatus.Changed,\n ).filter((name) => !isConnectorName(name));\n const alreadyInstalled = namesWithStatus(\n mcpResults,\n McpClientStatus.Unchanged,\n ).filter((name) => !isConnectorName(name));\n const pluginInstalled = namesWithStatus(\n pluginResults,\n McpClientStatus.Changed,\n );\n const pluginAlreadyInstalled = namesWithStatus(\n pluginResults,\n McpClientStatus.Unchanged,\n );\n // A failure the user can act on — the name alone says nothing, so carry the\n // reason the underlying CLI or file write gave us.\n const failures = [...mcpResults, ...pluginResults]\n .filter((r) => r.status === McpClientStatus.Failed)\n .map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name));\n\n const hasAnyResult =\n installedNow.length +\n alreadyInstalled.length +\n pluginInstalled.length +\n pluginAlreadyInstalled.length +\n failures.length +\n finishNotes.length >\n 0;\n const installSucceeded =\n !isRemove && [...mcpResults, ...pluginResults].some(isOk);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n {isRemove\n ? 'Remove the PostHog MCP'\n : phase === Phase.Done && installSucceeded\n ? \"You're all set — chat to your data from your client\"\n : 'Install the MCP so you can chat to your data'}\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n {phase === Phase.Detecting && (\n <Text dimColor>Detecting supported editors...</Text>\n )}\n\n {phase === Phase.None &&\n (detectError ? (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n {'\\u2716'} Couldn&apos;t check which editors are installed\n </Text>\n <Text dimColor> {detectError}</Text>\n <Text dimColor>\n {' '}\n Run with --debug for the full output, or report it at\n github.com/PostHog/wizard/issues.\n </Text>\n <DoneContinue onContinue={() => finishFlow.current?.()} />\n </Box>\n ) : (\n <Text dimColor>\n No {isRemove ? 'installed' : 'supported'} MCP clients detected.\n Skipping...\n </Text>\n ))}\n\n {phase === Phase.Ask && (\n <>\n <Text dimColor>\n Detected: {clients.map((c) => c.name).join(', ')}\n </Text>\n <Box marginTop={1}>\n <ConfirmationInput\n message={`Remove the PostHog MCP server${\n clients.some((c) => c.supportsPlugin) ? ' and plugin' : ''\n }?`}\n confirmLabel=\"Remove\"\n cancelLabel=\"No thanks\"\n onConfirm={() => void doRemove()}\n onCancel={handleSkip}\n />\n </Box>\n </>\n )}\n\n {phase === Phase.Pick && (\n <>\n <Box flexDirection=\"column\" marginBottom={1}>\n {installValueLines.map((line) => (\n <Text key={line} dimColor>\n {line}\n </Text>\n ))}\n </Box>\n <PickerMenu\n message={`Select clients to install the PostHog MCP server${\n clients.some((c) => c.supportsPlugin) ? ' and plugin' : ''\n }`}\n options={clients.map((c) => ({\n label: c.name,\n value: c.name,\n // Browser connectors can't be installed alongside local editors\n // and are configured on their own screen.\n exclusive: Boolean(c.finish),\n hint: c.finish\n ? 'connector'\n : c.supportsPlugin\n ? 'plugin'\n : 'MCP',\n }))}\n mode=\"multi\"\n onSelect={(selected) => {\n const names = Array.isArray(selected) ? selected : [selected];\n // Confirming with nothing ticked declines too.\n if (names.length === 0) {\n handleSkip();\n return;\n }\n proceedAfterClientPick(names);\n }}\n />\n </>\n )}\n\n {phase === Phase.FeatureSelect && (\n <GroupedPickerMenu\n message=\"Select the PostHog areas your agent can reach\"\n groups={AVAILABLE_FEATURES}\n initialSelected={[]}\n onSelect={(features) => {\n void doInstall(selectedClientNames, features);\n }}\n />\n )}\n\n {phase === Phase.Connector && (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text dimColor>\n You&apos;ll choose which PostHog areas to enable in\n Claude&apos;s UI after connecting.\n </Text>\n </Box>\n <ConnectorContinue\n onContinue={() => void doInstall(selectedClientNames, [])}\n />\n </Box>\n )}\n\n {phase === Phase.Working && (\n <Box flexDirection=\"row\" gap={1}>\n <Text dimColor>\n {isRemove ? 'Removing' : 'Installing'} MCP server...\n </Text>\n <Spinner />\n </Box>\n )}\n\n {phase === Phase.Done && (\n <Box flexDirection=\"column\">\n {hasAnyResult ? (\n <>\n <ResultGroup\n title=\"Plugin installed for:\"\n items={pluginInstalled}\n color=\"green\"\n icon={'\\u2714'}\n />\n <ResultGroup\n title=\"Plugin was already installed for:\"\n items={pluginAlreadyInstalled}\n color=\"green\"\n icon={'\\u2714'}\n note=\"It was already set up, so nothing changed. You are good to go.\"\n />\n <ResultGroup\n title={`MCP server ${\n isRemove ? 'removed from' : 'installed for'\n }:`}\n items={installedNow}\n color=\"green\"\n icon={'\\u2714'}\n />\n <ResultGroup\n title={\n isRemove\n ? 'No PostHog entry left to remove for:'\n : 'MCP server was already installed for:'\n }\n items={alreadyInstalled}\n color=\"green\"\n icon={'\\u2714'}\n note={\n isRemove\n ? 'It was already gone, so nothing was changed.'\n : 'Left as-is. To change which PostHog areas it can reach, run `wizard mcp remove` first, then `wizard mcp add`.'\n }\n />\n <ResultGroup\n title={`Couldn't ${\n isRemove ? 'remove from' : 'install for'\n }:`}\n items={failures}\n color=\"red\"\n icon={'\\u2716'}\n note=\"Run with --debug for the full output, or report it at github.com/PostHog/wizard/issues.\"\n />\n {loginCommands.length > 0 && (\n <Box flexDirection=\"column\" marginBottom={1}>\n {/* A step still to do, so not the green of the results. */}\n <Box marginBottom={1}>\n <Text>Authenticate to finish (opens your browser):</Text>\n </Box>\n {loginCommands.map((command) => (\n <Text key={command}>\n <Text dimColor>$ </Text>\n <Text bold color={Colors.primary}>\n {command}\n </Text>\n </Text>\n ))}\n </Box>\n )}\n {finishNotes.map((note) => (\n <Box key={note.name} flexDirection=\"column\" marginTop={1}>\n <Text color=\"green\" bold>\n {'\\u2714'} {note.name} {'\\u2014'} installs a PostHog\n connector:\n </Text>\n <Text>\n {' '}Opened <Text color=\"cyan\">{note.url}</Text>\n </Text>\n <Text dimColor>\n {' '}\n {note.instruction}\n </Text>\n <Text dimColor>\n {' '}(If it didn&apos;t open, paste the URL above.)\n </Text>\n </Box>\n ))}\n {installSucceeded && (\n // Result groups already end in a blank line; connector notes don't.\n <Box\n flexDirection=\"column\"\n marginTop={finishNotes.length > 0 ? 1 : 0}\n >\n {samplePrompts.length > 0 && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text>Open your client and try a prompt like:</Text>\n {samplePrompts.map((prompt) => (\n <Text key={prompt}>\n <Text color={Colors.primary}>\n {Icons.triangleSmallRight}\n </Text>{' '}\n <Text dimColor>{prompt}</Text>\n </Text>\n ))}\n </Box>\n )}\n <Text dimColor>\n Take the guided tour anytime with{' '}\n <Text bold>npx @posthog/wizard mcp tutorial</Text>.\n </Text>\n </Box>\n )}\n </>\n ) : flowError ? (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n {'\\u2716'} {isRemove ? 'Removal' : 'Installation'} failed\n </Text>\n <Text dimColor> {flowError}</Text>\n <Text dimColor>\n {' '}\n Run with --debug for the full output, or report it at\n github.com/PostHog/wizard/issues.\n </Text>\n </Box>\n ) : (\n <Text dimColor>\n {isRemove\n ? \"Nothing to remove \\u2014 the PostHog MCP server wasn't configured for any editor.\"\n : 'Nothing to install \\u2014 no editor was selected.'}\n </Text>\n )}\n <DoneContinue onContinue={() => finishFlow.current?.()} />\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import type { FlowStep } from '@tui/flow';\n\nexport const MCP_ADD_FLOW: FlowStep[] = [\n // One step: the install screen's results double as the success screen. The\n // tutorial stays opt-in via `wizard mcp tutorial`, so no surprise login.\n {\n id: 'mcp-add',\n label: 'Add MCP server',\n screenId: 'mcp-add',\n isComplete: (s) => s.mcpComplete,\n },\n];\n\n/**\n * `wizard mcp remove` — single-step uninstall flow.\n *\n * DO NOT append `mcp-suggested-prompts` (or any other tutorial-shaped\n * step) here. A user who just removed MCP is opting OUT of the agent having\n * access to PostHog; immediately pivoting into a tutorial that asks\n * them to log in and try prompts is wrong on intent and confusing on\n * UX. The screen also reads `session.mcpInstalledClients` for its\n * Choose-phase copy (\"MCP is installed for X\") — that array is empty\n * post-remove, so the copy would be a lie.\n *\n * If you want a \"did you mean to keep it?\" confirmation, build that as\n * a screen earlier in this flow — don't reuse the tutorial.\n */\nexport const MCP_REMOVE_FLOW: FlowStep[] = [\n {\n id: 'mcp-remove',\n label: 'Remove MCP server',\n screenId: 'mcp-remove',\n isComplete: (s) => s.mcpComplete,\n },\n];\n\n/**\n * Standalone tutorial flow — boots directly into the Choose phase of\n * McpSuggestedPromptsScreen without going through MCP install first.\n * Useful for users who already installed MCP and want to revisit the\n * tutorial, or anyone who just wants to try the agent against PostHog\n * without touching their IDE config.\n *\n * The screen handles its own OAuth (via services.performLogin) so this\n * flow doesn't pre-populate credentials.\n */\nexport const MCP_TUTORIAL_FLOW: FlowStep[] = [\n {\n id: 'mcp-suggested-prompts',\n label: 'MCP tutorial',\n screenId: 'mcp-suggested-prompts',\n isComplete: (s) => s.mcpSuggestedPromptsDismissed,\n },\n];\n","// The MCP prompt picker's copy, read by `mcp-role-prompts.ts`: plain data, typed by inference.\nconst copy = {\n pinnedFirstPrompt: {\n prompt: 'Show me my top 5 events from the last 7 days',\n description:\n 'A safe first pick — works on any project regardless of role or setup.',\n },\n defaultKit: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'top-events',\n prompt: 'Show me my top 5 events from the last 7 days',\n description: 'Get a feel for what your project is tracking.',\n },\n {\n key: 'main-funnel',\n prompt:\n 'Build me a funnel for my main user journey and show where the drop-off is',\n description: 'Insight discovery — your agent picks the events.',\n },\n {\n key: 'flags-inventory',\n prompt:\n 'Show me my feature flags and what each is currently rolled out to',\n description: 'Inventory the rollout state of every flag in your project.',\n },\n {\n key: 'error-trend',\n prompt:\n 'Show me daily error count for the last 30 days and flag anything that looks like a spike',\n description: 'Pulse-check on stability — no dashboard setup required.',\n },\n ],\n roleKits: {\n founder: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'exec-dashboard',\n prompt:\n 'Build me an exec dashboard with MRR, MAU, churn, and top events, then save it',\n description: 'A one-glance view of the business you can pin and share.',\n },\n {\n key: 'wau',\n prompt: 'Show me weekly active users for the last 90 days',\n description: 'The trendline you actually care about.',\n },\n {\n key: 'mau-trend',\n prompt:\n 'Show me weekly MAU for the last 12 weeks and where the inflection points are',\n description:\n 'See where growth bent — up or down — without setting up alerts.',\n },\n {\n key: 'nps-summary',\n prompt:\n 'Show me NPS responses from my paid users and summarize the themes',\n description: 'Pulse-check on the people paying you.',\n },\n ],\n product: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'onboarding',\n prompt:\n 'Build a funnel for my onboarding flow and show me the biggest drop-off step',\n description: 'See where new users drop off in their first session.',\n },\n {\n key: 'pricing-flag-state',\n prompt:\n \"Show me feature flags scoped to the pricing page and who's currently in each\",\n description:\n 'Inspect rollout state of pricing experiments without changing anything.',\n },\n {\n key: 'cta-compare',\n prompt:\n 'Show me how my upgrade CTA variants are converting across my recent experiments',\n description:\n 'Read the verdict on CTA tests without spinning up a new one.',\n },\n {\n key: 'retention',\n prompt: 'Compute week-1 retention split by acquisition channel',\n description: 'Find the channel that actually retains users.',\n },\n ],\n leadership: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'board-dashboard',\n prompt:\n 'Build a board dashboard with revenue, MAU, churn, and support backlog, then save it',\n description: 'Pre-board prep in one prompt.',\n },\n {\n key: 'mau-growth',\n prompt: 'Show MAU growth over the last 4 quarters',\n description: 'The chart for the next leadership slide.',\n },\n {\n key: 'churn-trend',\n prompt: 'Show me churn over the last 8 weeks and where it moved most',\n description: 'See the trend without configuring a notification.',\n },\n {\n key: 'upgrade-drivers',\n prompt: 'Which features drive the most upgrades?',\n description: 'Ranked breakdown of what actually moves the needle.',\n },\n ],\n marketing: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'pricing-leavers',\n prompt:\n \"Show me users who saw pricing but didn't sign up — what did they do next?\",\n description: 'Identify high-intent visitors and what they bounced to.',\n },\n {\n key: 'hero-compare',\n prompt:\n 'Show me how my landing page hero variants performed — which group converted best?',\n description: 'Read the verdict on hero copy tests.',\n },\n {\n key: 'newsletter-clicks',\n prompt:\n 'Find users who clicked our last newsletter and show me what they did next',\n description: 'See the downstream behavior of your last campaign.',\n },\n {\n key: 'landing-annotation',\n prompt: 'Annotate today as the launch of the new landing page',\n description: 'Pin the deploy on every chart so future you can find it.',\n },\n ],\n engineering: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'stale-flags',\n prompt:\n \"List flags rolled out to 100% — they're probably safe to delete\",\n description: 'Dead-code hunt for your feature flag config.',\n },\n {\n key: 'top-errors',\n prompt: 'Show me the top 5 unresolved errors this week',\n description: 'Triage queue without opening another tab.',\n },\n {\n key: 'reliability-trend',\n prompt: 'Show me 5xx error rate over the last 24 hours by endpoint',\n description: 'See where reliability is drifting, no alert setup.',\n },\n {\n key: 'zero-rollout-flags',\n prompt:\n 'Show me feature flags currently rolled out at 0% — anything ready to retire?',\n description: 'Find dead kill-switch flags you can clean up later.',\n },\n ],\n data: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'top-events-24h',\n prompt: 'Top 5 events by volume in the last 24 hours',\n description: 'Smoke test for ingestion + a sanity check on volumes.',\n },\n {\n key: 'paid-retention',\n prompt: 'Retention curve for paid users by signup month',\n description: \"The cohort chart you'd build first anyway.\",\n },\n {\n key: 'full-funnel',\n prompt: 'Funnel: signup → activated → first power feature → paid',\n description: 'Drop-off across the full journey, ready to slice.',\n },\n {\n key: 'power-users-query',\n prompt:\n 'Show me users with 5+ sessions per week over the last month and what they have in common',\n description:\n 'Profile your power-user segment without materializing a cohort.',\n },\n ],\n },\n roleFamilyOverrides: {\n product: {\n 'frontend-web': {\n 'cta-compare': {\n prompt:\n 'Compare conversion across the variants of my last upgrade CTA experiment (control, red, green)',\n description: 'Read the verdict on a three-arm frontend experiment.',\n },\n },\n mobile: {\n onboarding: {\n prompt:\n 'Build a funnel app_open → onboarding_complete → first_session_complete and show me the drop-off',\n description:\n 'Mobile-flavored onboarding funnel with sensible defaults.',\n },\n 'cta-compare': {\n prompt:\n \"Show me feature flags gated on app version — who's in each release tier?\",\n description: 'See which clients see what, without changing anything.',\n },\n },\n backend: {\n onboarding: {\n prompt: 'Funnel of signup → first API call → paid for last 30 days',\n description:\n 'Backend funnel that reflects what your service actually sees.',\n },\n },\n },\n engineering: {\n 'frontend-web': {\n 'top-errors': {\n prompt:\n 'Top 5 JS errors by occurrence count this week, with affected URLs',\n description:\n 'Frontend-specific error triage — sorted by blast radius.',\n },\n },\n mobile: {\n 'top-errors': {\n prompt:\n 'Top crashes this week by app version, sorted by affected users',\n description:\n 'Mobile crash triage straight from the same data PostHog has.',\n },\n 'reliability-trend': {\n prompt:\n 'Show me crash-free sessions over the last 7 days by app version',\n description:\n 'Crash-free trend per release — the one mobile metric that matters.',\n },\n },\n backend: {\n 'top-errors': {\n prompt: 'Top 5 server-side errors this week, grouped by endpoint',\n description: 'Backend error triage by route, sorted by frequency.',\n },\n 'reliability-trend': {\n prompt:\n 'Show me p95 response time over the last 24 hours by endpoint',\n description: 'Latency trend from the data you already collect.',\n },\n },\n },\n data: {\n backend: {\n 'full-funnel': {\n prompt:\n 'Funnel: api_signup → first_api_call → first_paid_event over last 30 days',\n description:\n 'Backend conversion funnel — captures the value your service delivers.',\n },\n },\n },\n },\n roleGreetings: {\n founder: {\n headline: 'Founders use MCP to keep a hand on growth.',\n bullets: [\n 'Weekly active users, retention, and revenue without leaving your IDE.',\n 'Spot stalls in your trends without setting up dashboards by hand.',\n 'Pin annotations on every chart so you remember what shipped.',\n ],\n outro:\n \"Pick a prompt — your agent will run it on your project's real data.\",\n },\n product: {\n headline: 'PMs use MCP to learn faster and decide quicker.',\n bullets: [\n 'Funnels for every onboarding flow you want to inspect.',\n 'Inspect feature flags and experiment outcomes without leaving your IDE.',\n 'Retention sliced by acquisition channel in seconds.',\n ],\n outro: 'Pick a prompt — your agent will do the legwork.',\n },\n leadership: {\n headline: 'Read the business from your terminal.',\n bullets: [\n 'Board-ready dashboards in one prompt.',\n 'Trend lines for MAU, churn, and revenue, one query away.',\n 'The numbers for the next leadership slide, on tap.',\n ],\n outro: 'Pick a prompt to see PostHog work for you.',\n },\n marketing: {\n headline: 'Inspect campaigns, end to end.',\n bullets: [\n 'Find high-intent visitors and what they did next.',\n 'Compare landing-copy experiments and see which arm is winning.',\n 'Tie every campaign to revenue with annotated launches.',\n ],\n outro: 'Pick a prompt to try it on your data.',\n },\n engineering: {\n headline: 'MCP is your shortest path from bug to root cause.',\n bullets: [\n 'Top errors this week, sorted by blast radius.',\n 'Latency and crash-free trends checked against real data.',\n 'Audit which flags are stale or fully rolled out.',\n ],\n outro: 'Pick a prompt — your agent has read access across your project.',\n },\n data: {\n headline: 'Data work without leaving the terminal.',\n bullets: [\n 'Profile any segment in seconds.',\n 'Retention curves by signup month, sliced any way you want.',\n 'Run SQL against your event stream — no copy-paste, no exports.',\n ],\n outro: 'Pick a prompt — every result is real data from your project.',\n },\n },\n neutralGreeting: {\n headline: 'PostHog MCP turns your agent into a product analyst.',\n bullets: [\n 'Run queries, build insights, save dashboards — straight from your IDE.',\n 'Every result is real data from your project.',\n 'No copy-pasting tokens, no context switching.',\n ],\n outro: 'Pick a prompt to see what MCP can do.',\n },\n toolFollowUps: {\n 'query-error-tracking-issue': [\n {\n label: 'Stack trace for the top error',\n prompt:\n 'Show me the stack trace and recent occurrences for the top error.',\n },\n {\n label: 'Who is most affected?',\n prompt:\n 'Which users have hit that error most often in the last 7 days?',\n },\n {\n label: 'When did it start?',\n prompt:\n 'Show me when that error first appeared and any deploy that landed nearby.',\n },\n {\n label: 'Find related sessions',\n prompt:\n 'Find session recordings that hit that error so I can see what users were doing.',\n },\n {\n label: 'Save the top-errors view',\n prompt: 'Save this top-errors view as an insight I can come back to.',\n },\n {\n label: 'Pin to engineering dashboard',\n prompt: 'Pin this errors view to my engineering dashboard.',\n },\n ],\n 'query-trends': [\n {\n label: 'Break down by property',\n prompt: 'Break that trend down by the most common user property.',\n },\n {\n label: 'Find the outlier day',\n prompt: 'Which day stood out the most and what else was going on?',\n },\n {\n label: 'Compare to last month',\n prompt: 'Compare that against the same period last month.',\n },\n {\n label: 'Build a funnel from it',\n prompt: 'Build a funnel using the top events from that trend.',\n },\n {\n label: 'Save as an insight',\n prompt: \"Save that trend as an insight named 'Trends'.\",\n },\n {\n label: 'Pin to main dashboard',\n prompt: 'Pin that trend to my main dashboard.',\n },\n ],\n 'query-funnel': [\n {\n label: 'Biggest drop-off',\n prompt: 'Which step has the biggest drop-off, and who falls out there?',\n },\n {\n label: 'Completion time',\n prompt: 'How long does it take users who complete that funnel?',\n },\n {\n label: 'Slice by platform',\n prompt: 'Show that funnel split by mobile vs desktop.',\n },\n {\n label: 'Find drop-off sessions',\n prompt:\n 'Find session recordings of users who dropped out at the biggest step.',\n },\n {\n label: 'Save the funnel',\n prompt: 'Save that funnel as an insight.',\n },\n {\n label: 'Pin to dashboard',\n prompt: 'Pin that funnel to my main dashboard.',\n },\n ],\n 'query-retention': [\n {\n label: 'Best-retaining cohort',\n prompt: 'Which cohort retains the longest in that curve?',\n },\n {\n label: 'Worst-retaining cohort',\n prompt: 'Which cohort drops off fastest in that curve?',\n },\n {\n label: 'Slice by acquisition channel',\n prompt: 'Re-run that retention split by acquisition channel.',\n },\n {\n label: 'Find churned users',\n prompt: 'Find session recordings of users who churned during week 1.',\n },\n {\n label: 'Save the retention chart',\n prompt: 'Save that retention chart as an insight.',\n },\n {\n label: 'Pin to growth dashboard',\n prompt: 'Pin that retention chart to my growth dashboard.',\n },\n ],\n 'query-feature-flag': [\n {\n label: \"Who's in this flag?\",\n prompt:\n 'Show me which users are currently in the rollout for that flag.',\n },\n {\n label: 'What changed recently?',\n prompt:\n 'Show me the rollout history for that flag — when did it last change?',\n },\n {\n label: 'Compare against another flag',\n prompt:\n 'Show me the audience overlap between that flag and one related flag.',\n },\n {\n label: 'Find sessions for that flag',\n prompt:\n 'Find recent session recordings from users currently in that flag.',\n },\n {\n label: 'Save flag inventory',\n prompt: 'Save this flag inventory as an insight.',\n },\n {\n label: 'Pin to release dashboard',\n prompt: 'Pin this flag view to my release dashboard.',\n },\n ],\n 'query-survey-responses': [\n {\n label: 'Summarize the themes',\n prompt: 'Summarize the themes from those survey responses.',\n },\n {\n label: 'Score distribution',\n prompt: 'Show me the score distribution across those responses.',\n },\n {\n label: 'Who are the detractors?',\n prompt: 'Show me users who left a low score and what they did next.',\n },\n {\n label: 'Find their sessions',\n prompt: 'Find session recordings from users who left a low score.',\n },\n {\n label: 'Save the response summary',\n prompt: 'Save this response summary as an insight.',\n },\n {\n label: 'Add to research notebook',\n prompt: 'Add this survey summary to my user research notebook.',\n },\n ],\n 'query-experiment': [\n {\n label: 'Which variant is winning?',\n prompt:\n 'Show me the conversion rate of each variant in that experiment.',\n },\n {\n label: 'Slice by segment',\n prompt: 'Show me how each variant performed by user segment.',\n },\n {\n label: 'Statistical significance',\n prompt: 'Has that experiment reached statistical significance yet?',\n },\n {\n label: 'Find variant sessions',\n prompt: 'Find session recordings from users in the winning variant.',\n },\n {\n label: 'Save the readout',\n prompt: 'Save that experiment readout as an insight.',\n },\n {\n label: 'Add to experiment notebook',\n prompt: 'Add this experiment readout to my experiments notebook.',\n },\n ],\n 'query-session-recordings-list': [\n {\n label: 'Summarize what users did',\n prompt: 'Summarize what users did in those sessions.',\n },\n {\n label: 'Find common drop-offs',\n prompt:\n \"What's the most common step where users got stuck in those sessions?\",\n },\n {\n label: 'Errors in those sessions',\n prompt: 'Which errors fired most often across those sessions?',\n },\n {\n label: 'Properties of those users',\n prompt:\n 'Show me the most common user properties across those sessions.',\n },\n {\n label: 'Save the session summary',\n prompt: 'Save the summary of those sessions as an insight.',\n },\n {\n label: 'Add to UX notebook',\n prompt: 'Add these session findings to my UX research notebook.',\n },\n ],\n 'execute-sql': [\n {\n label: 'Add p50/p90/p99',\n prompt: 'Re-run that query with p50/p90/p99 added.',\n },\n {\n label: 'Slice differently',\n prompt: 'Re-run that query grouped by the most common user property.',\n },\n {\n label: 'Find the outliers',\n prompt: 'Re-run that query and surface the top 5 outliers.',\n },\n {\n label: 'Compare to last week',\n prompt: 'Compare that query result to the same window last week.',\n },\n {\n label: 'Save as an insight',\n prompt: 'Turn that query result into a saved insight.',\n },\n {\n label: 'Pin to data dashboard',\n prompt: 'Pin that query result to my data dashboard.',\n },\n ],\n 'create-dashboard': [\n {\n label: 'Add another tile',\n prompt: 'Add a tile showing daily active users to that dashboard.',\n },\n {\n label: 'Add a leaderboard tile',\n prompt: 'Add a top-5 users tile to that dashboard.',\n },\n {\n label: 'Annotate today',\n prompt: 'Annotate today on that dashboard as the launch baseline.',\n },\n {\n label: 'Compare to last quarter',\n prompt:\n 'Add a tile comparing this quarter to the last on the same dashboard.',\n },\n {\n label: 'Add an errors tile',\n prompt:\n 'Add a tile showing the top 3 errors this week to that dashboard.',\n },\n {\n label: 'Add to dashboards notebook',\n prompt: 'Add a link to that dashboard in my dashboards notebook.',\n },\n ],\n 'create-insight': [\n {\n label: 'Pin to main dashboard',\n prompt: 'Pin that insight to my main dashboard.',\n },\n {\n label: 'Split by user property',\n prompt: 'Re-run that insight split by the most common user property.',\n },\n {\n label: 'Compare to a control',\n prompt:\n 'Re-run that insight comparing paid vs free users side-by-side.',\n },\n {\n label: 'Save the underlying query',\n prompt:\n 'Save the underlying query for that insight so I can edit it later.',\n },\n {\n label: 'Add to notebook',\n prompt: 'Add that insight to my analytics notebook.',\n },\n {\n label: 'Annotate the moment',\n prompt: 'Annotate today on the chart for that insight.',\n },\n ],\n },\n roleFollowUps: {\n founder: [\n {\n label: 'Pin to exec dashboard',\n prompt: 'Add that result to my exec dashboard.',\n },\n {\n label: 'Tie it to revenue',\n prompt: 'How does that correlate with paid conversions?',\n },\n {\n label: 'Compare to last quarter',\n prompt: 'How does that compare against the same period last quarter?',\n },\n {\n label: 'Save for board update',\n prompt:\n 'Save that as an insight I can attach to the next board update.',\n },\n ],\n product: [\n {\n label: 'Build a funnel around it',\n prompt: 'Build a funnel that includes that step.',\n },\n {\n label: 'Find high-intent users',\n prompt: 'Show me which users in that group also completed activation.',\n },\n {\n label: 'Check related experiments',\n prompt: 'Show me how this metric trended across my recent experiments.',\n },\n {\n label: 'Save to product notebook',\n prompt: 'Add this finding to my product analytics notebook.',\n },\n ],\n leadership: [\n {\n label: 'Compare to last quarter',\n prompt: 'How does that compare against the same period last quarter?',\n },\n {\n label: 'Pin to leadership dashboard',\n prompt: 'Pin this view to my leadership dashboard.',\n },\n {\n label: 'Save for next meeting',\n prompt:\n 'Save this as an insight I can pull up in the next leadership meeting.',\n },\n ],\n marketing: [\n {\n label: 'Annotate the launch',\n prompt: 'Annotate today as the campaign launch on that chart.',\n },\n {\n label: 'What did they do next?',\n prompt: 'Show me what users in that group did next.',\n },\n {\n label: 'Tie back to channel',\n prompt: 'Split that result by acquisition channel.',\n },\n {\n label: 'Compare to landing tests',\n prompt:\n 'Compare this result across my recent landing-page experiments.',\n },\n ],\n engineering: [\n {\n label: 'Did a deploy land?',\n prompt: 'Did that change land alongside a deploy in the last 24 hours?',\n },\n {\n label: 'Flag changes that fit',\n prompt:\n 'Show me which feature flag changes correlate with that change in metric.',\n },\n {\n label: 'Group by release',\n prompt: 'Re-run that broken down by app version or release.',\n },\n {\n label: 'Save to incident notebook',\n prompt: 'Save this analysis to my incident notebook.',\n },\n ],\n data: [\n {\n label: 'Add percentiles',\n prompt: 'Add p50/p90/p99 distributions to that result.',\n },\n {\n label: 'Compare to last month',\n prompt: 'Show me how that result trended over the last month.',\n },\n {\n label: 'Save as an insight',\n prompt: 'Save that query result as an insight.',\n },\n {\n label: 'Pin to data dashboard',\n prompt: 'Pin this result to my data team dashboard.',\n },\n ],\n },\n genericFollowUps: [\n {\n label: 'Go one level deeper',\n prompt: 'Run that same question one level deeper.',\n },\n {\n label: 'Take a different angle',\n prompt: 'Look at the same question from a completely different angle.',\n },\n {\n label: 'Find the surprise',\n prompt: \"What's the most surprising thing in that result?\",\n },\n {\n label: 'Slice by user',\n prompt: 'Re-run that split by the highest-value user segment.',\n },\n {\n label: 'Compare with last month',\n prompt: 'How does that look compared to the same window a month ago?',\n },\n {\n label: 'Save as an insight',\n prompt: 'Save that result as an insight I can come back to.',\n },\n {\n label: 'Pin to a dashboard',\n prompt: 'Pin this view to my main dashboard.',\n },\n {\n label: 'Add to a notebook',\n prompt: 'Add this finding to my notebook.',\n },\n ],\n deepDiveFollowUps: [\n {\n label: 'Save this exploration',\n prompt:\n 'Save the most useful chart from this session as a dashboard I can come back to.',\n },\n {\n label: 'Summarize what we found',\n prompt:\n 'Summarize the key findings from everything we just looked at in 3 bullets.',\n },\n {\n label: 'Pin a session summary',\n prompt: 'Pin a summary of this session to my main dashboard.',\n },\n {\n label: 'Write to a notebook',\n prompt:\n 'Write everything we just covered into a notebook entry I can revisit.',\n },\n ],\n crossSellByRole: {\n founder: [\n {\n product: 'Session Replay',\n prompt:\n 'Find 3 recent sessions where a user looked at pricing but did not sign up.',\n description:\n 'Watch what users see — replay turns funnel drop-offs into video.',\n },\n {\n product: 'Surveys',\n prompt:\n 'Show me how my NPS results have trended over the last quarter.',\n description: 'Quantitative pulse check on the survey side of PostHog.',\n },\n ],\n product: [\n {\n product: 'Experiments',\n prompt:\n 'Show me results from my latest onboarding experiment — which variant is winning?',\n description:\n 'Experiments piggyback on flags — same SDK, all readable here.',\n },\n {\n product: 'Session Replay',\n prompt:\n 'Find sessions where users got stuck on the empty state in onboarding.',\n description: \"See what funnels can't show you.\",\n },\n ],\n leadership: [\n {\n product: 'Surveys',\n prompt:\n 'Show me NPS scores from the last quarter — who are the detractors?',\n description: 'Read the survey data PostHog already collects for you.',\n },\n {\n product: 'Data Warehouse',\n prompt:\n 'Compare MRR by signup source using Stripe data joined with event data.',\n description:\n 'Query revenue alongside events when warehouse is connected.',\n },\n ],\n marketing: [\n {\n product: 'Session Replay',\n prompt:\n 'Watch 5 sessions from users who came via our last campaign and converted.',\n description: 'See campaign visitors behave — beyond aggregate numbers.',\n },\n {\n product: 'Web Analytics',\n prompt: 'Show me top traffic sources to the pricing page this week.',\n description: 'GA-style first-party web analytics, no cookie banner.',\n },\n ],\n engineering: [\n {\n product: 'Error Tracking',\n prompt: 'Show me the top 5 errors this week and who is affected.',\n description: 'Built-in error tracking — no Sentry subscription.',\n },\n {\n product: 'Session Replay',\n prompt: 'Replay the last 3 sessions that hit a 5xx error.',\n description: 'Stack trace meets replay — see what the user did.',\n },\n ],\n data: [\n {\n product: 'Data Warehouse',\n prompt:\n 'Join my event stream with Stripe subscriptions to surface churn signals.',\n description:\n 'Connect Stripe / Salesforce / S3, query everything with SQL.',\n },\n {\n product: 'LLM Observability',\n prompt: 'Show me the top 5 LLM prompts by cost over the last 7 days.',\n description:\n 'Track LLM calls, latency, and cost next to product events.',\n },\n ],\n },\n neutralCrossSell: [\n {\n product: 'Session Replay',\n prompt:\n 'Show me 5 recent sessions where users dropped off before completing signup.',\n description: 'Replay what users actually do — included on every plan.',\n },\n {\n product: 'Error Tracking',\n prompt: 'List the top errors my users hit this week.',\n description: 'Built-in error tracking — no separate tool.',\n },\n ],\n '$generated-note':\n \"Templates filled at runtime from the project's REAL event names (getGeneratedQuests). {events} → a comma list of top custom events; {event} → the single busiest custom event. The agent orders funnel steps sensibly, so volume-sorted input is fine.\",\n generatedQuests: {\n funnel: {\n label: 'Funnel your real events',\n prompt:\n 'Build a funnel from these events in the most sensible order — {events} — over the last 30 days, and show me the biggest drop-off.',\n },\n trend: {\n label: 'Trend {event}',\n prompt:\n 'Show me a daily trend of {event} over the last 30 days and call out the biggest spike or dip.',\n },\n breakdown: {\n label: 'Break down {event}',\n prompt:\n 'Break down {event} over the last 30 days by the most common user property and show me the top segments.',\n },\n },\n '$write-only-note':\n 'Quests for empty / data-less projects: every entry is a write on the dashboard/insight/notebook/annotation surfaces, so it produces a real artifact regardless of event history. No reads that would come back empty.',\n writeOnlyQuests: [\n {\n key: 'verify',\n prompt: \"Annotate today with 'PostHog wizard install'\",\n description:\n 'Creates a dated note on your project — visible on every chart. Delete anytime from PostHog.',\n },\n {\n key: 'starter-dashboard',\n prompt:\n \"Create a starter dashboard called 'My first dashboard (wizard MCP tutorial)' with a daily-active-users tile and a top-events tile.\",\n description:\n 'A real dashboard you can build on — no event history required.',\n },\n ],\n '$activation-note':\n \"Surfaced (getActivationCrossSell) for products the scout found NO data for — turns a data-less dead end into a product-discovery beat. Prompts route through docs-search, which always returns something, so they never dead-end. Picker prefixes 'Try {product} —'.\",\n activationCrossSell: {\n errorTracking: {\n product: 'Error Tracking',\n label: \"see what it'd catch\",\n prompt:\n \"I don't have error tracking data yet. Show me how to turn on PostHog Error Tracking in my stack and what it would capture.\",\n description: 'Built-in exception tracking — no separate Sentry bill.',\n },\n sessionReplay: {\n product: 'Session Replay',\n label: 'watch real sessions',\n prompt:\n \"I don't have session recordings yet. Show me how to enable PostHog Session Replay and what I'd be able to see.\",\n description: 'Watch what users actually do — included on every plan.',\n },\n surveys: {\n product: 'Surveys',\n label: 'ask your users',\n prompt:\n \"I'm not running surveys yet. Show me how to launch a PostHog survey and the kinds of questions teams ask.\",\n description: 'In-app surveys and NPS, collected next to your events.',\n },\n webAnalytics: {\n product: 'Web Analytics',\n label: 'GA-style dashboards',\n prompt:\n \"I don't have pageview data yet. Show me how to enable PostHog Web Analytics and what the dashboard shows.\",\n description: 'First-party web analytics — no cookie banner.',\n },\n experiments: {\n product: 'Experiments',\n label: 'A/B test safely',\n prompt:\n \"I haven't run experiments yet. Show me how PostHog Experiments work and what I'd need to start one.\",\n description: 'A/B tests that piggyback on your feature flags.',\n },\n featureFlags: {\n product: 'Feature Flags',\n label: 'ship behind a flag',\n prompt:\n \"I don't have feature flags yet. Show me how to add a PostHog feature flag in my framework and how rollout works.\",\n description: 'Gradual rollouts and kill switches, evaluated locally.',\n },\n dataWarehouse: {\n product: 'Data Warehouse',\n label: 'join external data',\n prompt:\n \"Show me how to connect a data warehouse source like Stripe to PostHog and what I could query once it's joined.\",\n description: 'Query Stripe / Salesforce / S3 alongside your events.',\n },\n },\n '$seed-offer-note':\n 'Shown in the SeedOffer phase for empty projects (idea 15).',\n seedOfferGreeting: {\n headline: \"Fresh project — let's put something on the map.\",\n bullets: [\n \"Your project hasn't logged events yet, so there's nothing to chart — yet.\",\n 'I can send a small demo dataset so you can see funnels, trends, and dashboards in action.',\n 'Everything is tagged wizard_seed:true and uses wizard-demo-user-* distinct IDs — events are immutable in PostHog, but you can filter these out of any query.',\n ],\n outro: 'Want me to seed some demo data to explore?',\n },\n};\n\nexport default copy;\n","/**\n * Role + framework-tailored MCP prompt suggestions.\n *\n * All copy lives in `mcp-role-prompts.copy.ts`, a plain data module, so\n * prompts can be edited without touching the logic. This file holds the\n * types, the lookup functions, and the framework-family mapping.\n *\n * Editing rule for the copy: every prompt is either (a) a read query on\n * any PostHog product, or (b) a write on dashboards, insights, notebooks,\n * or annotations — the four \"persistence\" surfaces. No prompt should ask\n * the agent to ship a flag, run an experiment, send a survey, or create an\n * alert. See prompt-tree.md §5 for the scope reality.\n *\n * The wizard surfaces these on the McpSuggestedPromptsScreen after\n * MCP install. Picking strategy for the kit:\n * 1. Known role + known framework → role kit with family overrides.\n * 2. Known role + unknown framework → role kit, no overrides.\n * 3. Unknown role → DEFAULT_KIT.\n */\n\nimport type { Integration } from '@shared/constants';\nimport type {\n ProductPresence,\n ProjectDataProfile,\n} from './mcp-project-profile';\nimport copyData from './mcp-role-prompts.copy';\n\n/** Keys of `ProductPresence` — the products an activation cross-sell can target. */\nexport type ProductKey = keyof ProductPresence;\n\n/**\n * Roles that ship from `role_at_organization` on the PostHog user object.\n * `security` isn't in the enum upstream — the engineering kit covers\n * that audience.\n */\nexport const TAILORED_ROLES = [\n 'founder',\n 'product',\n 'leadership',\n 'marketing',\n 'engineering',\n 'data',\n] as const;\n\nexport type TailoredRole = (typeof TAILORED_ROLES)[number];\n\n/**\n * Unified shape for every clickable picker entry the screen renders —\n * initial-picker kit prompts, cross-sell prompts, and follow-up prompts.\n * The three flavors are distinguished by which optional fields they\n * populate, not by separate types:\n *\n * kit prompt → { prompt, description }\n * cross-sell prompt → { prompt, description, product }\n * follow-up prompt → { prompt, label }\n */\nexport interface PromptOption {\n /** Sent to the agent when picked. Also serves as the picker label when `label` is omitted. */\n prompt: string;\n /** Optional picker label override. Follow-ups use this to show a short verb-phrase (\"Save as dashboard\") instead of the full prompt. */\n label?: string;\n /** Optional one-line description shown by the Goodbye sample list. */\n description?: string;\n /** Optional product tag — when present, picker prepends \"Try {product} —\" to the label. */\n product?: string;\n /** Stable identifier used by `roleFamilyOverrides` to target a kit entry by name (reorder-safe). Populated on kit entries; left out on cross-sells and follow-ups. */\n key?: string;\n}\n\nexport type PromptKit = PromptOption[];\n\n/**\n * Buckets `Integration` values into broader framework families so we can\n * write one kit per family instead of per individual integration.\n */\nexport type FrameworkFamily =\n | 'frontend-web'\n | 'mobile'\n | 'backend'\n | 'fullstack'\n | 'unknown';\n\nexport interface RoleGreeting {\n /** 1-line hook — typewrites in. */\n headline: string;\n /** 2-3 lines of value framing — revealed line-by-line. */\n bullets: string[];\n /** Sets up the picker, e.g. \"Pick one to try.\" — fades in. */\n outro: string;\n}\n\nexport const FOLLOW_UP_EXIT_SENTINEL = '__follow_up_exit__';\n/** How many follow-up suggestions to surface above the exit entry. */\nexport const FOLLOW_UP_COUNT = 3;\n\n// ── Data loaded from JSON ──────────────────────────────────────────────\n// One cast per top-level key. JSON imports lose the precise key\n// constraints (e.g. Record<TailoredRole, ...>), so we re-attach them\n// here. TypeScript can still catch shape mismatches at the call site.\n\n/**\n * Always shown as the picker's first option regardless of role —\n * a safe generic read that works on any project setup. The screen\n * prepends it and dedupes against the role kit so it never appears\n * twice when DEFAULT_KIT happens to include it.\n */\nexport const PINNED_FIRST_PROMPT = copyData.pinnedFirstPrompt as PromptOption;\n\nconst DEFAULT_KIT = copyData.defaultKit as PromptKit;\nconst ROLE_KITS = copyData.roleKits as Record<TailoredRole, PromptKit>;\n// Overrides are keyed by a base-kit entry's `key` (e.g. \"onboarding\",\n// \"top-errors\") so a kit reorder doesn't silently shift overrides to\n// the wrong slot. Each override is a partial PromptOption that gets\n// merged onto the base entry.\nconst ROLE_FAMILY_OVERRIDES = copyData.roleFamilyOverrides as Partial<\n Record<\n TailoredRole,\n Partial<Record<FrameworkFamily, Record<string, PromptOption>>>\n >\n>;\nconst ROLE_GREETINGS = copyData.roleGreetings as Record<\n TailoredRole,\n RoleGreeting\n>;\nconst NEUTRAL_GREETING = copyData.neutralGreeting as RoleGreeting;\nconst TOOL_FOLLOW_UPS = copyData.toolFollowUps as Record<\n string,\n PromptOption[]\n>;\nconst ROLE_FOLLOW_UPS = copyData.roleFollowUps as Record<\n TailoredRole,\n PromptOption[]\n>;\nconst GENERIC_FOLLOW_UPS = copyData.genericFollowUps as PromptOption[];\nconst DEEP_DIVE_FOLLOW_UPS = copyData.deepDiveFollowUps as PromptOption[];\nconst CROSS_SELL_BY_ROLE = copyData.crossSellByRole as Record<\n TailoredRole,\n PromptOption[]\n>;\nconst NEUTRAL_CROSS_SELL = copyData.neutralCrossSell as PromptOption[];\n// Data-aware surfaces — templates + copy for the scout-driven picker.\nconst GENERATED_QUESTS = copyData.generatedQuests as {\n funnel: { label: string; prompt: string };\n trend: { label: string; prompt: string };\n breakdown: { label: string; prompt: string };\n};\nconst WRITE_ONLY_QUESTS = copyData.writeOnlyQuests as PromptKit;\nconst ACTIVATION_CROSS_SELL = copyData.activationCrossSell as Record<\n ProductKey,\n PromptOption\n>;\nconst SEED_OFFER_GREETING = copyData.seedOfferGreeting as RoleGreeting;\n\n// ── Framework family map ───────────────────────────────────────────────\n// Stays in code (not JSON) because it's structural data tied to the\n// `Integration` enum, not user-facing copy.\n\nconst INTEGRATION_FAMILY: Record<string, FrameworkFamily> = {\n nextjs: 'fullstack',\n nuxt: 'fullstack',\n 'tanstack-start': 'fullstack',\n astro: 'fullstack',\n sveltekit: 'fullstack',\n vue: 'frontend-web',\n angular: 'frontend-web',\n 'react-router': 'frontend-web',\n 'tanstack-router': 'frontend-web',\n javascript_web: 'frontend-web',\n 'react-native': 'mobile',\n swift: 'mobile',\n android: 'mobile',\n django: 'backend',\n flask: 'backend',\n fastapi: 'backend',\n python: 'backend',\n laravel: 'backend',\n rails: 'backend',\n ruby: 'backend',\n javascript_node: 'backend',\n};\n\nconst EXIT_FOLLOW_UP: PromptOption = {\n label: \"I'm done — exit\",\n prompt: FOLLOW_UP_EXIT_SENTINEL,\n};\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\nfunction isTailoredRole(role: string | null | undefined): role is TailoredRole {\n return (\n typeof role === 'string' &&\n (TAILORED_ROLES as readonly string[]).includes(role)\n );\n}\n\n/**\n * Strip MCP tool-name prefixes so lookup keys can stay short. Real MCP\n * tool names arrive as `mcp__<server>__<tool>`; the agent SDK also\n * sometimes drops the prefix. We take the substring after the last\n * double-underscore (or the input untouched if there's none).\n */\nfunction normalizeToolName(toolName: string | null): string | null {\n if (!toolName) return null;\n const idx = toolName.lastIndexOf('__');\n return idx >= 0 ? toolName.slice(idx + 2) : toolName;\n}\n\n/**\n * CLI mode wraps every real tool in a single `exec` tool whose `command`\n * string names the inner tool: `call query-trends {…}` → `query-trends`. The\n * inner name is the first token after `call` (past any `--flag` options).\n */\nconst EXEC_INNER_TOOL = /^call\\s+(?:--\\w+\\s+)*([a-z0-9-]+)/;\n\n/**\n * Resolve the `TOOL_FOLLOW_UPS` lookup key from the last tool call, under both\n * server modes. Tools mode passes the real tool name directly; CLI mode passes\n * `exec` plus the command string, so we extract the inner tool from it. A\n * non-`call` exec command (`search`, `info`) has no inner tool and yields null,\n * so the lookup falls through to the generic pools.\n */\nfunction resolveToolKey(\n toolName: string | null,\n toolCommand: string | null,\n): string | null {\n const normalized = normalizeToolName(toolName);\n if (normalized !== 'exec') return normalized;\n return toolCommand?.match(EXEC_INNER_TOOL)?.[1] ?? null;\n}\n\n/** Pick `n` items from a pool starting at a rotation offset. */\nfunction pickRotated<T>(pool: T[], n: number, rotation: number): T[] {\n if (pool.length === 0) return [];\n if (pool.length <= n) return pool;\n const start =\n ((Math.floor(rotation) % pool.length) + pool.length) % pool.length;\n const result: T[] = [];\n for (let i = 0; i < n; i++) {\n result.push(pool[(start + i) % pool.length]);\n }\n return result;\n}\n\n/** Drop duplicates while preserving order (by prompt text). */\nfunction dedupeFollowUps(list: PromptOption[]): PromptOption[] {\n const seen = new Set<string>();\n const out: PromptOption[] = [];\n for (const f of list) {\n if (seen.has(f.prompt)) continue;\n seen.add(f.prompt);\n out.push(f);\n }\n return out;\n}\n\n// ── Public API ─────────────────────────────────────────────────────────\n\nexport function getFrameworkFamily(\n integration: Integration | null | undefined,\n): FrameworkFamily {\n if (!integration) return 'unknown';\n return INTEGRATION_FAMILY[integration] ?? 'unknown';\n}\n\n/**\n * Resolve the right kit given everything we know about the user + project.\n * Always returns at least DEFAULT_KIT; never throws.\n */\nexport function getRolePrompts(\n role: string | null | undefined,\n integration: Integration | null | undefined,\n): PromptKit {\n const family = getFrameworkFamily(integration);\n\n if (!isTailoredRole(role)) {\n // Unknown role — DEFAULT_KIT is already framework-agnostic and broad.\n return DEFAULT_KIT;\n }\n\n const baseKit = ROLE_KITS[role];\n const overridesForRole = ROLE_FAMILY_OVERRIDES[role];\n const overridesForFamily = overridesForRole?.[family];\n\n if (!overridesForFamily) {\n return baseKit;\n }\n\n // Look up overrides by each entry's stable `key` so a kit reorder\n // doesn't shift overrides to the wrong slot. An entry without a key,\n // or a key not present in the override map, passes through unchanged.\n return baseKit.map((entry) => {\n const override = entry.key ? overridesForFamily[entry.key] : undefined;\n return override ?? entry;\n });\n}\n\nexport function getRoleGreeting(role: string | null | undefined): RoleGreeting {\n if (!isTailoredRole(role)) return NEUTRAL_GREETING;\n return ROLE_GREETINGS[role];\n}\n\n/**\n * Resolve `FOLLOW_UP_COUNT` context-aware follow-ups + an always-present\n * exit entry. Pulls from up to four pools — tool-specific, role-specific,\n * deep-dive (only after the user has explored a few steps), and generic —\n * dedupes, filters out anything already in `branchHistory`, then picks\n * `FOLLOW_UP_COUNT` with a rotation offset driven by `branchHistory.length`\n * so successive visits surface different slices.\n */\nexport function getFollowUps(args: {\n lastToolName: string | null;\n /** CLI mode's exec `command` string, used to recover the inner tool name. */\n lastToolCommand?: string | null;\n lastPrompt: string;\n role: string | null | undefined;\n branchHistory: string[];\n}): PromptOption[] {\n const { lastToolName, lastToolCommand, role, branchHistory } = args;\n const normalized = resolveToolKey(lastToolName, lastToolCommand ?? null);\n const depth = branchHistory.length;\n\n // Build the candidate pool — order matters because dedup keeps the\n // first occurrence. Tool-specific first (most relevant), then role,\n // then deep-dive (only after the user's been exploring), then generic.\n const candidates: PromptOption[] = [];\n if (normalized && TOOL_FOLLOW_UPS[normalized]) {\n candidates.push(...TOOL_FOLLOW_UPS[normalized]);\n }\n if (isTailoredRole(role)) {\n candidates.push(...ROLE_FOLLOW_UPS[role]);\n }\n if (depth >= 3) {\n candidates.push(...DEEP_DIVE_FOLLOW_UPS);\n }\n candidates.push(...GENERIC_FOLLOW_UPS);\n\n const deduped = dedupeFollowUps(candidates);\n const seen = new Set(branchHistory);\n const fresh = deduped.filter((f) => !seen.has(f.prompt));\n\n // Rotate by depth so repeat visits to the same tool surface different\n // slices of the pool. A user who keeps picking `query-trends` won't\n // see the same three options every time.\n const selected = pickRotated(fresh, FOLLOW_UP_COUNT, depth);\n\n return [...selected, EXIT_FOLLOW_UP];\n}\n\n/**\n * Cross-sell prompts to surface above the role kit in PromptPicker.\n * Filtered by role so the recommendations stay coherent (founders see\n * the \"exec-friendly\" cross-sells, engineers see \"debug-friendly\", etc).\n */\nexport function getCrossSellPrompts(\n role: string | null | undefined,\n): PromptOption[] {\n if (!isTailoredRole(role)) return NEUTRAL_CROSS_SELL;\n return CROSS_SELL_BY_ROLE[role];\n}\n\n// ── Data-aware picker (scout-driven) ───────────────────────────────────\n// Everything below consumes a ProjectDataProfile from the scout\n// (`probeProjectData`) so the tutorial only ever offers playable moves:\n// quests built from the project's real events when data exists, write-only\n// quests + product-activation cross-sells when it doesn't.\n\n/**\n * Order in which to offer activation cross-sells per role — products most\n * relevant to each audience first. Only products the scout found *absent*\n * are surfaced; this just picks which absent ones to lead with.\n */\nconst ACTIVATION_PRIORITY: Record<TailoredRole, ProductKey[]> = {\n founder: [\n 'sessionReplay',\n 'surveys',\n 'webAnalytics',\n 'experiments',\n 'dataWarehouse',\n 'errorTracking',\n 'featureFlags',\n ],\n product: [\n 'sessionReplay',\n 'experiments',\n 'surveys',\n 'featureFlags',\n 'webAnalytics',\n 'errorTracking',\n 'dataWarehouse',\n ],\n leadership: [\n 'surveys',\n 'dataWarehouse',\n 'sessionReplay',\n 'webAnalytics',\n 'experiments',\n 'errorTracking',\n 'featureFlags',\n ],\n marketing: [\n 'sessionReplay',\n 'webAnalytics',\n 'surveys',\n 'experiments',\n 'dataWarehouse',\n 'featureFlags',\n 'errorTracking',\n ],\n engineering: [\n 'errorTracking',\n 'sessionReplay',\n 'featureFlags',\n 'experiments',\n 'webAnalytics',\n 'dataWarehouse',\n 'surveys',\n ],\n data: [\n 'dataWarehouse',\n 'experiments',\n 'sessionReplay',\n 'webAnalytics',\n 'errorTracking',\n 'surveys',\n 'featureFlags',\n ],\n};\nconst NEUTRAL_ACTIVATION_PRIORITY: ProductKey[] = [\n 'sessionReplay',\n 'errorTracking',\n 'surveys',\n 'webAnalytics',\n 'experiments',\n 'featureFlags',\n 'dataWarehouse',\n];\n\n/** How many custom events to feed into a generated funnel prompt. */\nconst FUNNEL_EVENT_LIMIT = 4;\n\n/** Fill `{placeholder}` tokens in a template; unknown tokens pass through. */\nfunction fillTemplate(template: string, vars: Record<string, string>): string {\n return template.replace(\n /\\{(\\w+)\\}/g,\n (_, key: string) => vars[key] ?? `{${key}}`,\n );\n}\n\nexport function getSeedOfferGreeting(): RoleGreeting {\n return SEED_OFFER_GREETING;\n}\n\n/**\n * Generate quests from the project's REAL event names (idea 9). Returns a\n * funnel (when ≥2 custom events exist), a trend, and a breakdown — all\n * templated off `topCustomEvents`. Empty when there's nothing usable to\n * build from (no profile, degraded, or no custom events), so callers fall\n * back to the static kit.\n */\nexport function getGeneratedQuests(\n profile: ProjectDataProfile | null | undefined,\n): PromptOption[] {\n if (!profile || profile.degraded) return [];\n const custom = profile.topCustomEvents;\n if (custom.length === 0) return [];\n\n const out: PromptOption[] = [];\n const top = custom[0].name;\n\n if (custom.length >= 2) {\n const events = custom\n .slice(0, FUNNEL_EVENT_LIMIT)\n .map((e) => e.name)\n .join(', ');\n out.push({\n label: GENERATED_QUESTS.funnel.label,\n prompt: fillTemplate(GENERATED_QUESTS.funnel.prompt, { events }),\n });\n }\n out.push({\n label: fillTemplate(GENERATED_QUESTS.trend.label, { event: top }),\n prompt: fillTemplate(GENERATED_QUESTS.trend.prompt, { event: top }),\n });\n out.push({\n label: fillTemplate(GENERATED_QUESTS.breakdown.label, { event: top }),\n prompt: fillTemplate(GENERATED_QUESTS.breakdown.prompt, { event: top }),\n });\n return out;\n}\n\n/**\n * Activation cross-sells (idea 4) for products the scout found NO data\n * for — turning a data-less dead end into \"here's how to turn this on\".\n * Ordered by role affinity, capped at `limit`. Empty when the profile is\n * missing/degraded (we only nag when we're confident a product is absent).\n */\nexport function getActivationCrossSell(\n role: string | null | undefined,\n profile: ProjectDataProfile | null | undefined,\n limit = 2,\n): PromptOption[] {\n if (!profile || profile.degraded) return [];\n const priority = isTailoredRole(role)\n ? ACTIVATION_PRIORITY[role]\n : NEUTRAL_ACTIVATION_PRIORITY;\n return priority\n .filter((key) => profile.products[key] === false)\n .slice(0, limit)\n .map((key) => ACTIVATION_CROSS_SELL[key])\n .filter((o): o is PromptOption => Boolean(o));\n}\n\n/**\n * The full, ordered candidate list for the tutorial picker, composed from\n * the scout's profile. The screen dedupes by prompt text and slices to its\n * display cap — this function owns *what* to offer and in what priority:\n *\n * • no profile / degraded → legacy composition (pinned + cross-sell + kit)\n * • empty → write-only quests + activation cross-sells\n * (no reads that would return nothing)\n * • rich (+ real events) → generated quests first, one activation nudge,\n * then role kit for flavor\n * • sparse → a safe pinned read + one generated quest +\n * role kit + one activation nudge\n */\nexport function getTutorialPicker(\n role: string | null | undefined,\n integration: Integration | null | undefined,\n profile: ProjectDataProfile | null | undefined,\n): PromptOption[] {\n if (!profile || profile.degraded) {\n return [\n PINNED_FIRST_PROMPT,\n ...getCrossSellPrompts(role),\n ...getRolePrompts(role, integration),\n ];\n }\n\n if (profile.tier === 'empty') {\n return [...WRITE_ONLY_QUESTS, ...getActivationCrossSell(role, profile, 2)];\n }\n\n const generated = getGeneratedQuests(profile);\n\n if (profile.tier === 'rich' && generated.length > 0) {\n return [\n ...generated,\n ...getActivationCrossSell(role, profile, 1),\n ...getRolePrompts(role, integration),\n ];\n }\n\n // sparse — real but thin data: lead with a safe read, add one generated\n // quest if available, then role flavor and a single activation nudge.\n return [\n PINNED_FIRST_PROMPT,\n ...generated.slice(0, 1),\n ...getRolePrompts(role, integration),\n ...getActivationCrossSell(role, profile, 1),\n ];\n}\n","/**\n * Project data profile — a cheap, best-effort \"scout\" of what a user's\n * PostHog project actually contains. Run once after auth, before the MCP\n * tutorial picker, so the tutorial can adapt to the terrain instead of\n * offering prompts that hit a data-less dead end (the failure mode where\n * a freshly-installed project has no events and the agent narrates\n * emptiness because it was told this is a demo).\n *\n * The profile drives three data-aware behaviours in the tutorial:\n * • tier empty → offer to seed demo events; sparse/rich → go\n * straight to quests.\n * • topEvents quests are generated from the project's REAL event names\n * (e.g. a funnel between the two busiest custom events),\n * never from a generic hardcoded list.\n * • products a product with no data becomes an \"enable X\" cross-sell\n * (which routes through docs-search and always returns\n * something) instead of a read that comes back empty.\n *\n * Every probe is best-effort and time-boxed: a slow or failing call\n * resolves to a conservative fallback rather than throwing. The tutorial\n * must never be blocked, slowed, or broken by the scout — a degraded\n * profile (`degraded: true`) simply falls back to the static role kit and\n * skips activation cross-sells (we only nag the user to \"enable X\" when\n * we are CONFIDENT X is absent).\n */\n\nimport axios from 'axios';\nimport { WIZARD_USER_AGENT } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\n\n// Time-box every probe call. The scout sits on the critical path between\n// auth and the picker, so a wedged endpoint must not stall the tutorial.\nconst PROBE_TIMEOUT_MS = 5000;\n// Below this 30-day event count a project is \"sparse\": real data exists\n// but not enough to build confident multi-step funnels from.\nconst SPARSE_EVENT_THRESHOLD = 50;\n// How many event names to pull. Enough to find usable custom events for\n// quest generation without bloating the response.\nconst TOP_EVENTS_LIMIT = 25;\n// Probe window. Matches the tutorial's default \"last 30 days\" framing.\nconst PROBE_WINDOW_DAYS = 30;\n\n/**\n * Non-`$`-prefixed events that are still PostHog system noise, so they\n * don't get templated into quests as if they were product events.\n */\nconst NON_DOLLAR_SYSTEM_EVENTS = new Set([\n 'survey sent',\n 'survey shown',\n 'survey dismissed',\n]);\n\nexport type DataTier = 'empty' | 'sparse' | 'rich';\n\nexport interface EventVolume {\n /** Raw event name as stored in PostHog (e.g. \"$pageview\", \"checkout_started\"). */\n name: string;\n count: number;\n}\n\n/**\n * Which PostHog products have data in the project. Drives activation\n * cross-sells: a `false` here means \"offer to help the user turn this on\"\n * rather than \"run a read that returns nothing\". Conservative by design —\n * a field is only `false` when a probe ran cleanly and found nothing; an\n * unknown (failed/timed-out probe) defaults to `true` so we never nag a\n * user to enable something they already have.\n */\nexport interface ProductPresence {\n /** `$pageview` events seen → web analytics is live. */\n webAnalytics: boolean;\n /** `$exception` events seen → error tracking is live. */\n errorTracking: boolean;\n sessionReplay: boolean;\n surveys: boolean;\n featureFlags: boolean;\n experiments: boolean;\n dataWarehouse: boolean;\n}\n\nexport interface ProjectDataProfile {\n tier: DataTier;\n /** Total event volume over the probe window (last 30 days). */\n totalEvents: number;\n /** Number of distinct event names seen in the window. */\n distinctEventCount: number;\n /** Top events by volume (system + custom), most-frequent first. */\n topEvents: EventVolume[];\n /** Top *custom* events (system noise stripped) — what quests are built from. */\n topCustomEvents: EventVolume[];\n products: ProductPresence;\n /** True when produced by seeding rather than a live probe. */\n seeded: boolean;\n /** True when the probe failed/timed out and this is a safe fallback. */\n degraded: boolean;\n}\n\n/** Every product assumed present — the safe \"don't nag\" default. */\nconst ALL_PRODUCTS_PRESENT: ProductPresence = {\n webAnalytics: true,\n errorTracking: true,\n sessionReplay: true,\n surveys: true,\n featureFlags: true,\n experiments: true,\n dataWarehouse: true,\n};\n\n/**\n * Conservative fallback used when the core events probe fails. Tier is\n * `sparse` (not `empty`) so we neither offer to seed a project we can't\n * confirm is empty nor claim it's rich; `degraded` tells consumers to use\n * the static role kit and skip activation cross-sells.\n */\nexport function degradedProfile(): ProjectDataProfile {\n return {\n tier: 'sparse',\n totalEvents: 0,\n distinctEventCount: 0,\n topEvents: [],\n topCustomEvents: [],\n products: { ...ALL_PRODUCTS_PRESENT },\n seeded: false,\n degraded: true,\n };\n}\n\n/** Is this event name PostHog system noise rather than a product event? */\nfunction isSystemEvent(name: string): boolean {\n return name.startsWith('$') || NON_DOLLAR_SYSTEM_EVENTS.has(name);\n}\n\n/**\n * True only when the given ingestion host is a PostHog-managed cloud\n * region we know maps to a working ingestion endpoint. Used as a gate on\n * the seed offer: PostHog events are immutable in ClickHouse, so we must\n * NOT offer to write demo events into a self-hosted deployment where we\n * can't be sure the ingestion route will succeed (and where the operator\n * hasn't opted in to us leaving artifacts). Cloud-hosted users have\n * consented to the wizard's writes as part of using the hosted service.\n */\nexport function isKnownCloudHost(apiHost: string): boolean {\n try {\n const { host } = new URL(apiHost);\n return host === 'us.i.posthog.com' || host === 'eu.i.posthog.com';\n } catch {\n return false;\n }\n}\n\n/**\n * Pure profile assembler — turns raw probe outputs into a classified\n * profile. Exported so tier classification, custom-event filtering, and\n * product derivation can be unit-tested without touching the network.\n *\n * `rest` carries the REST existence checks; a `null` entry means the\n * check was inconclusive (failed/timed out) and the product defaults to\n * present so we never nag the user to enable it.\n */\nexport function assembleProfile(\n topEvents: EventVolume[],\n rest: {\n sessionReplay: boolean | null;\n surveys: boolean | null;\n featureFlags: boolean | null;\n experiments: boolean | null;\n dataWarehouse: boolean | null;\n },\n opts?: { seeded?: boolean },\n): ProjectDataProfile {\n const totalEvents = topEvents.reduce((sum, e) => sum + e.count, 0);\n const distinctEventCount = topEvents.length;\n const topCustomEvents = topEvents.filter((e) => !isSystemEvent(e.name));\n\n const has = (name: string): boolean =>\n topEvents.some((e) => e.name === name && e.count > 0);\n\n let tier: DataTier;\n if (totalEvents === 0) {\n tier = 'empty';\n } else if (totalEvents < SPARSE_EVENT_THRESHOLD || distinctEventCount < 2) {\n tier = 'sparse';\n } else {\n tier = 'rich';\n }\n\n return {\n tier,\n totalEvents,\n distinctEventCount,\n topEvents,\n topCustomEvents,\n products: {\n // Event-derived: an empty 30-day window for these events strongly\n // implies the product isn't wired up.\n webAnalytics: has('$pageview'),\n errorTracking: has('$exception'),\n // REST-derived: null (inconclusive) defaults to present.\n sessionReplay: rest.sessionReplay ?? true,\n surveys: rest.surveys ?? true,\n featureFlags: rest.featureFlags ?? true,\n experiments: rest.experiments ?? true,\n dataWarehouse: rest.dataWarehouse ?? true,\n },\n seeded: opts?.seeded ?? false,\n degraded: false,\n };\n}\n\n/**\n * Run a single HogQL query returning the top events by volume in the\n * probe window. Throws on any failure — the caller degrades the whole\n * profile when the core events probe can't run.\n */\nasync function queryTopEvents(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n): Promise<EventVolume[]> {\n const url = `${baseUrl}/api/projects/${projectId}/query/`;\n const response = await axios.post(\n url,\n {\n query: {\n kind: 'HogQLQuery',\n query: `SELECT event, count() AS c FROM events WHERE timestamp > now() - INTERVAL ${PROBE_WINDOW_DAYS} DAY GROUP BY event ORDER BY c DESC LIMIT ${TOP_EVENTS_LIMIT}`,\n },\n },\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n 'Content-Type': 'application/json',\n },\n timeout: PROBE_TIMEOUT_MS,\n },\n );\n\n // HogQL responses are `{ results: [[event, count], ...], columns: [...] }`.\n const rows: unknown = (response.data as { results?: unknown })?.results;\n if (!Array.isArray(rows)) return [];\n return rows\n .map((row): EventVolume | null => {\n if (!Array.isArray(row)) return null;\n const name = String(row[0] ?? '');\n const count = Number(row[1] ?? 0);\n if (!name || !Number.isFinite(count)) return null;\n return { name, count };\n })\n .filter((e): e is EventVolume => e !== null);\n}\n\n/**\n * Best-effort existence check against a list endpoint. Resolves to:\n * true — at least one row exists\n * false — endpoint returned a clean empty list\n * null — inconclusive (error, timeout, unexpected shape)\n * Never throws; `null` lets the assembler default the product to present.\n */\nasync function restExists(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n resource: string,\n): Promise<boolean | null> {\n try {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/${resource}/`,\n {\n params: { limit: 1 },\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: PROBE_TIMEOUT_MS,\n },\n );\n const results: unknown = (response.data as { results?: unknown })?.results;\n if (!Array.isArray(results)) return null;\n return results.length > 0;\n } catch {\n return null;\n }\n}\n\n/**\n * Scout a project: one HogQL query for event volume + event names, plus a\n * handful of parallel REST existence checks for products that aren't\n * derivable from the event stream. Always resolves — returns a degraded\n * profile if the core events query fails.\n */\nexport async function probeProjectData(args: {\n accessToken: string;\n projectId: number;\n /** Event-ingestion / REST API host (e.g. https://us.i.posthog.com). */\n apiHost: string;\n}): Promise<ProjectDataProfile> {\n const { accessToken, projectId, apiHost } = args;\n const baseUrl = apiHost.replace(/\\/$/, '');\n\n try {\n const [\n events,\n sessionReplay,\n surveys,\n featureFlags,\n experiments,\n warehouse,\n ] = await Promise.all([\n queryTopEvents(accessToken, projectId, baseUrl),\n restExists(accessToken, projectId, baseUrl, 'session_recordings'),\n restExists(accessToken, projectId, baseUrl, 'surveys'),\n restExists(accessToken, projectId, baseUrl, 'feature_flags'),\n restExists(accessToken, projectId, baseUrl, 'experiments'),\n restExists(accessToken, projectId, baseUrl, 'warehouse_tables'),\n ]);\n\n const profile = assembleProfile(events, {\n sessionReplay,\n surveys,\n featureFlags,\n experiments,\n dataWarehouse: warehouse,\n });\n logToFile(\n `[probeProjectData] tier=${profile.tier} totalEvents=${profile.totalEvents} distinct=${profile.distinctEventCount} custom=${profile.topCustomEvents.length}`,\n );\n return profile;\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[probeProjectData] degraded — probe failed: ${text}`);\n return degradedProfile();\n }\n}\n","/**\n * McpSuggestedPromptsScreen — the `wizard mcp tutorial` screen.\n *\n * Phases:\n * 1. Choose — opens with a Log in / Exit picker, framed by a\n * teaser of what MCP can do.\n * 2. Authenticating — runs `services.performLogin()` (OAuth in\n * production, canned values in the playground).\n * Renders a spinner + login URL inline while the\n * promise is pending. Errors return to Choose\n * with an inline error line.\n * 3. Greeting — role-tuned welcome via `getRoleGreeting`. A\n * ContentSequencer animates the headline,\n * bullets, and outro, then hands off to\n * PromptPicker. Only fires once per session\n * (returning via `[p]` skips it).\n * 4. PromptPicker — lists the role-tailored kit from\n * `getRolePrompts`; user picks one to run.\n * 5. Running — streams the agent's response inline via\n * `services.runPromptStreaming`. Text chunks\n * typewrite in; tool calls and results render\n * as styled badges. `[esc]` aborts; `[p]`\n * returns to the picker. On `done`/`error`,\n * auto-advances to FollowUp.\n * 6. FollowUp — surfaces 3 context-aware next prompts inferred\n * from the last tool the agent used (via\n * `getFollowUps`), plus an explicit exit.\n * Picking a follow-up re-enters Running; the\n * conversation tree grows as deep as\n * MAX_PROMPT_RUNS allows.\n *\n * Credentials are guaranteed non-null once Greeting / PromptPicker /\n * Running / FollowUp are reached (the Choose → Authenticating gate\n * forces a successful login first). A defensive throw protects the\n * Running useEffect against a state-machine bug.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useSyncExternalStore } from 'react';\n\nimport type { WizardStore } from '@tui/store';\nimport { Colors, Icons } from '@tui/styles';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\nimport {\n ContentSequencer,\n LoadingBox,\n PickerMenu,\n TextRevealMode,\n type ContentBlock,\n} from '@tui/primitives/index';\nimport {\n getRolePrompts,\n getRoleGreeting,\n getFollowUps,\n getTutorialPicker,\n getGeneratedQuests,\n getSeedOfferGreeting,\n FOLLOW_UP_EXIT_SENTINEL,\n type PromptOption,\n type RoleGreeting,\n} from '../services/mcp-role-prompts.js';\nimport {\n degradedProfile,\n isKnownCloudHost,\n type ProjectDataProfile,\n} from '../services/mcp-project-profile.js';\nimport type { Integration } from '@shared/constants';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport type {\n McpPromptChunk,\n McpSuggestedPromptsServices,\n} from '../services/suggested-prompts.js';\n\ninterface McpSuggestedPromptsScreenProps {\n store: WizardStore;\n services: McpSuggestedPromptsServices;\n}\n\nenum Phase {\n Choose = 'choose',\n Authenticating = 'authenticating',\n /** Cheap, best-effort scout of the project's data (event volume, real\n * event names, which products have data). Drives the data-aware picker\n * so the tutorial only ever offers playable moves. */\n Scouting = 'scouting',\n /** Empty-project fork: offer to send a small demo dataset so the read\n * quests have something to show. */\n SeedOffer = 'seed-offer',\n /** Sending the demo dataset, then re-deriving the profile. */\n Seeding = 'seeding',\n Greeting = 'greeting',\n PromptPicker = 'prompt-picker',\n Running = 'running',\n FollowUp = 'follow-up',\n /** Final beat on every dismissal — reminds the user how to keep\n * talking to PostHog after the tutorial ends. */\n Goodbye = 'goodbye',\n Done = 'done',\n}\n\nenum ChoiceValue {\n Login = 'login',\n Exit = 'exit',\n}\n\nenum SeedChoice {\n Seed = 'seed',\n Skip = 'skip',\n}\n\n// Cap how many prompts a single tutorial session can run, including\n// follow-ups. Once reached, FollowUp shows a cap-reached state and the\n// only escape is [esc]. Keeps the wizard from becoming a free-tier MCP\n// front-end and gives the tutorial a natural \"done\" point.\nconst MAX_PROMPT_RUNS = 5;\n\n// How long to hold the final streamed result on screen before swapping\n// into FollowUp. Gives the user a beat to read the result before the\n// picker mounts underneath. [esc] / [p] still work during the delay.\nconst FOLLOW_UP_DELAY_MS = 3000;\n\nexport const McpSuggestedPromptsScreen = ({\n store,\n services,\n}: McpSuggestedPromptsScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const session = store.session;\n\n // Events report under the tutorial, not whichever program hosts the screen.\n // Sampled at mount so captures landing after dismissal still resolve here.\n const programId = useMemo(() => store.analyticsProgramId, [store]);\n const capture = useMemo(\n () =>\n (event: string, properties?: Record<string, unknown>): void => {\n analytics.wizardCapture(event, {\n program_id: programId,\n ...properties,\n });\n },\n [programId],\n );\n\n // Phase.Choose is the tutorial's no-commitment entry: login fires only when\n // the user picks 'Start tutorial' — explicit consent for the OAuth dance.\n const [phase, setPhase] = useState<Phase>(Phase.Choose);\n // The scout's read of the project, set in the Scouting phase. Drives the\n // data-aware picker, greeting flavor, and Goodbye samples. Null until the\n // probe completes (the picker treats null as legacy / data-unaware).\n const [profile, setProfile] = useState<ProjectDataProfile | null>(null);\n\n // Greeting copy is role-tuned (data-independent). The picker is fully\n // profile-driven via getTutorialPicker: generated quests on real data,\n // write-only + activation cross-sells when the project is empty.\n const greeting = useMemo(\n () => getRoleGreeting(session.roleAtOrganization),\n [session.roleAtOrganization],\n );\n const pickerCandidates = useMemo(\n () =>\n getTutorialPicker(\n session.roleAtOrganization,\n session.integration,\n profile,\n ),\n [session.roleAtOrganization, session.integration, profile],\n );\n const [loginError, setLoginError] = useState<string | null>(null);\n // Whether the user picked \"Start MCP tutorial\" — decides where a\n // successful login lands: Greeting for a started tutorial, Choose\n // for the up-front auth.\n const startedTutorialRef = useRef(false);\n const [runningPrompt, setRunningPrompt] = useState<string | null>(null);\n const [runChunks, setRunChunks] = useState<McpPromptChunk[]>([]);\n const [runStartedAt, setRunStartedAt] = useState<number | null>(null);\n // Frozen elapsed-seconds value, set the moment the stream emits\n // 'done' / 'error'. Without this, the \"Done in Xs.\" line ticks up\n // every render once the result is parked under the FollowUp picker.\n const [runDurationSecs, setRunDurationSecs] = useState<number | null>(null);\n // Count every prompt the user has selected this session (including ones\n // they aborted mid-stream). Counted at pick-time, not completion-time,\n // so a user can't tap-cancel-tap-cancel to bypass the cap.\n const [runCount, setRunCount] = useState(0);\n const canPickAnother = runCount < MAX_PROMPT_RUNS;\n\n // The last tool the agent invoked during the current run. Drives the\n // context-aware follow-up suggestions in FollowUp. Cleared at the\n // start of each new run.\n const [lastToolName, setLastToolName] = useState<string | null>(null);\n // CLI mode's exec command string for the last tool call — recovers the inner\n // tool name so follow-ups stay context-aware under both server modes.\n const [lastToolCommand, setLastToolCommand] = useState<string | null>(null);\n // Every prompt the user has picked this session — initial + follow-ups.\n // Used to filter out already-seen suggestions in getFollowUps().\n const [branchHistory, setBranchHistory] = useState<string[]>([]);\n\n // AbortController for the in-flight runPromptStreaming call. Lifted\n // to a ref so [esc] / unmount can call abort() without the closure\n // needing to re-bind on every state change.\n const runAbortRef = useRef<AbortController | null>(null);\n\n // Once-only guard for the Seeding phase. Seeding writes events to the\n // user's real project, so it must fire exactly once even if a re-render\n // re-runs the effect before the phase transition lands.\n const seedStartedRef = useRef(false);\n\n // The Claude Agent SDK session ID of the most recent completed run.\n // Carried forward into follow-up runs via `resumeSessionId` so the\n // agent sees prior turns as context. Held in a ref so updating it\n // doesn't re-trigger the Running useEffect. Cleared whenever the\n // user returns to PromptPicker — that's a fresh conversation.\n const currentSessionIdRef = useRef<string | null>(null);\n\n // Run OAuth when entering Authenticating phase.\n useEffect(() => {\n if (phase !== Phase.Authenticating) return;\n let cancelled = false;\n\n void (async () => {\n try {\n const { credentials, roleAtOrganization, user } =\n await services.performLogin();\n if (cancelled) return;\n store.setCredentials(credentials);\n store.setRoleAtOrganization(roleAtOrganization);\n store.setApiUser(user);\n store.setLoginUrl(null);\n // Only route into the scout when the user actually kicked off the\n // tutorial. A pre-auth login (no committed start) lands back on\n // Choose so the user still owns the \"begin tutorial\" decision.\n setPhase(startedTutorialRef.current ? Phase.Scouting : Phase.Choose);\n } catch (err) {\n if (cancelled) return;\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[McpSuggestedPromptsScreen] login failed: ${message}`);\n store.setLoginUrl(null);\n setLoginError(message);\n setPhase(Phase.Choose);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [phase, services, store]);\n\n // Scout the project once auth completes. Best-effort: the probe never\n // throws (returns a degraded profile on failure), but we still guard so\n // a rejection can't strand the user on the spinner. Empty projects fork\n // to the seed offer; everything else goes straight to the greeting.\n useEffect(() => {\n if (phase !== Phase.Scouting) return;\n if (!session.credentials) return;\n let cancelled = false;\n const credentials = session.credentials;\n\n void (async () => {\n let probed: ProjectDataProfile;\n try {\n probed = await services.probeProjectData(credentials);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[McpSuggestedPromptsScreen] probe failed: ${message}`);\n probed = degradedProfile();\n }\n if (cancelled) return;\n setProfile(probed);\n // Gate the seed offer on both an empty tier AND a known PostHog\n // cloud host. Self-hosted / --base-url deployments never see the\n // offer, because the seeder posts to `apiHost` verbatim — a\n // customer who split app + ingestion onto different subdomains\n // would silently 401, and PostHog events are immutable in\n // ClickHouse (only the person mapping can be deleted), so a\n // misroute or an unwanted write leaves a permanent trail.\n const offerSeed =\n probed.tier === 'empty' && isKnownCloudHost(credentials.host.apiHost);\n capture('mcp suggested prompts scouted', {\n tier: probed.tier,\n totalEvents: probed.totalEvents,\n distinctEvents: probed.distinctEventCount,\n degraded: probed.degraded,\n offerSeed,\n });\n setPhase(offerSeed ? Phase.SeedOffer : Phase.Greeting);\n })();\n\n return () => {\n cancelled = true;\n };\n }, [phase, services, session.credentials]);\n\n // Send demo events to an empty project, then proceed with the seeded\n // profile. On failure we keep the empty profile and still advance — the\n // picker falls back to write-only + activation quests, so the user is\n // never stranded.\n useEffect(() => {\n if (phase !== Phase.Seeding) return;\n if (seedStartedRef.current) return;\n if (!session.credentials || !profile) return;\n seedStartedRef.current = true;\n let cancelled = false;\n const controller = new AbortController();\n const credentials = session.credentials;\n const baseProfile = profile;\n\n void (async () => {\n try {\n const seeded = await services.seedDemoEvents({\n credentials,\n baseProfile,\n signal: controller.signal,\n });\n if (cancelled) return;\n setProfile(seeded);\n capture('mcp suggested prompts seeded', {\n totalEvents: seeded.totalEvents,\n });\n } catch (err) {\n if (cancelled) return;\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[McpSuggestedPromptsScreen] seeding failed: ${message}`);\n capture('mcp suggested prompts seed failed', {\n error: message,\n });\n // Keep the empty profile; the picker handles the empty case.\n }\n if (cancelled) return;\n setPhase(Phase.Greeting);\n })();\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n }, [phase, services, session.credentials, profile]);\n\n // Stream the chosen prompt against the agent. On terminal chunks\n // ('done' or 'error') we schedule a short delay before swapping into\n // FollowUp so the user gets a beat to read the final text.\n useEffect(() => {\n if (phase !== Phase.Running) return;\n if (!runningPrompt) return;\n if (!session.credentials) {\n throw new Error(\n '[McpSuggestedPromptsScreen] Running phase reached without credentials. The Choose gate should have prevented this.',\n );\n }\n\n const controller = new AbortController();\n runAbortRef.current = controller;\n const startedAt = Date.now();\n setRunStartedAt(startedAt);\n setRunChunks([]);\n setLastToolName(null);\n setLastToolCommand(null);\n setRunDurationSecs(null);\n\n const finishStream = (\n kind: 'done' | 'error',\n durationMs: number,\n errorText?: string,\n ) => {\n if (controller.signal.aborted) return;\n setRunDurationSecs(Math.round(durationMs / 1000));\n if (kind === 'done') {\n capture('mcp suggested prompts run', {\n prompt: runningPrompt,\n durationMs,\n });\n } else {\n capture('mcp suggested prompts run failed', {\n prompt: runningPrompt,\n error: errorText,\n });\n }\n // Hold the final result on screen for a beat before swapping into\n // FollowUp, so the user has a moment to read without the picker\n // jumping in underneath. Guard via the abort controller so an\n // [esc] / [p] press inside the delay window cancels the swap.\n setTimeout(() => {\n if (controller.signal.aborted) return;\n setPhase(Phase.FollowUp);\n }, FOLLOW_UP_DELAY_MS);\n };\n\n void (async () => {\n const credentials = session.credentials;\n if (!credentials) return;\n try {\n for await (const chunk of services.runPromptStreaming({\n prompt: runningPrompt,\n credentials,\n signal: controller.signal,\n // Read at call-time so a session id captured by the previous\n // run carries into the follow-up. Null on a fresh start.\n resumeSessionId: currentSessionIdRef.current ?? undefined,\n })) {\n if (controller.signal.aborted) return;\n setRunChunks((prev) => [...prev, chunk]);\n if (chunk.kind === 'tool-call') {\n setLastToolName(chunk.toolName);\n setLastToolCommand(chunk.command ?? null);\n }\n if (chunk.kind === 'done') {\n // Remember the SDK session id so the next follow-up can\n // resume it. The SDK may issue a new id on resume — always\n // overwrite with the latest.\n if (chunk.sessionId) {\n currentSessionIdRef.current = chunk.sessionId;\n }\n finishStream('done', Date.now() - startedAt);\n return;\n }\n if (chunk.kind === 'error') {\n finishStream('error', Date.now() - startedAt, chunk.text);\n return;\n }\n }\n } catch (err) {\n if (controller.signal.aborted) return;\n const text = err instanceof Error ? err.message : String(err);\n setRunChunks((prev) => [...prev, { kind: 'error', text }]);\n finishStream('error', Date.now() - startedAt, text);\n }\n })();\n\n return () => {\n controller.abort();\n if (runAbortRef.current === controller) runAbortRef.current = null;\n };\n }, [phase, runningPrompt, services, session.credentials]);\n\n // Two-stage exit so the user always sees the Goodbye reminder\n // (installed clients + sample prompts) before the screen actually\n // tears down. `enterGoodbye` routes any dismissal into the reminder;\n // `closeWizard` does the actual store mutation that lets the router\n // move on.\n const enterGoodbye = (): void => {\n runAbortRef.current?.abort();\n setPhase(Phase.Goodbye);\n };\n\n const closeWizard = (): void => {\n setPhase(Phase.Done);\n setTimeout(() => {\n store.setMcpSuggestedPromptsDismissed();\n }, 0);\n };\n\n const handleChoice = (value: ChoiceValue | ChoiceValue[]): void => {\n const choice = Array.isArray(value) ? value[0] : value;\n setLoginError(null);\n if (choice === ChoiceValue.Login) {\n capture('mcp suggested prompts choose', {\n choice: 'login',\n });\n startedTutorialRef.current = true;\n // Picking Start tutorial is the explicit OAuth consent moment.\n // If credentials already exist, skip auth and go straight to the\n // scout — same landing as post-auth for a started tutorial.\n setPhase(session.credentials ? Phase.Scouting : Phase.Authenticating);\n } else {\n capture('mcp suggested prompts choose', {\n choice: 'exit',\n });\n enterGoodbye();\n }\n };\n\n // Empty-project fork: send demo events or skip straight to the\n // (write-only + activation) picker.\n const handleSeedChoice = (value: string | string[]): void => {\n const choice = Array.isArray(value) ? value[0] : value;\n if (choice === SeedChoice.Seed) {\n capture('mcp suggested prompts seed offer', {\n choice: 'seed',\n });\n setPhase(Phase.Seeding);\n } else {\n capture('mcp suggested prompts seed offer', {\n choice: 'skip',\n });\n setPhase(Phase.Greeting);\n }\n };\n\n // Single entry-point for kicking off a stream. Used by both the\n // initial picker and the follow-up picker.\n const startRun = (prompt: string): void => {\n setRunningPrompt(prompt);\n setRunCount((c) => c + 1);\n setBranchHistory((h) => [...h, prompt]);\n setPhase(Phase.Running);\n };\n\n const handlePromptPick = (value: string | string[]): void => {\n const picked = Array.isArray(value) ? value[0] : value;\n startRun(picked);\n };\n\n const handleFollowUpPick = (value: string | string[]): void => {\n const picked = Array.isArray(value) ? value[0] : value;\n if (picked === FOLLOW_UP_EXIT_SENTINEL) {\n capture('mcp suggested prompts follow-up', {\n choice: 'exit',\n depth: branchHistory.length,\n });\n enterGoodbye();\n return;\n }\n capture('mcp suggested prompts follow-up', {\n choice: 'continue',\n depth: branchHistory.length,\n lastToolName,\n });\n startRun(picked);\n };\n\n // `[enter]` skips the auto-paced Greeting to the picker. Only\n // registered while Greeting is on screen — PickerMenu owns enter\n // during the picker phases, and Running auto-transitions on done\n // (no auto-advance timer left to short-circuit).\n const canSkipForward = phase === Phase.Greeting;\n\n useKeyBindings('mcp-suggested-prompts', [\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action:\n phase === Phase.Goodbye\n ? 'close'\n : phase === Phase.Authenticating\n ? 'cancel'\n : 'exit',\n handler: () => {\n if (phase === Phase.Goodbye) {\n closeWizard();\n } else if (phase === Phase.Authenticating) {\n // Cancel the OAuth dance — the login effect's cleanup discards\n // the in-flight result. Choose still works without credentials.\n setPhase(Phase.Choose);\n } else if (\n phase === Phase.Running ||\n phase === Phase.PromptPicker ||\n phase === Phase.FollowUp ||\n phase === Phase.Greeting ||\n phase === Phase.Scouting ||\n phase === Phase.SeedOffer ||\n phase === Phase.Seeding\n ) {\n enterGoodbye();\n }\n },\n },\n {\n // `[p]` is the primary \"pick a different prompt\" hotkey during\n // Running and FollowUp — always returns to the PromptPicker\n // (aborting the stream if necessary). No-op once the per-session\n // cap is reached. Clearing the session id here is what makes\n // the next pick a fresh conversation rather than a follow-up.\n match: 'p',\n label: 'p',\n action: canPickAnother ? 'pick new prompt' : 'cap reached',\n handler: () => {\n if (phase !== Phase.Running && phase !== Phase.FollowUp) return;\n if (!canPickAnother) return;\n runAbortRef.current?.abort();\n currentSessionIdRef.current = null;\n setPhase(Phase.PromptPicker);\n },\n },\n // Conditional enter binding — only active during the Greeting\n // (where it short-circuits the typewriter pacing). PickerMenu\n // owns enter in the picker phases; Running flips straight to\n // FollowUp the moment the stream completes.\n ...(canSkipForward\n ? [\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'continue',\n handler: () => {\n setPhase(Phase.PromptPicker);\n },\n },\n ]\n : []),\n ]);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box marginTop={1} flexDirection=\"column\">\n {phase === Phase.Choose && (\n <ChoosePhase error={loginError} onSelect={handleChoice} />\n )}\n\n {phase === Phase.Authenticating && (\n <AuthenticatingPhase loginUrl={store.loginUrl} />\n )}\n\n {phase === Phase.Scouting && <ScoutingPhase />}\n\n {phase === Phase.SeedOffer && (\n <SeedOfferPhase onSelect={handleSeedChoice} />\n )}\n\n {phase === Phase.Seeding && <SeedingPhase />}\n\n {phase === Phase.Greeting && (\n <GreetingPhase\n greeting={greeting}\n userDisplayName={session.apiUser?.first_name || null}\n onComplete={() => setPhase(Phase.PromptPicker)}\n />\n )}\n\n {phase === Phase.PromptPicker && (\n <PromptPickerPhase\n candidates={pickerCandidates}\n onSelect={handlePromptPick}\n />\n )}\n\n {phase === Phase.Running && runningPrompt && (\n <RunningPhase\n prompt={runningPrompt}\n chunks={runChunks}\n startedAt={runStartedAt}\n frozenDurationSecs={runDurationSecs}\n runCount={runCount}\n maxRuns={MAX_PROMPT_RUNS}\n />\n )}\n\n {phase === Phase.FollowUp && (\n <Box flexDirection=\"column\" flexGrow={1}>\n {/* Result area absorbs flex and shrinks first when the\n terminal is short. `capTextChunks` does the actual\n row-aware truncation; flexShrink here is belt-and-\n suspenders so Ink's layout never squeezes the picker. */}\n {runningPrompt && (\n <Box flexDirection=\"column\" flexShrink={1}>\n <RunningPhase\n prompt={runningPrompt}\n chunks={runChunks}\n startedAt={runStartedAt}\n frozenDurationSecs={runDurationSecs}\n runCount={runCount}\n maxRuns={MAX_PROMPT_RUNS}\n />\n </Box>\n )}\n {/* Picker is pinned: flexShrink={0} means it never gives\n up rows to siblings. flexBasis=\"auto\" keeps its\n natural height. */}\n <Box marginTop={1} flexShrink={0} flexDirection=\"column\">\n <FollowUpPhase\n lastToolName={lastToolName}\n lastToolCommand={lastToolCommand}\n lastPrompt={runningPrompt}\n chunks={runChunks}\n role={session.roleAtOrganization}\n branchHistory={branchHistory}\n canPickAnother={canPickAnother}\n maxRuns={MAX_PROMPT_RUNS}\n onSelect={handleFollowUpPick}\n />\n </Box>\n </Box>\n )}\n\n {phase === Phase.Goodbye && (\n <GoodbyePhase\n installedClients={store.mcpInstalledClients}\n role={session.roleAtOrganization}\n integration={session.integration}\n profile={profile}\n engaged={branchHistory.length > 0}\n loginCommands={store.mcpLoginCommands}\n onClose={closeWizard}\n />\n )}\n </Box>\n </Box>\n );\n};\n\n// ── Choose phase ───────────────────────────────────────────────────────\n\ninterface ChoosePhaseProps {\n error: string | null;\n onSelect: (value: ChoiceValue | ChoiceValue[]) => void;\n}\n\nconst ChoosePhase = ({ error, onSelect }: ChoosePhaseProps) => {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n PostHog MCP\n </Text>\n\n <Box marginTop={1}>\n <Text>\n With MCP your agent works directly with the PostHog platform. You can\n prompt it to:\n </Text>\n </Box>\n\n <Box marginTop={1} flexDirection=\"column\">\n <Text>\n <Text color=\"cyan\">{Icons.diamond}</Text> Build dashboards\n </Text>\n <Text>\n <Text color=\"cyan\">{Icons.diamond}</Text> Run SQL queries\n </Text>\n <Text>\n <Text color=\"cyan\">{Icons.diamond}</Text> Deploy feature flags\n </Text>\n <Text>\n <Text color=\"cyan\">{Icons.diamond}</Text> Debug exceptions and errors\n </Text>\n <Text>\n <Text color=\"cyan\">{Icons.diamond}</Text> And lots more...\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text>Want a live demo using real data from your project?</Text>\n </Box>\n\n <Box>\n <PickerMenu\n options={[\n { label: 'Start MCP tutorial', value: ChoiceValue.Login },\n { label: 'Exit', value: ChoiceValue.Exit },\n ]}\n onSelect={onSelect}\n />\n </Box>\n {error && (\n <Box marginTop={1}>\n <Text color=\"red\">Login failed: {error}. Try again or exit.</Text>\n </Box>\n )}\n </Box>\n );\n};\n\n// ── Authenticating phase ───────────────────────────────────────────────\n\ninterface AuthenticatingPhaseProps {\n loginUrl: string | null;\n}\n\nconst AuthenticatingPhase = ({ loginUrl }: AuthenticatingPhaseProps) => (\n <Box flexDirection=\"column\">\n <LoadingBox message=\"Waiting for authentication...\" />\n {loginUrl && (\n <Box marginTop={1} marginBottom={1} flexDirection=\"column\">\n <Text>\n <Text dimColor>If the browser didn&apos;t open, copy and paste:</Text>\n {'\\n\\n'}\n <Text color=\"cyan\">{loginUrl}</Text>\n </Text>\n </Box>\n )}\n </Box>\n);\n\n// ── Scouting phase ─────────────────────────────────────────────────────\n// Cheap, best-effort probe of the project's data. Just a spinner — the\n// probe is time-boxed and forks to the seed offer (empty) or the greeting.\n\nconst ScoutingPhase = () => (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n MCP tutorial\n </Text>\n </Box>\n <LoadingBox message=\"Scouting your project for data…\" />\n </Box>\n);\n\n// ── Seed-offer phase ───────────────────────────────────────────────────\n// Empty-project fork: offer to send a small demo dataset so the read\n// quests have something real to show instead of dead-ending.\n\ninterface SeedOfferPhaseProps {\n onSelect: (value: string | string[]) => void;\n}\n\nconst SeedOfferPhase = ({ onSelect }: SeedOfferPhaseProps) => {\n const copy = getSeedOfferGreeting();\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n {copy.headline}\n </Text>\n </Box>\n <Box marginBottom={1} flexDirection=\"column\">\n {copy.bullets.map((bullet, i) => (\n <Text key={i}>\n <Text color={Colors.primary}>{Icons.diamond}</Text>{' '}\n <Text dimColor>{bullet}</Text>\n </Text>\n ))}\n </Box>\n <Box marginBottom={1}>\n <Text>{copy.outro}</Text>\n </Box>\n <PickerMenu\n options={[\n { label: 'Yes — send demo data', value: SeedChoice.Seed },\n { label: 'No thanks, skip', value: SeedChoice.Skip },\n ]}\n onSelect={onSelect}\n />\n <Box marginTop={2}>\n <Text>\n <Text bold>[esc]</Text>\n <Text> to exit</Text>\n </Text>\n </Box>\n </Box>\n );\n};\n\n// ── Seeding phase ──────────────────────────────────────────────────────\n// Sending the demo dataset. Events are backdated, so we say they'll light\n// up time-windowed charts right away rather than implying a wait.\n\nconst SeedingPhase = () => (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n MCP tutorial\n </Text>\n </Box>\n <LoadingBox message=\"Sending demo events to your project…\" />\n <Box marginTop={1}>\n <Text dimColor>\n Backdated across the last 7 days, so your funnels and trends light up\n right away.\n </Text>\n </Box>\n </Box>\n);\n\n// ── Greeting phase ─────────────────────────────────────────────────────\n\ninterface GreetingPhaseProps {\n greeting: RoleGreeting;\n userDisplayName: string | null;\n onComplete: () => void;\n}\n\nconst GreetingPhase = ({\n greeting,\n userDisplayName,\n onComplete,\n}: GreetingPhaseProps) => {\n // Sequence: optional first-name greeting → role-tuned headline →\n // bullets reveal line-by-line → outro fades in → handoff to picker.\n //\n // Pacing notes: `pause` is the time the sequencer waits AFTER a\n // block finishes before advancing — that's the user's reading\n // window. Each typed block is \"ready to read\" only after the\n // typewriter finishes, so the pauses are sized for the absorbed\n // length, not the typing time.\n const blocks: ContentBlock[] = [];\n\n if (userDisplayName) {\n blocks.push({\n content: `Hi ${userDisplayName}!`,\n mode: TextRevealMode.Typewriter,\n animationInterval: 70,\n pause: 1200,\n });\n }\n\n blocks.push({\n content: greeting.headline,\n mode: TextRevealMode.Typewriter,\n animationInterval: 45,\n pause: 2000,\n });\n\n blocks.push({\n type: 'lines',\n lines: greeting.bullets.map((bullet, i) => (\n <Text key={i}>\n <Text color={Colors.primary}>{Icons.diamond}</Text>{' '}\n <Text dimColor>{bullet}</Text>\n </Text>\n )),\n interval: 700,\n pause: 2200,\n });\n\n blocks.push({\n content: greeting.outro,\n mode: TextRevealMode.Typewriter,\n animationInterval: 38,\n pause: 1800,\n });\n\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n MCP tutorial\n </Text>\n </Box>\n <ContentSequencer\n blocks={blocks}\n mode={TextRevealMode.Typewriter}\n blockInterval={500}\n onSequenceComplete={onComplete}\n />\n </Box>\n );\n};\n\n// ── Prompt picker phase ────────────────────────────────────────────────\n\ninterface PromptPickerPhaseProps {\n candidates: PromptOption[];\n onSelect: (value: string | string[]) => void;\n}\n\nconst PromptPickerPhase = ({\n candidates,\n onSelect,\n}: PromptPickerPhaseProps) => {\n // `candidates` is the full ordered list from getTutorialPicker — already\n // role + data aware (generated quests on real data, write-only +\n // activation cross-sells on an empty project, legacy kit when degraded).\n // Dedupe by prompt text and cap at 4 so the picker fits without\n // scrolling. Entries with a `product` tag get the \"Try {product} —\"\n // prefix so cross-sells stand out.\n const seenPrompts = new Set<string>();\n const options = candidates\n .filter((o) => {\n if (seenPrompts.has(o.prompt)) return false;\n seenPrompts.add(o.prompt);\n return true;\n })\n .slice(0, 4)\n .map((o) => ({\n label: o.product\n ? `Try ${o.product} — ${o.label ?? o.prompt}`\n : o.label ?? o.prompt,\n value: o.prompt,\n }));\n\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n MCP tutorial\n </Text>\n </Box>\n <Box marginBottom={1}>\n <Text>Pick a prompt to see the PostHog MCP in action.</Text>\n </Box>\n <PickerMenu\n options={options}\n optionMarginBottom={1}\n onSelect={onSelect}\n />\n <Box marginTop={2}>\n <Text>\n <Text bold>[esc]</Text>\n <Text> to exit</Text>\n </Text>\n </Box>\n </Box>\n );\n};\n\n// ── Running phase ──────────────────────────────────────────────────────\n\ninterface RunningPhaseProps {\n prompt: string;\n chunks: McpPromptChunk[];\n startedAt: number | null;\n /** Set the instant the stream finishes; freezes the displayed elapsed\n * time so re-renders under FollowUp don't keep ticking it forward. */\n frozenDurationSecs: number | null;\n runCount: number;\n maxRuns: number;\n}\n\nconst RunningPhase = ({\n prompt,\n chunks,\n startedAt,\n frozenDurationSecs,\n runCount,\n maxRuns,\n}: RunningPhaseProps) => {\n const isDone = chunks.some((c) => c.kind === 'done');\n const errorChunk = chunks.find((c) => c.kind === 'error');\n const finished = isDone || !!errorChunk;\n const elapsed =\n frozenDurationSecs ??\n (startedAt ? Math.round((Date.now() - startedAt) / 1000) : 0);\n\n // When finished, collapse to just the agent's final answer + any\n // error. The tool-call / tool-result chatter has already served its\n // purpose as a \"work in progress\" indicator. We also drop every text\n // block EXCEPT the last one — Sonnet often emits a \"I'll query X…\"\n // preamble alongside its first tool_use, and showing both the\n // preamble and the final answer doubles the noise above the picker.\n const visibleChunks = finished\n ? capTextChunks(collapseToFinalAnswer(chunks))\n : chunks;\n\n return (\n <Box flexDirection=\"column\">\n <Text>\n <Text bold>Prompt:</Text> <Text color={Colors.accent}>{prompt}</Text>\n </Text>\n\n <Box marginTop={1} gap={1}>\n {/* Spinner spins for the full duration of the stream — visual\n confirmation that work is still in flight even during pauses\n between chunks. */}\n {!finished && <Spinner />}\n <Text bold={finished}>\n {finished\n ? errorChunk\n ? `Failed after ${elapsed}s.`\n : `Done in ${elapsed}s.`\n : 'Streaming from PostHog MCP'}\n </Text>\n <Text dimColor>\n ({runCount}/{maxRuns} prompts)\n </Text>\n </Box>\n\n <Box marginTop={1} flexDirection=\"column\">\n {visibleChunks.map((chunk, idx) => (\n <ChunkLine key={idx} chunk={chunk} />\n ))}\n </Box>\n </Box>\n );\n};\n\n/**\n * Strip everything except the agent's final answer + any error chunks.\n * Drops tool-call / tool-result chatter (their work is done once the\n * stream completes) and any text blocks emitted BEFORE the last text\n * block — those are typically Sonnet's \"I'll query X…\" preamble that\n * arrives alongside the first tool_use and adds noise above the picker.\n *\n * If the run produced no text at all (pure tool calls, or only errors),\n * fall through to whatever chunks survived so the user isn't left with\n * a blank result.\n */\nfunction collapseToFinalAnswer(chunks: McpPromptChunk[]): McpPromptChunk[] {\n const textChunks = chunks.filter((c) => c.kind === 'text');\n const errors = chunks.filter((c) => c.kind === 'error');\n if (textChunks.length === 0) return errors;\n // Keep only the last text block — that's the model's final answer.\n // Anything earlier was preamble emitted alongside tool_use.\n return [textChunks[textChunks.length - 1], ...errors];\n}\n\n/**\n * Belt-and-suspenders fallback for runs where Claude ignored the\n * terminal-fit system prompt and produced an overlong response. Joins\n * all text chunks, then walks them from the bottom keeping only as many\n * lines as fit in the visual row budget — wide lines that wrap to\n * multiple rows on a narrow terminal cost their wrapped row count, not\n * 1. Prepends an indicator showing how many source lines got cut. Tool\n * calls, results, and errors are preserved separately so they don't\n * disappear into the truncation.\n *\n * Visual-row-aware truncation is what makes the FollowUp picker feel\n * pinned: a 5-row table that wraps to 12 visual rows on a 60-col\n * terminal correctly counts as 12, so the cap leaves exactly the room\n * the picker needs.\n */\nfunction capTextChunks(chunks: McpPromptChunk[]): McpPromptChunk[] {\n const rows = process.stdout.rows ?? 24;\n const cols = process.stdout.columns ?? 120;\n // Reserve rows for the FollowUp picker that sits below the result:\n // recap line, 4 picker options, marginTop, plus the prompt + status\n // chrome above the result and the global keyboard hints bar. Be\n // pessimistic — `process.stdout.rows` doesn't always match the actual\n // visible area (terminal padding, host UI chrome, etc.), and an\n // off-by-a-few rows shows up as the result overlapping the picker.\n // Better to leave the picker breathing room than risk overprint.\n const maxVisualRows = Math.max(3, rows - 19);\n\n const textChunks = chunks.filter((c) => c.kind === 'text');\n const errors = chunks.filter((c) => c.kind === 'error');\n if (textChunks.length === 0) return chunks;\n\n const joined = textChunks.map((c) => c.text).join('');\n const lines = joined.split('\\n');\n\n // How many visual rows does this source line consume after wrap?\n // Empty lines still take 1; everything else is ceil(width / cols).\n const visualRows = (line: string): number =>\n Math.max(1, Math.ceil(line.length / cols));\n\n // Walk from the bottom, accumulating visual rows until budget runs\n // out, so we keep the tail of the message (which has the punchline).\n let used = 0;\n let keepFrom = lines.length;\n for (let i = lines.length - 1; i >= 0; i--) {\n const cost = visualRows(lines[i]);\n if (used + cost > maxVisualRows) break;\n used += cost;\n keepFrom = i;\n }\n\n if (keepFrom === 0) return chunks;\n\n const hidden = keepFrom;\n const tail = lines.slice(keepFrom).join('\\n');\n\n return [\n {\n kind: 'text',\n text: `[${hidden} line${\n hidden === 1 ? '' : 's'\n } above — expand terminal to see more]\\n\\n${tail}`,\n },\n ...errors,\n ];\n}\n\ninterface ChunkLineProps {\n chunk: McpPromptChunk;\n}\n\nconst ChunkLine = ({ chunk }: ChunkLineProps) => {\n if (chunk.kind === 'text') {\n return <Text>{chunk.text}</Text>;\n }\n if (chunk.kind === 'tool-call') {\n return (\n <Text>\n {' '}\n <Text color=\"cyan\">↳ {chunk.toolName}</Text>\n {chunk.detail ? ` ${chunk.detail}` : ''}\n </Text>\n );\n }\n if (chunk.kind === 'tool-result') {\n return (\n <Text>\n {' '}\n <Text color=\"green\">✓</Text> {chunk.detail}\n </Text>\n );\n }\n if (chunk.kind === 'error') {\n return <Text color=\"red\">Error: {chunk.text}</Text>;\n }\n // 'done' — no visual chunk; the dim status line above handles it.\n return null;\n};\n\n// ── Follow-up phase ────────────────────────────────────────────────────\n\ninterface FollowUpPhaseProps {\n lastToolName: string | null;\n lastToolCommand: string | null;\n lastPrompt: string | null;\n chunks: McpPromptChunk[];\n role: string | null;\n branchHistory: string[];\n canPickAnother: boolean;\n maxRuns: number;\n onSelect: (value: string | string[]) => void;\n}\n\nconst FollowUpPhase = ({\n lastToolName,\n lastToolCommand,\n lastPrompt,\n chunks,\n role,\n branchHistory,\n canPickAnother,\n maxRuns,\n onSelect,\n}: FollowUpPhaseProps) => {\n const followUps = useMemo(\n () =>\n getFollowUps({\n lastToolName,\n lastToolCommand,\n lastPrompt: lastPrompt || '',\n role,\n branchHistory,\n }),\n [lastToolName, lastToolCommand, lastPrompt, role, branchHistory],\n );\n\n // When the cap is reached, only the exit entry is available. Follow-up\n // entries always set `label`; fall back to `prompt` defensively in case\n // a future contributor omits it.\n const options = canPickAnother\n ? followUps.map((f) => ({ label: f.label ?? f.prompt, value: f.prompt }))\n : [{ label: 'Exit', value: FOLLOW_UP_EXIT_SENTINEL }];\n\n const errorChunk = chunks.find((c) => c.kind === 'error');\n const recap = errorChunk\n ? 'That one errored out — try a different angle?'\n : !canPickAnother\n ? `You've hit the ${maxRuns}-prompt tutorial cap.`\n : `Want to keep exploring? Select a follow-up prompt.`;\n\n return (\n <Box flexDirection=\"column\">\n <Text>{recap}</Text>\n <PickerMenu options={options} onSelect={onSelect} />\n </Box>\n );\n};\n\n// ── Goodbye phase ──────────────────────────────────────────────────────\n// Always shown before final dismissal. Reminds the user where MCP is\n// available and what to ask once they're back in their IDE.\n\ninterface GoodbyePhaseProps {\n installedClients: string[];\n role: string | null;\n integration: Integration | null;\n /** Scout profile, so the parting samples can reference real events. */\n profile: ProjectDataProfile | null;\n /** True if the user actually ran at least one prompt this session. */\n engaged: boolean;\n /** Editor-owned login commands still to run (e.g. `claude mcp login posthog`). */\n loginCommands: string[];\n onClose: () => void;\n}\n\nconst GoodbyePhase = ({\n installedClients,\n role,\n integration,\n profile,\n engaged,\n loginCommands,\n onClose,\n}: GoodbyePhaseProps) => {\n // Three \"next time you open your IDE, try this\" reminders. Prefer quests\n // generated from the project's real events when we have them; otherwise\n // fall back to the role-tailored kit.\n const generated = getGeneratedQuests(profile);\n const samples = (\n generated.length > 0 ? generated : getRolePrompts(role, integration)\n ).slice(0, 3);\n\n const headline = engaged\n ? 'Nice work. You can keep talking to PostHog anytime.'\n : \"You're all set — PostHog MCP is here when you're ready.\";\n\n const introLine =\n installedClients.length > 0 ? (\n <Text>\n MCP is set up in{' '}\n <Text bold color={Colors.primary}>\n {installedClients.join(', ')}\n </Text>\n . Open one and try a prompt like:\n </Text>\n ) : (\n <Text>\n Wherever you have MCP set up (Claude Code, Cursor, VS Code, Windsurf,\n Zed, etc.), open the agent and try a prompt like:\n </Text>\n );\n\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold color={Colors.accent}>\n {headline}\n </Text>\n </Box>\n\n <Box marginBottom={1}>{introLine}</Box>\n\n {loginCommands.length > 0 && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"green\" bold>\n {'\\u2714'} Authenticate to finish (opens your browser):\n </Text>\n {loginCommands.map((command) => (\n <Text key={command}>\n {' '}\n <Text bold color=\"green\">\n {command}\n </Text>\n </Text>\n ))}\n </Box>\n )}\n\n <Box marginBottom={1} flexDirection=\"column\">\n {samples.map((p, i) => (\n <Box key={i}>\n <Text color={Colors.primary}>{Icons.triangleSmallRight}</Text>\n <Text> </Text>\n <Text dimColor>{p.prompt}</Text>\n </Box>\n ))}\n </Box>\n\n {profile?.seeded && (\n <Box marginBottom={1}>\n <Text dimColor>\n Demo data is tagged <Text bold>wizard_seed:true</Text> and uses{' '}\n <Text bold>wizard-demo-user-*</Text> distinct IDs — events are\n immutable in PostHog, but you can filter these out of any query or\n dashboard.\n </Text>\n </Box>\n )}\n\n <Box marginBottom={1}>\n <Text dimColor>\n Re-run this tutorial anytime with{' '}\n <Text bold>npx @posthog/wizard mcp tutorial</Text>.\n </Text>\n </Box>\n\n <PickerMenu\n options={[{ label: 'Close', value: 'close' }]}\n onSelect={() => onClose()}\n />\n </Box>\n );\n};\n","/** A decided failure in the TUI: the outro screen shows it, and the run ends once the user is done with it. */\nimport { wizardAbort, type WizardAbortOptions } from '@host/wizard-abort';\nimport type { WizardStore } from './store.js';\n\n/** `wizardAbort` with the outro screen as its presenter and the store's exit request as its end. */\nexport function abortOnScreens(\n store: WizardStore,\n options?: WizardAbortOptions,\n): Promise<never> {\n return wizardAbort(\n {\n present: async (outro) => {\n store.showOutroError(outro);\n // The MintFailure handoff never sets outroDismissed, so leaving it counts.\n await store.waitUntil(\n (s) =>\n s.outroDismissed || s.mintHandoff === 'exit' || s.skillsComplete,\n );\n },\n exit: { end: (code) => store.requestExit(code) },\n },\n options,\n );\n}\n","import * as crypto from 'node:crypto';\nimport * as http from 'node:http';\nimport { execSync } from 'node:child_process';\nimport axios from 'axios';\nimport {\n getOAuthClientId,\n missingOAuthScopes,\n OAuthTokenResponseSchema,\n parseOAuthScopes,\n} from '@programs';\nimport type { OAuthTokenResponse } from '@programs/types';\nimport {\n OAUTH_PORTS,\n OAUTH_TIMEOUT_MS,\n WIZARD_USER_AGENT,\n} from '@shared/constants';\nimport { abortOnScreens } from '@tui/abort';\nimport type { WizardStore } from '@tui/store';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport { openTrackedLink, withUtm } from '@utils/links';\nimport {\n OAuthError,\n buildCallbackErrorHtml,\n buildOAuthFailureMessage,\n oauthErrorFromCallbackParams,\n oauthErrorFromTokenBody,\n} from '@utils/oauth-errors';\nimport { getOAuthUrl, resolveBaseUrl } from '@utils/urls';\n\nconst OAUTH_CALLBACK_STYLES = `\n <style>\n * {\n font-family: monospace;\n background-color: #1b0a00;\n color: #F7A502;\n font-weight: medium;\n font-size: 24px;\n margin: .25rem;\n }\n\n .blink {\n animation: blink-animation 1s steps(2, start) infinite;\n }\n\n @keyframes blink-animation {\n to {\n opacity: 0;\n }\n }\n </style>\n`;\n\nexport const WIZARD_COMPLETION_SCOPE = 'event_definition:write';\n\nexport function assertWizardCompletionScope(scope: string): void {\n if (parseOAuthScopes(scope).includes(WIZARD_COMPLETION_SCOPE)) return;\n\n throw new Error(\n `This run was authorized without the ${WIZARD_COMPLETION_SCOPE} permission, which the wizard needs to finish setup. Please try again, approving all permissions on the PostHog authorization screen. If that screen does not reappear, revoke the existing PostHog Wizard authorization in your PostHog settings first.`,\n );\n}\n\n// Stable marker for the authorization-flow timeout. Detection keys off the exact\n// message rather than a loose substring — `.includes('timeout')` never matched\n// `'timed out'`, which silently routed timeouts to the generic failure message.\nconst AUTHORIZATION_TIMEOUT_MESSAGE = 'Authorization timed out';\n\nexport function isAuthorizationTimeout(error: Error): boolean {\n return error.message === AUTHORIZATION_TIMEOUT_MESSAGE;\n}\n\ninterface OAuthConfig {\n scopes: string[];\n signup?: boolean;\n /** Project to pre-select on the consent screen (the `--project-id` flag). */\n projectId?: number;\n /**\n * Explicit base URL override (`--base-url`, from `session.baseUrl`). Pins the\n * OAuth server and selects the matching client ID.\n */\n baseUrl?: string;\n}\n\nfunction getLocalOAuthOrigin(port: number): string {\n return `http://localhost:${port}`;\n}\n\nfunction getCallbackUrl(port: number): string {\n return `${getLocalOAuthOrigin(port)}/callback`;\n}\n\nfunction getLocalLoginUrl(port: number): string {\n return `${getLocalOAuthOrigin(port)}/authorize`;\n}\n\nfunction getLocalSignupUrl(port: number): string {\n return `${getLocalLoginUrl(port)}?signup=true`;\n}\n\n/**\n * Extract an OAuth authorization code from raw user input. Accepts either the\n * bare code, the full callback URL the browser was redirected to\n * (`http://localhost:8239/callback?code=abc123&...`), or just the query\n * string. Returns null when no code can be found.\n *\n * This backs the manual-entry fallback: in headless/remote environments the\n * browser can't reach the wizard's local callback server, so the user copies\n * the failed callback URL (or the code from it) back into the terminal.\n */\nexport function extractOAuthCode(input: string): string | null {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n // Full URL — pull the `code` query param.\n let looksLikeUrl = false;\n try {\n const url = new URL(trimmed);\n looksLikeUrl = true;\n const code = url.searchParams.get('code');\n if (code) return code;\n } catch {\n // Not a parseable URL — fall through to the looser checks below.\n }\n\n // A pasted query string or `code=...` fragment.\n const match = trimmed.match(/[?&]?code=([^&\\s]+)/);\n if (match) return decodeURIComponent(match[1]);\n\n // A URL with no code is invalid — don't mistake the whole URL for a code.\n if (looksLikeUrl) return null;\n\n // Otherwise treat the whole input as the bare code (no embedded whitespace).\n if (!/\\s/.test(trimmed)) return trimmed;\n\n return null;\n}\n\nfunction generateCodeVerifier(): string {\n return crypto.randomBytes(32).toString('base64url');\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return crypto.createHash('sha256').update(verifier).digest('base64url');\n}\n\nexport async function startCallbackServer(\n authUrl: string,\n signupUrl: string,\n port: number,\n): Promise<{\n port: number;\n server: http.Server;\n waitForCallback: () => Promise<string>;\n}> {\n return new Promise((resolve, reject) => {\n let callbackResolve: (code: string) => void;\n let callbackReject: (error: Error) => void;\n\n const waitForCallback = () =>\n new Promise<string>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n const url = new URL(req.url, getLocalOAuthOrigin(port));\n\n if (url.pathname === '/authorize') {\n const isSignup = url.searchParams.get('signup') === 'true';\n const redirectUrl = isSignup ? signupUrl : authUrl;\n res.writeHead(302, { Location: redirectUrl });\n res.end();\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n // Carries error_description / error_uri (RFC 6749 §4.1.2.1) along\n // with the code, so the terminal message can show the server's own\n // explanation instead of just the bare code.\n const callbackError = oauthErrorFromCallbackParams(url.searchParams);\n const isAccessDenied = callbackError.code === 'access_denied';\n logToFile(\n `[oauth] callback received with error: ${callbackError.code}` +\n (callbackError.description\n ? ` (${callbackError.description})`\n : ''),\n );\n res.writeHead(isAccessDenied ? 200 : 400, {\n 'Content-Type': 'text/html; charset=utf-8',\n });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Authorization ${\n isAccessDenied ? 'cancelled' : 'failed'\n }</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n ${buildCallbackErrorHtml(callbackError)}\n <p>Return to your terminal. This window will close automatically.</p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackReject(callbackError);\n return;\n }\n\n if (code) {\n logToFile('[oauth] callback received with authorization code');\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard is ready</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>PostHog login complete!</p>\n <p>Return to your terminal: the wizard is hard at work on your project<span class=\"blink\">█</span></p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackResolve(code);\n } else {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Invalid request</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>Invalid request - no authorization code received.</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n }\n });\n\n server.on('clientError', (error: NodeJS.ErrnoException, socket) => {\n if (socket.destroyed || socket.writableEnded) return;\n if (error.code === 'ECONNRESET' || !socket.writable) {\n socket.destroy();\n return;\n }\n\n // Parser errors may contain cookies and OAuth codes in rawPacket.\n logToFile(\n `[oauth] local HTTP request rejected: ${error.code ?? 'unknown'}`,\n );\n const overflow = error.code === 'HPE_HEADER_OVERFLOW';\n let status = '400 Bad Request';\n // Preserve Node's other parser error statuses when replacing its default handler.\n switch (error.code) {\n case 'HPE_HEADER_OVERFLOW':\n status = '431 Request Header Fields Too Large';\n break;\n case 'HPE_CHUNK_EXTENSIONS_OVERFLOW':\n status = '413 Payload Too Large';\n break;\n case 'ERR_HTTP_REQUEST_TIMEOUT':\n status = '408 Request Timeout';\n break;\n }\n const body = overflow\n ? `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Browser request too large</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>Your browser sent more than ${\n http.maxHeaderSize / 1024\n } KiB of request headers.</p>\n <p>This can happen when cookies from other localhost apps accumulate.</p>\n <p>Clear cookies for localhost and retry, or open the login link from your terminal in a private/incognito window.</p>\n </body>\n</html>`\n : '';\n\n socket.end(\n `HTTP/1.1 ${status}\\r\\n` +\n 'Content-Type: text/html; charset=utf-8\\r\\n' +\n `Content-Length: ${Buffer.byteLength(body)}\\r\\n` +\n 'Connection: close\\r\\n' +\n 'Cache-Control: no-store\\r\\n\\r\\n' +\n body,\n );\n });\n\n server.listen(port, () => {\n resolve({ port, server, waitForCallback });\n });\n\n server.on('error', reject);\n });\n}\n\nfunction getPortProcessInfo(port: number): {\n command: string;\n pid: string;\n port: number;\n user: string;\n} {\n try {\n const output = execSync(`lsof -i :${port} -sTCP:LISTEN 2>/dev/null`, {\n encoding: 'utf-8',\n timeout: 3000,\n }).trim();\n const lines = output.split('\\n');\n // First line is header, second is the process\n if (lines.length < 2)\n return { command: 'unknown', pid: 'unknown', port, user: 'unknown' };\n const fields = lines[1].split(/\\s+/);\n // lsof columns: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n const command = fields[0] ?? 'unknown';\n const pid = fields[1] ?? 'unknown';\n const user = fields[2] ?? 'unknown';\n return { command, pid, port, user };\n } catch {\n return { command: 'unknown', pid: 'unknown', port, user: 'unknown' };\n }\n}\n\nfunction isPortInUseError(error: unknown): boolean {\n return (\n error instanceof Error &&\n 'code' in error &&\n (error as NodeJS.ErrnoException).code === 'EADDRINUSE'\n );\n}\n\nasync function exchangeCodeForToken(\n code: string,\n codeVerifier: string,\n callbackUrl: string,\n baseUrl?: string,\n): Promise<OAuthTokenResponse> {\n const clientId = getOAuthClientId(baseUrl);\n const oauthUrl = getOAuthUrl(baseUrl);\n\n logToFile(`[oauth] exchanging code for token at ${oauthUrl}/oauth/token`);\n let response;\n try {\n response = await axios.post(\n `${oauthUrl}/oauth/token`,\n {\n grant_type: 'authorization_code',\n code,\n redirect_uri: callbackUrl,\n client_id: clientId,\n code_verifier: codeVerifier,\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n );\n } catch (e) {\n const status = axios.isAxiosError(e) ? e.response?.status : undefined;\n logToFile(\n `[oauth] token exchange failed${status ? ` (HTTP ${status})` : ''}:`,\n e instanceof Error ? e.message : e,\n );\n // Surface the OAuth error body (RFC 6749 §5.2) when the token endpoint\n // sent one — otherwise `invalid_grant`, PKCE mismatches, etc. reach the\n // user as a bare axios \"Request failed with status code 400\".\n const exchangeError = axios.isAxiosError(e)\n ? oauthErrorFromTokenBody(e.response?.data)\n : null;\n if (exchangeError) {\n logToFile(\n `[oauth] token endpoint error: ${exchangeError.code}` +\n (exchangeError.description ? ` (${exchangeError.description})` : ''),\n );\n throw exchangeError;\n }\n throw e;\n }\n\n const token = OAuthTokenResponseSchema.parse(response.data);\n logToFile(\n `[oauth] token exchange succeeded, granted scopes: ${token.scope}` +\n `${token.posthog_region ? `, region: ${token.posthog_region}` : ''}` +\n `${\n token.scoped_teams\n ? `, scoped_teams: [${token.scoped_teams.join(', ')}]`\n : ''\n }` +\n `${\n token.scoped_organizations\n ? `, scoped_organizations: ${token.scoped_organizations.length}`\n : ''\n }`,\n );\n return token;\n}\n\n/**\n * Warn — at login, while the user is still watching — when the grant came back\n * narrower than the request, and record the gap so narrowed runs are countable.\n * Non-fatal by design: deselecting an optional scope is the user's call, and\n * most flows survive it. The one scope the wizard cannot run without has its\n * own hard check (`assertWizardCompletionScope`).\n */\nfunction reportNarrowedGrant(\n requestedScopes: readonly string[],\n grantedScope: string,\n store: WizardStore,\n): void {\n const missing = missingOAuthScopes(requestedScopes, grantedScope);\n if (missing.length === 0) return;\n\n logToFile(\n `[oauth] grant narrower than request, missing: ${missing.join(' ')}`,\n );\n analytics.wizardCapture('oauth grant narrowed', {\n requested_scopes: [...requestedScopes].sort().join(' '),\n granted_scopes: parseOAuthScopes(grantedScope).sort().join(' '),\n missing_scopes: missing.join(' '),\n missing_scope_count: missing.length,\n });\n const plural = missing.length > 1;\n store.pushStatus(\n `Your PostHog authorization is missing ${\n plural ? `${missing.length} permissions` : 'a permission'\n } the wizard asked for: ${missing.join(', ')}. ` +\n `Setup will continue, but steps that need ${\n plural ? 'them' : 'it'\n } may fail. ` +\n `To grant ${\n plural ? 'them' : 'it'\n }, re-run the wizard and approve all permissions on the ` +\n 'authorization screen. If that screen does not reappear, revoke the ' +\n 'existing PostHog Wizard authorization in your PostHog settings first.',\n );\n}\n\nexport async function performOAuthFlow(\n config: OAuthConfig,\n store: WizardStore,\n): Promise<OAuthTokenResponse> {\n const clientId = getOAuthClientId(config.baseUrl);\n const oauthUrl = getOAuthUrl(config.baseUrl);\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n let shouldRetry = false;\n\n logToFile(\n `[oauth] starting flow against ${oauthUrl}, ` +\n `requested scopes: ${config.scopes.join(' ')}`,\n );\n\n do {\n shouldRetry = false;\n let lastProcessInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null = null;\n\n for (const port of OAUTH_PORTS) {\n const callbackUrl = getCallbackUrl(port);\n const authUrl = new URL(`${oauthUrl}/oauth/authorize`);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set('redirect_uri', callbackUrl);\n authUrl.searchParams.set('response_type', 'code');\n authUrl.searchParams.set('code_challenge', codeChallenge);\n authUrl.searchParams.set('code_challenge_method', 'S256');\n authUrl.searchParams.set('scope', config.scopes.join(' '));\n authUrl.searchParams.set('required_access_level', 'project');\n if (config.projectId !== undefined) {\n // Pre-select this project on the consent screen so the user just clicks Authorize.\n authUrl.searchParams.set('team_id', String(config.projectId));\n }\n\n // UTM-tag both kickoff URLs so the journey into the app is\n // attributable to the wizard command that started it.\n const taggedAuthUrl = withUtm(authUrl.toString(), 'oauth-authorize');\n const signupUrl = new URL(\n withUtm(\n `${oauthUrl}/signup?next=${encodeURIComponent(taggedAuthUrl)}`,\n 'oauth-signup',\n ),\n );\n const localSignupUrl = getLocalSignupUrl(port);\n const localLoginUrl = getLocalLoginUrl(port);\n const urlToOpen = config.signup ? localSignupUrl : localLoginUrl;\n\n logToFile(`[oauth] attempting callback server on port ${port}`);\n\n let server: http.Server;\n let waitForCallback: () => Promise<string>;\n try {\n ({ server, waitForCallback } = await startCallbackServer(\n taggedAuthUrl,\n signupUrl.toString(),\n port,\n ));\n } catch (e) {\n if (!isPortInUseError(e)) throw e;\n lastProcessInfo = getPortProcessInfo(port);\n continue;\n }\n\n logToFile('[oauth] callback server ready, showing login URL');\n\n store.setLoginUrl(urlToOpen);\n // The localhost proxy above only works on this machine. Surface the\n // direct PostHog authorize URL too, for the manual-paste modal — on a\n // remote/headless box the user opens it from another machine, where\n // localhost:<port> is unreachable.\n store.setAuthorizeUrl(\n config.signup ? signupUrl.toString() : taggedAuthUrl,\n );\n\n // The localhost proxy URL stays untagged — the PostHog destination\n // it redirects to carries the UTMs.\n openTrackedLink(urlToOpen, 'oauth', { auto: true, skipUtm: true });\n\n store.pushStatus('Waiting for authorization...');\n\n try {\n // Race the local callback server against a manually-pasted code. The\n // manual path is the fallback for headless/remote shells where the\n // browser can't reach localhost — the user opens the auth screen's\n // paste modal and submits the callback URL or code by hand.\n const code = await Promise.race([\n waitForCallback(),\n store.waitForManualAuthCode(),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(AUTHORIZATION_TIMEOUT_MESSAGE)),\n OAUTH_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const token = await exchangeCodeForToken(\n code,\n codeVerifier,\n callbackUrl,\n config.baseUrl,\n );\n\n server.close();\n store.setLoginUrl(null);\n store.setAuthorizeUrl(null);\n store.pushStatus('Authorization complete!');\n\n reportNarrowedGrant(config.scopes, token.scope, store);\n\n return token;\n } catch (e) {\n const error = e instanceof Error ? e : new Error('Unknown error');\n const timedOut = isAuthorizationTimeout(error);\n const flowError = error instanceof OAuthError ? error : null;\n\n store.pushStatus(\n timedOut ? 'Session timed out.' : 'Authorization failed.',\n );\n server.close();\n\n logToFile('[oauth] flow failed:', error);\n if (flowError?.description) {\n logToFile(\n `[oauth] server error_description: ${flowError.description}`,\n );\n }\n\n const accessDenied = flowError\n ? flowError.code === 'access_denied'\n : error.message.includes('access_denied');\n\n if (timedOut) {\n // Overlay bypasses the auth-step gating (which never completes\n // without credentials), so the user sees the failure instead of a\n // spinner that never stops; any key exits.\n store.showSessionTimeout();\n } else if (accessDenied) {\n store.pushStatus(\n `Authorization was cancelled.\\n\\nYou denied access to PostHog. To use the wizard, you need to authorize access to your PostHog account.\\n\\nYou can try again by re-running the wizard.`,\n );\n } else {\n store.pushStatus(\n buildOAuthFailureMessage({\n error,\n requestedScopes: config.scopes,\n clientId,\n oauthUrl,\n // Same condition that selects the dev client ID: a resolvable\n // base URL means a dev-seeded stack, where \"fix your local\n // OAuth app\" beats pointing at the production runbook.\n isDevStack: resolveBaseUrl(config.baseUrl) !== undefined,\n }),\n );\n }\n\n const oauthErrorCode = flowError\n ? flowError.code\n : error.message.startsWith('OAuth error: ')\n ? error.message.slice('OAuth error: '.length)\n : timedOut\n ? 'timeout'\n : 'unknown';\n\n analytics.captureException(error, {\n step: 'oauth_flow',\n oauth_error_code: oauthErrorCode,\n oauth_error_description: flowError?.description,\n client_id: clientId,\n requested_scopes: config.scopes.join(' '),\n // Collapse OAuth callback failures of the same kind into one issue\n // instead of fragmenting by each user's install path in the stack trace.\n $exception_fingerprint: `wizard_oauth_${oauthErrorCode}`,\n });\n\n await abortOnScreens(store);\n throw error;\n }\n }\n\n if (!lastProcessInfo) {\n throw new Error('No OAuth callback ports configured');\n }\n\n await store.showPortConflict(lastProcessInfo);\n shouldRetry = true;\n } while (shouldRetry);\n\n throw new Error('OAuth port retry loop exited unexpectedly');\n}\n","export type GrantedProjectResolution =\n | { ok: true; projectId: number | undefined }\n | { ok: false; requested: number; granted: number };\n\n/**\n * Decide which project to use after OAuth. `--project-id` (when passed) is authoritative,\n * but only when the user granted access to it on the consent screen; a different grant is a\n * mismatch the caller must surface. With no `--project-id` this returns the granted project\n * (`scopedTeams[0]`), preserving the pre-flag behavior for every wizard program (the main\n * integration flow included).\n */\nexport function resolveGrantedProject(\n requestedProjectId: number | undefined,\n scopedTeams: number[] | undefined,\n): GrantedProjectResolution {\n // No --project-id: use whatever the user granted, exactly as before the flag existed.\n if (requestedProjectId === undefined) {\n return { ok: true, projectId: scopedTeams?.[0] };\n }\n // --project-id was among the granted teams: honor it.\n if (scopedTeams?.includes(requestedProjectId)) {\n return { ok: true, projectId: requestedProjectId };\n }\n // --project-id requested but a different project was authorized: mismatch.\n if (scopedTeams && scopedTeams.length > 0) {\n return {\n ok: false,\n requested: requestedProjectId,\n granted: scopedTeams[0],\n };\n }\n // Nothing granted at all — let the caller's \"no project access\" guard handle it.\n return { ok: true, projectId: undefined };\n}\n","/**\n * Login: resolve the PostHog credentials and project for a run, through the\n * browser OAuth flow or a provisioning signup. UI-bound, so it\n * lives with the TUI's store; programs receive credentials, never log in.\n */\n\nimport { withProgress } from '@utils/telemetry';\nimport type { CloudRegion, WizardRunOptions } from '@utils/types';\nimport {\n DUMMY_PROJECT_API_KEY,\n ISSUES_URL,\n WIZARD_OAUTH_SCOPES,\n WIZARD_PROVISIONING_SCOPES,\n} from '@shared/constants';\nimport { withScopeAdditions } from '@shared/oauth-scopes';\nimport {\n getOAuthScopesForProgram,\n getProvisioningScopesForProgram,\n} from '@programs';\nimport type { ProgramId } from '@programs/types';\nimport { analytics } from '@utils/analytics';\nimport type { WizardStore } from '@tui/store';\nimport { HostResolution } from '@shared/host-resolution';\nimport { detectOrgAndProject } from '@utils/setup-utils';\nimport { missingOAuthScopes } from '@programs';\nimport { assertWizardCompletionScope, performOAuthFlow } from './oauth.js';\nimport { resolveGrantedProject } from '@utils/project-resolution';\nimport {\n ProvisionedAccountUnreadableError,\n provisionNewAccount,\n} from '@utils/provisioning';\nimport {\n fetchUserData,\n fetchProjectData,\n type ApiUser,\n type ApiProject,\n} from '@shared/api';\nimport { abortOnScreens } from '@tui/abort';\nimport { OutroKind } from '@shared/outro';\n\ninterface ProjectData {\n projectApiKey: string;\n accessToken: string;\n refreshToken?: string;\n /** Epoch ms when `accessToken` expires. */\n expiresAt?: number;\n /** Minting OAuth client when it differs from the default login app (provisioning signups). */\n oauthClientId?: string;\n host: HostResolution;\n distinctId: string;\n projectId: number;\n /**\n * Optional `role_at_organization` from `/api/users/@me/`. Drives the\n * role-tailored prompt suggestions on the McpSuggestedPromptsScreen. Null\n * for signup flows (no role picked yet) and older accounts.\n */\n roleAtOrganization?: string | null;\n /**\n * Full user payload from `/api/users/@me/`. Carried through so\n * `getOrAskForProjectData` can forward it to the session as\n * `session.apiUser`. Null when the request failed.\n */\n user?: ApiUser | null;\n /**\n * Full project payload from `/api/projects/:id/`. Carries the team's\n * product opt-ins (replay, exception autocapture, surveys) so prompts\n * can state project-level product enablement instead of agents\n * inferring it from repo evidence. Null on signup flows.\n */\n project?: ApiProject | null;\n /**\n * Requested OAuth scopes the grant came back without (consent deselection\n * or ceiling clamp). Forwarded to `session.credentials.missingScopes` so\n * runs can degrade scope-gated steps instead of failing on a 403. Empty on\n * the signup-provisioning path.\n */\n missingScopes?: readonly string[];\n}\n\n/**\n * Get project data for the wizard via OAuth or a provisioning signup.\n */\nexport async function getOrAskForProjectData(\n _options: Pick<WizardRunOptions, 'signup' | 'projectId'> & {\n /** Where login progress and errors are shown. */\n store: WizardStore;\n email?: string;\n region?: CloudRegion;\n /** Explicit base URL override (`--base-url`, from `session.baseUrl`). When\n * set, pins every PostHog origin and bypasses region resolution. */\n baseUrl?: string;\n /** `--local-mcp`: forwarded into the resolved host so `host.mcpUrl` is local. */\n localMcp?: boolean;\n /** Optional — picks the OAuth scope set via\n * `getOAuthScopesForProgram`. Omitted → default\n * `WIZARD_OAUTH_SCOPES`. Threaded into `askForWizardLogin`. */\n programId?: ProgramId | null;\n /** A tool's or a screen's own widening of the base scopes; wins over `programId`'s. */\n scopeAdditions?: readonly string[];\n },\n): Promise<{\n host: HostResolution;\n projectApiKey: string;\n accessToken: string;\n refreshToken?: string;\n /** Epoch ms when `accessToken` expires. */\n expiresAt?: number;\n /** Minting OAuth client when it differs from the default login app (provisioning signups). */\n oauthClientId?: string;\n projectId: number;\n roleAtOrganization: string | null;\n user: ApiUser | null;\n project: ApiProject | null;\n /** Requested OAuth scopes the grant came back without. Empty on the signup path. */\n missingScopes: readonly string[];\n}> {\n const { store } = _options;\n const {\n host,\n projectApiKey,\n accessToken,\n refreshToken,\n expiresAt,\n oauthClientId,\n projectId,\n roleAtOrganization,\n user,\n project,\n missingScopes,\n } = await withProgress('login', () =>\n askForWizardLogin({\n store,\n signup: _options.signup,\n email: _options.email,\n region: _options.region,\n baseUrl: _options.baseUrl,\n programId: _options.programId,\n scopeAdditions: _options.scopeAdditions,\n projectId: _options.projectId,\n localMcp: _options.localMcp,\n }),\n );\n\n if (!projectApiKey) {\n const cloudUrl = host.appHost;\n store.pushStatus(`Didn't receive a project token. This shouldn't happen :(\n\nPlease let us know if you think this is a bug in the wizard:\n${ISSUES_URL}`);\n\n store.pushStatus(`In the meantime, we'll add a dummy project token (\"${DUMMY_PROJECT_API_KEY}\") for you to replace later.\nYou can find your project token here:\n${cloudUrl}/settings/project#variables`);\n }\n\n return {\n accessToken,\n refreshToken,\n expiresAt,\n oauthClientId,\n host,\n projectApiKey: projectApiKey || DUMMY_PROJECT_API_KEY,\n projectId,\n roleAtOrganization: roleAtOrganization ?? null,\n user: user ?? null,\n project: project ?? null,\n missingScopes: missingScopes ?? [],\n };\n}\n\nasync function askForWizardLogin(options: {\n store: WizardStore;\n signup: boolean;\n email?: string;\n region?: CloudRegion;\n /** Explicit base URL override (`--base-url`); pins every PostHog origin. */\n baseUrl?: string;\n /** Used to pick the right scope set via `getOAuthScopesForProgram`.\n * Omitted → default `WIZARD_OAUTH_SCOPES`. */\n programId?: ProgramId | null;\n scopeAdditions?: readonly string[];\n /** `--project-id`, if passed. When the user granted access to it on the consent\n * screen we use it directly; otherwise we fall back to the first granted team. */\n projectId?: number;\n /** `--local-mcp`: forwarded into the resolved host so `host.mcpUrl` is local. */\n localMcp?: boolean;\n}): Promise<ProjectData> {\n const { store } = options;\n if (options.signup) {\n return askForProvisioningSignup(\n store,\n options.email,\n options.region,\n options.baseUrl,\n options.localMcp,\n options.programId,\n options.scopeAdditions,\n options.projectId,\n );\n }\n\n const requestedScopes = [\n ...(options.scopeAdditions\n ? withScopeAdditions(WIZARD_OAUTH_SCOPES, options.scopeAdditions)\n : getOAuthScopesForProgram(options.programId)),\n ];\n const tokenResponse = await performOAuthFlow(\n {\n scopes: requestedScopes,\n signup: false,\n projectId: options.projectId,\n baseUrl: options.baseUrl,\n },\n store,\n );\n\n try {\n assertWizardCompletionScope(tokenResponse.scope);\n } catch (error) {\n const scopeError =\n error instanceof Error ? error : new Error('OAuth scope check failed');\n const missing = missingOAuthScopes(requestedScopes, tokenResponse.scope);\n analytics.captureException(scopeError, {\n step: 'wizard_login',\n missing_scope: 'event_definition:write',\n });\n await abortOnScreens(store, {\n message: scopeError.message,\n outroData: {\n kind: OutroKind.Error,\n message: 'Setup needs permissions that were not granted',\n body: [\n 'Missing permissions:',\n ...missing.map((scope) => ` • ${scope}`),\n '',\n 'Re-run the wizard and approve all permissions on the PostHog authorization screen.',\n 'If that screen does not reappear, revoke the existing PostHog Wizard authorization in your PostHog settings first.',\n ].join('\\n'),\n },\n });\n }\n\n // `--project-id`, when provided, is authoritative — but only if the user actually\n // granted access to it on the consent screen. If they authorized a different\n // project, fail loudly instead of silently capturing into the wrong one. With no\n // `--project-id` this falls back to the granted project, unchanged for every program.\n const resolution = resolveGrantedProject(\n options.projectId,\n tokenResponse.scoped_teams,\n );\n if (!resolution.ok) {\n const error = new Error(\n `You authorized project ${resolution.granted}, but setup is targeting project ${resolution.requested} (from --project-id). ` +\n `If ${resolution.requested} is not a project you own — a copy-pasted example value, say — re-run without --project-id, or with the id shown in your PostHog project settings. ` +\n `If it is yours, re-run and grant access to project ${resolution.requested} on the authorization screen.`,\n );\n analytics.captureException(error, {\n step: 'wizard_login',\n requested_project_id: resolution.requested,\n granted_project_id: resolution.granted,\n });\n store.pushStatus(error.message);\n await abortOnScreens(store, { message: error.message });\n }\n\n const projectId = resolution.ok ? resolution.projectId : undefined;\n\n if (projectId === undefined) {\n const error = new Error(\n 'No project access granted. Please authorize with project-level access.',\n );\n analytics.captureException(error, {\n step: 'wizard_login',\n has_scoped_teams: !!tokenResponse.scoped_teams,\n });\n store.pushStatus(error.message);\n await abortOnScreens(store, { message: error.message });\n }\n\n // The issuing region comes with the token; the us/eu @me probe only runs when omitted.\n const host = await HostResolution.fromAccessToken(\n tokenResponse.access_token,\n {\n region: tokenResponse.posthog_region,\n localMcp: options.localMcp,\n baseUrl: options.baseUrl,\n },\n );\n const cloudUrl = host.appHost;\n\n const projectData = await fetchProjectData(\n tokenResponse.access_token,\n projectId!,\n cloudUrl,\n );\n const userData = await fetchUserData(tokenResponse.access_token, cloudUrl);\n\n const data = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token,\n expiresAt: Date.now() + tokenResponse.expires_in * 1000,\n projectApiKey: projectData.api_token,\n host,\n distinctId: userData.distinct_id,\n projectId: projectId!,\n roleAtOrganization: userData.role_at_organization ?? null,\n user: userData,\n project: projectData,\n // What the user declined at consent (or the ceiling clamped) — carried to\n // the session so runs degrade scope-gated steps instead of 403ing blind.\n missingScopes: missingOAuthScopes(requestedScopes, tokenResponse.scope),\n };\n\n store.pushStatus('Login complete.');\n analytics.setTag('opened-wizard-link', true);\n analytics.identifyUser(userData);\n\n return data;\n}\n\nasync function askForProvisioningSignup(\n store: WizardStore,\n email?: string,\n region?: CloudRegion,\n baseUrl?: string,\n localMcp?: boolean,\n programId?: ProgramId | null,\n scopeAdditions?: readonly string[],\n projectId?: number,\n): Promise<ProjectData> {\n if (!email || !email.includes('@')) {\n store.pushStatus(\n 'Email is required for signup. Use --email your@email.com with --signup.',\n );\n await abortOnScreens(store);\n throw new Error('unreachable');\n }\n\n store.pushStatus('Creating your PostHog account...');\n\n try {\n const provisionRegion = (region ?? 'us').toUpperCase() as 'US' | 'EU';\n const { orgName, projectName } = detectOrgAndProject(email);\n const result = await provisionNewAccount(email, '', provisionRegion, {\n orgName,\n projectName,\n baseUrl,\n scopes: scopeAdditions\n ? withScopeAdditions(WIZARD_PROVISIONING_SCOPES, scopeAdditions)\n : getProvisioningScopesForProgram(programId),\n });\n\n store.pushStatus('Account created!');\n store.pushStatus('Welcome to PostHog!');\n\n const host = HostResolution.fromApiHost(result.host, { localMcp });\n\n analytics.setTag('provisioning-signup', true);\n\n return {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: result.expiresAt,\n oauthClientId: result.oauthClientId,\n projectApiKey: result.projectApiKey,\n host,\n distinctId: email,\n projectId: parseInt(result.projectId, 10) || 0,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n // The account exists — reporting a failed signup would send the user off to create a\n // second one on top of the org they already own.\n if (error instanceof ProvisionedAccountUnreadableError) {\n store.pushStatus(\n 'Account created, but the project could not be read back.',\n );\n store.pushStatus(message);\n store.pushStatus('Signing you in to your new account instead...');\n\n return askForWizardLogin({\n store,\n signup: false,\n baseUrl,\n localMcp,\n programId,\n scopeAdditions,\n projectId,\n });\n }\n\n store.pushStatus('Account creation failed.');\n\n if (message.includes('already associated')) {\n store.pushStatus(\n 'This email already has a PostHog account. Switching to login flow...',\n );\n\n return askForWizardLogin({\n store,\n signup: false,\n baseUrl,\n localMcp,\n programId,\n scopeAdditions,\n projectId,\n });\n }\n\n store.pushStatus(`Failed to create account: ${message}`);\n analytics.captureException(\n error instanceof Error ? error : new Error(message),\n { step: 'provisioning_signup' },\n );\n await abortOnScreens(store);\n throw error;\n }\n}\n","/**\n * Demo-event seeder for the MCP tutorial's empty-project path.\n *\n * When the scout (`probeProjectData`) finds a project with zero events, the\n * tutorial offers to send a small, coherent demo dataset so the read\n * quests have something real to chew on instead of dead-ending. The\n * dataset is a recognizable SaaS product funnel —\n *\n * $pageview → signed_up → activated → feature_used → upgraded_to_paid\n *\n * — spread across ~12 synthetic users and backdated over the last 7 days,\n * so time-windowed funnels and trends include the data the moment it lands\n * (sidestepping ingestion lag for the queries the tutorial actually runs).\n *\n * Every seeded event carries `wizard_seed: true` and a synthetic\n * `wizard-demo-user-*` distinct id, so the user can find and clean up the\n * demo data from a single search in PostHog — the same \"leave a trail\"\n * principle as the `(wizard MCP tutorial)` artifact tagging.\n *\n * `$exception` is deliberately NOT seeded: leaving error tracking empty\n * keeps it available as an \"enable error tracking\" activation cross-sell,\n * which is exactly the kind of product-discovery beat the empty path is\n * meant to create.\n */\n\nimport { logToFile } from '@utils/debug';\nimport {\n assembleProfile,\n type EventVolume,\n type ProjectDataProfile,\n} from './mcp-project-profile';\n\nexport interface SeedEvent {\n event: string;\n distinctId: string;\n timestamp: Date;\n properties: Record<string, unknown>;\n}\n\nconst SEED_USER_COUNT = 12;\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nconst demoUser = (i: number): string => `wizard-demo-user-${i + 1}`;\n\n/**\n * A timestamp `daysAgo` days plus `hour` hours BEFORE `now`. Both offsets\n * are subtracted so every seeded event lands strictly in the past (daysAgo\n * maxes at 6 and hour at ~15, keeping the oldest event under the 7-day\n * window the tutorial's queries use).\n */\nconst at = (now: Date, daysAgo: number, hour: number): Date =>\n new Date(now.getTime() - daysAgo * DAY_MS - hour * 60 * 60 * 1000);\n\n/**\n * Build the deterministic demo dataset. Deterministic (no randomness) so\n * the returned profile counts always match what was sent and tests are\n * stable. Drop-off down the funnel is modelled by fewer users reaching\n * each step.\n */\nexport function buildSeedEvents(now: Date): SeedEvent[] {\n const events: SeedEvent[] = [];\n const push = (\n event: string,\n userIdx: number,\n daysAgo: number,\n hour: number,\n properties: Record<string, unknown> = {},\n ): void => {\n events.push({\n event,\n distinctId: demoUser(userIdx),\n timestamp: at(now, daysAgo, hour),\n properties: { ...properties, wizard_seed: true },\n });\n };\n\n // Pageviews: every user, a few visits spread across the week.\n const PAGES = ['/', '/pricing', '/signup', '/app'];\n for (let i = 0; i < SEED_USER_COUNT; i++) {\n for (let k = 0; k < 4; k++) {\n push('$pageview', i, (i + k) % 7, 9 + k, {\n $current_url: `https://example.com${PAGES[k % PAGES.length]}`,\n });\n }\n }\n\n // signed_up: 10 of 12 users (2 bounce before signing up).\n for (let i = 0; i < 10; i++) {\n push('signed_up', i, 6 - (i % 7), 10, {\n source: i % 2 ? 'organic' : 'ads',\n });\n }\n\n // activated: 7 of the 10 who signed up.\n for (let i = 0; i < 7; i++) {\n push('activated', i, 5 - (i % 6), 11);\n }\n\n // feature_used: the 7 activated users exercise features a few times each.\n const FEATURES = ['dashboards', 'insights', 'session_replay'];\n for (let i = 0; i < 7; i++) {\n for (let k = 0; k < 3; k++) {\n push('feature_used', i, 4 - ((i + k) % 5), 12 + k, {\n feature: FEATURES[k % FEATURES.length],\n });\n }\n }\n\n // upgraded_to_paid: 3 of the activated users convert.\n for (let i = 0; i < 3; i++) {\n push('upgraded_to_paid', i, 2 - (i % 3), 13, { plan: 'pro' });\n }\n\n return events;\n}\n\n/** Tally a seed-event list into volume-sorted `EventVolume[]`. */\nexport function tallySeedEvents(events: SeedEvent[]): EventVolume[] {\n const counts = new Map<string, number>();\n for (const e of events) {\n counts.set(e.event, (counts.get(e.event) ?? 0) + 1);\n }\n return [...counts.entries()]\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n}\n\n/**\n * The profile a successful seed produces, without sending anything.\n * Event-derived fields come from the demo dataset; REST-derived product\n * presence is carried forward from the pre-seed probe (so a project that\n * already had, say, feature flags defined keeps that signal). Exported so\n * the screen can preview the seeded state and tests can assert on it.\n */\nexport function seededProfile(\n baseProfile: ProjectDataProfile,\n now: Date,\n): ProjectDataProfile {\n const counts = tallySeedEvents(buildSeedEvents(now));\n return assembleProfile(\n counts,\n {\n sessionReplay: baseProfile.products.sessionReplay,\n surveys: baseProfile.products.surveys,\n featureFlags: baseProfile.products.featureFlags,\n experiments: baseProfile.products.experiments,\n dataWarehouse: baseProfile.products.dataWarehouse,\n },\n { seeded: true },\n );\n}\n\n/**\n * Send the demo dataset to the project's ingestion endpoint via\n * posthog-node, then resolve with the seeded profile. Throws if the send\n * fails so the caller can surface a soft error and fall back to the\n * write-only empty path.\n */\nexport async function seedDemoEvents(args: {\n /** Public project API key (write key) — the SDK's ingestion credential. */\n projectApiKey: string;\n /** Event-ingestion host (e.g. https://us.i.posthog.com). */\n apiHost: string;\n /** The pre-seed probe result; its REST product flags are carried forward. */\n baseProfile: ProjectDataProfile;\n signal?: AbortSignal;\n /** Injectable clock for deterministic tests. */\n now?: Date;\n}): Promise<ProjectDataProfile> {\n const { projectApiKey, apiHost, baseProfile, signal } = args;\n const now = args.now ?? new Date();\n\n if (signal?.aborted) throw new Error('Seeding aborted');\n\n const events = buildSeedEvents(now);\n logToFile(\n `[seedDemoEvents] sending ${events.length} demo events to ${apiHost}`,\n );\n\n const { PostHog } = await import('posthog-node');\n const client = new PostHog(projectApiKey, {\n host: apiHost,\n // Send everything in one batch on shutdown; no background timer.\n flushAt: events.length,\n flushInterval: 0,\n disableGeoip: true,\n });\n\n try {\n for (const e of events) {\n client.capture({\n distinctId: e.distinctId,\n event: e.event,\n properties: e.properties,\n timestamp: e.timestamp,\n });\n }\n // shutdown() flushes any queued events and waits for delivery.\n await client.shutdown();\n } catch (err) {\n // Best-effort teardown so we don't leak a flush timer on failure.\n try {\n await client.shutdown();\n } catch {\n /* already failing — swallow */\n }\n throw err;\n }\n\n if (signal?.aborted) throw new Error('Seeding aborted');\n\n return seededProfile(baseProfile, now);\n}\n","/**\n * McpSuggestedPromptsServices — service layer between\n * McpSuggestedPromptsScreen and the network. Decouples the screen from\n * OAuth and the streaming-agent run so the playground can inject mocks\n * (skip login, canned streaming responses) without a special-case\n * branch in the screen itself.\n *\n * Mirrors the McpInstaller pattern: thin interface, production factory\n * that wires the real implementation, no dynamic imports in the React\n * tree.\n */\n\nimport type { Credentials } from '@shared/api';\nimport { getOrAskForProjectData } from '@tui/auth/project-data';\nimport {\n MCP_TUTORIAL_SCOPE_ADDITIONS,\n streamMcpPrompt,\n type McpPromptChunk,\n} from '@tools';\nimport type { WizardStore } from '@tui/store';\nimport type { ApiUser } from '@shared/api';\nimport {\n probeProjectData as runProbe,\n type ProjectDataProfile,\n} from './mcp-project-profile.js';\nimport { seedDemoEvents as runSeed } from './seed-events.js';\n\n// The streamed event shape is the agent's; re-exported so the screen and the\n// playground keep their import path.\nexport type { McpPromptChunk };\n\nexport interface McpSuggestedPromptsServices {\n /**\n * Kicks off the OAuth dance. Production wires this to\n * `getOrAskForProjectData`; the playground returns canned values\n * after a fake delay.\n *\n * While the promise is pending, the implementation is expected to set\n * `store.loginUrl` (via `store.setLoginUrl`) so the screen can\n * render the URL inline. Mocks may set/clear this URL too if they\n * want to exercise the spinner + URL layout.\n */\n performLogin(): Promise<{\n credentials: Credentials;\n roleAtOrganization: string | null;\n user: ApiUser | null;\n }>;\n\n /**\n * Run a prompt against Claude with the PostHog MCP server available\n * for tool use. Yields chunks as the agent streams. Caller is\n * responsible for honoring the abort signal — implementations should\n * also short-circuit when `signal.aborted` becomes true.\n *\n * In production this calls the Claude Agent SDK's `query()` with the\n * user's OAuth token as the MCP Bearer. In the playground, the demo\n * provides canned scripts.\n */\n runPromptStreaming(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n /** When set, resume the named SDK session so the agent sees the\n * earlier turns as context. Used by follow-up picks; omitted on\n * the first prompt and after `[p]` restarts the conversation. */\n resumeSessionId?: string;\n }): AsyncIterable<McpPromptChunk>;\n\n /**\n * Scout the project after auth: a cheap, best-effort probe of event\n * volume, the project's real event names, and which products have data.\n * Drives the data-aware picker so the tutorial never offers a prompt\n * that hits an empty result. Always resolves (degraded profile on\n * failure) — never throws, never blocks the tutorial.\n */\n probeProjectData(credentials: Credentials): Promise<ProjectDataProfile>;\n\n /**\n * Send a small, backdated demo dataset to an empty project so the read\n * quests have something to show. Resolves with the seeded profile;\n * rejects if the send fails so the screen can fall back to the\n * write-only empty path.\n */\n seedDemoEvents(args: {\n credentials: Credentials;\n baseProfile: ProjectDataProfile;\n signal: AbortSignal;\n }): Promise<ProjectDataProfile>;\n}\n\n/**\n * Production services. The agent's streaming module loads on the first\n * prompt, so a session that never runs one never pays for it.\n */\nexport function createMcpSuggestedPromptsServices(\n store: WizardStore,\n): McpSuggestedPromptsServices {\n return {\n performLogin: async () => {\n const result = await getOrAskForProjectData({\n store,\n signup: false,\n projectId: undefined,\n email: undefined,\n region: undefined,\n baseUrl: store.session.baseUrl,\n // Widens the OAuth scope grant: base `WIZARD_OAUTH_SCOPES` plus\n // read on every product surface (flags, experiments, surveys,\n // replays, errors, web analytics, AI Observability, cohorts, persons) plus\n // annotation read/write. Persistence writes (dashboard, insight,\n // notebook) come for free from the base set. See\n // `src/tools/mcp/scopes.ts`.\n scopeAdditions: MCP_TUTORIAL_SCOPE_ADDITIONS,\n });\n return {\n credentials: {\n accessToken: result.accessToken,\n projectApiKey: result.projectApiKey,\n host: result.host,\n projectId: result.projectId,\n },\n roleAtOrganization: result.roleAtOrganization,\n user: result.user,\n };\n },\n\n runPromptStreaming: (args) =>\n streamMcpPrompt({\n ...args,\n // Gateway cost attribution. Only the id crosses here; the rest of the\n // trace tags are built where the headers are, keeping the agent module\n // out of the TUI's startup graph.\n programId: store.analyticsProgramId,\n integration: store.session.integration ?? undefined,\n }),\n\n probeProjectData: (credentials) =>\n runProbe({\n accessToken: credentials.accessToken,\n projectId: credentials.projectId,\n apiHost: credentials.host.apiHost,\n }),\n\n seedDemoEvents: ({ credentials, baseProfile, signal }) =>\n runSeed({\n projectApiKey: credentials.projectApiKey,\n apiHost: credentials.host.apiHost,\n baseProfile,\n signal,\n }),\n };\n}\n","/** The MCP tools' TUI: add, remove and the tutorial. */\nimport { McpScreen } from '@tui/screens/McpScreen';\nimport type { TuiTool, TuiTools } from '@tui/tools/types';\nimport { MCP_ADD_FLOW, MCP_REMOVE_FLOW, MCP_TUTORIAL_FLOW } from './flow.js';\nimport { McpScreenId } from './screen-ids.js';\nimport { McpSuggestedPromptsScreen } from './screens/McpSuggestedPromptsScreen.js';\nimport { createMcpSuggestedPromptsServices } from './services/suggested-prompts.js';\nimport { getRolePrompts } from './services/mcp-role-prompts.js';\n\nexport { McpScreenId } from './screen-ids.js';\nexport type { McpSuggestedPromptsServices } from './services/suggested-prompts.js';\n\nconst screens: TuiTool['screens'] = {\n [McpScreenId.Add]: (store, services) => (\n <McpScreen\n store={store}\n installer={services.mcpInstaller}\n samplePrompts={getRolePrompts(\n store.session.roleAtOrganization,\n store.session.integration,\n )\n .slice(0, 3)\n .map((p) => p.prompt)}\n />\n ),\n [McpScreenId.Remove]: (store, services) => (\n <McpScreen store={store} installer={services.mcpInstaller} mode=\"remove\" />\n ),\n [McpScreenId.SuggestedPrompts]: (store) => (\n <McpSuggestedPromptsScreen\n store={store}\n services={createMcpSuggestedPromptsServices(store)}\n />\n ),\n};\n\nconst shared = { screens };\n\nexport const TUI_TOOLS: TuiTools = {\n 'mcp-add': { flow: MCP_ADD_FLOW, ...shared },\n 'mcp-remove': { flow: MCP_REMOVE_FLOW, ...shared },\n 'mcp-tutorial': { flow: MCP_TUTORIAL_FLOW, ...shared },\n};\n","import type { FlowStep } from '@tui/flow';\n\nexport const SLACK_FLOW: FlowStep[] = [\n {\n id: 'slack-connect',\n label: 'Connect Slack',\n screenId: 'slack-connect',\n isComplete: (s) => s.slackStepDismissed,\n },\n];\n","/** The `wizard slack` TUI: the shared Connect-Slack screen as the whole flow. */\nimport type { TuiTools } from '@tui/tools/types';\nimport { SLACK_FLOW } from './flow.js';\n\nexport const TUI_TOOLS: TuiTools = { slack: { flow: SLACK_FLOW } };\n","/**\n * The TUI tool registry: each tool's screens, gathered from its folder's entry\n * (`tools/<id>/index.ts`). The core reaches this module only through\n * `getTuiTool` and `listTuiTools`, and names no tool; a tool folder never\n * imports it.\n */\n\nimport type { TuiTool, TuiTools } from './types.js';\nimport { TUI_TOOLS as doctor } from '@tui/tools/doctor';\nimport { TUI_TOOLS as mcp } from '@tui/tools/mcp';\nimport { TUI_TOOLS as slack } from '@tui/tools/slack';\n\nexport type { TuiTool };\n\nconst TUI_TOOLS: Readonly<Record<string, TuiTool | undefined>> = {\n ...doctor,\n ...mcp,\n ...slack,\n} satisfies TuiTools;\n\n/** The tool's TUI, or undefined for a program's id. */\nexport function getTuiTool(id: string): TuiTool | undefined {\n return TUI_TOOLS[id];\n}\n\n/** Every TUI tool. */\nexport function listTuiTools(): readonly TuiTool[] {\n return Object.values(TUI_TOOLS).filter(\n (tool): tool is TuiTool => tool !== undefined,\n );\n}\n","/**\n * Who owns a flow id: a tool's TUI, else a program's (the generic skill\n * program for an id neither registry knows). Every core lookup of a flow goes\n * through here, so a tool never falls through to the skill program.\n */\n\nimport { getTuiProgram, listTuiPrograms } from '@tui/programs/index';\nimport { getTuiTool, listTuiTools } from '@tui/tools/index';\nimport type { TuiProgram } from './programs/types.js';\n\nexport function flowOwner(id: string): TuiProgram {\n return getTuiTool(id) ?? getTuiProgram(id);\n}\n\n/** Every program's and tool's TUI, for the screens each one adds. */\nexport function listFlowOwners(): readonly TuiProgram[] {\n return [...listTuiPrograms(), ...listTuiTools()];\n}\n","import { ErrorCodes } from '@shared/errors';\nimport { OutroKind } from '@shared/outro';\nimport type { WizardSession } from '@programs/types';\n\nexport const MINT_FAILURE_MESSAGE = \"The Wizard's a little busy\";\n\nexport const MINT_FAILURE_BODY =\n 'The wizard can still share spells. Grab a skill and let your agent take over.';\n\nexport const MINT_FAILURE_CONTACT =\n 'Email wizard@posthog.com and tell us what happened. Please attach this log:';\n\n/** The agent run ended in an error, whatever the reason. Login failures also\n * set an error outro but never had credentials, so they stay on the outro. */\nexport function isRunFailure(\n session: Pick<WizardSession, 'outroData' | 'credentials'>,\n): boolean {\n return (\n session.outroData?.kind === OutroKind.Error &&\n session.credentials !== null &&\n // A security stop is a decision, not an outage: it shows its own outro, never the busy handoff.\n session.outroData.errorCode !== ErrorCodes.AgentYaraViolation\n );\n}\n","/**\n * A program's screen flow in the TUI: the ordered screens, their visibility\n * and completion predicates, and the gates the TUI host waits on. Program\n * logic (detection, composed runs) stays on the program's `ProgramConfig`.\n */\n\nimport type { TuiView } from './tui-state.js';\nimport type { WizardReadinessResult } from '@shared/health-checks/readiness';\nimport type { WizardSession } from '@programs/types';\n\n/**\n * Context passed to onInit callbacks — fires when the TUI starts\n * rendering, before bin.ts has assigned the real session.\n */\nexport interface StoreInitContext {\n readonly session: WizardSession;\n readonly setReadinessResult: (result: WizardReadinessResult | null) => void;\n readonly setFrameworkContext: (key: string, value: unknown) => void;\n readonly emitChange: () => void;\n}\n\nexport interface FlowStep {\n /** Unique identifier for this step; `ProgramConfig.runSteps` keys match it. */\n id: string;\n\n /** Human-readable label for progress display */\n label: string;\n\n /**\n * TUI screen this step owns, if any.\n * Matches the ScreenId enum values (e.g. 'intro', 'run', 'outro').\n */\n screenId?: string;\n\n /**\n * Whether this step should be visible in the current program.\n * If omitted, the step is always visible.\n */\n show?: (view: TuiView) => boolean;\n\n /**\n * Exit condition for the screen. Router advances when true.\n * Defaults to `gate` if unset.\n */\n isComplete?: (view: TuiView) => boolean;\n\n /**\n * Define a gate if your screen needs to await user interactions.\n * The TUI host can `await store.getGate(stepId)` to pause until the\n * predicate becomes true.\n */\n gate?: (view: TuiView) => boolean;\n\n /**\n * Called once when the TUI starts rendering, with the default\n * session. Use for session-independent fire-and-forget work that\n * should start as early as possible (e.g. health check kicked off\n * while the user is still reading the intro screen). Never fires for\n * a store that isn't rendering screens (tests, playground).\n */\n onInit?: (ctx: StoreInitContext) => void;\n}\n\n/**\n * Project program steps into the narrower Screen shape the router consumes.\n *\n * Two things happen here:\n * 1. Headless steps (no `screenId`) are filtered out. The router walks\n * visible screens; gate-only steps like `detect` are store concerns.\n * 2. The step is narrowed to just { id, show, isComplete } — the\n * router has no business touching gate, onInit, or label.\n *\n * This intentional separation keeps the router focused on one question:\n * \"Which screen should be rendered right now?\"\n */\nexport function createProgramSequence(steps: FlowStep[]): Array<{\n id: string;\n show?: (view: TuiView) => boolean;\n isComplete?: (view: TuiView) => boolean;\n}> {\n const entries = steps\n .filter((step) => step.screenId != null)\n .map((step) => ({\n id: step.screenId!,\n show: step.show,\n // `isComplete` defaults to `gate` — for most steps they're the same\n // predicate (e.g. intro: setupConfirmed unblocks the TUI host AND\n // finishes the screen). Only override when the two conditions diverge.\n isComplete: step.isComplete ?? step.gate,\n }));\n\n // Every program ends with the exit screen.\n entries.push({ id: 'exit', show: undefined, isComplete: undefined });\n\n return entries;\n}\n","/**\n * AI opt-in gate — step injection for programs whose agent run sends\n * source to Anthropic Claude.\n *\n * Injected after the `auth` step of every program's flow; a tool runs no\n * agent, so its flow never gets it. The injected step carries three\n * predicates:\n *\n * show — renders AiOptInRequiredScreen when the org hasn't\n * approved third-party AI\n * isComplete — router advances once approval lands\n * gate — `await store.getGate('ai-opt-in')` parks the agent\n * runner until approval lands. THIS is the enforcement:\n * the screen alone is cosmetic; the gate is what stops\n * source from leaving the machine.\n *\n * Used by BOTH screen-sequences.ts (screen injection) and the store's\n * _initFromProgram (gate registration) so the two layers can't drift.\n *\n * The predicates mirror Max's strict reading of\n * `organization.is_ai_data_processing_approved`: only literal `true`\n * proceeds; `null` / `undefined` / `false` all block. CI and signup\n * sessions skip the gate:\n * - `--ci` auto-consents to AI usage per the README, and the\n * interactive kill screen would be unworkable headless.\n * - signup (account provisioning) auto-consents too: the provisioning\n * access token deliberately omits the `organization:read` scope\n * (`WIZARD_PROVISIONING_SCOPES` in constants.ts), so the org's\n * approval can never be read back — `apiUser` stays null and the gate\n * could never clear. Creating an account through the wizard to run the\n * AI agent is itself the consent, mirroring how `shouldDisableAsk`\n * already treats `ci || signup` as one non-interactive mode.\n */\n\nimport { findProgramConfig, type ProgramId } from '@programs';\nimport type { ProgramConfig, WizardSession } from '@programs/types';\nimport type { FlowStep } from './flow.js';\nimport { flowOwner } from './flow-owner.js';\n\n/** Step id — also the ScreenId.AiOptIn enum value in screen-sequences. */\nexport const AI_OPT_IN_STEP_ID = 'ai-opt-in';\n\nfunction aiApproved(session: WizardSession): boolean {\n return !!session.apiUser?.organization?.is_ai_data_processing_approved;\n}\n\n/**\n * Returns the program's flow with the AI opt-in gate injected after\n * `auth`. A tool's flow (no program config) or one with no auth step\n * passes through unchanged — without auth, `apiUser` would never be\n * populated for evaluation anyway.\n */\nexport function withAiOptInGate(\n config: ProgramConfig | undefined,\n steps: FlowStep[],\n): FlowStep[] {\n if (!config) return steps;\n\n const authIdx = steps.findIndex((s) => s.id === 'auth');\n if (authIdx === -1) return steps;\n\n const gateStep: FlowStep = {\n id: AI_OPT_IN_STEP_ID,\n label: 'AI opt-in check',\n screenId: AI_OPT_IN_STEP_ID,\n // Only fire once apiUser has actually been populated — between\n // setCredentials and setApiUser there's a brief emitChange window\n // where apiUser is null, and we don't want to flash the gate then.\n show: ({ session }) =>\n !session.ci &&\n !session.signup &&\n session.apiUser != null &&\n !aiApproved(session),\n isComplete: ({ session }) =>\n session.ci || session.signup || aiApproved(session),\n gate: ({ session }) => session.ci || session.signup || aiApproved(session),\n };\n\n return [\n ...steps.slice(0, authIdx + 1),\n gateStep,\n ...steps.slice(authIdx + 1),\n ];\n}\n\n/** A program's or a tool's flow with the AI opt-in gate injected. */\nexport function programFlowSteps(programId: ProgramId): FlowStep[] {\n return withAiOptInGate(\n findProgramConfig(programId),\n flowOwner(programId).flow,\n );\n}\n","/**\n * Core screen ids + per-program screen sequences.\n *\n * Owns the core ScreenId enum and projects a program's flow into the\n * router-shaped screen sequence (filtering headless steps and appending the\n * exit screen). No store, no React, and no program by name.\n */\n\nimport type { TuiView } from '@tui/tui-state';\nimport type { ProgramId } from '@programs';\nimport { createProgramSequence } from './flow.js';\nimport { programFlowSteps } from './ai-opt-in-gate.js';\nimport { ScreenId } from './screen-ids.js';\n\nexport { ScreenId };\n\nexport interface Screen {\n /** Screen to show: a core `ScreenId` or a program's own screen id. */\n id: string;\n /** If provided, screen is skipped when this returns false. Omit = always show. */\n show?: (view: TuiView) => boolean;\n /** If provided, screen is considered complete when this returns true. */\n isComplete?: (view: TuiView) => boolean;\n}\n\n/** An ordered list of screens — a program's screen journey. */\nexport type Sequence = Screen[];\n\n/** Post-run steps a mint-failure handoff continues through; ends on exit. */\nexport const MINT_HANDOFF_SEQUENCE: Sequence = [\n { id: ScreenId.Mcp, isComplete: (s) => s.mcpComplete },\n { id: ScreenId.KeepSkills, isComplete: (s) => s.skillsComplete },\n { id: ScreenId.Exit },\n];\n\n/** A program's or a tool's screen sequence: its flow's screens, a program's AI opt-in gate, then exit. */\nexport function programSequence(programId: ProgramId): Sequence {\n return createProgramSequence(programFlowSteps(programId));\n}\n","/**\n * WizardRouter — declarative program pipelines + overlay stack.\n *\n * Two layers:\n * Program cursor — linear sequence of screens, advanced with next()\n * Overlay stack — interrupts (outage, auth-expired, etc.) that push/pop\n *\n * The visible screen is: top of overlay stack if non-empty, otherwise the program cursor.\n *\n * Adding a program screen = append to a sequence array.\n * Adding an overlay = call pushOverlay() from anywhere.\n * No switch statements, no hardcoded transitions in business logic.\n */\n\nimport { RunPhase } from '@shared/run-state';\nimport { OutroKind } from '@shared/outro';\nimport { type TuiView } from '@tui/tui-state';\nimport { isRunFailure } from '@tui/mint-failure';\nimport { Program, type ProgramId } from '@programs';\nimport {\n MINT_HANDOFF_SEQUENCE,\n ScreenId,\n programSequence,\n type Screen,\n type Sequence,\n} from './screen-sequences.js';\nimport { Overlay } from './screen-ids.js';\n\n// Re-export so existing imports from './router.js' keep working\nexport { ScreenId, Overlay, Program };\nexport type { Screen, Sequence, ProgramId };\n\n/** Any screen name: a core `ScreenId`, an `Overlay`, or a program's own screen id. */\nexport type ScreenName = string;\n\n// ── Router ────────────────────────────────────────────────────────────\n\nexport class WizardRouter {\n private sequence: Sequence;\n private programId: ProgramId;\n private overlays: Overlay[] = [];\n\n constructor(programId: ProgramId = Program.PostHogIntegration) {\n this.setProgram(programId);\n }\n\n /** Point the router at a different program. */\n setProgram(programId: ProgramId): void {\n this.programId = programId;\n this.sequence = programSequence(programId);\n this.overlays = [];\n }\n\n /**\n * Resolve which screen should be active based on the session and the TUI state.\n * Walks the program sequence, skipping hidden entries and completed entries,\n * returns the first incomplete screen.\n */\n resolve(view: TuiView): ScreenName {\n const { session } = view;\n // A failed agent run interrupts every program until the user leaves the\n // handoff screen: exit, or continue through the post-run steps.\n const runFailed = isRunFailure(session);\n if (runFailed && view.mintHandoff === 'exit') return ScreenId.Exit;\n if (runFailed && !view.mintHandoff) return ScreenId.MintFailure;\n\n if (this.overlays.length > 0) {\n return this.overlays[this.overlays.length - 1];\n }\n\n // Early aborts must be dismissible even when intro, setup, or auth is incomplete.\n if (\n !runFailed &&\n session.runPhase === RunPhase.Error &&\n session.outroData?.kind === OutroKind.Error\n ) {\n return view.outroDismissed ? ScreenId.Exit : ScreenId.Outro;\n }\n\n const sequence = runFailed ? MINT_HANDOFF_SEQUENCE : this.sequence;\n for (const entry of sequence) {\n if (entry.show && !entry.show(view)) continue;\n if (entry.isComplete && entry.isComplete(view)) continue;\n return entry.id;\n }\n\n // All entries complete — show the last screen (outro)\n return sequence[sequence.length - 1].id;\n }\n\n /** The screen that should be rendered right now. */\n get activeScreen(): ScreenName {\n // Overlays take priority — resolve() handles this too,\n // but activeScreen is called before session is available in some paths\n if (this.overlays.length > 0) {\n return this.overlays[this.overlays.length - 1];\n }\n return this.sequence[0].id;\n }\n\n /** The id of the active program. */\n get activeProgram(): ProgramId {\n return this.programId;\n }\n\n /** Whether an overlay is currently active. */\n get hasOverlay(): boolean {\n return this.overlays.length > 0;\n }\n\n /**\n * Push an overlay that interrupts the current program.\n * The program resumes when the overlay is dismissed via popOverlay().\n */\n pushOverlay(overlay: Overlay): void {\n this.overlays.push(overlay);\n }\n\n /**\n * Dismiss the topmost overlay. The program screen underneath resumes.\n */\n popOverlay(): void {\n this.overlays.pop();\n }\n\n /**\n * Direction hint for screen transitions.\n */\n private _lastDirection: 'push' | 'pop' | null = null;\n\n get lastNavDirection(): 'push' | 'pop' | null {\n return this._lastDirection;\n }\n\n /** @internal — called by store wrapper to track direction */\n _setDirection(dir: 'push' | 'pop' | null): void {\n this._lastDirection = dir;\n }\n}\n","// Display the dependencies reported by the health check.\n\nimport { Box, Text } from 'ink';\nimport {\n ServiceHealthStatus,\n type AllServicesHealth,\n type HealthCheckKey,\n} from '@shared/health-checks/types';\nimport { SERVICE_LABELS } from '@shared/health-checks/readiness';\nimport { Icons } from '@tui/styles';\n\nfunction statusIcon(status: ServiceHealthStatus): {\n icon: string;\n color: string;\n} {\n switch (status) {\n case ServiceHealthStatus.Down:\n return { icon: Icons.squareFilled, color: 'red' };\n case ServiceHealthStatus.Degraded:\n return { icon: Icons.squareFilled, color: '#DC9300' };\n case ServiceHealthStatus.NoConnection:\n return { icon: Icons.squareFilled, color: 'gray' };\n case ServiceHealthStatus.Healthy:\n return { icon: Icons.check, color: 'green' };\n }\n}\n\ninterface ServiceHealthListProps {\n health: AllServicesHealth;\n /** If set, only show services with these keys */\n filterKeys?: HealthCheckKey[];\n /** Show healthy services (default true) */\n showHealthy?: boolean;\n}\n\nexport const ServiceHealthList = ({\n health,\n filterKeys,\n showHealthy = true,\n}: ServiceHealthListProps) => {\n const topLevelKeys = Object.keys(health) as HealthCheckKey[];\n\n const keysToShow = filterKeys\n ? topLevelKeys.filter((k) => filterKeys.includes(k))\n : topLevelKeys;\n\n return (\n <Box flexDirection=\"column\" paddingLeft={1}>\n {keysToShow.map((key) => {\n const result = health[key];\n if (!showHealthy && result.status === ServiceHealthStatus.Healthy) {\n return null;\n }\n\n const { icon, color } = statusIcon(result.status);\n const label = SERVICE_LABELS[key];\n\n return (\n <Box key={key} flexDirection=\"column\">\n <Text>\n <Text color={color}>{icon}</Text>{' '}\n <Text bold={result.status !== ServiceHealthStatus.Healthy}>\n {label}\n </Text>\n </Text>\n </Box>\n );\n })}\n </Box>\n );\n};\n","/**\n * AiOptInRequiredScreen — Renders when the wizard authenticates against an\n * org whose `is_ai_data_processing_approved` is not `true`. Mirrors Max's\n * strict reading: `null`, `undefined`, and `false` all block.\n *\n * Two variants selected from `apiUser.organization.membership_level`:\n * - Admin (>= 8): can fix it themselves — [O] opens settings in browser.\n * - Non-admin: needs to escalate — settings URL is displayed prominently\n * to copy and share with the admin.\n *\n * Both variants offer [S] (show skill source for BYOAI), [R] (retry —\n * re-fetches user data and re-evaluates the gate without restarting), and\n * [E] (exit).\n */\n\nimport opn from 'opn';\nimport { Box, Text } from 'ink';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { useKeyBindings } from '@tui/hooks/useKeyBindings';\nimport { Colors } from '@tui/styles';\nimport { useSkillEntry } from '@tui/screens/SkillSourceInfo';\nimport { fetchUserData } from '@shared/api';\nimport { CONTEXT_MILL_RELEASES_URL, POSTHOG_APP_URL } from '@shared/constants';\nimport { analytics } from '@utils/analytics';\nimport { LoadingBox } from '@tui/primitives/index';\n\nconst ORG_ADMIN_LEVEL = 8;\nconst SETTINGS_PATH = 'settings/organization-details';\nconst SETTINGS_ANCHOR = '#organization-ai-consent';\n\ninterface AiOptInRequiredScreenProps {\n store: WizardStore;\n}\n\nexport const AiOptInRequiredScreen = ({\n store,\n}: AiOptInRequiredScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const { session } = store;\n const org = session.apiUser?.organization;\n const isAdmin = (org?.membership_level ?? 0) >= ORG_ADMIN_LEVEL;\n const variant: 'admin' | 'non-admin' = isAdmin ? 'admin' : 'non-admin';\n\n const projectId = session.credentials?.projectId;\n // Use the region-agnostic app.posthog.com URL so the redirect routes\n // the user to their actual region (us / eu) based on their profile.\n // This avoids relying on a possibly-stale local session.region.\n // `projectId != null` (not just `projectId`) so that 0 — possible in\n // synthetic playground sessions — still picks the project-scoped URL.\n const settingsUrl =\n projectId != null\n ? `${POSTHOG_APP_URL}/project/${projectId}/${SETTINGS_PATH}${SETTINGS_ANCHOR}`\n : `${POSTHOG_APP_URL}/${SETTINGS_PATH}${SETTINGS_ANCHOR}`;\n\n const [showSkill, setShowSkill] = useState(false);\n const [retrying, setRetrying] = useState(false);\n const [retryError, setRetryError] = useState<string | null>(null);\n\n const { skillEntry } = useSkillEntry(session.skillId);\n\n // Fire the \"shown\" event once per variant transition.\n useEffect(() => {\n analytics.wizardCapture('ai opt-in shown', { variant });\n }, [variant]);\n\n const handleOpenSettings = () => {\n analytics.wizardCapture('ai opt-in action', {\n variant,\n action: 'open_settings',\n });\n opn(settingsUrl, { wait: false }).catch(() => {\n // Best-effort — if the browser doesn't open, the URL is still\n // visible in the screen for manual navigation.\n });\n };\n\n const handleShowSkill = () => {\n analytics.wizardCapture('ai opt-in action', {\n variant,\n action: 'show_skill',\n });\n setShowSkill(true);\n };\n\n const handleRetry = () => {\n analytics.wizardCapture('ai opt-in action', { variant, action: 'retry' });\n const credentials = session.credentials;\n if (!credentials?.accessToken) {\n setRetryError('Missing credentials — cannot retry.');\n return;\n }\n setRetrying(true);\n setRetryError(null);\n void fetchUserData(credentials.accessToken, credentials.host.appHost)\n .then((user) => {\n store.setApiUser(user);\n })\n .catch((err: unknown) => {\n setRetryError(err instanceof Error ? err.message : 'Retry failed.');\n })\n .finally(() => {\n setRetrying(false);\n });\n };\n\n const handleExit = () => {\n analytics.wizardCapture('ai opt-in action', { variant, action: 'exit' });\n store.requestExit(0);\n };\n\n useKeyBindings('ai-opt-in', [\n ...(isAdmin\n ? [\n {\n match: ['o', 'O'],\n label: 'O',\n action: 'open settings',\n handler: handleOpenSettings,\n },\n ]\n : []),\n {\n match: ['s', 'S'],\n label: 'S',\n action: 'show skill',\n handler: handleShowSkill,\n },\n {\n match: ['r', 'R'],\n label: 'R',\n action: 'retry',\n handler: handleRetry,\n },\n {\n match: ['e', 'E'],\n label: 'E',\n action: 'exit',\n handler: handleExit,\n },\n ]);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={Colors.accent}>\n PostHog Setup Wizard\n </Text>\n {session.apiUser?.email && (\n <Text>\n <Text color=\"green\">{'✔'} </Text>\n <Text>Authenticated as {session.apiUser.email}</Text>\n </Text>\n )}\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"yellow\" bold>\n ⚠ PostHog AI services are disabled for your organization\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1} width={68}>\n {isAdmin ? (\n <Text>\n The wizard uses Anthropic Claude. To proceed, enable{' '}\n <Text italic>\n \"Enable PostHog features that use third-party AI services\"\n </Text>{' '}\n in your organization settings.\n </Text>\n ) : (\n <>\n <Text>\n The wizard uses Anthropic Claude. Your organization admin needs to\n enable{' '}\n <Text italic>\n \"Enable PostHog features that use third-party AI services\"\n </Text>{' '}\n in organization settings.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>Share this link with your admin:</Text>\n </Box>\n </>\n )}\n </Box>\n\n <Box marginBottom={1}>\n <Text color=\"cyan\">{settingsUrl}</Text>\n </Box>\n\n {/* Release PAGE, not the direct asset URL — asset URLs hard-wrap in\n the terminal and corrupt copy/paste (same rationale as\n PrivacyPanel). The resolved entry names the asset to grab. */}\n {showSkill && (\n <Box marginBottom={1} flexDirection=\"column\">\n <Text>\n Prefer your own AI? Download{' '}\n {skillEntry ? (\n <>\n the <Text bold>{skillEntry.id}</Text> skill\n </>\n ) : (\n 'the skill for your framework'\n )}{' '}\n and run it in your own agent:\n </Text>\n <Text color=\"cyan\">{CONTEXT_MILL_RELEASES_URL}</Text>\n </Box>\n )}\n\n {retrying && (\n <Box marginBottom={1}>\n <LoadingBox message=\"Re-checking organization settings...\" />\n </Box>\n )}\n\n {retryError && (\n <Box marginBottom={1}>\n <Text color=\"red\">{retryError}</Text>\n </Box>\n )}\n\n <Box flexDirection=\"column\" marginTop={1}>\n {isAdmin && (\n <Text>\n <Text color={Colors.accent}>[O]</Text> Open settings in browser\n </Text>\n )}\n <Text>\n <Text color={Colors.accent}>[S]</Text> Show how to use your own AI\n </Text>\n <Text>\n <Text color={Colors.accent}>[R]</Text> Retry (after the toggle is\n enabled)\n </Text>\n <Text>\n <Text color={Colors.accent}>[E]</Text> Exit\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * LearnCard — Generic render shell for an animated content deck.\n *\n * Callers pass the script via `blocks`. The script lives under\n * `src/tui/programs/<name>/deck/`. The shell handles\n * dimension tracking, status-bar height math, and the `display=\"none\"`\n * clamp on narrow terminals.\n */\n\nimport { Box, Text } from 'ink';\nimport { Colors } from '@tui/styles';\nimport type { WizardStore } from '@tui/store';\nimport { ContentSequencer, TextRevealMode } from '@tui/primitives/index';\nimport type { ContentBlock } from '@tui/primitives/index';\nimport { useStdoutDimensions } from '@tui/hooks/useStdoutDimensions';\nimport { COLLAPSED_COUNT, EXPANDED_COUNT } from '@tui/primitives/TabContainer';\n\n/** Fixed chrome: ScreenContainer (3) + TabContainer tab bar (2) */\nconst FIXED_CHROME = 5;\nconst HEADER_ROWS = 2; // title + spacer\nconst MIN_CONTENT_ROWS = 6;\n\ninterface LearnCardProps {\n store?: WizardStore;\n /** The script to play. Program-owned; see programs/<name>/content/. */\n blocks: ContentBlock[];\n onComplete?: () => void;\n}\n\nexport const LearnCard = ({ store, blocks, onComplete }: LearnCardProps) => {\n const [columns, rows] = useStdoutDimensions();\n\n // Dynamic status bar height: messages + border when present\n const hasStatus = store ? store.statusMessages.length > 0 : false;\n const statusBarRows = hasStatus\n ? (store?.statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT) + 1\n : 0;\n\n const contentHeight = rows - FIXED_CHROME - statusBarRows;\n const tooSmall = contentHeight < MIN_CONTENT_ROWS;\n\n const maxHeight = Math.max(1, contentHeight - HEADER_ROWS);\n // Half of clamped content width, minus paddingX on both sides\n const paneWidth = Math.floor((Math.min(120, columns) - 2) / 2) - 2;\n\n // Always render so ContentSequencer stays mounted (preserves activeIdx).\n // When too small, hide visually via display=\"none\".\n return (\n <Box\n flexDirection=\"column\"\n paddingX={1}\n display={tooSmall ? 'none' : 'flex'}\n >\n <Text bold color={Colors.accent}>\n Learn\n </Text>\n <Box height={1} />\n <ContentSequencer\n blocks={blocks}\n mode={TextRevealMode.SentenceBySentence}\n maxHeight={maxHeight}\n availableWidth={paneWidth}\n startDelay={2000}\n initialBlockIdx={store?.learnCardBlockIdx ?? 0}\n onBlockChange={(idx) => store?.setLearnCardBlockIdx(idx)}\n onSequenceComplete={onComplete}\n />\n </Box>\n );\n};\n","/**\n * useTick — forces a re-render every `intervalMs`. Returns a monotonically\n * increasing counter, which is rarely needed — most callers just want the\n * re-render side effect.\n */\n\nimport { useEffect, useState } from 'react';\n\nexport function useTick(intervalMs: number): number {\n const [tick, setTick] = useState(0);\n useEffect(() => {\n const id = setInterval(() => setTick((t) => t + 1), intervalMs);\n return () => clearInterval(id);\n }, [intervalMs]);\n return tick;\n}\n","/**\n * WizardAmp palette — Matrix-green tones for the wizard's forced-dark canvas.\n */\n\nexport type VisualizerPalette = {\n /** Panel borders, scaffolding, dim glyphs */\n fade: string;\n bright: string;\n mid: string;\n head: string;\n book: readonly string[];\n deleteRed: string;\n upGreen: string;\n};\n\nexport const VISUALIZER_PALETTE: VisualizerPalette = {\n fade: '#0E7A0E',\n bright: '#7CFF7C',\n mid: '#22D622',\n head: '#E6FFE6',\n book: ['#22D622', '#7CFF7C', '#5BE05B', '#A0F0A0', '#36B536'],\n deleteRed: '#D63B22',\n upGreen: '#7CFF7C',\n};\n","/**\n * Shared scaffolding for the phase visuals — Matrix-green color, common\n * VisualProps shape, and the rounded `Panel` shell every visual sits in.\n *\n * Visuals each render their own grid then wrap it in `<Panel>` so phase\n * transitions stay visually continuous.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\nimport { VISUALIZER_PALETTE } from './palette';\n\n// The deep, dimmed end of the Matrix code-rain palette. Used as the framing\n// color for every visual (panel border, axis lines, scaffolding glyphs).\nexport const MATRIX_FADE = VISUALIZER_PALETTE.fade;\n\nexport interface VisualProps {\n width: number;\n height: number;\n}\n\nexport const Panel = ({ children }: { children: ReactNode }) => (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={MATRIX_FADE}>\n {children}\n </Box>\n);\n","/**\n * MatrixRain — code-rain visual used for the codebase-scan phase.\n *\n * Independent of the phase orchestrator so it can be reused elsewhere\n * (e.g. standalone in a demo). `bordered` toggles the rounded green frame.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState } from 'react';\nimport { MATRIX_FADE } from './panel';\nimport { VISUALIZER_PALETTE } from './palette';\n\nconst {\n head: MATRIX_HEAD,\n bright: MATRIX_BRIGHT,\n mid: MATRIX_MID,\n} = VISUALIZER_PALETTE;\n\nconst DEFAULT_TICK_MS = 110;\nconst DEFAULT_MAX_TAIL = 7;\n// Half-width katakana + digits + a few symbols — the classic Matrix code\n// rain alphabet, all single-width in monospace terminals.\nconst RAIN_GLYPHS =\n 'ヲァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン0123456789Z<>=*+:.';\n\ninterface RainColumn {\n headY: number;\n speed: number;\n tail: number;\n glyphs: Map<number, string>;\n dormant: number;\n}\n\nfunction pickGlyph(): string {\n return RAIN_GLYPHS[Math.floor(Math.random() * RAIN_GLYPHS.length)];\n}\n\nfunction makeRainColumn(height: number, maxTail: number): RainColumn {\n return {\n headY: -Math.random() * height,\n speed: 0.3 + Math.random() * 0.9,\n tail: 3 + Math.floor(Math.random() * (maxTail - 2)),\n glyphs: new Map(),\n dormant: Math.floor(Math.random() * 18),\n };\n}\n\nfunction tickRainColumn(\n col: RainColumn,\n height: number,\n maxTail: number,\n): RainColumn {\n if (col.dormant > 0) {\n return { ...col, dormant: col.dormant - 1 };\n }\n const next = col.headY + col.speed;\n if (next > height + col.tail) {\n return makeRainColumn(height, maxTail);\n }\n const glyphs = new Map(col.glyphs);\n for (\n let y = Math.max(0, Math.ceil(col.headY));\n y <= Math.min(Math.floor(next), height - 1);\n y++\n ) {\n glyphs.set(y, pickGlyph());\n }\n // Glyphs in the tail occasionally mutate — gives the \"live data\" twitch.\n if (glyphs.size > 0 && Math.random() < 0.22) {\n const keys = [...glyphs.keys()];\n const k = keys[Math.floor(Math.random() * keys.length)];\n glyphs.set(k, pickGlyph());\n }\n return { ...col, headY: next, glyphs };\n}\n\ninterface MatrixRainProps {\n width: number;\n height: number;\n /** Frame interval in ms. Defaults to 110. */\n tickMs?: number;\n /** Maximum tail length per column. Defaults to 7. */\n maxTail?: number;\n /** Wrap the rain in a rounded border. Defaults to true. */\n bordered?: boolean;\n}\n\nexport const MatrixRain = ({\n width,\n height,\n tickMs = DEFAULT_TICK_MS,\n maxTail = DEFAULT_MAX_TAIL,\n bordered = true,\n}: MatrixRainProps) => {\n const columnsRef = useRef<RainColumn[]>(\n Array.from({ length: width }, () => makeRainColumn(height, maxTail)),\n );\n const [, setTick] = useState(0);\n\n useEffect(() => {\n const interval = setInterval(() => {\n columnsRef.current = columnsRef.current.map((c) =>\n tickRainColumn(c, height, maxTail),\n );\n setTick((t) => t + 1);\n }, tickMs);\n return () => clearInterval(interval);\n }, [height, maxTail, tickMs]);\n\n const columns = columnsRef.current;\n const body = Array.from({ length: height }).map((_, y) => (\n <Box key={y}>\n {columns.map((col, x) => {\n const glyph = col.glyphs.get(y);\n if (!glyph) return <Text key={x}> </Text>;\n const dist = col.headY - y;\n if (dist < 0 || dist > col.tail) return <Text key={x}> </Text>;\n if (dist < 1) {\n return (\n <Text key={x} bold color={MATRIX_HEAD}>\n {glyph}\n </Text>\n );\n }\n if (dist < 2) {\n return (\n <Text key={x} color={MATRIX_BRIGHT}>\n {glyph}\n </Text>\n );\n }\n if (dist < col.tail * 0.55) {\n return (\n <Text key={x} color={MATRIX_MID}>\n {glyph}\n </Text>\n );\n }\n return (\n <Text key={x} color={MATRIX_FADE} dimColor>\n {glyph}\n </Text>\n );\n })}\n </Box>\n ));\n\n if (!bordered) {\n return <Box flexDirection=\"column\">{body}</Box>;\n }\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={MATRIX_FADE}>\n {body}\n </Box>\n );\n};\n","/**\n * Bounds-safe ASCII grid shared by the phase visuals.\n *\n * Every visual builds a width×height character grid and then wraps it in\n * <Panel>. Historically each visual did its own `grid[y][x] = ch` writes, and\n * one that miscomputed a coordinate on a short or narrow panel would index an\n * undefined row (`grid[-1][x]`) and crash the *entire* TUI — see the Tumblers\n * negative-pin-row bug that took the Visualizer tab down.\n *\n * Routing every write through `plot` makes an out-of-bounds coordinate a\n * silent no-op, so a geometry bug degrades to a cosmetic glitch instead of a\n * crash. New visuals should build their grid with `createGrid` and write to it\n * with `plot` / `writeText` rather than indexing rows directly.\n */\n\nexport type Grid = string[][];\n\n/** Allocate a blank `width`×`height` grid of spaces. Degenerate or negative\n * dimensions collapse to an empty grid rather than throwing. */\nexport const createGrid = (width: number, height: number): Grid => {\n const h = Math.max(0, Math.floor(height));\n const w = Math.max(0, Math.floor(width));\n return Array.from({ length: h }, () => new Array<string>(w).fill(' '));\n};\n\n/** Write a single cell, ignoring any coordinate outside the grid (including\n * negative or fractional ones). This is the one guard the visuals rely on to\n * never crash regardless of panel size. */\nexport const plot = (grid: Grid, x: number, y: number, ch: string): void => {\n const row = grid[y];\n if (row === undefined) return;\n if (x < 0 || x >= row.length) return;\n row[x] = ch;\n};\n\n/** Write `text` left-to-right starting at (x, y). Clips at the grid edge and,\n * when given, after `maxW` characters. Off-grid cells are dropped by `plot`. */\nexport const writeText = (\n grid: Grid,\n x: number,\n y: number,\n text: string,\n maxW?: number,\n): void => {\n const limit = maxW === undefined ? text.length : Math.max(0, maxW);\n for (let i = 0; i < text.length && i < limit; i++) {\n plot(grid, x + i, y, text[i]);\n }\n};\n","/**\n * LibraryShelf — skill-selection phase.\n *\n * A row of book spines. One spine peels forward each cycle, the chosen\n * title hovers next to it, then it slides home and the next one is picked.\n */\n\nimport { Box, Text } from 'ink';\nimport { useTick } from '@tui/hooks/useTick';\nimport { MATRIX_FADE, Panel, type VisualProps } from './panel';\nimport { createGrid, plot, writeText } from './grid';\nimport { VISUALIZER_PALETTE } from './palette';\n\nconst BOOK_LABELS = [\n 'nx',\n 'rt',\n 'sv',\n 'fl',\n 'jg',\n 'rb',\n 'go',\n 'dj',\n 'fa',\n 'lv',\n 'ts',\n 'py',\n];\nconst BOOK_COLORS = VISUALIZER_PALETTE.book;\n\nexport const LibraryShelf = ({ width, height }: VisualProps) => {\n const tick = useTick(380);\n const bookCount = Math.min(Math.floor((width - 2) / 2), BOOK_LABELS.length);\n // Cycle phases: 0 = at rest, 1 = selecting, 2 = pulled out, 3 = returning.\n const cyclePos = tick % (bookCount * 4);\n const selectedIdx = Math.floor(cyclePos / 4);\n const phase = cyclePos % 4;\n const offset = phase === 0 ? 0 : phase === 1 ? 1 : phase === 2 ? 2 : 1;\n const wobble = phase === 2 && tick % 2 === 0 ? 1 : 0;\n\n // Clamp the shelf so all three book rows stay on-grid on short panels; the\n // grid writes are bounds-safe anyway, but this keeps the books visible.\n const shelfY = Math.min(Math.max(1, Math.floor(height / 2) - 1), height - 3);\n const rows = createGrid(width, height);\n\n for (let i = 0; i < bookCount; i++) {\n const x = 1 + i * 2;\n const isSelected = i === selectedIdx;\n const shift = isSelected ? offset : 0;\n const wob = isSelected && wobble ? -1 : 0;\n plot(rows, x + shift, shelfY - 1, '█');\n plot(rows, x + shift, shelfY, BOOK_LABELS[i][0]);\n plot(rows, x + shift, shelfY + 1, BOOK_LABELS[i][1]);\n plot(rows, x + shift, shelfY + 2 + wob, '█');\n }\n\n // Shelf board underneath\n const boardY = shelfY + 3;\n for (let x = 0; x < width; x++) plot(rows, x, boardY, '─');\n // Floating label next to the selected book\n if (phase === 2) {\n const labelStartX = 1 + selectedIdx * 2 + 4;\n const labelText = BOOK_LABELS[selectedIdx] + '-app';\n writeText(rows, labelStartX, shelfY, labelText);\n plot(rows, labelStartX - 1, shelfY, '▶');\n }\n\n return (\n <Panel>\n {rows.map((row, y) => (\n <Box key={y}>\n {row.map((ch, x) => {\n if (ch === ' ') return <Text key={x}> </Text>;\n if (ch === '─') {\n return (\n <Text key={x} color={MATRIX_FADE} dimColor>\n ─\n </Text>\n );\n }\n if (ch === '▶') {\n return (\n <Text key={x} bold color={VISUALIZER_PALETTE.head}>\n ▶\n </Text>\n );\n }\n const booksColor =\n BOOK_COLORS[\n (Math.floor((x - 1) / 2) + 17 * y) % BOOK_COLORS.length\n ];\n const selectedX = 1 + selectedIdx * 2 + offset;\n const isSel = x === selectedX;\n return (\n <Text\n key={x}\n bold={isSel}\n color={isSel ? VISUALIZER_PALETTE.head : booksColor}\n >\n {ch}\n </Text>\n );\n })}\n </Box>\n ))}\n </Panel>\n );\n};\n","/**\n * CrateStack — dependency-install phase.\n *\n * Boxes drop from the top and stack at the bottom. Each new arrival lands\n * with a tiny shake.\n */\n\nimport { Box, Text } from 'ink';\nimport { useRef } from 'react';\nimport { useTick } from '@tui/hooks/useTick';\nimport { Panel, type VisualProps } from './panel';\nimport { createGrid, plot } from './grid';\nimport { VISUALIZER_PALETTE } from './palette';\n\nconst PACKAGE_NAMES = [\n 'posthog-js',\n 'posthog-py',\n 'posthog-rb',\n 'posthog-go',\n 'posthog-node',\n 'react-ph',\n 'next-ph',\n 'svelte-ph',\n 'ph-mcp',\n 'ph-ai',\n];\n// Crate width is derived from the longest label so names never get sliced.\nconst CRATE_CONTENT_W = Math.max(...PACKAGE_NAMES.map((n) => n.length));\nconst CRATE_W = CRATE_CONTENT_W + 2;\n\ninterface CrateState {\n stack: { label: string; x: number; landedAt: number }[];\n falling: { label: string; x: number; y: number } | null;\n spawnCooldown: number;\n}\n\nexport const CrateStack = ({ width, height }: VisualProps) => {\n const tick = useTick(95);\n const stateRef = useRef<CrateState>({\n stack: [],\n falling: null,\n spawnCooldown: 0,\n });\n\n const state = stateRef.current;\n const crateW = CRATE_W;\n const crateH = 1;\n const floorY = height - 1;\n\n if (state.falling) {\n state.falling.y += 1;\n const collisionStackHeight =\n state.stack.filter((c) => Math.abs(c.x - state.falling!.x) < crateW - 1)\n .length * crateH;\n if (state.falling.y >= floorY - collisionStackHeight) {\n state.stack.push({\n label: state.falling.label,\n x: state.falling.x,\n landedAt: tick,\n });\n state.falling = null;\n state.spawnCooldown = 3;\n }\n } else if (state.spawnCooldown > 0) {\n state.spawnCooldown -= 1;\n } else if (state.stack.length < Math.floor(height / crateH) - 1) {\n state.falling = {\n label: PACKAGE_NAMES[Math.floor(Math.random() * PACKAGE_NAMES.length)],\n x: 2 + Math.floor(Math.random() * Math.max(1, width - crateW - 4)),\n y: -1,\n };\n } else {\n // Stack full — wipe and restart for the next cycle.\n if (tick % 20 === 0) {\n state.stack = [];\n }\n }\n\n const grid = createGrid(width, height);\n const drawCrate = (cx: number, cy: number, label: string, shake: number) => {\n const x = cx + shake;\n const labelTrimmed = label.slice(0, crateW - 2);\n const padded = `[${labelTrimmed}]`.padEnd(crateW, ' ');\n for (let i = 0; i < crateW; i++) {\n plot(grid, x + i, cy, padded[i]);\n }\n };\n\n state.stack.forEach((c, idx) => {\n const cy = floorY - idx;\n const shake =\n tick - c.landedAt === 0 ? 1 : tick - c.landedAt === 1 ? -1 : 0;\n drawCrate(c.x, cy, c.label, shake);\n });\n if (state.falling) {\n drawCrate(state.falling.x, state.falling.y, state.falling.label, 0);\n }\n\n return (\n <Panel>\n {grid.map((row, y) => (\n <Box key={y}>\n {row.map((ch, x) => {\n if (ch === ' ') return <Text key={x}> </Text>;\n const isFalling =\n state.falling &&\n y === state.falling.y &&\n Math.abs(x - state.falling.x) < crateW;\n return (\n <Text\n key={x}\n bold={!!isFalling}\n color={\n isFalling ? VISUALIZER_PALETTE.head : VISUALIZER_PALETTE.mid\n }\n >\n {ch}\n </Text>\n );\n })}\n </Box>\n ))}\n </Panel>\n );\n};\n","/**\n * DiffCascade — code-edits phase.\n *\n * + and - code lines scroll upward continuously. Occasional comment-rewrite\n * gag: a \"// hmm…\" line appears, gets - struck out, then a + replaces it.\n */\n\nimport { Box, Text } from 'ink';\nimport { useRef } from 'react';\nimport { useTick } from '@tui/hooks/useTick';\nimport { MATRIX_FADE, Panel, type VisualProps } from './panel';\nimport { VISUALIZER_PALETTE } from './palette';\n\nconst CODE_SNIPPETS = [\n \"import posthog from 'posthog-js'\",\n 'posthog.init(KEY, { host: HOST })',\n '<PostHogProvider client={posthog}>',\n ' {children}',\n '</PostHogProvider>',\n \"posthog.capture('page_viewed')\",\n \"posthog.capture('signup_started')\",\n 'posthog.identify(user.id, { email })',\n \"if (process.env.NODE_ENV !== 'test') posthog.init(KEY)\",\n 'export const posthog = new PostHog(KEY)',\n '// TODO: enable replay',\n 'window.posthog = posthog',\n];\n\nconst WHIMSY_COMMENTS = [\n '// hmm — that should be a hook',\n '// wait, refactor incoming',\n '// posthog says hi',\n];\n\ninterface DiffLine {\n sign: '+' | '-' | ' ';\n text: string;\n}\n\nexport const DiffCascade = ({ width, height }: VisualProps) => {\n const tick = useTick(280);\n const linesRef = useRef<DiffLine[]>([]);\n\n if (linesRef.current.length === 0) {\n for (let i = 0; i < height; i++) {\n linesRef.current.push({\n sign: Math.random() < 0.75 ? '+' : '-',\n text: CODE_SNIPPETS[Math.floor(Math.random() * CODE_SNIPPETS.length)],\n });\n }\n }\n // Scroll up by one each tick, push a new line at bottom.\n linesRef.current.shift();\n const whimsy = tick % 23 === 0;\n linesRef.current.push({\n sign: whimsy ? '-' : Math.random() < 0.78 ? '+' : '-',\n text: whimsy\n ? WHIMSY_COMMENTS[Math.floor(Math.random() * WHIMSY_COMMENTS.length)]\n : CODE_SNIPPETS[Math.floor(Math.random() * CODE_SNIPPETS.length)],\n });\n\n const lines = linesRef.current;\n return (\n <Panel>\n {Array.from({ length: height }).map((_, y) => {\n // The line buffer can lag `height` for a frame after a resize; fall\n // back to a blank line rather than dereferencing `undefined`.\n const line = lines[y] ?? { sign: ' ' as const, text: '' };\n const cap = width - 2;\n const text = `${line.sign} ${line.text}`.slice(0, cap);\n const color =\n line.sign === '+'\n ? VISUALIZER_PALETTE.mid\n : line.sign === '-'\n ? VISUALIZER_PALETTE.deleteRed\n : MATRIX_FADE;\n return (\n <Box key={y}>\n <Text color={color}>{text.padEnd(cap, ' ')}</Text>\n </Box>\n );\n })}\n </Panel>\n );\n};\n","/**\n * Tumblers — env-setup phase.\n *\n * Pins fall into a lock cylinder one by one; when all six align the bolt\n * pulses green for a beat, then the cycle restarts.\n */\n\nimport { Box, Text } from 'ink';\nimport { useRef } from 'react';\nimport { useTick } from '@tui/hooks/useTick';\nimport { MATRIX_FADE, Panel, type VisualProps } from './panel';\nimport { createGrid, plot } from './grid';\nimport { VISUALIZER_PALETTE } from './palette';\n\ninterface TumblerState {\n heights: number[]; // settled height per pin, 0 = unset\n current: number; // index of pin currently falling\n fallY: number; // current Y of the falling pin (in rows)\n pulse: number; // pulse counter once all pins land\n}\n\nexport const Tumblers = ({ width, height }: VisualProps) => {\n const tick = useTick(80);\n const pinCount = Math.min(Math.floor((width - 2) / 2), 6);\n const stateRef = useRef<TumblerState>({\n heights: new Array(pinCount).fill(0),\n current: 0,\n fallY: 0,\n pulse: 0,\n });\n const state = stateRef.current;\n\n const cylinderTop = 1;\n const cylinderBottom = height - 2;\n // Clamp to the cylinder interior: on short panels the raw formula can drop a\n // pin's target above cylinderTop (even negative), which used to be written\n // back as a settled height and indexed as grid[negativeRow][pinX] -> crash.\n const targetForPin = (i: number) =>\n Math.max(\n cylinderTop,\n Math.min(cylinderBottom, cylinderBottom - 1 - (i % 3) - Math.floor(i / 2)),\n );\n\n if (state.pulse > 0) {\n state.pulse -= 1;\n if (state.pulse === 0) {\n state.heights = new Array(pinCount).fill(0);\n state.current = 0;\n state.fallY = 0;\n }\n } else if (state.current < pinCount) {\n state.fallY += 1;\n if (state.fallY >= targetForPin(state.current)) {\n state.heights[state.current] = targetForPin(state.current);\n state.current += 1;\n state.fallY = cylinderTop;\n }\n } else {\n state.pulse = 14;\n }\n\n const grid = createGrid(width, height);\n // Outer cylinder walls\n for (let y = 0; y < height; y++) {\n plot(grid, 0, y, '│');\n plot(grid, width - 1, y, '│');\n }\n // Top notches (where pins enter)\n for (let i = 0; i < pinCount; i++) {\n plot(grid, 1 + i * 2 + 1, 0, '▼');\n }\n // Floor\n for (let x = 1; x < width - 1; x++) plot(grid, x, height - 1, '─');\n // Settled pins\n for (let i = 0; i < pinCount; i++) {\n const pinX = 1 + i * 2 + 1;\n const top = state.heights[i] || cylinderTop;\n for (let y = top; y <= cylinderBottom; y++) {\n plot(grid, pinX, y, '█');\n }\n }\n // Falling pin\n if (state.pulse === 0 && state.current < pinCount) {\n const pinX = 1 + state.current * 2 + 1;\n plot(grid, pinX, state.fallY, '█');\n }\n\n const pulsing = state.pulse > 0;\n const pulseBright = pulsing && tick % 2 === 0;\n return (\n <Panel>\n {grid.map((row, y) => (\n <Box key={y}>\n {row.map((ch, x) => {\n if (ch === ' ') return <Text key={x}> </Text>;\n if (ch === '│' || ch === '─' || ch === '▼') {\n const c = pulsing\n ? pulseBright\n ? VISUALIZER_PALETTE.bright\n : MATRIX_FADE\n : MATRIX_FADE;\n return (\n <Text key={x} color={c} dimColor={!pulsing}>\n {ch}\n </Text>\n );\n }\n const isFalling =\n state.pulse === 0 &&\n state.current < pinCount &&\n y === state.fallY &&\n x === 1 + state.current * 2 + 1;\n const color = pulsing\n ? pulseBright\n ? VISUALIZER_PALETTE.head\n : VISUALIZER_PALETTE.bright\n : isFalling\n ? VISUALIZER_PALETTE.head\n : VISUALIZER_PALETTE.mid;\n return (\n <Text key={x} bold={pulsing || isFalling} color={color}>\n {ch}\n </Text>\n );\n })}\n </Box>\n ))}\n </Panel>\n );\n};\n","/**\n * DashboardGrid — dashboards phase.\n *\n * 2×2 grid of mini-charts to evoke a real PostHog dashboard. When the area\n * is too small, the layout collapses to 1×2 or 1×1 so something always\n * renders.\n */\n\nimport { Box, Text } from 'ink';\nimport { useTick } from '@tui/hooks/useTick';\nimport { MATRIX_FADE, Panel, type VisualProps } from './panel';\nimport { createGrid, plot, writeText, type Grid } from './grid';\nimport { VISUALIZER_PALETTE } from './palette';\n\ntype TileKind = 'bars' | 'line' | 'gauge' | 'pulse';\n\nconst DASHBOARD_TILES: Array<{ title: string; kind: TileKind }> = [\n { title: 'Visitors', kind: 'bars' },\n { title: 'Sessions', kind: 'line' },\n { title: 'Revenue', kind: 'gauge' },\n { title: 'Errors', kind: 'pulse' },\n];\n\nconst SPARK_GLYPHS = '▁▂▃▄▅▆▇█';\n\nexport const DashboardGrid = ({ width, height }: VisualProps) => {\n const tick = useTick(220);\n const grid = createGrid(width, height);\n\n // Collapse to fewer cells when there isn't room for a real 2×2.\n const cols = width >= 22 ? 2 : 1;\n const rows = height >= 7 ? 2 : 1;\n const vSplit = cols === 2 ? Math.floor(width / 2) : -1;\n const hSplit = rows === 2 ? Math.floor(height / 2) : -1;\n\n if (vSplit >= 0) {\n for (let y = 0; y < height; y++) plot(grid, vSplit, y, '│');\n }\n if (hSplit >= 0) {\n for (let x = 0; x < width; x++) plot(grid, x, hSplit, '─');\n if (vSplit >= 0) plot(grid, vSplit, hSplit, '┼');\n }\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tile = DASHBOARD_TILES[r * cols + c];\n const tileX = c === 0 ? 0 : vSplit + 1;\n const tileY = r === 0 ? 0 : hSplit + 1;\n const tileW =\n cols === 2 ? (c === 0 ? vSplit : width - vSplit - 1) : width;\n const tileH =\n rows === 2 ? (r === 0 ? hSplit : height - hSplit - 1) : height;\n\n const innerX = tileX;\n const innerW = Math.max(1, tileW);\n const titleY = tileY;\n const valueY = tileY + tileH - 1;\n const chartY0 = tileY + 1;\n const chartY1 = Math.max(chartY0, valueY - 1);\n const chartH = Math.max(1, chartY1 - chartY0 + 1);\n const seed = (r * cols + c) * 13;\n\n writeText(grid, innerX, titleY, tile.title, innerW);\n renderTile(grid, tile.kind, innerX, chartY0, innerW, chartH, tick, seed);\n writeText(grid, innerX, valueY, tileValue(tile.kind, tick, seed), innerW);\n }\n }\n\n return (\n <Panel>\n {grid.map((row, y) => (\n <Box key={y}>\n {row.map((ch, x) => {\n if (ch === ' ') return <Text key={x}> </Text>;\n if (ch === '│' || ch === '─' || ch === '┼') {\n return (\n <Text key={x} color={MATRIX_FADE} dimColor>\n {ch}\n </Text>\n );\n }\n if (SPARK_GLYPHS.includes(ch) || ch === '█') {\n return (\n <Text key={x} color={VISUALIZER_PALETTE.mid}>\n {ch}\n </Text>\n );\n }\n if (ch === '●' || ch === '∙' || ch === '·') {\n const color =\n ch === '●'\n ? VISUALIZER_PALETTE.head\n : ch === '∙'\n ? VISUALIZER_PALETTE.bright\n : VISUALIZER_PALETTE.mid;\n return (\n <Text key={x} bold={ch === '●'} color={color}>\n {ch}\n </Text>\n );\n }\n if (ch === '▲' || ch === '▼') {\n return (\n <Text\n key={x}\n bold\n color={\n ch === '▲'\n ? VISUALIZER_PALETTE.upGreen\n : VISUALIZER_PALETTE.deleteRed\n }\n >\n {ch}\n </Text>\n );\n }\n return (\n <Text key={x} color={VISUALIZER_PALETTE.bright}>\n {ch}\n </Text>\n );\n })}\n </Box>\n ))}\n </Panel>\n );\n};\n\nfunction renderTile(\n grid: Grid,\n kind: TileKind,\n x0: number,\n y0: number,\n w: number,\n h: number,\n tick: number,\n seed: number,\n): void {\n const set = (x: number, y: number, ch: string) => plot(grid, x, y, ch);\n\n if (kind === 'bars') {\n // Vertical bars driven by a slow per-column sine. Most tile feels\n // \"spectrum analyzer\"-y.\n for (let i = 0; i < w; i++) {\n const t = tick * 0.18 + (i + seed) * 0.6;\n const level = 0.55 + 0.35 * Math.sin(t) + 0.1 * Math.sin(t * 2.7);\n const filled = Math.max(0, Math.min(h, Math.round(level * h)));\n for (let j = 0; j < filled; j++) {\n set(x0 + i, y0 + h - 1 - j, '█');\n }\n if (filled > 0 && filled < h) {\n const frac = level * h - Math.floor(level * h);\n const glyph =\n SPARK_GLYPHS[Math.floor(frac * (SPARK_GLYPHS.length - 1))];\n set(x0 + i, y0 + h - filled, glyph);\n }\n }\n } else if (kind === 'line') {\n // Ascending trend with a single deterministic spike.\n const spikeAt = (((tick / 12) | 0) + seed) % Math.max(1, w);\n for (let i = 0; i < w; i++) {\n const norm = i / Math.max(1, w - 1);\n const base = h - 1 - norm * (h - 1);\n let yf = base + 0.6 * Math.sin(i * 0.7 + seed + tick * 0.05);\n if (i === spikeAt) yf = Math.max(0, base - 1.5);\n const y = Math.max(0, Math.min(h - 1, Math.round(yf)));\n const dist = Math.abs(i - (w - 1));\n const ch = dist === 0 ? '●' : dist < 3 ? '∙' : '·';\n set(x0 + i, y0 + y, ch);\n }\n } else if (kind === 'gauge') {\n // Progress bar that fills, drains, refills. Suggests a goal/target.\n const cycle = (tick + seed) % 40;\n const pct = cycle < 30 ? cycle / 30 : 1 - (cycle - 30) / 10;\n const midY = y0 + Math.floor(h / 2);\n const filled = Math.max(0, Math.min(w, Math.round(pct * w)));\n for (let i = 0; i < w; i++) {\n set(x0 + i, midY, i < filled ? '█' : '·');\n }\n } else if (kind === 'pulse') {\n // Mostly quiet bars with occasional spikes — like an error rate that\n // mostly hovers low.\n for (let i = 0; i < w; i++) {\n const t = (i + seed + Math.floor(tick / 3)) % 17;\n let level: number;\n if (t === 0) level = 0.9;\n else if (t === 1 || t === 16) level = 0.5;\n else level = 0.12 + 0.06 * Math.sin((i + tick) * 0.5);\n const filled = Math.max(1, Math.min(h, Math.round(level * h)));\n for (let j = 0; j < filled; j++) {\n set(x0 + i, y0 + h - 1 - j, '█');\n }\n }\n }\n}\n\nfunction tileValue(kind: TileKind, tick: number, seed: number): string {\n const wave = 0.5 + 0.5 * Math.sin(tick * 0.05 + seed);\n if (kind === 'bars') {\n const n = Math.round(8000 + wave * 6000);\n return `${(n / 1000).toFixed(1)}k ▲`;\n }\n if (kind === 'line') {\n const n = 2 + wave * 4;\n return `${n.toFixed(1)}% ▲`;\n }\n if (kind === 'gauge') {\n const n = Math.round(20 + wave * 60);\n return `$${n}k`;\n }\n // pulse\n const n = Math.round(1 + wave * 5);\n return `${n} ▼`;\n}\n","/**\n * Phase visuals — ambient ASCII visualizations of what the agent is currently\n * doing. The active phase is derived from the in-progress task labels (best-\n * effort heuristic). Each phase has its own component (under ./visualizer);\n * the orchestrator `PhaseVisual` picks which one to render.\n *\n * Width and height are passed in from the parent so visuals adapt to the\n * column they're placed in.\n */\n\nimport { Box, Text, measureElement, type DOMElement } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { useTick } from '@tui/hooks/useTick';\nimport { AgentPhase } from '@shared/agent-phase';\nimport { MATRIX_FADE } from './visualizer/panel';\nimport { VISUALIZER_PALETTE } from './visualizer/palette';\nimport { MatrixRain } from './visualizer/MatrixRain';\nimport { LibraryShelf } from './visualizer/LibraryShelf';\nimport { CrateStack } from './visualizer/CrateStack';\nimport { DiffCascade } from './visualizer/DiffCascade';\nimport { Tumblers } from './visualizer/Tumblers';\nimport { DashboardGrid } from './visualizer/DashboardGrid';\n\nexport { AgentPhase };\n\n// Track titles (PostHog being the \"artist\" — see VisualizerTab render).\nconst PHASE_LABELS: Record<AgentPhase, string> = {\n [AgentPhase.CodebaseScan]: 'Reading the Code',\n [AgentPhase.SkillInstall]: 'Picking the Right Skill',\n [AgentPhase.DepInstall]: 'Installing Packages',\n [AgentPhase.CodeEdits]: 'Editing Source',\n [AgentPhase.EnvSetup]: 'Wiring Up Secrets',\n [AgentPhase.Dashboards]: 'Building Dashboards',\n};\n\n/** Reads the active phase from the store. The agent's `stage` progress\n * events push it in through `store.setCurrentStage` whenever a new tool fires. */\nexport function useAgentPhase(store: WizardStore): AgentPhase {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n return (store.currentStage?.stage as AgentPhase) ?? AgentPhase.CodebaseScan;\n}\n\ninterface PhaseVisualProps {\n store: WizardStore;\n width: number;\n height: number;\n}\n\nexport const PhaseVisual = ({ store, width, height }: PhaseVisualProps) => {\n const phase = useAgentPhase(store);\n return <PhaseBody phase={phase} width={width} height={height} />;\n};\n\n/**\n * VisualizerTab — Winamp-style fullscreen take on the phase visual.\n * \"NOW PLAYING\" header, centered visual, transport bar with elapsed time.\n *\n * Sizes itself off the *measured* container rather than the raw terminal so\n * the tab bar / hints / status panel above don't get pushed off-screen on\n * short terminals. When height runs out, chrome rows drop in order:\n * transport bar first, then track title, then the NOW PLAYING header.\n */\nexport const VisualizerTab = ({ store }: { store: WizardStore }) => {\n const phase = useAgentPhase(store);\n const containerRef = useRef<DOMElement>(null);\n const [size, setSize] = useState<{ width: number; height: number }>({\n width: 0,\n height: 0,\n });\n const tick = useTick(EQ_TICK_MS);\n\n useEffect(() => {\n if (!containerRef.current) return;\n const m = measureElement(containerRef.current);\n if (m.width !== size.width || m.height !== size.height) {\n setSize({ width: m.width, height: m.height });\n }\n }, [tick, size.width, size.height]);\n\n // Each chrome line below counts the row + its 1-row margin.\n const HEADER_ROWS = 2;\n const TITLE_ROWS = 2;\n const TRANSPORT_ROWS = 2;\n const BORDER_ROWS = 2;\n const MIN_VISUAL_H = 5;\n\n const availH = size.height;\n const availW = size.width;\n // Drop chrome rows greedily from the bottom up if there isn't room for the\n // minimum visual plus border.\n let chromeBudget = BORDER_ROWS + HEADER_ROWS + TITLE_ROWS + TRANSPORT_ROWS;\n let showHeader = true;\n let showTitle = true;\n let showTransport = true;\n if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {\n showTransport = false;\n chromeBudget -= TRANSPORT_ROWS;\n }\n if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {\n showTitle = false;\n chromeBudget -= TITLE_ROWS;\n }\n if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {\n showHeader = false;\n chromeBudget -= HEADER_ROWS;\n }\n\n const visualH =\n availH > 0\n ? Math.max(MIN_VISUAL_H, Math.min(18, availH - chromeBudget))\n : MIN_VISUAL_H;\n const visualW = availW > 0 ? Math.max(20, Math.min(64, availW - 12)) : 40;\n\n // Anchor both the elapsed clock and the EQ beat grid to the stage's\n // startedAt — a fresh stage drops the needle on beat 1.\n const now = Date.now();\n const beatTimeMs = now - (store.currentStage?.startedAt ?? now);\n const elapsedSec = Math.max(0, Math.floor(beatTimeMs / 1000));\n const timeStr = formatElapsed(elapsedSec);\n const eqLevelsRef = useRef<number[]>(new Array(EQ_BARS).fill(0));\n const equalizer = renderMiniEqualizer(beatTimeMs, eqLevelsRef.current);\n\n return (\n <Box\n ref={containerRef}\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n overflow=\"hidden\"\n >\n {showHeader && (\n <Box flexDirection=\"row\" marginBottom={1}>\n <Text color={MATRIX_FADE}>┌─</Text>\n <Text bold color={VISUALIZER_PALETTE.bright}>\n {' ► NOW PLAYING '}\n </Text>\n <Text color={MATRIX_FADE}>─┐</Text>\n </Box>\n )}\n {showTitle && (\n <Box marginBottom={1}>\n <Text bold color={VISUALIZER_PALETTE.head}>\n {PHASE_LABELS[phase]} - PostHog\n </Text>\n </Box>\n )}\n <PhaseBody phase={phase} width={visualW} height={visualH} />\n {showTransport && (\n <Box flexDirection=\"row\" marginTop={1} gap={2}>\n <Text color={VISUALIZER_PALETTE.mid}>[{timeStr}]</Text>\n <Text color={MATRIX_FADE}>{equalizer}</Text>\n <Text color={VISUALIZER_PALETTE.mid}>WizardAmp</Text>\n </Box>\n )}\n </Box>\n );\n};\n\nfunction formatElapsed(totalSec: number): string {\n const m = Math.floor(totalSec / 60);\n const s = totalSec % 60;\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\n}\n\n// 120 BPM techno in 4/4: a beat is 500 ms, a bar (measure) is 4 beats = 2 s.\nconst BPM = 120;\nconst BEAT_MS = (60 / BPM) * 1000;\nconst EQ_BARS = 12;\nconst EQ_TICK_MS = 67; // ~15 fps\n// 0.08 / frame at ~15 fps ≈ 0.8 s peak-to-silence. Scale with EQ_TICK_MS if\n// you change the frame rate so the decay *time* stays the same.\nconst EQ_FALL_PER_FRAME = 0.08;\n\n// One \"drum hit\": a value that snaps to 1.0 on the beat and fades out before\n// the next one. Higher `decay` = snappier (quicker fade). `phaseMs` shifts\n// when the hit fires (e.g. snare lands on beat 2, not beat 1).\nfunction pulse(\n t: number,\n periodMs: number,\n decay: number,\n phaseMs = 0,\n): number {\n // `+ periodMs * 100` keeps the modulo positive when phaseMs > t (start of stage).\n const since = (t - phaseMs + periodMs * 100) % periodMs;\n return Math.exp((-decay * since) / periodMs);\n}\n\nconst EQ_GLYPHS = '▁▂▃▄▅▆▇█';\n\nfunction renderMiniEqualizer(beatTimeMs: number, levels: number[]): string {\n // Voices — what you'd hear in a techno track:\n // kick = the BOOM on every beat (the four-on-the-floor thing)\n // bass = a longer-ringing sub note that overlaps the kick (the rumble)\n // clap = the CLAP on beats 2 & 4 (the backbeat)\n // hat8 = the TSSSS on eighth notes (twice per beat)\n // hat16 = the faster ticka-ticka on sixteenth notes\n // pad = a slow background hum so the track never feels totally silent\n const kick = pulse(beatTimeMs, BEAT_MS, 4);\n const bass = pulse(beatTimeMs, BEAT_MS, 1.5);\n const clap = pulse(beatTimeMs, BEAT_MS * 2, 5, BEAT_MS);\n const hat8 = pulse(beatTimeMs, BEAT_MS / 2, 8);\n const hat16 = pulse(beatTimeMs, BEAT_MS / 4, 12);\n // Slow ~4 s wobble between 0.05 and 0.35 — ambient floor.\n const pad = 0.2 + 0.15 * Math.sin((2 * Math.PI * beatTimeMs) / 4000);\n\n // Each of the 12 bars is a mix of voices, going low → high like a real\n // spectrum analyzer. Low bars feel the kick + bass, mid bars feel the clap,\n // high bars feel the hats. Pad layered in everywhere so nothing dies.\n const mix = [\n bass * 0.7 + kick * 0.5 + pad,\n bass * 0.6 + kick * 0.6 + pad * 0.9,\n bass * 0.4 + kick * 0.7 + pad * 0.8,\n kick * 0.6 + clap * 0.3 + pad * 0.7,\n kick * 0.4 + clap * 0.5 + pad * 0.7,\n clap * 0.7 + hat8 * 0.3 + pad * 0.6,\n clap * 0.6 + hat8 * 0.5 + pad * 0.5,\n hat8 * 0.7 + clap * 0.3 + pad * 0.5,\n hat8 * 0.5 + hat16 * 0.4 + pad * 0.4,\n hat8 * 0.4 + hat16 * 0.5 + pad * 0.4,\n hat16 * 0.6 + hat8 * 0.3 + pad * 0.3,\n hat16 * 0.7 + pad * 0.3,\n ];\n\n // Winamp-style smoothing: each bar jumps up instantly to the current audio\n // level (so kicks read as snap), then drifts down by EQ_FALL_PER_FRAME each\n // frame until the next hit catches it.\n let out = '';\n for (let i = 0; i < EQ_BARS; i++) {\n const target = Math.min(1, mix[i]);\n levels[i] = Math.max(target, levels[i] - EQ_FALL_PER_FRAME);\n out += EQ_GLYPHS[Math.floor(levels[i] * (EQ_GLYPHS.length - 1))];\n }\n return out;\n}\n\nconst PhaseBody = ({\n phase,\n width,\n height,\n}: {\n phase: AgentPhase;\n width: number;\n height: number;\n}) => {\n switch (phase) {\n case AgentPhase.CodebaseScan:\n return <MatrixRain width={width} height={height} />;\n case AgentPhase.SkillInstall:\n return <LibraryShelf width={width} height={height} />;\n case AgentPhase.DepInstall:\n return <CrateStack width={width} height={height} />;\n case AgentPhase.CodeEdits:\n return <DiffCascade width={width} height={height} />;\n case AgentPhase.EnvSetup:\n return <Tumblers width={width} height={height} />;\n case AgentPhase.Dashboards:\n return <DashboardGrid width={width} height={height} />;\n }\n};\n","/**\n * TipsCard — Shows PostHog tips during the agent run.\n * Reactively shows/hides tips based on discovered features.\n */\n\nimport { Box, Text } from 'ink';\nimport type { WizardStore } from '@tui/store';\nimport { Colors, Icons } from '@tui/styles';\nimport { DiscoveredFeature } from '@shared/discovered-feature';\n\n/** A discrete tip shown in the TipsCard during the agent run. */\nexport interface Tip {\n /** Unique identifier */\n id: string;\n /** Title line */\n title: string;\n /** Description shown below the title */\n description: string;\n /** Optional URL shown after the description */\n url?: string;\n /** When provided, the tip is only shown if this returns true */\n visible?: (store: WizardStore) => boolean;\n}\n\n/**\n * The default deck — generic PostHog onboarding tips, shown for any\n * program that doesn't supply its own via `ProgramConfig.getTips`.\n * Program-specific copy (e.g. the self-driving scout/source\n * explainers) lives in that program's content, not here — this stays the\n * neutral fallback.\n */\nexport const DEFAULT_TIPS: Tip[] = [\n {\n id: 'persons',\n title: 'You can also track people and groups with PostHog',\n description:\n \"Events can be associated with the humans who generate them, letting you understand a specific user or customer's situation.\",\n },\n {\n id: 'properties',\n title: 'Get way more detail using properties',\n description:\n 'Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more.',\n },\n {\n id: 'slack',\n title: 'Use PostHog in Slack',\n description:\n 'Connect the PostHog Slack app to analyze data and ship product changes — deploy flags, open PRs, run queries — just by tagging @PostHog:',\n url: 'https://posthog.com/slack',\n },\n {\n id: 'stripe',\n title: 'You can track Stripe revenue with PostHog',\n description: 'Add Stripe as a data source while you wait:',\n // No project segment: `/project/` without a team id matches no route and\n // renders the 404 scene. Without it the app resolves the current project.\n url: 'https://app.posthog.com/data-warehouse/new-source?kind=Stripe',\n visible: (store) =>\n store.session.discoveredFeatures.includes(DiscoveredFeature.Stripe),\n },\n];\n\nexport const TipsCard = ({\n store,\n tips = DEFAULT_TIPS,\n}: {\n store: WizardStore;\n tips?: Tip[];\n}) => {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Tips\n </Text>\n <Box height={1} />\n\n {tips\n .filter((tip) => !tip.visible || tip.visible(store))\n .map((tip) => (\n <Box key={tip.id} flexDirection=\"column\" marginBottom={1}>\n <Text>\n <Text color={Colors.accent}>{Icons.diamond} </Text>\n <Text bold>{tip.title}</Text>\n </Text>\n\n <Text dimColor>\n {tip.description}\n {tip.url && (\n <>\n {' '}\n <Text color=\"cyan\">{tip.url}</Text>\n </>\n )}\n </Text>\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * The \"Take PostHog to Slack\" card the Connect Slack screen shows, after a\n * program's run and in `wizard slack`. Every string is presentation copy shown\n * to the user, never sent to the agent. Connecting Slack is a manual OAuth\n * step in the PostHog app, so the card links out to `setupUrl`.\n */\nexport interface SlackAppCard {\n headline: string;\n /** One-line hook covering both analysis and shipping. */\n pitch: string;\n /** posthog.com/slack — \"learn more\". */\n learnMoreUrl: string;\n /** integrations/slack — where the user connects Slack. */\n setupUrl: string;\n /** The Slack agent's two capabilities (code/PR + data) — fixed, not role-tailored. */\n capabilities: string[];\n}\n\nconst SLACK_APP: SlackAppCard = {\n learnMoreUrl: 'https://posthog.com/slack',\n setupUrl: 'https://app.posthog.com/integrations/slack',\n headline: '@PostHog in Slack',\n pitch:\n 'Ask about your product data, debug issues, and generate PRs without leaving the thread.',\n capabilities: [\n 'Tag @PostHog with a bug, edit, or a feature idea. It will spin up a sandboxed environment, plan, edit files, run tests, and open a draft PR.',\n \"Tag @PostHog with any data question. It's the same SQL-writing, statistically-minded assistant as PostHog AI, but it responds where you send work memes.\",\n ],\n};\n\n/**\n * Resolve the \"Take PostHog to Slack\" card. Role-independent — the Slack\n * agent's two capabilities (code/PR + data) describe the product itself,\n * not role-specific examples.\n */\nexport function getSlackAppCard(): SlackAppCard {\n return {\n headline: SLACK_APP.headline,\n pitch: SLACK_APP.pitch,\n learnMoreUrl: SLACK_APP.learnMoreUrl,\n setupUrl: SLACK_APP.setupUrl,\n capabilities: SLACK_APP.capabilities,\n };\n}\n","/**\n * SlackConnectScreen — the dedicated \"Connect Slack\" step shown after the\n * MCP tutorial (`wizard mcp tutorial`), after a successful install\n * (`wizard mcp add`), at the end of the integration flow, and as the whole\n * program in the standalone `wizard slack` flow.\n *\n * Presents the PostHog Slack app plus role-tailored use-cases. The copy\n * adapts to whether Slack is already connected (polled while the screen\n * is up, held as local state):\n * • not connected (or unknown) — nudge + \"Open Slack setup\", which\n * launches the browser at the integration settings page and keeps\n * the screen alive; the poll flips it to connected once the user\n * finishes the manual OAuth step in the browser.\n * • already connected — confirm it and skip the connect CTA, so users\n * who already have it aren't nagged.\n * \"Skip\" / \"Done\" / esc dismiss the step (`slackStepDismissed`) and let\n * the router advance to exit.\n *\n * The mcp and integration flows arrive here already authenticated. The\n * standalone `wizard slack` flow lands without credentials and only\n * triggers OAuth when the user explicitly picks \"Open Slack setup\" —\n * once authed, the connected-state poll lets the screen flip to the\n * \"Slack connected\" copy without nagging users who already have it.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useRef, useState, useSyncExternalStore } from 'react';\n\nimport type { WizardStore } from '@tui/store';\nimport { Colors, Icons } from '@tui/styles';\nimport { PickerMenu, LoadingBox } from '@tui/primitives/index';\nimport { useKeyBindings, KeyMatch } from '@tui/hooks/useKeyBindings';\nimport { getSlackAppCard } from '@tui/services/slack-app-card';\nimport { fetchSlackConnected } from '@shared/api';\nimport { CONNECT_SLACK_SCOPE_ADDITIONS } from '@shared/oauth-scopes';\nimport { getOrAskForProjectData } from '@tui/auth/project-data';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport { openTrackedLink, withUtm } from '@utils/links';\n\ninterface SlackConnectScreenProps {\n store: WizardStore;\n}\n\nenum ChoiceValue {\n Open = 'open',\n Skip = 'skip',\n}\n\nenum Phase {\n /** Default — the marketing card with the picker. */\n Nudge = 'nudge',\n /** User picked \"Open Slack setup\" without credentials; OAuth is in flight. */\n Authenticating = 'authenticating',\n}\n\nconst POLL_INTERVAL_MS = 3000;\n\nexport const SlackConnectScreen = ({ store }: SlackConnectScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const role = store.session.roleAtOrganization;\n const slack = getSlackAppCard();\n const setupUrl = withUtm(slack.setupUrl, 'slack-connect-setup');\n const learnMoreUrl = withUtm(slack.learnMoreUrl, 'slack-connect-learn-more');\n\n const credentials = store.session.credentials;\n\n // `slackConnected` is three-state: null until something has actually\n // checked (the tutorial's prefetch, or this screen's first poll tick).\n const connectedState = store.slackConnected;\n const connected = connectedState === true;\n\n // Phase.Nudge is the default; Phase.Authenticating fires only when the\n // no-creds user picks \"Open Slack setup\" — explicit consent for the OAuth\n // dance. Without credentials the connected-state poll can't run, so\n // logging in is what unlocks the screen flipping to \"Slack connected\" on\n // its own once the browser-side Slack OAuth completes.\n const [phase, setPhase] = useState<Phase>(Phase.Nudge);\n const [loginError, setLoginError] = useState<string | null>(null);\n\n // Track whether we've already opened the Slack setup link this session.\n // Once we have, the picker drops the \"Open Slack setup\" CTA (it would\n // just re-fire the same browser action) and swaps in copy telling the\n // user to finish the steps in their browser. The poll will flip the\n // screen to \"Slack connected\" on its own when it succeeds.\n const [setupOpened, setSetupOpened] = useState(false);\n const openSlackSetup = (): void => {\n openTrackedLink(setupUrl, 'slack-connect-setup');\n setSetupOpened(true);\n };\n\n // Impression — once, and only when the connected state is known, so\n // `already_connected` is real: users who arrive connected segment apart\n // from users who connect during the screen ('slack connect completed').\n // The no-creds path can't know the state, so it fires\n // `slack connect nudge shown` instead — see below.\n const known = connectedState !== null;\n const impressionFired = useRef(false);\n useEffect(() => {\n if (!known || impressionFired.current) return;\n impressionFired.current = true;\n analytics.wizardCapture('slack connect shown', {\n role,\n already_connected: connected,\n });\n }, [known, connected, role]);\n\n // Separate impression for the no-creds path: we render the nudge but\n // don't know whether the user is already connected. Lets funnel\n // readers see those impressions distinctly from authenticated views.\n const nudgeImpressionFired = useRef(false);\n useEffect(() => {\n if (credentials || nudgeImpressionFired.current) return;\n nudgeImpressionFired.current = true;\n analytics.wizardCapture('slack connect nudge shown', { role });\n }, [credentials, role]);\n\n // While not connected, poll: connecting Slack is a manual OAuth step in\n // the browser, so the poll is what flips the screen to the connected\n // state when the user comes back. The first tick also resolves the\n // null/unknown state. Without credentials (user skipped login) it\n // renders the connect nudge.\n useEffect(() => {\n if (!credentials || connected) return;\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const controller = new AbortController();\n const check = (): void => {\n fetchSlackConnected(\n credentials.accessToken,\n credentials.projectId,\n credentials.host.apiHost,\n controller.signal,\n )\n .then((isConnected) => {\n if (cancelled) return;\n if (isConnected) {\n // Only a false→true flip means the user completed the Slack\n // OAuth during this screen; true on the first-ever check just\n // means they arrived connected.\n if (store.slackConnected === false) {\n analytics.wizardCapture('slack connect completed', { role });\n }\n store.setSlackConnected(true);\n } else {\n if (store.slackConnected === null) {\n store.setSlackConnected(false);\n }\n timer = setTimeout(check, POLL_INTERVAL_MS);\n }\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n // Capture once and stop polling — repeating a failing call\n // every tick would spam error tracking. The nudge copy is\n // the fallback either way; a failed check counts as not\n // connected so the screen doesn't sit on the loading state.\n if (store.slackConnected === null) {\n store.setSlackConnected(false);\n }\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'slack_connected_check' },\n );\n });\n };\n check();\n return () => {\n // Tear down fully on exit: no new ticks (cancelled), no pending\n // tick (clearTimeout), no in-flight request (abort).\n cancelled = true;\n if (timer) clearTimeout(timer);\n controller.abort();\n };\n }, [credentials, connected, store]);\n\n // Leaving while connected is \"done\"; leaving while not connected is a\n // skip. Two events so the funnel reads without prop gymnastics. The\n // `connection_state` property on `skipped` distinguishes \"we knew the\n // user wasn't connected\" (had creds, polled, false) from \"we never\n // knew\" (no creds, never polled).\n const dismiss = (): void => {\n if (connected) {\n analytics.wizardCapture('slack connect done', { role });\n } else {\n analytics.wizardCapture('slack connect skipped', {\n role,\n connection_state: credentials ? 'not_connected' : 'unknown',\n });\n }\n store.setSlackStepDismissed();\n };\n\n const handleSelect = (value: ChoiceValue | ChoiceValue[]): void => {\n const choice = Array.isArray(value) ? value[0] : value;\n if (choice === ChoiceValue.Open) {\n analytics.wizardCapture('slack connect opened', { role });\n setLoginError(null);\n // With credentials, the screen stays up and the existing poll flips\n // it to connected once the user finishes the browser Slack OAuth.\n // Without credentials, we kick off the wizard OAuth first so the\n // poll can run after the user returns — opening Slack setup before\n // login would mean we never get to confirm the connection.\n if (credentials) {\n openSlackSetup();\n return;\n }\n setPhase(Phase.Authenticating);\n return;\n }\n dismiss();\n };\n\n // OAuth runs when entering Authenticating. On success we land creds in\n // the store, open the Slack setup link, and return to Nudge — the\n // connected-state poll (keyed on credentials) then kicks in\n // automatically. On failure we surface the error inline and stay put.\n useEffect(() => {\n if (phase !== Phase.Authenticating) return;\n let cancelled = false;\n\n void (async () => {\n try {\n const data = await getOrAskForProjectData({\n store,\n signup: false,\n projectId: undefined,\n scopeAdditions: CONNECT_SLACK_SCOPE_ADDITIONS,\n });\n if (cancelled) return;\n store.setCredentials({\n accessToken: data.accessToken,\n projectApiKey: data.projectApiKey,\n host: data.host,\n projectId: data.projectId,\n });\n store.setRoleAtOrganization(data.roleAtOrganization);\n store.setApiUser(data.user);\n store.setLoginUrl(null);\n openSlackSetup();\n setPhase(Phase.Nudge);\n } catch (err) {\n if (cancelled) return;\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[SlackConnectScreen] login failed: ${message}`);\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'slack_connect_login' },\n );\n store.setLoginUrl(null);\n setLoginError(message);\n setPhase(Phase.Nudge);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [phase, role, setupUrl, store]);\n\n useKeyBindings('slack-connect', [\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action:\n phase === Phase.Authenticating ? 'cancel' : connected ? 'done' : 'skip',\n handler: () => {\n // Cancelling OAuth from the Authenticating phase returns to the\n // nudge without dismissing — the user can retry, skip, or pick\n // another action. The effect's cleanup discards the in-flight\n // login result via the cancelled flag.\n if (phase === Phase.Authenticating) {\n store.setLoginUrl(null);\n setPhase(Phase.Nudge);\n return;\n }\n dismiss();\n },\n },\n ]);\n\n if (phase === Phase.Authenticating) {\n return (\n <Box flexDirection=\"column\" flexGrow={1} marginTop={1}>\n <LoadingBox message=\"Waiting for authentication...\" />\n {store.loginUrl && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text>\n <Text dimColor>\n If the browser didn&apos;t open, copy and paste:\n </Text>\n {'\\n\\n'}\n <Text color=\"cyan\">{store.loginUrl}</Text>\n </Text>\n </Box>\n )}\n </Box>\n );\n }\n\n // Credentials in hand but the first integration check hasn't resolved —\n // hold the nudge so an already-connected user is never asked to connect.\n // Flows that prefetch (mcp tutorial) arrive with the state seeded and\n // never see this.\n if (credentials && connectedState === null) {\n return (\n <Box flexDirection=\"column\" flexGrow={1} marginTop={1}>\n <LoadingBox message=\"Checking for an existing Slack connection...\" />\n </Box>\n );\n }\n\n // Waiting-for-browser state: after the user has picked \"Open Slack\n // setup\" we've already triggered the browser action. Re-offering it as\n // the headline CTA is confusing; surface \"go finish it in your browser\"\n // copy and demote re-open to a recovery action.\n const awaitingBrowser = setupOpened && !connected;\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box marginTop={1} flexDirection=\"column\">\n {connected ? (\n <Text bold color={Colors.success}>\n {Icons.check} Slack connected\n </Text>\n ) : awaitingBrowser ? (\n <Text bold color={Colors.accent}>\n Finish connecting Slack\n </Text>\n ) : (\n <Text bold color={Colors.accent}>\n {slack.headline}\n </Text>\n )}\n\n <Box marginTop={1}>\n <Text>\n {connected\n ? \"Slack is connected — here's what you can do:\"\n : awaitingBrowser\n ? \"We've opened PostHog's Slack setup page in your browser. Authorize the Slack app there — we'll detect the connection automatically and continue.\"\n : slack.pitch}\n </Text>\n </Box>\n\n <Box marginTop={1} flexDirection=\"column\">\n {slack.capabilities.map((capability, i) => (\n // Marker + copy in one <Text> so the (long) line wraps as a\n // single flow — separate row-Box siblings drop the marker on\n // wrapped bullets.\n <Box key={i} marginTop={i === 0 ? 0 : 1}>\n <Text>\n <Text color=\"cyan\">{Icons.diamond} </Text>\n {capability}\n </Text>\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1} flexDirection=\"column\">\n {!connected && (\n <Text dimColor>\n {awaitingBrowser ? 'Setup page: ' : 'Connect it: '}\n <Text color=\"cyan\">{setupUrl}</Text>\n </Text>\n )}\n <Text dimColor>\n Learn more: <Text color=\"cyan\">{learnMoreUrl}</Text>\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <PickerMenu\n options={\n connected\n ? [{ label: 'Done', value: ChoiceValue.Skip }]\n : awaitingBrowser\n ? [\n {\n label: 'Re-open Slack setup',\n value: ChoiceValue.Open,\n },\n { label: 'Skip / Continue', value: ChoiceValue.Skip },\n ]\n : [\n { label: 'Open Slack setup', value: ChoiceValue.Open },\n { label: 'Skip / Continue', value: ChoiceValue.Skip },\n ]\n }\n onSelect={handleSelect}\n />\n </Box>\n\n {loginError && (\n <Box marginTop={1}>\n <Text color=\"red\">\n Login failed: {loginError}. Try again or skip.\n </Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * OutroScreen — Default post-run summary.\n *\n * Renders the success / error / cancel views from `outroData`. Programs\n * that need a different success view (e.g. with extra summary content)\n * ship their own screen component (see audit/AuditOutroScreen.tsx).\n */\n\nimport { Box, Text } from 'ink';\nimport { useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@tui/store';\nimport { OutroKind } from '@shared/outro';\nimport { Colors } from '@tui/styles';\nimport { withUtm } from '@utils/links';\nimport { LinkText } from '@tui/primitives/LinkText';\nimport { useDismissOnAnyKey } from '@tui/hooks/useDismissOnAnyKey';\n\ninterface OutroScreenProps {\n store: WizardStore;\n}\n\nexport const OutroScreen = ({ store }: OutroScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Dismissal here chains into ExitScreen's exit request, so a modifier\n // combo (e.g. Ctrl+T toggling the token/cost HUD) must not trigger it too.\n useDismissOnAnyKey(() => store.setOutroDismissed());\n\n const outroData = store.session.outroData;\n\n if (!outroData) {\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text dimColor>Finishing up...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {outroData.kind === OutroKind.Success && (\n <Box flexDirection=\"column\">\n <Text color=\"green\" bold>\n ✔ {outroData.message || 'Done!'}\n </Text>\n\n {outroData.primaryLink && (\n <Box marginTop={1}>\n <Text>\n {outroData.primaryLink.label}:{' '}\n <Text color=\"cyan\">{outroData.primaryLink.url}</Text>\n </Text>\n </Box>\n )}\n\n {outroData.notebookUrl && (\n <>\n <Box marginTop={1}>\n <Text>\n The wizard has set up PostHog in your codebase and written a\n full report of what it instrumented. Read the notebook for\n more details!\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text>\n Notebook:{' '}\n <Text color=\"cyan\">\n {withUtm(outroData.notebookUrl, 'outro-notebook')}\n </Text>\n </Text>\n </Box>\n </>\n )}\n\n {outroData.dashboardUrl && (\n <Box marginTop={1}>\n <Text>\n Dashboard:{' '}\n <Text color=\"cyan\">\n {withUtm(outroData.dashboardUrl, 'outro-dashboard')}\n </Text>\n </Text>\n </Box>\n )}\n\n {outroData.body && (\n <Box marginTop={1}>\n <Text dimColor>{outroData.body}</Text>\n </Box>\n )}\n\n {outroData.reportFile && (\n <Box marginTop={1}>\n <Text>\n Check <Text bold>./{outroData.reportFile}</Text> for details\n </Text>\n </Box>\n )}\n\n {outroData.changes && outroData.changes.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"cyan\" bold>\n What the agent did:\n </Text>\n {outroData.changes.map((change, i) => (\n <Text key={i}>• {change}</Text>\n ))}\n </Box>\n )}\n\n {store.eventPlan.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"cyan\" bold>\n Events added:\n </Text>\n {store.eventPlan.map((event) => (\n <Text key={event.name}>\n • <Text bold>{event.name}</Text>\n <Text dimColor> {event.description}</Text>\n </Text>\n ))}\n </Box>\n )}\n\n {outroData.docsUrl && (\n <Box marginTop={1}>\n <Text>\n Learn more:{' '}\n <Text color=\"cyan\">\n {withUtm(outroData.docsUrl, 'outro-docs')}\n </Text>\n </Text>\n </Box>\n )}\n\n {outroData.continueUrl && (\n <Box>\n <Text>\n Continue onboarding:{' '}\n <Text color=\"cyan\">\n {withUtm(outroData.continueUrl, 'outro-continue')}\n </Text>\n </Text>\n </Box>\n )}\n\n {/* Suggestions (e.g. unconnected warehouse sources) go after\n everything the run actually produced. */}\n {outroData.nextSteps && outroData.nextSteps.items.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"cyan\" bold>\n {outroData.nextSteps.heading}\n </Text>\n {/* Items can carry a URL, so render through LinkText: it keeps the\n full address as the click target and shortens the visible label\n instead of wrapping it across lines. */}\n {outroData.nextSteps.items.map((item, i) => (\n <Box key={i} flexDirection=\"row\">\n <Text>• </Text>\n <LinkText text={item} />\n </Box>\n ))}\n </Box>\n )}\n\n <Box marginTop={1}>\n <Text dimColor>\n Note: This wizard uses an LLM agent to analyze and modify your\n project. Please review the changes made.\n </Text>\n </Box>\n <Text dimColor>\n How did this work for you? Drop us a line: wizard@posthog.com\n </Text>\n </Box>\n )}\n\n {outroData.kind === OutroKind.Error && (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✘ {outroData.message || 'An error occurred'}\n </Text>\n\n {outroData.instruction && (\n <Box marginTop={1}>\n <Text>{outroData.instruction}</Text>\n </Box>\n )}\n\n {outroData.body && (\n <Box marginTop={outroData.instruction ? 0 : 1}>\n <Text dimColor>{outroData.body}</Text>\n </Box>\n )}\n\n {outroData.docsUrl && (\n <Box marginTop={1} flexDirection=\"column\">\n {outroData.docsLabel ? (\n <>\n <Text dimColor>{outroData.docsLabel}</Text>\n <Text color=\"cyan\">{outroData.docsUrl}</Text>\n </>\n ) : (\n <Text>\n Docs: <Text color=\"cyan\">{outroData.docsUrl}</Text>\n </Text>\n )}\n </Box>\n )}\n </Box>\n )}\n\n {outroData.kind === OutroKind.Cancel && (\n <Box flexDirection=\"column\">\n <Text color=\"yellow\">■ {outroData.message || 'Cancelled'}</Text>\n </Box>\n )}\n\n <Box marginTop={outroData.kind === OutroKind.Error ? 2 : 1}>\n <Text color={Colors.muted}>\n Press any key to{' '}\n {outroData.kind === OutroKind.Error ? 'exit' : 'continue'}\n </Text>\n </Box>\n </Box>\n );\n};\n","/** TuiState: what only the TUI's screens read and write, kept in its store beside the shared session. */\n\nimport type { AuthErrorDetail } from '@agent/types';\nimport type { SettingsConflict } from '@shared/claude-settings';\nimport type { McpOutcome } from '@shared/run-state';\nimport type { WizardSession } from '@programs/types';\n\n/** The launch choices only the TUI takes. */\nexport type TuiLaunchChoices = {\n /** `mcp add --features`: the features to preselect. */\n mcpFeatures?: string[];\n /** `--integrate`: integrate PostHog without asking. */\n integrate?: boolean;\n};\n\nexport type TuiState = {\n /** `mcp add --features`: the features to preselect. */\n mcpFeatures: string[] | undefined;\n\n /** The program this invocation runs; null until a host launches the store with one. */\n programLabel: string | null;\n\n // From detection + screens\n setupConfirmed: boolean;\n\n // Login overlays\n /** The localhost login URL the auth screen shows while the OAuth flow waits. */\n loginUrl: string | null;\n /** Direct PostHog authorize URL, shown in the manual-paste modal for remote shells. */\n authorizeUrl: string | null;\n\n // Screen completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n /** Editor-owned login commands still to run (e.g. `claude mcp login posthog`), echoed at exit. */\n mcpLoginCommands: string[];\n /** The editors the MCP step installed into, for the suggested-prompts screen. */\n mcpInstalledClients: string[];\n mcpSuggestedPromptsDismissed: boolean;\n /** True once the user has acted on (opened or skipped) the Connect-Slack step. */\n slackStepDismissed: boolean;\n /** Whether the project already has a Slack integration; `null` until detected. */\n slackConnected: boolean | null;\n skillsComplete: boolean;\n outroDismissed: boolean;\n\n /**\n * Self-driving only: whether to integrate PostHog as part of this run.\n * `null` until decided; `--integrate` pre-sets it to `true`.\n */\n integrate: boolean | null;\n /** Ids of composed run steps that have completed, e.g. self-driving's `integrate-run`. */\n completedRuns: string[];\n /** Self-driving only: the user confirmed the handoff after the integration run. */\n selfDrivingHandoffConfirmed: boolean;\n /** Self-driving only: whether the PostHog GitHub App is connected; `null` until checked. */\n githubConnected: boolean | null;\n /** Self-driving only: the user can't connect GitHub now, so the run is skipped. */\n githubDeclined: boolean;\n\n // Overlays\n outageDismissed: boolean;\n settingsOverrideKeys: string[] | null;\n settingsConflicts: SettingsConflict[] | null;\n authErrorDetail: AuthErrorDetail | null;\n portConflictProcess: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null;\n /** Skill saved for the user's own agent during the handoff. */\n spellbook: { path: string; skillsIncluded: boolean } | null;\n /** How the user left the mint-failure screen; null until then. */\n mintHandoff: 'continue' | 'exit' | null;\n};\n\n/** What a step predicate reads: the shared session and the TUI's own state. A `WizardStore` is one. */\nexport type TuiView = Readonly<TuiState> & { readonly session: WizardSession };\n\n/** The TUI state a run starts with: the screens' defaults, the launch choices and the program it runs. */\nexport function initialTuiState(\n choices: TuiLaunchChoices = {},\n programLabel: string | null = null,\n): TuiState {\n return {\n mcpFeatures: choices.mcpFeatures,\n programLabel,\n setupConfirmed: false,\n loginUrl: null,\n authorizeUrl: null,\n mcpComplete: false,\n mcpOutcome: null,\n mcpLoginCommands: [],\n mcpInstalledClients: [],\n mcpSuggestedPromptsDismissed: false,\n slackStepDismissed: false,\n slackConnected: null,\n skillsComplete: false,\n outroDismissed: false,\n // `--integrate` forces integration (skip the question); otherwise the\n // integration-check screen resolves it from null.\n integrate: choices.integrate === true ? true : null,\n completedRuns: [],\n selfDrivingHandoffConfirmed: false,\n githubConnected: null,\n githubDeclined: false,\n outageDismissed: false,\n settingsOverrideKeys: null,\n settingsConflicts: null,\n authErrorDetail: null,\n portConflictProcess: null,\n spellbook: null,\n mintHandoff: null,\n };\n}\n","/**\n * WizardStore — the TUI's store: the shared `SessionStore` plus the state only\n * the screens use. React components subscribe via useSyncExternalStore.\n *\n * The session and the run state live in `sessions`, the same kind of store\n * headless and embedders use, so `runProgram` writes them directly. This store\n * adds the TUI's own state (`TuiState`: the screens' answers and what an\n * overlay shows, read as `store.X`), display state (the token HUD, learn\n * cards), the router and the flow's gates, and re-resolves the screen and the\n * gates after every change to either.\n *\n * The active screen is derived from the session and the TUI state —\n * WizardRouter walks the flow and shows the first step whose `isComplete` is\n * still false. Define a step `gate` if its screen needs to await user\n * interactions; the TUI host calls `await store.getGate(stepId)` to pause\n * until it holds.\n */\n\nimport { atom } from 'nanostores';\nimport { logToFile } from '@utils/debug';\nimport { type AuthErrorDetail, type TokenUsageDelta } from '@agent/types';\nimport {\n initialTuiState,\n type TuiLaunchChoices,\n type TuiState,\n type TuiView,\n} from '@tui/tui-state';\nimport {\n type OutroData,\n type PendingQuestion,\n type AskAnswers,\n type TaskNotice,\n} from '@agent/types';\nimport { type DiscoveredFeature } from '@shared/discovered-feature';\nimport { McpOutcome, RunPhase } from '@shared/run-state';\nimport type { SettingsConflict } from '@shared/claude-settings';\nimport type { CloudRegion } from '@utils/types';\nimport { type WizardReadinessResult } from '@shared/health-checks/readiness';\nimport {\n WizardRouter,\n type ScreenName,\n ScreenId,\n Overlay,\n Program,\n type ProgramId,\n} from './router.js';\nimport { analytics, sessionProperties } from '@utils/analytics';\nimport {\n buildSession,\n findProgramConfig,\n reportCodebaseScan,\n scanCodebaseFor,\n SessionStore,\n} from '@programs';\nimport type { PlannedEvent, TaskItem, WizardSession } from '@programs/types';\nimport {\n addTokenUsage,\n EMPTY_TOKEN_USAGE,\n type TokenUsageSnapshot,\n} from './token-usage.js';\nimport type { StoreInitContext } from './flow.js';\nimport { programFlowSteps } from './ai-opt-in-gate.js';\nimport { flowOwner } from './flow-owner.js';\nimport { IS_DEV } from '@shared/constants';\n\nexport { ScreenId, Overlay, Program };\nexport type { ScreenName, OutroData, TuiState, TuiView, ProgramId };\n\ninterface GateEntry {\n predicate: (view: TuiView) => boolean;\n promise: Promise<void>;\n resolve: () => void;\n resolved: boolean;\n}\n\nexport class WizardStore implements TuiView {\n /** The shared session and run state; every session write goes through it. */\n readonly sessions: SessionStore;\n\n /** The TUI's own state: the screens' answers, overlay contents and launch choices. */\n private $tui = atom<TuiState>(initialTuiState());\n\n // ── Display-only atoms ────────────────────────────────────────────\n private $statusExpanded = atom(false);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n // Defaults on for local/dev/test runs (tsx, `pnpm try`, vitest) so\n // contributors see it without needing to know the shortcut; defaults off\n // for the published build, where it stays genuinely hidden. Still\n // Ctrl+T-toggleable either way.\n private $tokenHudVisible = atom(IS_DEV);\n /** The Visualizer tab's NOW PLAYING stage, and when it started. */\n private $currentStage = atom<{ stage: string; startedAt: number } | null>(\n null,\n );\n private $tokenUsage = atom<TokenUsageSnapshot>(EMPTY_TOKEN_USAGE);\n /** The code a screen asked to end the run with; the host applies it. */\n private $exitRequest = atom<number | null>(null);\n\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n /** The ask and notice the overlays last showed, to open and close them as the session changes. */\n private _shownQuestion: PendingQuestion | null = null;\n private _shownNotice: TaskNotice | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n /** Gate promises derived from program step definitions. */\n private _gates = new Map<string, GateEntry>();\n private _mcpOutcomeReported = false;\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n /** Resolves the OAuth flow with a manually-entered authorization code. */\n private _resolveManualAuthCode: ((code: string) => void) | null = null;\n\n constructor(\n program: ProgramId = Program.PostHogIntegration,\n sessions: SessionStore = new SessionStore(buildSession({})),\n ) {\n this.sessions = sessions;\n this.router = new WizardRouter(program);\n this._initFromProgram(program);\n this._shownQuestion = sessions.session.pendingQuestion;\n this._shownNotice = sessions.session.taskNotice;\n sessions.subscribe(() => this._onSessionChange());\n }\n\n /**\n * Scan program steps for gate predicates and create gate promises.\n *\n * Steps come from programFlowSteps (withAiOptInGate applied), so the injected ai-opt-in step's\n * gate registers here — the TUI host awaits it before any source leaves the\n * machine. Same wrapper screen-sequences.ts uses, so the gate and its screen\n * can't drift apart.\n */\n private _initFromProgram(program: ProgramId): void {\n const steps = programFlowSteps(program);\n for (const step of steps) {\n if (step.gate) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n this._gates.set(step.id, {\n predicate: step.gate,\n promise,\n resolve,\n resolved: false,\n });\n }\n }\n }\n\n /** Open or close the ask and notice overlays as the shared store's requests come and go. */\n private _onSessionChange(): void {\n const { pendingQuestion, taskNotice } = this.session;\n let closedOnly = false;\n if (pendingQuestion !== this._shownQuestion) {\n if (this._shownQuestion) this.router.popOverlay();\n if (pendingQuestion) this.router.pushOverlay(Overlay.WizardAsk);\n closedOnly = !pendingQuestion;\n this._shownQuestion = pendingQuestion;\n }\n if (taskNotice !== this._shownNotice) {\n if (this._shownNotice) this.router.popOverlay();\n if (taskNotice) this.router.pushOverlay(Overlay.TaskNotice);\n closedOnly = !taskNotice;\n this._shownNotice = taskNotice;\n }\n this.emitChange();\n if (closedOnly) this.router._setDirection('pop');\n }\n\n /**\n * Run the program steps' onInit callbacks. startTUI calls this once\n * the screens are actually rendering — constructing a store alone\n * (tests, playground) must not fire init work like the health-check\n * pre-flight, whose probes belong only to flows that show its screen.\n */\n runInitHooks(): void {\n const steps = flowOwner(this.router.activeProgram).flow;\n const getSession = (): WizardSession => this.session;\n const ctx: StoreInitContext = {\n get session() {\n return getSession();\n },\n setReadinessResult: (r) => this.setReadinessResult(r),\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n emitChange: () => this.emitChange(),\n };\n for (const step of steps) {\n step.onInit?.(ctx);\n }\n }\n\n /**\n * Run the active program's `onReady` detection through the shared store, and\n * mark detection complete so `runProgram` doesn't repeat it. Call it after\n * the session is set, so it sees the real installDir.\n */\n async runReadyHooks(): Promise<void> {\n const config = findProgramConfig(this.router.activeProgram);\n const ctx = this.sessions.readyContext();\n if (config) await scanCodebaseFor(config, ctx);\n await config?.onReady?.(ctx);\n this.sessions.setDetectionComplete();\n }\n\n // ── Gate API ────────────────────────────────────────────────────\n\n /**\n * Get a gate promise by step ID — the primary blocking checkpoint API\n * for the TUI host. `await store.getGate('...')` parks the caller until the\n * corresponding program step's gate predicate flips to true (if the\n * predicate stays false, the caller stays parked indefinitely — the\n * TUI keeps rendering so the user can resolve whatever is blocking).\n *\n * If the program doesn't define a step with this ID, or the step\n * has no `gate` predicate, this returns an already-resolved promise\n * so the TUI host flows straight through. This lets programs opt in to\n * gates on a per-step basis without the TUI host needing to know which\n * gates exist in which flow.\n */\n getGate(stepId: string): Promise<void> {\n return this._gates.get(stepId)?.promise ?? Promise.resolve();\n }\n\n /**\n * Resolve once `predicate(store)` is true. Unlike a gate, this is created\n * at the await point and evaluated live against the store, so it\n * never latches on a startup value — the orchestrator uses it to wait for a\n * decision (a project picked, a handoff acknowledged) without the \"true while\n * undecided\" trap that latched gate predicates have.\n */\n waitUntil(predicate: (view: TuiView) => boolean): Promise<void> {\n if (predicate(this)) return Promise.resolve();\n return new Promise((resolve) => {\n const unsub = this.subscribe(() => {\n if (predicate(this)) {\n unsub();\n resolve();\n }\n });\n });\n }\n\n /**\n * Resolve once the flow has reached `stepId`: every step before it is\n * hidden or complete. Resolves whether `stepId` itself shows; a step the\n * active flow doesn't have shows.\n */\n reachStep(stepId: string): Promise<boolean> {\n const program = this.router.activeProgram;\n const steps = programFlowSteps(program);\n const index = steps.findIndex((step) => step.id === stepId);\n if (index === -1) return Promise.resolve(true);\n const before = steps.slice(0, index);\n const passed = (view: TuiView): boolean =>\n before.every((step) => {\n if (step.show && !step.show(view)) return true;\n const done = step.isComplete ?? step.gate;\n return !done || done(view);\n });\n const shows = steps[index].show;\n return this.waitUntil(passed).then(() => !shows || shows(this));\n }\n\n /**\n * Re-evaluate every gate predicate against the store and\n * resolve any whose predicate now returns true. Called after every\n * emitChange(), so gates unblock as soon as the session mutation\n * that satisfies them lands. Gates only resolve once — a predicate\n * that goes true → false → true will NOT re-block a caller that\n * already awaited through.\n */\n private _checkGates(): void {\n for (const [, gate] of this._gates) {\n if (!gate.resolved && gate.predicate(this)) {\n gate.resolved = true;\n gate.resolve();\n }\n }\n }\n\n // ── Reads ─────────────────────────────────────────────────────────\n\n get session(): WizardSession {\n return this.sessions.session;\n }\n\n /** Replace the session; the TUI state stays. */\n set session(value: WizardSession) {\n this.sessions.session = value;\n }\n\n get statusMessages(): string[] {\n return this.sessions.statusMessages;\n }\n\n get tasks(): TaskItem[] {\n return this.sessions.tasks;\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.sessions.eventPlan;\n }\n\n get handoffText(): string | null {\n return this.sessions.handoffText;\n }\n\n // ── TUI state ─────────────────────────────────────────────────────\n\n get mcpFeatures(): TuiState['mcpFeatures'] {\n return this.$tui.get().mcpFeatures;\n }\n\n get programLabel(): TuiState['programLabel'] {\n return this.$tui.get().programLabel;\n }\n\n get setupConfirmed(): TuiState['setupConfirmed'] {\n return this.$tui.get().setupConfirmed;\n }\n\n get loginUrl(): TuiState['loginUrl'] {\n return this.$tui.get().loginUrl;\n }\n\n get authorizeUrl(): TuiState['authorizeUrl'] {\n return this.$tui.get().authorizeUrl;\n }\n\n get mcpComplete(): TuiState['mcpComplete'] {\n return this.$tui.get().mcpComplete;\n }\n\n get mcpOutcome(): TuiState['mcpOutcome'] {\n return this.$tui.get().mcpOutcome;\n }\n\n get mcpLoginCommands(): TuiState['mcpLoginCommands'] {\n return this.$tui.get().mcpLoginCommands;\n }\n\n get mcpInstalledClients(): TuiState['mcpInstalledClients'] {\n return this.$tui.get().mcpInstalledClients;\n }\n\n get mcpSuggestedPromptsDismissed(): TuiState['mcpSuggestedPromptsDismissed'] {\n return this.$tui.get().mcpSuggestedPromptsDismissed;\n }\n\n get slackStepDismissed(): TuiState['slackStepDismissed'] {\n return this.$tui.get().slackStepDismissed;\n }\n\n get slackConnected(): TuiState['slackConnected'] {\n return this.$tui.get().slackConnected;\n }\n\n get skillsComplete(): TuiState['skillsComplete'] {\n return this.$tui.get().skillsComplete;\n }\n\n get outroDismissed(): TuiState['outroDismissed'] {\n return this.$tui.get().outroDismissed;\n }\n\n get integrate(): TuiState['integrate'] {\n return this.$tui.get().integrate;\n }\n\n get completedRuns(): TuiState['completedRuns'] {\n return this.$tui.get().completedRuns;\n }\n\n get selfDrivingHandoffConfirmed(): TuiState['selfDrivingHandoffConfirmed'] {\n return this.$tui.get().selfDrivingHandoffConfirmed;\n }\n\n get githubConnected(): TuiState['githubConnected'] {\n return this.$tui.get().githubConnected;\n }\n\n get githubDeclined(): TuiState['githubDeclined'] {\n return this.$tui.get().githubDeclined;\n }\n\n get outageDismissed(): TuiState['outageDismissed'] {\n return this.$tui.get().outageDismissed;\n }\n\n get settingsOverrideKeys(): TuiState['settingsOverrideKeys'] {\n return this.$tui.get().settingsOverrideKeys;\n }\n\n get settingsConflicts(): TuiState['settingsConflicts'] {\n return this.$tui.get().settingsConflicts;\n }\n\n get authErrorDetail(): TuiState['authErrorDetail'] {\n return this.$tui.get().authErrorDetail;\n }\n\n get portConflictProcess(): TuiState['portConflictProcess'] {\n return this.$tui.get().portConflictProcess;\n }\n\n get spellbook(): TuiState['spellbook'] {\n return this.$tui.get().spellbook;\n }\n\n get mintHandoff(): TuiState['mintHandoff'] {\n return this.$tui.get().mintHandoff;\n }\n\n /** Write TUI state, then `sessionWrites`' session fields, with one notification either way. */\n private _write(patch: Partial<TuiState>, sessionWrites?: () => void): void {\n this.$tui.set({ ...this.$tui.get(), ...patch });\n const before = this.sessions.getVersion();\n if (sessionWrites) this.sessions.batch(sessionWrites);\n if (this.sessions.getVersion() === before) this.emitChange();\n }\n\n // ── Display state ───────────────────────────────────────────────\n\n get currentStage(): { stage: string; startedAt: number } | null {\n return this.$currentStage.get();\n }\n\n get tokenUsage(): TokenUsageSnapshot {\n return this.$tokenUsage.get();\n }\n\n /** No-op when the stage hasn't changed, so `startedAt` survives across\n * re-renders and tab switches and measures real stage time. */\n setCurrentStage(stage: string): void {\n const cur = this.$currentStage.get();\n if (cur?.stage === stage) return;\n this.$currentStage.set({ stage, startedAt: Date.now() });\n this.emitChange();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n get exitRequest(): number | null {\n return this.$exitRequest.get();\n }\n\n /** A screen ends the run with `code`; the first request wins. */\n requestExit(code: number): void {\n if (this.$exitRequest.get() !== null) return;\n this.$exitRequest.set(code);\n this.emitChange();\n }\n\n // ── Writes ──────────────────────────────────────────────────────\n\n /** Start from the host's launch values: the session, and the TUI state from its defaults, `choices` and the program's label. */\n launch(\n session: WizardSession,\n choices: TuiLaunchChoices = {},\n programLabel: string | null = null,\n ): void {\n this.$tui.set(initialTuiState(choices, programLabel));\n this.sessions.session = session;\n }\n\n /** Sets setupConfirmed, and is the point consent becomes final. */\n completeSetup(): void {\n // Reports first: analytics merges tags into an event as it is sent, so\n // `setup confirmed` only carries the warehouse tags if they are already\n // set. On main they were, because reporting happened back in detect.\n reportCodebaseScan(this.sessions);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this._write({ setupConfirmed: true });\n }\n\n /**\n * Sharing is on: either the user turned it back on in the panel, or they\n * pressed Continue without ever touching it. Both are reversible until\n * completeSetup() resolves the intro gate and reports.\n */\n grantSharing(): void {\n this.sessions.grantSharing();\n }\n\n /**\n * Sharing is off. Suppresses reporting only — local detection still ran and\n * the results stay in the session, so the outro suggestion and the warehouse\n * task are unaffected; see `scanConsent` on `WizardSession`.\n *\n * Deliberately does not report. The panel's toggle can come back here, so\n * marking the run reported would strand a user who turns sharing off and\n * then on again. completeSetup() owns the single report.\n */\n declineSharing(): void {\n this.sessions.declineSharing();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.sessions.setRunPhase(phase);\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.sessions.setCredentials(credentials);\n }\n\n /** Post-refresh credential swap. No `auth complete`. */\n setAccessToken(credentials: WizardSession['credentials']): void {\n this.sessions.setAccessToken(credentials);\n }\n\n setRoleAtOrganization(role: string | null): void {\n this.sessions.setRoleAtOrganization(role);\n }\n\n setApiUser(user: WizardSession['apiUser']): void {\n this.sessions.setApiUser(user);\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.sessions.setFrameworkConfig(integration, config);\n }\n\n setDetectionComplete(): void {\n this.sessions.setDetectionComplete();\n }\n\n setDetectedFramework(label: string): void {\n this.sessions.setDetectedFramework(label);\n }\n\n setPosthogSdkDetected(detected: boolean): void {\n this.sessions.setPosthogSdkDetected(detected);\n }\n\n setSpellbook(spellbook: NonNullable<TuiState['spellbook']>): void {\n this._write({ spellbook });\n }\n\n setMintHandoff(action: NonNullable<TuiState['mintHandoff']>): void {\n // The parked agent may still hold a question or notice open.\n this._write({ mintHandoff: action }, () => {\n this.cancelPendingQuestion();\n if (this.session.taskNotice) this.resolveTaskNotice(false);\n });\n }\n\n setSkillId(skillId: string | null): void {\n this.sessions.setSkillId(skillId);\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.sessions.setUnsupportedVersion(info);\n }\n\n setLoginUrl(url: string | null): void {\n this._write({ loginUrl: url });\n }\n\n setAuthorizeUrl(url: string | null): void {\n this._write({ authorizeUrl: url });\n }\n\n setReadinessResult(result: WizardReadinessResult | null): void {\n this.sessions.setReadinessResult(result);\n }\n\n /** User dismissed the blocking outage screen. Gate resolves via _checkGates(). */\n dismissOutage(): void {\n logToFile('[health-checks] user dismissed outage screen, continuing');\n this._write({ outageDismissed: true });\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.router.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.router.pushOverlay(Overlay.SettingsOverride);\n }\n this._write({\n settingsOverrideKeys: conflicts.flatMap((c) => c.keys),\n settingsConflicts: conflicts,\n });\n\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user frees the ports and retries, or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n this.router.pushOverlay(Overlay.PortConflict);\n this._write({ portConflictProcess: processInfo });\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay and retry the OAuth port loop. */\n resolvePortConflict(): void {\n this.router.popOverlay();\n this._write({ portConflictProcess: null });\n this.router._setDirection('pop');\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Show an optional step's notice and return whether to keep that step.\n * Asked before the step runs, so nobody is surprised by a prompt mid-run.\n */\n showTaskNotice(notice: TaskNotice): Promise<boolean> {\n return this.sessions.showTaskNotice(notice);\n }\n\n /** Dismiss the notice, keeping (`true`) or skipping (`false`) the step. */\n resolveTaskNotice(keep: boolean): void {\n this.sessions.resolveTaskNotice(keep);\n }\n\n /**\n * Return a promise that resolves when the user submits a manually-entered\n * OAuth code via the paste modal. The OAuth flow races this against the\n * local callback server — see `performOAuthFlow`.\n */\n waitForManualAuthCode(): Promise<string> {\n return new Promise<string>((resolve) => {\n this._resolveManualAuthCode = resolve;\n });\n }\n\n /** Open the manual OAuth code-entry overlay over the auth screen. */\n showManualAuthCode(): void {\n this.pushOverlay(Overlay.ManualAuthCode);\n }\n\n /** Dismiss the manual OAuth code overlay without submitting. */\n dismissManualAuthCode(): void {\n this.popOverlay();\n }\n\n /**\n * Submit a manually-entered authorization code: dismiss the overlay and\n * resolve the in-flight OAuth flow so it can exchange the code for a token.\n */\n submitManualAuthCode(code: string): void {\n this.popOverlay();\n this._resolveManualAuthCode?.(code);\n this._resolveManualAuthCode = null;\n }\n\n /**\n * Open the WizardAsk overlay with a set of questions and return a promise\n * that resolves once the user submits answers (or the request is cancelled).\n *\n * Only one request is in flight at a time — calling this while a request\n * is already pending throws.\n */\n requestQuestion(\n question: PendingQuestion,\n onAnswer?: () => void,\n ): Promise<AskAnswers> {\n return this.sessions.requestQuestion(question, onAnswer);\n }\n\n /**\n * Report that the user answered one question of the in-flight request and\n * another is coming — the ask bridge's timeout heartbeat.\n */\n noteAskProgress(): void {\n this.sessions.noteAskProgress();\n }\n\n /**\n * Resolve the in-flight wizard_ask request with the user's answers and\n * dismiss the overlay. Answers flow back to the agent as the tool result.\n */\n resolvePendingQuestion(answers: AskAnswers): void {\n this.sessions.resolvePendingQuestion(answers);\n }\n\n /**\n * Cancel the in-flight wizard_ask request — the bridge sends a sentinel\n * answer (\"__cancelled__\") so the skill can decide how to handle it.\n */\n cancelPendingQuestion(): void {\n this.sessions.cancelPendingQuestion();\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.router.popOverlay();\n this._write({ settingsOverrideKeys: null, settingsConflicts: null });\n this.router._setDirection('pop');\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(detail?: AuthErrorDetail): void {\n this.router.pushOverlay(Overlay.AuthError);\n this._write({ authErrorDetail: detail ?? null });\n }\n\n /** Push the session-timeout overlay (no dismiss — user must exit). */\n showSessionTimeout(): void {\n this.pushOverlay(Overlay.SessionTimeout);\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n this.sessions.addDiscoveredFeature(feature);\n }\n\n /** Capture the MCP step's outcome once; the screen reports it as the results show, before Enter. */\n reportMcpOutcome(\n outcome: McpOutcome,\n installedClients: string[] = [],\n featuresSelected?: 'all' | string[],\n ): void {\n if (this._mcpOutcomeReported) return;\n this._mcpOutcomeReported = true;\n const featuresPayload =\n outcome === McpOutcome.Installed && featuresSelected !== undefined\n ? { mcp_features_selected: featuresSelected }\n : {};\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...featuresPayload,\n ...sessionProperties(this.session),\n });\n }\n\n /** Complete the MCP step; its `mcp complete` capture goes through `reportMcpOutcome`, so once per store. */\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n featuresSelected?: 'all' | string[],\n loginCommands: string[] = [],\n ): void {\n this.reportMcpOutcome(outcome, installedClients, featuresSelected);\n this._write({\n mcpComplete: true,\n mcpOutcome: outcome,\n mcpLoginCommands: loginCommands,\n mcpInstalledClients: installedClients,\n });\n }\n\n setSkillsComplete(kept: boolean): void {\n analytics.wizardCapture('skills complete', {\n skills_kept: kept,\n ...sessionProperties(this.session),\n });\n this._write({ skillsComplete: true });\n }\n\n setMcpSuggestedPromptsDismissed(): void {\n this._write({ mcpSuggestedPromptsDismissed: true });\n }\n\n setSlackStepDismissed(): void {\n this._write({ slackStepDismissed: true });\n }\n\n setSlackConnected(connected: boolean): void {\n this._write({ slackConnected: connected });\n }\n\n setGithubConnected(connected: boolean): void {\n this._write({ githubConnected: connected });\n }\n\n /**\n * Self-driving GitHub gate declined. Carries the outro the user lands on,\n * since declining ends the flow before the agent runs and there is no abort\n * case to render one.\n */\n declineGithub(outroData: OutroData): void {\n this._write({ githubDeclined: true }, () =>\n this.sessions.update({ outroData }),\n );\n }\n\n /**\n * Self-driving integration-check answer. `true` → integrate the SDK as part\n * of this run; `false` → PostHog is already set up, go straight to\n * Self-driving. Resolves `store.integrate` from null.\n */\n setIntegrate(\n integrate: boolean,\n extra?: { via?: string; path?: string },\n ): void {\n analytics.wizardCapture('self-driving integration check', {\n self_driving_integrate: integrate,\n ...(extra?.via ? { self_driving_integrate_via: extra.via } : {}),\n ...(extra?.path ? { self_driving_integrate_path: extra.path } : {}),\n ...sessionProperties(this.session),\n });\n this._write({ integrate });\n }\n\n /**\n * Self-driving \"no PostHog account\" branch of the integration check. The\n * project has no SDK, so we always integrate (`integrate = true`); and since\n * the user has no account, we flip `signup` and record the `email` / `region`\n * collected on the screen so `authenticate` → `getOrAskForProjectData` takes\n * the provisioning path (create account + email a login link) instead of\n * OAuth. The \"yes, I have an account\" branch uses `setIntegrate(true)` and\n * leaves `signup` false so auth runs the normal OAuth login.\n */\n chooseProvisionAccount(email: string, region: CloudRegion): void {\n analytics.wizardCapture('self-driving integration check', {\n self_driving_integrate: true,\n self_driving_has_account: false,\n provision_region: region,\n ...sessionProperties(this.session),\n });\n this._write({ integrate: true }, () =>\n this.sessions.update({ signup: true, email, region }),\n );\n }\n\n /**\n * Self-driving handoff confirmed — the user acknowledged the post-integration\n * screen, so the Self-driving run can begin. Gate resolves via _checkGates().\n */\n confirmSelfDrivingHandoff(): void {\n this._write({ selfDrivingHandoffConfirmed: true });\n }\n\n /**\n * Mark a composed run step complete (e.g. self-driving's `integrate-run`).\n * Records the step id so its `isComplete` predicate holds, clears the task\n * list, and resets run phase to Idle so the next run step starts fresh.\n */\n completeRunStep(stepId: string): void {\n const done = this.completedRuns;\n this._write(\n { completedRuns: done.includes(stepId) ? done : [...done, stepId] },\n () => {\n this.sessions.setTasks([]);\n this.sessions.setRunPhase(RunPhase.Idle);\n },\n );\n }\n\n setOutroDismissed(dismissed = true): void {\n this._write({ outroDismissed: dismissed });\n }\n\n setOutroData(data: OutroData): void {\n this.sessions.setOutroData(data);\n }\n\n /** Show `data` on the outro screen: the error outro, with the run phase moved to Error. */\n showOutroError(data: OutroData): void {\n this.sessions.batch(() => {\n this.sessions.setOutroData(data);\n if (this.session.runPhase !== RunPhase.Error) {\n this.sessions.setRunPhase(RunPhase.Error);\n }\n });\n }\n\n setDashboardUrl(url: string): void {\n this.sessions.setDashboardUrl(url);\n }\n\n setNotebookUrl(url: string): void {\n this.sessions.setNotebookUrl(url);\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n this.sessions.setFrameworkContext(key, value);\n }\n\n switchProgram(program: ProgramId): void {\n if (program === this.router.activeProgram) return;\n\n // Flush unresolved promises so the wizard can advance\n for (const gate of this._gates.values()) gate.resolve();\n this._gates.clear();\n\n this.router.setProgram(program);\n this._initFromProgram(program);\n // start-tui stamps this once at launch; without it here every event\n // after the switch still reports under the program the run started as.\n analytics.setTag('program_id', program);\n\n this._write({ setupConfirmed: false, programLabel: program }, () =>\n this.sessions.update({\n skillId: findProgramConfig(program)?.skillId ?? null,\n }),\n );\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session and TUI state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n * Gate predicates are checked and resolved if ready.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._checkGates();\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── ScreenId transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /** The program the visible screen reports under; screens stamp this on their\n * own events rather than relying on the run-level `program_id` tag. */\n get analyticsProgramId(): ProgramId {\n return this.router.activeProgram;\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this);\n const prev = this._lastScreen;\n if (next !== prev) {\n // Every event carries the active TUI screen, filling the\n // \"URL / Screen\" column in PostHog.\n analytics.setTag('$screen_name', next);\n }\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n program_id: this.router.activeProgram,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n this.sessions.pushStatus(message);\n }\n\n get tokenHudVisible(): boolean {\n return this.$tokenHudVisible.get();\n }\n\n /** Hidden Ctrl+T shortcut — see ScreenContainer. Not registered as a\n * keyboard hint, so it never shows in the hints bar. */\n toggleTokenHud(): void {\n this.$tokenHudVisible.set(!this.$tokenHudVisible.get());\n this.emitChange();\n }\n\n /**\n * Accumulate one assistant turn's token usage into the running estimate.\n * Approximate by design (no dedup for SDK-retried/replayed turns, unlike\n * the benchmark middleware's TurnCounterPlugin) — it's a live indicator\n * for a hidden debug HUD, not a billing record, and `setFinalTokenCostUsd`\n * corrects the total once the run's authoritative cost is known.\n */\n addTokenUsage(delta: TokenUsageDelta): void {\n const next = addTokenUsage(this.$tokenUsage.get(), delta);\n if (next === this.$tokenUsage.get()) return;\n this.$tokenUsage.set(next);\n this.emitChange();\n }\n\n /** Reconcile the running cost estimate to the SDK's authoritative total\n * once the agent run completes — same trick the benchmark's\n * CostTrackerPlugin.onFinalize uses to correct any per-turn drift. */\n setFinalTokenCostUsd(costUsd: number): void {\n const cur = this.$tokenUsage.get();\n this.$tokenUsage.set({ ...cur, costUsd, costIsFinal: true });\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.sessions.setTasks(tasks);\n }\n\n updateTask(index: number, done: boolean): void {\n this.sessions.updateTask(index, done);\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.sessions.setEventPlan(events);\n }\n\n setHandoffText(text: string): void {\n this.sessions.setHandoffText(text);\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{\n id?: string;\n source?: string;\n content: string;\n status: string;\n activeForm?: string;\n }>,\n ): void {\n this.sessions.syncTodos(todos);\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n","/**\n * Terminal setup shared by the wizard TUI and the primitives playground.\n *\n * Both enter the alternate screen buffer and paint a black background so\n * Ink renders on a consistent dark canvas regardless of the user's terminal\n * theme (light mode profiles included).\n */\n\n// ANSI escape sequences\nconst RESET_ATTRS = '\\x1b[0m';\nconst CLEAR_SCREEN = '\\x1b[2J';\nconst CURSOR_HOME = '\\x1b[H';\nconst BG_BLACK = '\\x1b[48;2;0;0;0m';\nconst ENTER_ALT_SCREEN = '\\x1b[?1049h';\nconst LEAVE_ALT_SCREEN = '\\x1b[?1049l';\n\n/** Enter alt screen and paint a black background. */\nexport function enterDarkTerminal(): void {\n process.stdout.write(\n ENTER_ALT_SCREEN + BG_BLACK + CLEAR_SCREEN + CURSOR_HOME,\n );\n}\n\n/** Leave alt screen and reset attributes. */\nexport function releaseTerminal(): void {\n process.stdout.write(RESET_ATTRS + LEAVE_ALT_SCREEN);\n}\n"],"mappings":"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ACE,KAAK;GACL,QAAQ;GACR,aAAa;GACd;EACD;GACE,KAAK;GACL,QACE;GACF,aAAa;GACd;EACD;GACE,KAAK;GACL,QACE;GACF,aAAa;GACd;EACD;GACE,KAAK;GACL,QACE;GACF,aAAa;GACd;EACF;CACD,UAAU;EACR,SAAS;GACP;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACF;EACD,SAAS;GACP;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aACE;IACH;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACF;EACD,YAAY;GACV;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACF;EACD,WAAW;GACT;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACF;EACD,aAAa;GACX;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aAAa;IACd;GACF;EACD,MAAM;GACJ;IACE,KAAK;IACL,QAAQ;IACR,aACE;IACH;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QAAQ;IACR,aAAa;IACd;GACD;IACE,KAAK;IACL,QACE;IACF,aACE;IACH;GACF;EACF;CACD,qBAAqB;EACnB,SAAS;GACP,gBAAgB,EACd,eAAe;IACb,QACE;IACF,aAAa;IACd,EACF;GACD,QAAQ;IACN,YAAY;KACV,QACE;KACF,aACE;KACH;IACD,eAAe;KACb,QACE;KACF,aAAa;KACd;IACF;GACD,SAAS,EACP,YAAY;IACV,QAAQ;IACR,aACE;IACH,EACF;GACF;EACD,aAAa;GACX,gBAAgB,EACd,cAAc;IACZ,QACE;IACF,aACE;IACH,EACF;GACD,QAAQ;IACN,cAAc;KACZ,QACE;KACF,aACE;KACH;IACD,qBAAqB;KACnB,QACE;KACF,aACE;KACH;IACF;GACD,SAAS;IACP,cAAc;KACZ,QAAQ;KACR,aAAa;KACd;IACD,qBAAqB;KACnB,QACE;KACF,aAAa;KACd;IACF;GACF;EACD,MAAM,EACJ,SAAS,EACP,eAAe;GACb,QACE;GACF,aACE;GACH,EACF,EACF;EACF;CACD,eAAe;EACb,SAAS;GACP,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OACE;GACH;EACD,SAAS;GACP,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OAAO;GACR;EACD,YAAY;GACV,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OAAO;GACR;EACD,WAAW;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OAAO;GACR;EACD,aAAa;GACX,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OAAO;GACR;EACD,MAAM;GACJ,UAAU;GACV,SAAS;IACP;IACA;IACA;IACD;GACD,OAAO;GACR;EACF;CACD,iBAAiB;EACf,UAAU;EACV,SAAS;GACP;GACA;GACA;GACD;EACD,OAAO;EACR;CACD,eAAe;EACb,8BAA8B;GAC5B;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,gBAAgB;GACd;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,gBAAgB;GACd;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,mBAAmB;GACjB;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,sBAAsB;GACpB;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,0BAA0B;GACxB;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,oBAAoB;GAClB;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,iCAAiC;GAC/B;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,eAAe;GACb;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,oBAAoB;GAClB;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,kBAAkB;GAChB;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACF;CACD,eAAe;EACb,SAAS;GACP;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACF;EACD,SAAS;GACP;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,YAAY;GACV;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACF;EACD,WAAW;GACT;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACF;EACD,aAAa;GACX;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QACE;IACH;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACD,MAAM;GACJ;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACD;IACE,OAAO;IACP,QAAQ;IACT;GACF;EACF;CACD,kBAAkB;EAChB;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACF;CACD,mBAAmB;EACjB;GACE,OAAO;GACP,QACE;GACH;EACD;GACE,OAAO;GACP,QACE;GACH;EACD;GACE,OAAO;GACP,QAAQ;GACT;EACD;GACE,OAAO;GACP,QACE;GACH;EACF;CACD,iBAAiB;EACf,SAAS,CACP;GACE,SAAS;GACT,QACE;GACF,aACE;GACH,EACD;GACE,SAAS;GACT,QACE;GACF,aAAa;GACd,CACF;EACD,SAAS,CACP;GACE,SAAS;GACT,QACE;GACF,aACE;GACH,EACD;GACE,SAAS;GACT,QACE;GACF,aAAa;GACd,CACF;EACD,YAAY,CACV;GACE,SAAS;GACT,QACE;GACF,aAAa;GACd,EACD;GACE,SAAS;GACT,QACE;GACF,aACE;GACH,CACF;EACD,WAAW,CACT;GACE,SAAS;GACT,QACE;GACF,aAAa;GACd,EACD;GACE,SAAS;GACT,QAAQ;GACR,aAAa;GACd,CACF;EACD,aAAa,CACX;GACE,SAAS;GACT,QAAQ;GACR,aAAa;GACd,EACD;GACE,SAAS;GACT,QAAQ;GACR,aAAa;GACd,CACF;EACD,MAAM,CACJ;GACE,SAAS;GACT,QACE;GACF,aACE;GACH,EACD;GACE,SAAS;GACT,QAAQ;GACR,aACE;GACH,CACF;EACF;CACD,kBAAkB,CAChB;EACE,SAAS;EACT,QACE;EACF,aAAa;EACd,EACD;EACE,SAAS;EACT,QAAQ;EACR,aAAa;EACd,CACF;CACD,mBACE;CACF,iBAAiB;EACf,QAAQ;GACN,OAAO;GACP,QACE;GACH;EACD,OAAO;GACL,OAAO;GACP,QACE;GACH;EACD,WAAW;GACT,OAAO;GACP,QACE;GACH;EACF;CACD,oBACE;CACF,iBAAiB,CACf;EACE,KAAK;EACL,QAAQ;EACR,aACE;EACH,EACD;EACE,KAAK;EACL,QACE;EACF,aACE;EACH,CACF;CACD,oBACE;CACF,qBAAqB;EACnB,eAAe;GACb,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,eAAe;GACb,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,SAAS;GACP,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,cAAc;GACZ,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,aAAa;GACX,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,cAAc;GACZ,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACD,eAAe;GACb,SAAS;GACT,OAAO;GACP,QACE;GACF,aAAa;GACd;EACF;CACD,oBACE;CACF,m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"}