@posthog/wizard 2.79.1 → 2.80.1

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 (227) hide show
  1. package/README.md +187 -57
  2. package/dist/{PickerMenu-dG5DQCZA.js → PickerMenu-BGGeYqd-.js} +112 -12
  3. package/dist/PickerMenu-BGGeYqd-.js.map +1 -0
  4. package/dist/README.md +9 -6
  5. package/dist/{agent-interface-FkbaBJwz.js → agent-interface-CemBvTAA.js} +130 -324
  6. package/dist/agent-interface-CemBvTAA.js.map +1 -0
  7. package/dist/{agent-prompt-loader-D0weQ-7k.js → agent-prompt-loader-DPnj6SwU.js} +6 -5
  8. package/dist/agent-prompt-loader-DPnj6SwU.js.map +1 -0
  9. package/dist/analytics-B3ROGuIr.js +2 -0
  10. package/dist/analytics-D21z3E5l.js +732 -0
  11. package/dist/analytics-D21z3E5l.js.map +1 -0
  12. package/dist/{api-CrbCIQOz.js → api-DtGIqQ2U.js} +2 -3
  13. package/dist/api-DtGIqQ2U.js.map +1 -0
  14. package/dist/api-IhROOQNv.js +2 -0
  15. package/dist/api-key-login-OEntFvu5.js +2 -0
  16. package/dist/api-key-login-h3E2G3zu.js +55 -0
  17. package/dist/api-key-login-h3E2G3zu.js.map +1 -0
  18. package/dist/bin.js +2 -2
  19. package/dist/bin.js.map +1 -1
  20. package/dist/{bounded-fs-vAq-T-K7.js → bounded-fs-CAsuF6al.js} +3 -3
  21. package/dist/{bounded-fs-vAq-T-K7.js.map → bounded-fs-CAsuF6al.js.map} +1 -1
  22. package/dist/{ci-install-COcV8SY2.js → ci-install-CEYE02t-.js} +22 -26
  23. package/dist/ci-install-CEYE02t-.js.map +1 -0
  24. package/dist/console-log-O828zyiq.js +32 -0
  25. package/dist/console-log-O828zyiq.js.map +1 -0
  26. package/dist/{debug-kAHwWGg7.js → debug-BfQPD2Hg.js} +18 -52
  27. package/dist/debug-BfQPD2Hg.js.map +1 -0
  28. package/dist/{defaults-a9TelDhJ.js → defaults-DDVl3tKN.js} +2 -51
  29. package/dist/defaults-DDVl3tKN.js.map +1 -0
  30. package/dist/{emit-BSetXzDV.js → emit-RfAewcWv.js} +1 -1
  31. package/dist/{emit-BSetXzDV.js.map → emit-RfAewcWv.js.map} +1 -1
  32. package/dist/{errors-C2domSkK.js → errors-CHrJzAZb.js} +4 -4
  33. package/dist/{errors-C2domSkK.js.map → errors-CHrJzAZb.js.map} +1 -1
  34. package/dist/family-picker-BKs-tTyu.js +46 -0
  35. package/dist/family-picker-BKs-tTyu.js.map +1 -0
  36. package/dist/{gateway-C9-GlLO9.js → gateway-D3gIlR6b.js} +122 -11
  37. package/dist/gateway-D3gIlR6b.js.map +1 -0
  38. package/dist/headless-BJjhP0SI.js +10 -0
  39. package/dist/headless-BJjhP0SI.js.map +1 -0
  40. package/dist/headless-DIX68UUA.js +3 -0
  41. package/dist/host-resolution-D8GhEVoX.js +114 -0
  42. package/dist/host-resolution-D8GhEVoX.js.map +1 -0
  43. package/dist/install-Bw8tvDvS.js +2 -0
  44. package/dist/{add-mcp-server-to-clients-DIaTRWMY.js → install-paPCzPHI.js} +34 -100
  45. package/dist/install-paPCzPHI.js.map +1 -0
  46. package/dist/interactive-tdxZKWax.js +11 -0
  47. package/dist/interactive-tdxZKWax.js.map +1 -0
  48. package/dist/{telemetry-B7zJdRmA.js → links-Cyj6v8kg.js} +4 -13
  49. package/dist/links-Cyj6v8kg.js.map +1 -0
  50. package/dist/{main-CgKxbwMP.js → main-0p-YxUNa.js} +233 -490
  51. package/dist/main-0p-YxUNa.js.map +1 -0
  52. package/dist/{mcp-DnAyW0-w.js → mcp-D3Z5MXhA.js} +3 -4
  53. package/dist/{mcp-DnAyW0-w.js.map → mcp-D3Z5MXhA.js.map} +1 -1
  54. package/dist/mcp-install-smoke-test.ts +2 -2
  55. package/dist/{mcp-prompt-streaming-DDWQ-FCA.js → mcp-prompt-streaming-COVbWnHt.js} +12 -12
  56. package/dist/mcp-prompt-streaming-COVbWnHt.js.map +1 -0
  57. package/dist/mode-label-DB3ol_sj.js +9 -0
  58. package/dist/mode-label-DB3ol_sj.js.map +1 -0
  59. package/dist/{models-WcwUnSKb.js → models-D1SnCzvl.js} +2 -2
  60. package/dist/{models-WcwUnSKb.js.map → models-D1SnCzvl.js.map} +1 -1
  61. package/dist/non-interactive-DxRBc73O.js +18 -0
  62. package/dist/non-interactive-DxRBc73O.js.map +1 -0
  63. package/dist/{oauth-session-DYM2Hrl2.js → oauth-session-Dde79Ycm.js} +3 -3
  64. package/dist/{oauth-session-DYM2Hrl2.js.map → oauth-session-Dde79Ycm.js.map} +1 -1
  65. package/dist/{orchestrator-tools-DbgNBFGA.js → orchestrator-tools-BSNhzzkT.js} +3 -3
  66. package/dist/{orchestrator-tools-DbgNBFGA.js.map → orchestrator-tools-BSNhzzkT.js.map} +1 -1
  67. package/dist/{package-json-Atg34fa4.js → package-json-2UrhE6kP.js} +1 -1
  68. package/dist/{package-json-Atg34fa4.js.map → package-json-2UrhE6kP.js.map} +1 -1
  69. package/dist/package-json-Dblip2_X.js +2 -0
  70. package/dist/package-manager-BRXlXo0p.js +105 -0
  71. package/dist/package-manager-BRXlXo0p.js.map +1 -0
  72. package/dist/{pi-8KsYsPmM.js → pi-cM_4Gd_9.js} +19 -20
  73. package/dist/pi-cM_4Gd_9.js.map +1 -0
  74. package/dist/playground-DTKy0XHT.js +12 -0
  75. package/dist/playground-DTKy0XHT.js.map +1 -0
  76. package/dist/posthog-integration-bwHwE87a.js +10291 -0
  77. package/dist/posthog-integration-bwHwE87a.js.map +1 -0
  78. package/dist/programs-BhtyA3lE.js +3 -0
  79. package/dist/programs-SeT1qNik.js +5348 -0
  80. package/dist/programs-SeT1qNik.js.map +1 -0
  81. package/dist/provisioning-BcXfeCMc.js +2 -0
  82. package/dist/{provisioning-Bo2NRxFz.js → provisioning-JbJtq7hq.js} +5 -67
  83. package/dist/provisioning-JbJtq7hq.js.map +1 -0
  84. package/dist/{queue-tools-C8mXOh7e.js → queue-tools-BIZSJyt6.js} +7 -9
  85. package/dist/queue-tools-BIZSJyt6.js.map +1 -0
  86. package/dist/results-DtKICAdz.js +55 -0
  87. package/dist/results-DtKICAdz.js.map +1 -0
  88. package/dist/run-CDurA5tO.js +248 -0
  89. package/dist/run-CDurA5tO.js.map +1 -0
  90. package/dist/run-DDCvLILJ.js +246 -0
  91. package/dist/run-DDCvLILJ.js.map +1 -0
  92. package/dist/run-tool-CTq9OOdT.js +2 -0
  93. package/dist/run-tool-DML8JJvt.js +2420 -0
  94. package/dist/run-tool-DML8JJvt.js.map +1 -0
  95. package/dist/runners-Dhu4pZTN.js +253 -0
  96. package/dist/runners-Dhu4pZTN.js.map +1 -0
  97. package/dist/{security-C71pkwqH.js → security-DEH8Rn0_.js} +5 -5
  98. package/dist/security-DEH8Rn0_.js.map +1 -0
  99. package/dist/setup-utils-C5-WM-hS.js +118 -0
  100. package/dist/setup-utils-C5-WM-hS.js.map +1 -0
  101. package/dist/smoke-test.sh +1 -1
  102. package/dist/{playground-BlYRBMj7.js → start-playground-DL4mVEUx.js} +63 -54
  103. package/dist/start-playground-DL4mVEUx.js.map +1 -0
  104. package/dist/{subagent-D1TrTchE.js → subagent-CnFvAq6E.js} +3 -3
  105. package/dist/{subagent-D1TrTchE.js.map → subagent-CnFvAq6E.js.map} +1 -1
  106. package/dist/{task-DqRlQBfs.js → task-BOScSm4W.js} +17 -18
  107. package/dist/task-BOScSm4W.js.map +1 -0
  108. package/dist/{tasks-ChWufsdO.js → tasks-BfJhVky2.js} +1 -1
  109. package/dist/tasks-BfJhVky2.js.map +1 -0
  110. package/dist/telemetry-CP4rGicd.js +13 -0
  111. package/dist/telemetry-CP4rGicd.js.map +1 -0
  112. package/dist/terminal-J3OD3dN0.js +16162 -0
  113. package/dist/terminal-J3OD3dN0.js.map +1 -0
  114. package/dist/tools-CCMV3DmB.js +544 -0
  115. package/dist/tools-CCMV3DmB.js.map +1 -0
  116. package/dist/{tools-CkJ2y9Wt.js → tools-Cz8tDptL.js} +9 -9
  117. package/dist/tools-Cz8tDptL.js.map +1 -0
  118. package/dist/tui-BUZ2PWqN.js +2 -0
  119. package/dist/tui-Csf7VJxt.js +25 -0
  120. package/dist/tui-Csf7VJxt.js.map +1 -0
  121. package/dist/{steps-BPcg3_3Q.js → upload-step-CEacB2RV.js} +17 -19
  122. package/dist/upload-step-CEacB2RV.js.map +1 -0
  123. package/dist/urls-BDELGZHq.js +67 -0
  124. package/dist/urls-BDELGZHq.js.map +1 -0
  125. package/dist/warlock-smoke-test.ts +1 -2
  126. package/dist/{wizard-abort-BPdv07np.js → wizard-abort-D3-75KyV.js} +41 -32
  127. package/dist/wizard-abort-D3-75KyV.js.map +1 -0
  128. package/dist/yara-hooks-CZ1tKxy_.js +2 -0
  129. package/dist/{yara-hooks-BnxejtXK.js → yara-hooks-D8YDyX7o.js} +283 -21
  130. package/dist/yara-hooks-D8YDyX7o.js.map +1 -0
  131. package/package.json +7 -8
  132. package/dist/PickerMenu-dG5DQCZA.js.map +0 -1
  133. package/dist/add-mcp-server-to-clients-DIaTRWMY.js.map +0 -1
  134. package/dist/add-mcp-server-to-clients-artmN7mz.js +0 -2
  135. package/dist/agent-BEjARD2a.js +0 -6
  136. package/dist/agent-BWFhuLgo.js +0 -3178
  137. package/dist/agent-BWFhuLgo.js.map +0 -1
  138. package/dist/agent-interface-FkbaBJwz.js.map +0 -1
  139. package/dist/agent-prompt-loader-D0weQ-7k.js.map +0 -1
  140. package/dist/analytics-DFtbRjYh.js +0 -2
  141. package/dist/analytics-DXK1gc12.js +0 -301
  142. package/dist/analytics-DXK1gc12.js.map +0 -1
  143. package/dist/api-Cm9UtKZh.js +0 -2
  144. package/dist/api-CrbCIQOz.js.map +0 -1
  145. package/dist/check-screens.tsx +0 -190
  146. package/dist/ci-install-COcV8SY2.js.map +0 -1
  147. package/dist/constants-DHCBSfnx.js +0 -260
  148. package/dist/constants-DHCBSfnx.js.map +0 -1
  149. package/dist/debug-BuYHGr6_.js +0 -2
  150. package/dist/debug-kAHwWGg7.js.map +0 -1
  151. package/dist/defaults-a9TelDhJ.js.map +0 -1
  152. package/dist/endpoints-BVMYm9F4.js +0 -108
  153. package/dist/endpoints-BVMYm9F4.js.map +0 -1
  154. package/dist/env-api-key-BP-NFFXt.js +0 -17
  155. package/dist/env-api-key-BP-NFFXt.js.map +0 -1
  156. package/dist/env-api-key-CaWEDj_9.js +0 -2
  157. package/dist/environment-BATlQxcQ.js +0 -39
  158. package/dist/environment-BATlQxcQ.js.map +0 -1
  159. package/dist/environment-CwD8OPYj.js +0 -2
  160. package/dist/file-C5JMsyR1.js +0 -2
  161. package/dist/file-DcRKycV8.js +0 -60
  162. package/dist/file-DcRKycV8.js.map +0 -1
  163. package/dist/file-watcher-Brq2nnHV.js +0 -123
  164. package/dist/file-watcher-Brq2nnHV.js.map +0 -1
  165. package/dist/gateway-C9-GlLO9.js.map +0 -1
  166. package/dist/headless-ui-CqI2gXlD.js +0 -44
  167. package/dist/headless-ui-CqI2gXlD.js.map +0 -1
  168. package/dist/interactive-B_Ti_CsS.js +0 -11
  169. package/dist/interactive-B_Ti_CsS.js.map +0 -1
  170. package/dist/local-dev-McsurOC-.js +0 -135
  171. package/dist/local-dev-McsurOC-.js.map +0 -1
  172. package/dist/logging-ui-Dza4D0MK.js +0 -226
  173. package/dist/logging-ui-Dza4D0MK.js.map +0 -1
  174. package/dist/main-CgKxbwMP.js.map +0 -1
  175. package/dist/mcp-prompt-streaming-DDWQ-FCA.js.map +0 -1
  176. package/dist/mint-failure-u8xQKNOn.js +0 -6392
  177. package/dist/mint-failure-u8xQKNOn.js.map +0 -1
  178. package/dist/non-interactive-DyVC1AGc.js +0 -18
  179. package/dist/non-interactive-DyVC1AGc.js.map +0 -1
  180. package/dist/package-json-D8Ga03tK.js +0 -2
  181. package/dist/pi-8KsYsPmM.js.map +0 -1
  182. package/dist/playground-BlYRBMj7.js.map +0 -1
  183. package/dist/posthog-Bt0Aplb8.js +0 -124
  184. package/dist/posthog-Bt0Aplb8.js.map +0 -1
  185. package/dist/posthog-CUgCEhH0.js +0 -2
  186. package/dist/provisioning-Bo2NRxFz.js.map +0 -1
  187. package/dist/provisioning-OGFGlzf7.js +0 -2
  188. package/dist/queue-tools-C8mXOh7e.js.map +0 -1
  189. package/dist/registry-C06e_x-p.js +0 -2
  190. package/dist/registry-CD5RQt38.js +0 -3464
  191. package/dist/registry-CD5RQt38.js.map +0 -1
  192. package/dist/run-agent-legacy-ChacZImU.js +0 -2
  193. package/dist/run-agent-legacy-DOlM6DQu.js +0 -3540
  194. package/dist/run-agent-legacy-DOlM6DQu.js.map +0 -1
  195. package/dist/runners-ov3EXF1n.js +0 -834
  196. package/dist/runners-ov3EXF1n.js.map +0 -1
  197. package/dist/security-C71pkwqH.js.map +0 -1
  198. package/dist/setup-utils-B26Lf2yF.js +0 -1512
  199. package/dist/setup-utils-B26Lf2yF.js.map +0 -1
  200. package/dist/setup-utils-CVS86NYR.js +0 -2
  201. package/dist/start-tui-Bo2L0bar.js +0 -6962
  202. package/dist/start-tui-Bo2L0bar.js.map +0 -1
  203. package/dist/steps-BPcg3_3Q.js.map +0 -1
  204. package/dist/store-BTzcvRGT.js +0 -992
  205. package/dist/store-BTzcvRGT.js.map +0 -1
  206. package/dist/store-BpqySPXm.js +0 -5
  207. package/dist/task-DqRlQBfs.js.map +0 -1
  208. package/dist/task-stream-Bw6JaLCX.js +0 -363
  209. package/dist/task-stream-Bw6JaLCX.js.map +0 -1
  210. package/dist/tasks-ChWufsdO.js.map +0 -1
  211. package/dist/telemetry-B7zJdRmA.js.map +0 -1
  212. package/dist/terminal-zgkEfoCL.js +0 -7196
  213. package/dist/terminal-zgkEfoCL.js.map +0 -1
  214. package/dist/tools-CkJ2y9Wt.js.map +0 -1
  215. package/dist/ui-Q6-RvERF.js +0 -15
  216. package/dist/ui-Q6-RvERF.js.map +0 -1
  217. package/dist/version-CHhJjz_H.js +0 -6
  218. package/dist/version-CHhJjz_H.js.map +0 -1
  219. package/dist/wizard-abort-BPdv07np.js.map +0 -1
  220. package/dist/wizard-abort-Br1qMDNa.js +0 -3
  221. package/dist/wizard-session-2w4Ru-Wz.js +0 -131
  222. package/dist/wizard-session-2w4Ru-Wz.js.map +0 -1
  223. package/dist/wizard-session-DGaUHOF3.js +0 -2
  224. package/dist/wizard-ui-DVqrYaOM.js +0 -16
  225. package/dist/wizard-ui-DVqrYaOM.js.map +0 -1
  226. package/dist/yara-hooks-BnxejtXK.js.map +0 -1
  227. package/dist/yara-hooks-DSuExwb4.js +0 -2
@@ -1 +0,0 @@
1
- {"version":3,"file":"runners-ov3EXF1n.js","names":["isUUID","validVersion"],"sources":["../src/lib/runners/resolve-no-telemetry.ts","../src/programs/task-stream/wizard-run-sync.ts","../src/lib/runners/run-wizard.ts","../src/programs/detect-map.ts","../src/lib/runners/run-non-interactive.ts","../src/lib/runners/run-wizard-ci.ts","../src/lib/runners/run-wizard-headless.ts"],"sourcesContent":["/**\n * `--no-telemetry` flips `telemetry: false` via yargs negation;\n * `POSTHOG_WIZARD_NO_TELEMETRY` is honoured separately so the env-var\n * form documented in the README keeps working.\n */\nexport function resolveNoTelemetry(options: Record<string, unknown>): boolean {\n if (options.telemetry === false) return true;\n const env = process.env.POSTHOG_WIZARD_NO_TELEMETRY;\n if (env == null || env === '') return false;\n const norm = env.toLowerCase();\n return norm !== '0' && norm !== 'false';\n}\n","import { randomUUID } from 'node:crypto';\nimport { basename, resolve } from 'node:path';\nimport { validate as isUUID } from 'uuid';\nimport { valid as validVersion } from 'semver';\nimport { VERSION } from '@shared/version';\nimport {\n RunPhase,\n type Credentials,\n type WizardSession,\n} from '@lib/wizard-session';\nimport { currentCredentials } from '@shared/oauth-session';\nimport { isGrantRevoked } from '@shared/auth-session-state';\nimport { logToFile } from '@utils/debug';\nimport { parseRetryAfter } from './destinations/posthog';\n\nexport type RunOutcome = 'completed' | 'failed' | 'cancelled';\ntype RunTask = {\n name: string;\n status: 'created' | 'running' | 'completed' | 'failed';\n};\n// The task fields a snapshot reads, local so task-stream stays off the TUI store.\ntype TaskItem = {\n id?: string;\n source?: string;\n sourceStatus?: string;\n label: string;\n status: string;\n};\ntype Options = {\n mode: 'local' | 'cloud';\n programId: string;\n assignedId?: string;\n getSession: () => WizardSession;\n fetchImpl?: typeof fetch;\n onError?: (message: string) => void;\n};\n\nconst STATUS: Record<string, RunTask['status']> = {\n pending: 'created',\n in_progress: 'running',\n completed: 'completed',\n failed: 'failed',\n skipped: 'completed',\n};\n\nexport class RunTaskNames {\n private names = new Map<string, string>();\n private used = new Set<string>();\n\n snapshot(items: readonly TaskItem[]): RunTask[] {\n if (items.length > 100) throw new Error('task limit exceeded (100)');\n const occurrences = new Map<string, number>();\n const ids = new Set<string>();\n return items.map((item) => {\n const subject = item.label.trim();\n if (!subject) throw new Error('blank task name');\n const rawStatus = item.sourceStatus ?? item.status;\n const status = STATUS[rawStatus];\n if (!Object.hasOwn(STATUS, rawStatus))\n throw new Error('invalid task status');\n const occurrence = (occurrences.get(subject) ?? 0) + 1;\n occurrences.set(subject, occurrence);\n const id = item.id\n ? JSON.stringify([item.source, item.id])\n : JSON.stringify([subject, occurrence]);\n if (ids.has(id)) throw new Error('duplicate task identity');\n ids.add(id);\n let name = this.names.get(id);\n if (!name) {\n name = subject.slice(0, 255);\n for (let n = 2; this.used.has(name); n++) {\n const suffix = ` (${n})`;\n name = subject.slice(0, 255 - suffix.length) + suffix;\n }\n this.names.set(id, name);\n this.used.add(name);\n }\n return { name, status };\n });\n }\n}\n\nexport function createWizardRunSync(\n options: Omit<Options, 'mode'> & {\n mode: 'local' | 'headless' | 'ci';\n noTelemetry: boolean;\n },\n): WizardRunSync | undefined {\n if (options.noTelemetry || options.mode === 'ci') return;\n if (options.mode === 'headless' && options.assignedId === undefined) return;\n return new WizardRunSync({\n ...options,\n mode: options.assignedId !== undefined ? 'cloud' : 'local',\n });\n}\n\nexport class WizardRunSync {\n private readonly names = new RunTaskNames();\n private readonly tasksAbort = new AbortController();\n private readonly reported = new Set<string>();\n private context?: {\n apiHost: string;\n projectId: number;\n programId: string;\n mode: Options['mode'];\n id?: string;\n };\n private queue: Promise<void> = Promise.resolve();\n private lastBody?: string;\n private stopped = false;\n private tasksDisabled = false;\n private authDisabled = false;\n private closing?: Promise<void>;\n\n constructor(private readonly options: Options) {}\n\n capture(items: readonly TaskItem[] | undefined): void {\n if (this.stopped || this.tasksDisabled || !items) return;\n if (\n this.options.mode === 'cloud' &&\n !isUUID(this.options.assignedId ?? '')\n ) {\n this.tasksDisabled = true;\n this.report('invalid cloud run assignment');\n return;\n }\n const session = this.options.getSession();\n if (session.runPhase === RunPhase.Idle) return;\n if (!this.context) {\n if (session.runPhase !== RunPhase.Running || !session.credentials) return;\n const { host, projectId } = session.credentials;\n this.context = {\n apiHost: host.appHost.replace(/\\/$/, ''),\n projectId,\n programId: this.options.programId,\n mode: this.options.mode,\n id: this.options.assignedId,\n };\n this.queue = this.initialize(session);\n }\n try {\n const body = JSON.stringify({ tasks: this.names.snapshot(items) });\n if (body === this.lastBody) return;\n this.lastBody = body;\n this.queue = this.queue.then(async () => {\n if (\n this.tasksDisabled ||\n this.tasksAbort.signal.aborted ||\n !this.context?.id\n )\n return;\n const ok = await this.request(\n 'PUT',\n `${this.context.id}/tasks/`,\n body,\n this.tasksAbort.signal,\n );\n if (!ok) this.tasksDisabled = true;\n });\n } catch {\n this.report(\n 'invalid task snapshot (names, statuses, identities or 100-task limit)',\n );\n }\n }\n\n shutdown(outcome: RunOutcome, timeoutMs: number): Promise<void> {\n if (this.closing) return this.closing;\n this.stopped = true;\n this.closing = this.finish(outcome, Math.max(0, timeoutMs));\n return this.closing;\n }\n\n private async initialize(session: WizardSession): Promise<void> {\n const context = this.context;\n if (!context || context.mode === 'cloud') return;\n const projectName = basename(resolve(session.installDir))\n .trim()\n .slice(0, 255);\n if (!projectName) {\n this.tasksDisabled = true;\n this.report('unsupported program or workspace configuration');\n return;\n }\n const body = JSON.stringify({\n program_id: context.programId,\n environment: 'local',\n workspace: { type: 'local_folder', project_name: projectName },\n ...(validVersion(VERSION) ? { wizard_version: VERSION } : {}),\n idempotency_key: randomUUID(),\n });\n // POST retries remain disabled until deployed local idempotency is verified.\n const result = await this.request('POST', '', body, this.tasksAbort.signal);\n if (\n result &&\n typeof result === 'object' &&\n 'id' in result &&\n typeof result.id === 'string' &&\n isUUID(result.id)\n ) {\n context.id = result.id;\n } else {\n this.tasksDisabled = true;\n this.report(\n 'local creation failed or returned an invalid ID; creation was not retried',\n );\n }\n }\n\n private credentials(\n creds = this.options.getSession().credentials,\n ): Credentials | undefined {\n const context = this.context;\n if (!context) return;\n if (\n !creds ||\n creds.host.appHost.replace(/\\/$/, '') !== context.apiHost ||\n creds.projectId !== context.projectId\n ) {\n this.report('execution credentials changed host or project');\n return;\n }\n if (\n creds.missingScopes?.includes('wizard_run:write') ||\n !creds.accessToken.startsWith('pha_')\n ) {\n this.authDisabled = true;\n this.report('wizard_run:write OAuth grant required; authorize again');\n return;\n }\n return creds;\n }\n\n private async request(\n method: 'POST' | 'PUT' | 'PATCH',\n suffix: string,\n body: string,\n signal: AbortSignal,\n ): Promise<unknown> {\n const context = this.context;\n if (!context || this.authDisabled || signal.aborted) return;\n let refreshed = false;\n let rateLimited = false;\n const attempts = method === 'POST' ? 1 : 3;\n for (let attempt = 0; attempt < attempts && !signal.aborted; attempt++) {\n let retryMs = 500 * 2 ** attempt;\n try {\n const creds = this.credentials();\n if (!creds) return;\n const response = await this.bounded(\n async (requestSignal) => {\n // The run's OAuth session owns refresh, so the agent reads the same rotated token.\n const current = this.credentials(await currentCredentials(creds));\n if (!current) throw new Error('credentials unavailable');\n const res = await (this.options.fetchImpl ?? fetch)(\n `${context.apiHost}/api/projects/${context.projectId}/wizard/runs/${suffix}`,\n {\n method,\n body,\n signal: requestSignal,\n headers: {\n Authorization: `Bearer ${current.accessToken}`,\n 'Content-Type': 'application/json',\n },\n },\n );\n const data: unknown =\n method === 'POST' && (res.status === 200 || res.status === 201)\n ? await res.json()\n : undefined;\n return { res, data, current };\n },\n signal,\n 5000,\n );\n const { res, data, current } = response;\n if (\n (method === 'POST' && [200, 201].includes(res.status)) ||\n (method === 'PUT' && res.status === 204) ||\n (method === 'PATCH' && res.status === 200)\n )\n return data ?? true;\n if (\n res.status === 401 &&\n current.refreshToken &&\n !isGrantRevoked() &&\n !refreshed &&\n method !== 'POST'\n ) {\n refreshed = true;\n const rotated = await this.bounded(\n () => currentCredentials(current, true),\n signal,\n 5000,\n );\n if (rotated.accessToken === current.accessToken) {\n this.authDisabled = true;\n this.report(\n 'OAuth refresh could not recover the grant; authorize again',\n );\n return;\n }\n continue;\n }\n if (res.status === 401 || res.status === 403) this.authDisabled = true;\n if (res.status === 429 && !rateLimited) {\n rateLimited = true;\n retryMs = parseRetryAfter(res.headers.get('Retry-After'));\n } else if (res.status < 500 || res.status >= 600) {\n this.report(\n `${method} rejected (${res.status}); check assignment, grant and program configuration`,\n );\n return;\n }\n } catch {\n if (signal.aborted) return;\n }\n if (attempt + 1 < attempts) {\n try {\n await this.sleep(retryMs, signal);\n } catch {\n return;\n }\n }\n }\n this.report(`${method} delivery exhausted`);\n }\n\n private async finish(outcome: RunOutcome, timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n try {\n await this.bounded(\n () => this.queue,\n new AbortController().signal,\n Math.floor(timeoutMs * 0.75),\n );\n } catch {\n this.report('task drain timed out');\n }\n this.tasksAbort.abort();\n if (this.context?.mode !== 'local' || !this.context.id || this.authDisabled)\n return;\n if (Date.now() >= deadline) {\n this.report('terminal update budget exhausted');\n return;\n }\n const finalAbort = new AbortController();\n const timer = setTimeout(\n () => finalAbort.abort(),\n Math.max(0, deadline - Date.now()),\n );\n try {\n await this.request(\n 'PATCH',\n `${this.context.id}/`,\n JSON.stringify({ status: outcome }),\n finalAbort.signal,\n );\n } finally {\n clearTimeout(timer);\n finalAbort.abort();\n }\n }\n\n private async bounded<T>(\n operation: (signal: AbortSignal) => Promise<T>,\n parent: AbortSignal,\n ms: number,\n ): Promise<T> {\n const controller = new AbortController();\n const abort = () => controller.abort();\n parent.addEventListener('abort', abort, { once: true });\n if (parent.aborted) controller.abort();\n const timer = setTimeout(abort, ms);\n let onAbort: () => void = () => undefined;\n const cancelled = new Promise<never>((_, reject) => {\n onAbort = () => reject(new Error('request cancelled'));\n controller.signal.addEventListener('abort', onAbort, { once: true });\n if (controller.signal.aborted) onAbort();\n });\n try {\n return await Promise.race([operation(controller.signal), cancelled]);\n } finally {\n clearTimeout(timer);\n parent.removeEventListener('abort', abort);\n controller.signal.removeEventListener('abort', onAbort);\n controller.abort();\n }\n }\n\n private sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const finish = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', finish);\n resolve();\n };\n const timer = setTimeout(finish, ms);\n signal.addEventListener('abort', finish, { once: true });\n if (signal.aborted) finish();\n });\n }\n\n private report(message: string): void {\n if (this.reported.has(message)) return;\n this.reported.add(message);\n (this.options.onError ?? ((m) => logToFile(`[wizard-run-sync] ${m}`)))(\n message,\n );\n }\n}\n","import { VERSION } from '@shared/version';\nimport { logToFile, getLogFilePath } from '@utils/debug';\nimport { runProgramAgent } from '@programs/run-agent-legacy';\nimport { authenticate } from '@programs/authenticate';\nimport { getProgramConfig } from '@programs';\nimport { getAuditChecks } from '@programs/audit/types';\nimport { maybeStampAiSdkDetected } from '@programs/posthog-integration/detect';\nimport type { ProgramConfig } from '@programs/types';\nimport type { Harness, Sequence } from '@shared/constants';\nimport type { startTUI as StartTUIFn } from '@ui/tui/start-tui';\nimport type { WizardStore } from '@ui/tui/store';\nimport { OutroKind, type WizardSession } from '@lib/wizard-session';\nimport type { TaskStreamPush as TaskStreamPushClass } from '@programs/task-stream/task-stream-push';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport { checkLocalServices, getLocalDev } from '@shared/local-dev';\nimport { createWizardRunSync } from '@programs/task-stream/wizard-run-sync';\nimport { runtimeEnv } from '@env';\nimport { runCleanups, registerShutdown } from '@utils/wizard-abort';\nimport { classifyRunFailure, emitWizardError } from '@shared/errors';\nimport { isRunFailure } from '@ui/mint-failure';\nimport { getUI } from '@ui';\nimport { analytics } from '@utils/analytics';\nimport { join } from 'node:path';\n\nconst WIZARD_VERSION = VERSION;\n\ntype Step = ProgramConfig['steps'][number];\n\n/** The session a run step's agent runs in: scoped to the step's target dir\n * (e.g. a monorepo sub-app) with its own framework context, after any prep.\n * A step without `targetDir` runs in the live session, unchanged.\n * The frameworkContext copy is shallow and unfiltered — name keys per owning program. */\nasync function prepareRunSession(\n step: Step,\n live: WizardSession,\n): Promise<WizardSession> {\n const session = step.targetDir\n ? {\n ...live,\n installDir: step.targetDir(live),\n frameworkContext: { ...live.frameworkContext },\n }\n : live;\n if (step.onRunPrep) await step.onRunPrep(session);\n return session;\n}\n\n/** Advance one step of a composed run to completion: the auth screen\n * authenticates (every later run reuses it); a step carrying its own `run`\n * thunk runs that agent in its dir and is recorded in `completedRuns`; the\n * host program's own run screen runs `config.run`; any other screen waits for\n * the user to satisfy `isComplete`. */\nasync function advanceStep(\n step: Step,\n store: WizardStore,\n config: ProgramConfig,\n): Promise<void> {\n if (step.screenId === 'auth') {\n await authenticate(store.session, config.id);\n maybeStampAiSdkDetected(store.session);\n } else if (step.run) {\n await step.run(await prepareRunSession(step, store.session));\n store.completeRunStep(step.id);\n } else if (step.screenId === 'run') {\n await runProgramAgent(config, await prepareRunSession(step, store.session));\n } else if (step.isComplete) {\n await store.waitUntil(step.isComplete);\n }\n}\n\n/**\n * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,\n * build session, run detection, wait for intro gate, execute the\n * agent pipeline, wait for outro dismissal, then exit.\n */\nexport function runWizard(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n let tui: ReturnType<typeof StartTUIFn> | null = null;\n let taskStream: TaskStreamPushClass | null = null;\n let onSignal: (() => void) | null = null;\n let exitInProgress = false;\n let signalled = false;\n let unregisterShutdown: (() => void) | undefined;\n\n void (async () => {\n try {\n const installDir = (options.installDir as string) || process.cwd();\n\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession, RunPhase } = await import('@lib/wizard-session');\n const { TaskStreamPush } = await import('@programs/task-stream/index');\n const { PostHogDestination } = await import(\n '@programs/task-stream/destinations/posthog'\n );\n const { createFileDestination } = await import(\n '@programs/task-stream/destinations/file'\n );\n\n // Before the TUI mounts: once Ink owns the alt screen, anything written\n // to it is wiped on unmount (see the catch block below), so an abort here\n // would leave the user on a loading screen with no message.\n const local = getLocalDev();\n const localServicesError = await checkLocalServices({\n ...local,\n // An explicit --base-url wins over --local-posthog (see buildSession),\n // so don't probe :8010 when one was given.\n localPosthog: local.localPosthog && !options.baseUrl,\n });\n if (localServicesError) {\n const { wizardAbort } = await import('@utils/wizard-abort');\n await wizardAbort({ message: localServicesError });\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tui = startTUI(WIZARD_VERSION, config.id as any, () => onSignal?.());\n const activeTui = tui;\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n installDir,\n ci: false,\n signup: options.signup as boolean | undefined,\n apiKey: options.apiKey as string | undefined,\n projectId: options.projectId as string | undefined,\n email: options.email as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n integrate: options.integrate as boolean | undefined,\n captureAio: options.captureAio as boolean | undefined,\n });\n session.programLabel = config.id;\n if (options.skillId) {\n session.skillId = options.skillId as string;\n } else if (config.skillId) {\n session.skillId = config.skillId;\n }\n\n activeTui.store.session = session;\n\n // Flush a terminal-phase push on Ctrl-C so the web app sees the\n // run ended in error rather than hanging on the last \"running\"\n // snapshot. Registered before the stream exists: Ctrl-C on the intro\n // must still restore the terminal and run the cleanups, and there is\n // no run to report yet.\n onSignal = (): void => {\n if (signalled || exitInProgress) return;\n signalled = true;\n logToFile('[run-wizard] signal received, flushing task stream');\n // Run cleanups synchronously first — settings restore is sync fs work\n // and must complete even if the stream shutdown below times out.\n runCleanups();\n if (activeTui.store.session.runPhase === RunPhase.Running) {\n activeTui.store.setRunPhase(RunPhase.Error);\n }\n const teardown = (): void => {\n unregisterShutdown?.();\n if (onSignal) {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n try {\n activeTui.unmount();\n } catch {\n // terminal may already be torn down\n }\n process.exit(130);\n };\n void Promise.all([\n taskStream?.shutdown(2000, 'cancelled'),\n analytics.shutdown('cancelled'),\n ])\n .catch(() => logToFile('[run-wizard] cancellation shutdown failed'))\n .finally(teardown);\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n for (;;) {\n await activeTui.store.runReadyHooks();\n // Settle the pre-run screens; `integration-check` is a no-op gate here.\n await activeTui.store.getGate('intro');\n\n const active = activeTui.store.router.activeProgram;\n if (active === config.id) break;\n config = getProgramConfig(active);\n }\n\n // After the switch loop, not before: the stream bakes its program id,\n // session id, and event-plan path in at construction, so a stream built\n // for the launch program would report the whole run under a program the\n // user left on the intro screen. Nothing before this point produces a\n // task to push.\n // Consent gates the push, not the dump: `--no-telemetry` still logs.\n const fileDestination = createFileDestination(options.taskStreamLog);\n const destinations = [\n ...(session.noTelemetry\n ? []\n : [\n new PostHogDestination({\n getCredentials: () => activeTui.store.session.credentials,\n onError: (err) => logToFile('[task-stream-push]', err.message),\n }),\n ]),\n ...(fileDestination ? [fileDestination] : []),\n ];\n const taskStreamEnabled = destinations.length > 0;\n const activeStream = new TaskStreamPush({\n store: activeTui.store,\n getFlags: () => analytics.getCachedWizardFlags(),\n programId: config.streamWorkflowId ?? config.id,\n runSync: createWizardRunSync({\n mode: 'local',\n programId: config.id,\n assignedId:\n (options.runId as string | undefined) ??\n runtimeEnv('POSTHOG_WIZARD_RUN_ID'),\n noTelemetry: session.noTelemetry,\n getSession: () => activeTui.store.session,\n }),\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(activeTui.store.session)\n : undefined,\n enabled: taskStreamEnabled,\n });\n taskStream = activeStream;\n activeStream.attach();\n unregisterShutdown = registerShutdown((outcome) => {\n if (activeTui.store.session.runPhase === RunPhase.Running) {\n activeTui.store.setRunPhase(RunPhase.Error);\n }\n return activeStream.shutdown(2000, outcome);\n });\n\n await activeTui.store.getGate('integration-check');\n await activeTui.store.getGate('health-check');\n\n const skipAgent = config.run == null;\n const shown = (s: ProgramConfig['steps'][number]) =>\n !s.show || s.show(activeTui.store.session);\n\n if (config.steps.some((s) => s.run || s.targetDir)) {\n // A composed program: its step list splices in run steps that carry\n // their own agent (self-driving runs the integration before its own\n // run), or scopes its own run to a picked project (error-tracking).\n // Walk the list once, advancing each step to completion.\n for (const step of config.steps) {\n if (step.screenId === 'outro') break; // run-completion wait owns it\n if (shown(step)) await advanceStep(step, activeTui.store, config);\n }\n } else if (skipAgent) {\n const { getOrAskForProjectData } = await import('@utils/setup-utils');\n const { projectApiKey, host, accessToken, projectId } =\n await getOrAskForProjectData({\n signup: session.signup,\n ci: session.ci,\n apiKey: session.apiKey,\n projectId: session.projectId,\n baseUrl: session.baseUrl,\n programId: config.id,\n });\n activeTui.store.setCredentials({\n accessToken,\n projectApiKey,\n host,\n projectId,\n });\n } else {\n try {\n await runProgramAgent(config, activeTui.store.session);\n } catch (error) {\n // The run threw before its own error handling rendered an outro.\n // Show the handoff screen and let the user's agent take over.\n const failure = classifyRunFailure(error);\n logToFile('[run-wizard] run failed, handing off:', error);\n runCleanups();\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { error_code: failure.code },\n );\n getUI().outroError({\n kind: OutroKind.Error,\n errorCode: failure.code,\n message: failure.message,\n });\n }\n }\n\n if (signalled) return;\n const runFailed = isRunFailure(activeTui.store.session);\n await activeStream.finishRun(runFailed ? 'failed' : 'completed');\n await activeTui.store.waitUntil((s) => {\n if (s.mintHandoff === 'exit') return true;\n if (skipAgent && !runFailed) return s.outroDismissed;\n return s.skillsComplete;\n });\n\n exitInProgress = true;\n await activeStream.shutdown(2000);\n unregisterShutdown?.();\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n if (runFailed) await analytics.shutdown('error');\n activeTui.unmount();\n process.exit(runFailed ? 1 : 0);\n } catch (err) {\n if (signalled) return;\n // File-log first — the cleanup below can throw or exit.\n logToFile('[run-wizard] FATAL:', err);\n // Run cleanups before anything async so settings are restored even if\n // the stream shutdown hangs.\n runCleanups();\n // The task-stream debounce timer keeps the event loop alive, so\n // we have to drain it before exiting on the error path.\n exitInProgress = true;\n if (onSignal) {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n if (taskStream) {\n try {\n await taskStream.shutdown(2000, 'failed');\n } catch {\n // ignore\n }\n }\n unregisterShutdown?.();\n if (tui) {\n try {\n tui.unmount();\n } catch {\n // ignore\n }\n }\n // Print after unmount: anything printed into the alt screen is wiped.\n // A coded failure is a decision with its own message; anything else is\n // unexpected and goes out whole.\n const failure = classifyRunFailure(err);\n if (failure.coded) {\n // eslint-disable-next-line no-console\n console.error(failure.message);\n } else {\n // eslint-disable-next-line no-console\n console.error('Wizard run failed:', err);\n }\n // eslint-disable-next-line no-console\n console.error(`Full logs: ${getLogFilePath()}`);\n emitWizardError({ code: failure.code, message: failure.message });\n process.exit(1);\n }\n })();\n}\n","import { ErrorCodes, type ErrorCode } from '@shared/errors';\nimport type { RevenueDetectError } from '@programs/revenue-analytics/detect';\nimport type { SelfDrivingDetectError } from '@programs/self-driving/detect';\nimport type { SourceMapsDetectError } from '@programs/error-tracking-upload-source-maps/detect';\nimport type { WarehouseDetectError } from '@programs/warehouse-source/detect';\nimport type { WebAnalyticsDetectError } from '@programs/web-analytics-doctor/detect';\n\n/**\n * Every `kind` a program detect step can write into\n * `frameworkContext.detectError`, assembled from the programs' own unions.\n * Type-only imports, so this adds no runtime edge from the catalog to the\n * programs (same shape as `skill-map.ts` keying on `InstallSkillResult`).\n *\n * The point is the compile error: add a kind to any program's `DetectError`\n * and `DETECT_CODES` stops type-checking until it gets a code.\n */\nexport type DetectErrorKind =\n | RevenueDetectError['kind']\n | SelfDrivingDetectError['kind']\n | SourceMapsDetectError['kind']\n | WarehouseDetectError['kind']\n | WebAnalyticsDetectError['kind'];\n\nconst DETECT_CODES: Record<DetectErrorKind, ErrorCode> = {\n 'bad-directory': ErrorCodes.DetectBadDirectory,\n 'unsupported-platform': ErrorCodes.DetectUnsupportedPlatform,\n 'no-project-files': ErrorCodes.DetectNoProjectFiles,\n 'no-sources': ErrorCodes.DetectNoSources,\n 'no-package-json': ErrorCodes.DetectNoPackageJson,\n 'no-sdks': ErrorCodes.DetectNoSdks,\n 'missing-stripe': ErrorCodes.DetectMissingStripe,\n // Three kinds, one failure class: the program needs a PostHog SDK and the\n // project has none. Hosts that care which program asked read `detail.kind`.\n 'no-posthog-sdk': ErrorCodes.DetectNoPosthogSdk,\n 'no-posthog': ErrorCodes.DetectNoPosthogSdk,\n 'missing-posthog': ErrorCodes.DetectNoPosthogSdk,\n};\n\n/**\n * `kind` arrives as a bare string — `frameworkContext.detectError` is untyped\n * storage — so the lookup can still miss. It falls back to a detect-group code\n * with `retry: 'no'`, never to `InternalUnhandled`: an unrecognized precondition\n * failure is still a precondition failure, and telling a sandbox to retry one\n * costs it the whole budget.\n */\nexport function detectErrorCode(kind: string): ErrorCode {\n return DETECT_CODES[kind as DetectErrorKind] ?? ErrorCodes.DetectUnclassified;\n}\n","import {\n POSTHOG_DOCS_URL,\n type Harness,\n type Sequence,\n} from '@shared/constants';\nimport {\n createWizardRunSync,\n type RunOutcome,\n} from '@programs/task-stream/wizard-run-sync';\nimport { runtimeEnv } from '@env';\nimport { registerShutdown, runCleanups } from '@utils/wizard-abort';\nimport {\n checkLocalServices,\n getLocalDev,\n POSTHOG_LOCAL_URL,\n} from '@shared/local-dev';\nimport type { CloudRegion } from '@utils/types';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport type { ProgramConfig } from '@programs/types';\nimport { getAuditChecks } from '@programs/audit/types';\nimport { analytics } from '@utils/analytics';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport type { WizardStore } from '@ui/tui/store';\nimport type { TaskStreamPush } from '@programs/task-stream/task-stream-push';\nimport { join } from 'node:path';\nimport {\n ErrorCodes,\n classifyRunFailure,\n emitWizardError,\n} from '@shared/errors';\nimport { detectErrorCode } from '@programs/detect-map';\nimport type { OutroData, RunPhase as RunPhaseT } from '@lib/wizard-session';\n\n/**\n * The two non-interactive run modes. Both drive the same pipeline today; the\n * mode is threaded explicitly (rather than sniffed from a flag) so the dispatch\n * picks an entry point — runWizardCI vs runWizardHeadless — and this core stays\n * mode-agnostic except at the few documented forks. The string values double as\n * the analytics `build` tag, so they segment runs in analytics and on\n * LLM-gateway traces (which read analytics.build).\n */\nexport type NonInteractiveMode = 'ci' | 'headless';\n\n/** User-facing label for a non-interactive mode. */\nfunction modeLabel(mode: NonInteractiveMode): string {\n return mode === 'headless' ? 'Headless' : 'CI';\n}\n\n/** The credentials every non-interactive mode accepts, for error messages. */\nexport const API_KEY_HINT =\n 'personal API key phx_xxx or wizard-app OAuth access token pha_xxx';\n\n/**\n * The single non-interactive validation layer: requires api-key and\n * install-dir. Every non-interactive entry point routes through\n * `runNonInteractive`, so this is the one place these checks live. UI must be\n * initialized before calling.\n */\nexport function validateNonInteractiveOptions(\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n const label = modeLabel(mode);\n if (!options.apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(`${label} mode requires --api-key (${API_KEY_HINT})`);\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: `${label} mode requires --api-key (${API_KEY_HINT})`,\n });\n process.exit(1);\n }\n if (!options.installDir) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n `${label} mode requires --install-dir (directory to install in)`,\n );\n emitWizardError({\n code: ErrorCodes.ArgsMissingInstallDir,\n message: `${label} mode requires --install-dir`,\n });\n process.exit(1);\n }\n}\n\n/**\n * Non-interactive pipeline shared by CI (`runWizardCI`) and headless\n * (`runWizardHeadless`) runs.\n *\n * Validates flags, builds a `ci:true` session, runs `config.ciPreRun` (or the\n * program's `onReady` hooks by default), executes `runProgramAgent`, and routes any\n * failure through `wizardAbort`. `wizardAbort` owns all exits — never add a\n * raw `process.exit` here.\n *\n * `mode` is the only difference between the two callers today (it sets the\n * analytics build tag and the user-facing label). Keeping it a parameter is\n * what lets CI and headless share this body now and diverge later — branch on\n * `mode` here, or stop sharing this function entirely.\n */\nexport function runNonInteractive(\n config: ProgramConfig,\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n setUI(new LoggingUI());\n validateNonInteractiveOptions(options, mode);\n // Upgrade the build tag so runs segment cleanly in analytics (and on\n // LLM-gateway traces, which read analytics.build). A published headless run\n // (cloud / CI/CD) tags 'headless'; a dev/test `--ci` run upgrades 'dev' to\n // 'ci'. The mode string is the tag value.\n analytics.setTag('build', mode);\n\n void (async () => {\n const path = await import('path');\n const { buildSession, RunPhase, OutroKind } = await import(\n '@lib/wizard-session'\n );\n const { readEnvironment } = await import('@utils/environment');\n const { readApiKeyFromEnv } = await import('@utils/env-api-key');\n const { configureLogFileFromEnvironment, logToFile } = await import(\n '@utils/debug'\n );\n const { wizardAbort, WizardError } = await import('@utils/wizard-abort');\n\n configureLogFileFromEnvironment();\n\n const env = readEnvironment();\n const apiKey =\n (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n const installDir = path.isAbsolute(options.installDir as string)\n ? (options.installDir as string)\n : path.join(process.cwd(), options.installDir as string);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n installDir,\n ci: true,\n signup: options.signup as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n apiKey,\n email: options.email as string | undefined,\n projectId: options.projectId as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n captureAio: options.captureAio as boolean | undefined,\n ...env,\n // After the spread: yargs already resolves flag-over-env for --region,\n // so the parsed value must win over the raw env bag.\n region: (options.region ?? env.region) as CloudRegion | undefined,\n });\n session.programLabel = config.id;\n if (config.skillId) {\n session.skillId = config.skillId;\n }\n const runDef = typeof config.run === 'object' ? config.run : null;\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info(`Running ${config.id} in ${modeLabel(mode)} mode`);\n\n // Before auth: a dead local PostHog otherwise surfaces as \"Failed to fetch\n // user data\". Aborts even non-interactively — a CI run pointed at a local\n // server that isn't there is testing nothing.\n const localServicesError = await checkLocalServices({\n ...getLocalDev(),\n localMcp: session.localMcp,\n localPosthog: session.baseUrl === POSTHOG_LOCAL_URL,\n });\n if (localServicesError) {\n await wizardAbort({\n code: ErrorCodes.EnvLocalServicesDown,\n message: localServicesError,\n });\n return;\n }\n\n // Headless streams run state to the PostHog backend so the web app can show\n // live progress. Reuses the interactive TaskStreamPush + WizardStore (no Ink\n // render): HeadlessUI keeps LoggingUI's output and feeds task updates into\n // the store; this runner drives the phase transitions. Headless pushes to\n // PostHog (the web app is that run's only UI); `--ci` is synthetic, so it\n // dumps locally and pushes nothing. Telemetry consent gates the push only.\n let store: WizardStore | null = null;\n let taskStream: TaskStreamPush | null = null;\n {\n const { WizardStore } = await import('@ui/tui/store');\n const { HeadlessUI } = await import('@ui/headless-ui');\n const { TaskStreamPush, PostHogDestination, createFileDestination } =\n await import('@programs/task-stream/index');\n\n // `''` resolves to the default path, so `--ci` always dumps.\n const logTarget =\n mode === 'ci' ? options.taskStreamLog ?? '' : options.taskStreamLog;\n const fileDestination = createFileDestination(logTarget);\n const posthogDestination =\n mode === 'headless' && !session.noTelemetry\n ? new PostHogDestination({\n getCredentials: () =>\n store?.session.credentials ?? session.credentials,\n onError: (e) => logToFile('[headless task-stream]', e.message),\n })\n : null;\n const destinations = [\n ...(posthogDestination ? [posthogDestination] : []),\n ...(fileDestination ? [fileDestination] : []),\n ];\n\n const headlessStore = new WizardStore(config.id);\n store = headlessStore;\n headlessStore.session = session;\n setUI(new HeadlessUI(headlessStore));\n taskStream = new TaskStreamPush({\n store: headlessStore,\n getFlags: () => analytics.getCachedWizardFlags(),\n programId: config.streamWorkflowId ?? config.id,\n runSync: createWizardRunSync({\n mode,\n programId: config.id,\n assignedId:\n (options.runId as string | undefined) ??\n runtimeEnv('POSTHOG_WIZARD_RUN_ID'),\n noTelemetry: session.noTelemetry,\n getSession: () => headlessStore.session,\n }),\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(headlessStore.session)\n : undefined,\n enabled: destinations.length > 0,\n });\n taskStream.attach();\n\n if (fileDestination) {\n logToFile(`[task-stream] ${mode} dump: ${fileDestination.path}`);\n }\n }\n\n // wizardAbort exits via process.exit, so flush the terminal phase before any\n // exit. No-op for CI.\n const settleStream = async (\n phase: RunPhaseT,\n outroData?: OutroData,\n outcome: RunOutcome = phase === RunPhase.Completed\n ? 'completed'\n : 'failed',\n ): Promise<void> => {\n if (!store || !taskStream) return;\n if (outroData) store.setOutroData(outroData);\n store.setRunPhase(phase);\n await taskStream.shutdown(2000, outcome);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n unregisterShutdown();\n };\n\n const unregisterShutdown = registerShutdown((outcome) =>\n settleStream(RunPhase.Error, undefined, outcome),\n );\n let signalled = false;\n const onSignal = (): void => {\n if (signalled) return;\n signalled = true;\n runCleanups();\n void settleStream(RunPhase.Error, undefined, 'cancelled').then(() =>\n wizardAbort({ exitCode: 130 }),\n );\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n try {\n if (mode === 'ci') {\n const { configureGatewayFromCIEnvironment } = await import('@agent');\n configureGatewayFromCIEnvironment(\n Number(session.projectId),\n session.region ?? 'us',\n );\n }\n if (config.ciPreRun) {\n await config.ciPreRun(session, {\n log: {\n info: (message) => getUI().log.info(message),\n warn: (message) => getUI().log.warn(message),\n },\n });\n } else {\n const readyCtx = {\n session,\n setFrameworkContext: (key: string, value: unknown) => {\n session.frameworkContext[key] = value;\n },\n setFrameworkConfig: () => undefined,\n setDetectedFramework: () => undefined,\n // Non-interactive session is a plain object (no nanostore\n // copy-on-write), so direct assignment is safe here.\n setSkillId: (skillId: string | null) => {\n session.skillId = skillId;\n },\n setUnsupportedVersion: (info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }) => {\n session.unsupportedVersion = info;\n },\n addDiscoveredFeature: () => undefined,\n setDetectionComplete: () => undefined,\n setPosthogSdkDetected: (detected: boolean) => {\n session.posthogSdkDetected = detected;\n },\n };\n for (const step of config.steps) {\n if (step.onReady) {\n await step.onReady(readyCtx);\n }\n }\n\n const detectError = session.frameworkContext.detectError as\n | { kind: string; [k: string]: unknown }\n | undefined;\n if (session.unsupportedVersion) {\n const { current, minimum, docsUrl } = session.unsupportedVersion;\n const message = `Detected framework version ${current} is not supported. Minimum supported version is ${minimum}.`;\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message,\n errorCode: ErrorCodes.DetectUnsupportedVersion,\n });\n await wizardAbort({\n code: ErrorCodes.DetectUnsupportedVersion,\n message: `${message}\\n\\nSee ${docsUrl}`,\n error: new WizardError(\n `${config.id} unsupported framework version`,\n {\n integration: config.id,\n current,\n minimum,\n },\n ErrorCodes.DetectUnsupportedVersion,\n ),\n });\n }\n if (detectError) {\n const code = detectErrorCode(detectError.kind);\n const detectKind = detectError.kind;\n // `kind` stays in the detail: several kinds share one code, so it is\n // the only thing telling a host which precondition actually failed.\n const detail = { ...detectError };\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: `Prerequisites not met: ${detectKind}`,\n errorCode: code,\n errorDetail: detail,\n });\n await wizardAbort({\n code,\n detail,\n message: `Prerequisites not met: ${detectKind}\\n\\nSee ${\n runDef?.docsUrl ?? POSTHOG_DOCS_URL\n }`,\n error: new WizardError(\n `${config.id} prerequisites failed`,\n {\n integration: config.id,\n detect_error_kind: detectKind,\n },\n code,\n ),\n });\n }\n }\n\n const { runProgramAgent } = await import('@programs/run-agent-legacy');\n await runProgramAgent(config, session);\n if (signalled) return;\n await settleStream(RunPhase.Completed);\n } catch (error) {\n if (signalled) return;\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[${mode}] ERROR: ${errorMessage}`);\n if (errorStack) logToFile(`[${mode}] STACK: ${errorStack}`);\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n const docsUrl =\n session.frameworkConfig?.metadata.docsUrl ??\n runDef?.docsUrl ??\n POSTHOG_DOCS_URL;\n // A coded failure is a decision with its own message; anything else is\n // unexpected and gets the generic framing.\n const failure = classifyRunFailure(error);\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: errorMessage,\n errorCode: failure.code,\n });\n await wizardAbort({\n code: failure.code,\n message: failure.coded\n ? `${errorMessage}${debugInfo}`\n : `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,\n error: error as Error,\n });\n }\n })().catch((error: unknown) => {\n emitWizardError({\n code: ErrorCodes.InternalUnhandled,\n message: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n });\n}\n","import type { ProgramConfig } from '@programs/types';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * CI-mode entry point (`--ci`, dev/test builds). A thin shell over the shared\n * non-interactive pipeline — see `runNonInteractive`. Kept as its own function\n * so CI and headless (`runWizardHeadless`) can diverge without re-threading the\n * many callers that route here.\n */\nexport function runWizardCI(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'ci');\n}\n","import type { ProgramConfig } from '@programs/types';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * Headless entry point (the experimental published-build, non-interactive run\n * path; see @lib/headless-mode). A thin shell over the shared non-interactive\n * pipeline — see `runNonInteractive`. Today it behaves exactly like\n * `runWizardCI`; it exists as a separate function so headless can diverge later\n * (its own auth handling, telemetry, prompts, …) without touching CI or its\n * callers. Diverge by branching on the mode inside `runNonInteractive`, or by\n * giving this function its own body.\n */\nexport function runWizardHeadless(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'headless');\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"security-C71pkwqH.js","names":[],"sources":["../src/agent/runner/harness/pi/security.ts"],"sourcesContent":["/**\n * Fail-closed security for the pi backend (#525). pi has no built-in\n * permission layer, so we attach an extension that intercepts every tool call\n * — built-in (bash/read/edit/write/grep) AND custom — through pi's `tool_call`\n * hook and reuses the EXACT anthropic policy: `wizardCanUseTool` (the bash\n * allowlist + .env fencing) plus the YARA pre-scan. A `tool_result` hook\n * post-scans output. Both fail closed: a scanner error blocks, and a critical\n * post-scan violation latches so every subsequent tool call is blocked and the\n * run terminates as a YARA violation.\n *\n * Scanning runs through @posthog/warlock via yara-hooks' `scanAndTriage` — the\n * same engine, rules, chunking, and LLM triage policy as the anthropic\n * harness. pi handlers are async (pi's ExtensionHandler accepts promises), so\n * the WASM scan awaits inline.\n *\n * This is the one fence. Subagents run their own pi session with the SAME\n * extension installed (see subagent.ts), so a child cannot escape it.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport type { LLMProvider, ScanMatch } from '@posthog/warlock';\nimport { wizardCanUseTool } from '@agent/agent-interface';\nimport {\n createRepeatBlockTracker,\n isWizardDocumentationPath,\n recordExternalScan,\n repeatBlockReason,\n scanAndTriage,\n type RepeatBlockTracker,\n} from '@agent/yara-hooks';\nimport {\n publishBlockingMatch,\n scanVerdict,\n type ScanContext,\n} from '@agent/yara-policy';\nimport { logToFile } from '@utils/debug';\nimport { analytics } from '@utils/analytics';\n\n/** warlock ScanMatch → the report shape `recordExternalScan` expects. */\nfunction toReportViolation(m: ScanMatch) {\n return {\n rule: m.rule,\n severity: m.metadata.severity ?? 'unknown',\n category: m.metadata.category ?? 'unknown',\n description: m.metadata.description ?? '',\n };\n}\n\n/** Runaway backstop: hard cap on tool calls per (sub)agent session. */\nexport const MAX_TOOL_CALLS = 250;\n\n/**\n * Passive telemetry for an unfixed upstream failure: gpt-5.x streaming with\n * tools leaks its function-call grammar into string values, and the leak lands\n * on disk (run 9704a73e shipped `…functions.complete_task (commentary…` plus a\n * DEL byte inside a customer's global-error.tsx). Observe-only — never blocks.\n * Prior art: https://github.com/BerriAI/litellm/issues/14260 (closed stale),\n * https://community.openai.com/t/1386422 (gpt-5.6-luna, no fix).\n */\nconst TRANSPORT_LEAK_PATTERNS: readonly { pattern: RegExp; label: string }[] = [\n // The litellm#14260 signature, scoped to the wizard's own tool names — a\n // generic `functions.*` would false-positive on real code (Firebase).\n {\n pattern: /functions\\.(?:complete_task|enqueue_task|read_handoffs)/,\n label: 'leaked tool-call tokens',\n },\n {\n pattern: /<\\|(?:channel|constrain|message|call|end|start|return)\\|>/,\n label: 'leaked channel markers',\n },\n // C0 controls and DEL minus tab/newline/CR — never valid in source text.\n // eslint-disable-next-line no-control-regex\n { pattern: /[\\0-\\x08\\x0B\\f\\x0E-\\x1F\\x7F]/, label: 'control characters' },\n];\n\n/** Capture one event per leaking write/edit: which pattern fired and where it sat — no matched text, ever. */\nexport function observeTransportLeak(tool: string, content: string): void {\n for (const { pattern, label } of TRANSPORT_LEAK_PATTERNS) {\n const match = pattern.exec(content);\n if (!match) continue;\n analytics.wizardCapture('file content leak observed', {\n tool,\n leak: label,\n leak_offset: match.index,\n content_length: content.length,\n // End-of-string leaks are the upstream decoder signature.\n at_end: content.length - match.index < 80,\n });\n logToFile(\n `[transport-leak] observed ${tool}: ${label} at ${match.index}/${content.length}`,\n );\n return;\n }\n}\n\nexport const READ_ONLY_PI_TOOLS: ReadonlySet<string> = new Set([\n 'read',\n 'grep',\n 'find',\n 'ls',\n]);\n\nexport interface ToolGateContext {\n readOnly?: boolean;\n disallowedTools?: readonly string[];\n /** True while a wizard_ask overlay is open (interactive); blocks Write/Edit. */\n getWizardAskPending?: () => boolean;\n /** Scan-triage classifier, resolved once in bootstrap. Absent → every flagged match is acted on. */\n triageProvider?: LLMProvider;\n /**\n * Per-run tracker of YARA-blocked payloads. When the agent retries content\n * that was already blocked, the block reason escalates (\"change the code,\n * not the retry\" → \"report it and move on\"). The extension wires one in;\n * absent (tests calling `evaluateToolCall` directly) every block reads as\n * a first attempt.\n */\n repeatTracker?: RepeatBlockTracker;\n /** Project root; rm is only allowed for files resolving strictly inside it. */\n workingDirectory?: string;\n}\n\nexport interface GateDecision {\n block: boolean;\n reason?: string;\n /** End the run, don't just refuse the call. Set when a blocked publish_handoff would otherwise leave no report. */\n terminate?: boolean;\n}\n\nconst str = (v: unknown): string => (typeof v === 'string' ? v : '');\n\n// Shell metacharacters that chain, substitute, or redirect. A command carrying\n// any of these is more than one action, so we never treat it as a plain `rm`.\nconst SHELL_OPERATORS = /[;&|`$(){}<>\\n'\"\\\\]/;\n\n/** True when a target resolves to a file strictly inside the project root. */\nfunction isDeletableProjectFile(\n target: string,\n root: string,\n p: typeof path,\n): boolean {\n if (target.startsWith('-')) return false; // a flag, not a file\n if (/[*?[\\]~]/.test(target)) return false; // glob / home expansion\n if (p.basename(target).startsWith('.env')) return false; // secrets\n\n const resolved = p.resolve(root, target);\n return resolved !== root && resolved.startsWith(root + p.sep);\n}\n\n/**\n * A plain `rm [-f] <file...>` whose every target is a file inside the project\n * root — the deletion shape the anthropic arm permits (there bash isn't\n * allowlisted; the shared YARA destructive-delete rules catch the dangerous\n * forms). pi rescues the same shape so the fall-through YARA scan can judge\n * it, but refuses any shell operator so it can't smuggle a second command.\n * Path checks run through the host's `path` (win32 on Windows, posix elsewhere);\n * pi always executes commands via a POSIX bash, so targets use forward slashes.\n */\nexport function isScopedFileRemoval(\n command: string,\n rawRoot: string | undefined,\n p: typeof path = path,\n): boolean {\n if (!rawRoot) return false; // no root to contain against → never rescue\n const root = p.resolve(rawRoot);\n const trimmed = command.trim();\n if (SHELL_OPERATORS.test(trimmed)) return false;\n\n const [executable, ...args] = trimmed.split(/\\s+/);\n if (executable !== 'rm') return false;\n\n if (args[0] === '-f') args.shift();\n if (args.length === 0) return false;\n\n return args.every((arg) => isDeletableProjectFile(arg, root, p));\n}\n\n/** A write that removes more than this fraction of an existing file's\n * non-whitespace content reads as a destructive whole-file rewrite. */\nconst OVERWRITE_SHRINK_LIMIT = 0.3;\n\n/** Existing files below this many non-whitespace chars are stubs; replacing one\n * wholesale is legitimate, so the shrink guard leaves them alone. */\nconst OVERWRITE_MIN_CHARS = 400;\n\nconst nonWhitespaceLength = (s: string): number => s.replace(/\\s+/g, '').length;\n\n/**\n * Refuse a write that replaces an existing file with far less content than it\n * held, steering the agent back to targeted edits. Prior art — the destructive\n * whole-file rewrite is a known model failure that targeted-edit formats exist to\n * prevent: Aider's search/replace and unified-diff, OpenAI's apply_patch,\n * Anthropic's str_replace with replace_all; pi's edit tool has no replace_all, so\n * a rejected scoped edit can fall back to a lossy full write. Additive by design:\n * the wizard only adds instrumentation, so a large shrink is the rewrite, not intent.\n */\nexport function overwriteShrinkReason(\n existing: string,\n next: string,\n): string | undefined {\n const before = nonWhitespaceLength(existing);\n if (before < OVERWRITE_MIN_CHARS) return undefined;\n const after = nonWhitespaceLength(next);\n if (after >= before * (1 - OVERWRITE_SHRINK_LIMIT)) return undefined;\n const removed = Math.round((1 - after / before) * 100);\n return `This write replaces an existing file and removes ~${removed}% of its content. Make targeted edits instead of rewriting the whole file; only write a file in full when creating it.`;\n}\n\n/**\n * Read the file a write would replace and flag a destructive shrink. A path that\n * does not exist yet is a new file, so it never triggers; with no project root to\n * resolve against (unit tests calling `evaluateToolCall` bare), it stays inert.\n */\nasync function overwriteShrinkBlock(\n input: Record<string, unknown>,\n workingDirectory: string | undefined,\n): Promise<string | undefined> {\n const target = str(input.path);\n if (!workingDirectory || !target) return undefined;\n let existing: string;\n try {\n existing = await fs.promises.readFile(\n path.resolve(workingDirectory, target),\n 'utf8',\n );\n } catch {\n return undefined; // new file (ENOENT) or unreadable — nothing to preserve\n }\n return overwriteShrinkReason(existing, str(input.content));\n}\n\n/**\n * Translate a pi tool name to the claude-cased name + input the shared policy\n * expects. pi field names (from the live tool stream): bash{command},\n * read/edit/write{path}, write adds {content}, edit adds {edits}, grep{path}.\n */\nfunction toClaudePolicyCall(\n toolName: string,\n input: Record<string, unknown>,\n): { name: string; input: Record<string, unknown> } {\n switch (toolName) {\n case 'bash':\n return { name: 'Bash', input: { command: str(input.command) } };\n case 'read':\n return { name: 'Read', input: { file_path: input.path } };\n case 'write':\n return { name: 'Write', input: { file_path: input.path } };\n case 'edit':\n return { name: 'Edit', input: { file_path: input.path } };\n case 'grep':\n return { name: 'Grep', input: { path: input.path } };\n default:\n // Custom tools (load_skill_menu, set_env_values, dispatch_agent, …) +\n // find/ls: no path/command, policy allows (their own handlers are fenced).\n return { name: toolName, input };\n }\n}\n\n/**\n * The agent-facing block message. Includes the rule's remediation so a blocked\n * agent can self-correct (e.g. \"move PII to identify()/$set\") instead of\n * retrying near-identical content.\n */\nfunction blockMessage(m: ScanMatch): string {\n const remediation = m.metadata.remediation\n ? ` Fix: ${m.metadata.remediation}.`\n : '';\n return `[YARA] ${m.rule}: ${\n m.metadata.description ?? 'security rule matched'\n }.${remediation} Blocked for security.`;\n}\n\n/**\n * YARA scan of the content a tool is about to act on, BEFORE it executes.\n * - bash → scan the command ('command'-context rules: exfiltration,\n * destructive, force-push). No triage — a flagged command always blocks,\n * same as the anthropic PreToolUse hook, so the LLM call would be wasted.\n * - write/edit → scan the content being written ('output'-context rules:\n * hardcoded keys, PII), WITH triage, and with the same wizard-doc\n * `posthog_pii` suppression the anthropic path uses so the agent's own\n * event-plan files aren't blocked.\n * - publish_handoff → scan the report ('output'-context rules) with triage,\n * but only a CRITICAL match refuses the publish — it's the only channel.\n * Returns a block reason, or undefined to allow. Read/grep are post-scanned on\n * their output (in the tool_result hook), not here.\n */\nasync function preExecutionYaraBlock(\n toolName: string,\n input: Record<string, unknown>,\n llmProvider: LLMProvider | undefined,\n repeatTracker?: RepeatBlockTracker,\n): Promise<string | undefined> {\n let content: string;\n let ctx: ScanContext;\n let triage: LLMProvider | undefined;\n // Report labels for the scan report (phase/tool), matching the anthropic\n // hooks so pi and anthropic runs read the same in telemetry.\n let phase: string;\n let tool: string;\n switch (toolName) {\n case 'bash':\n content = str(input.command);\n ctx = 'command';\n triage = undefined;\n phase = 'PreToolUse';\n tool = 'Bash';\n break;\n case 'write':\n content = str(input.content);\n ctx = 'output';\n triage = llmProvider;\n phase = 'PostToolUse';\n tool = 'Write';\n break;\n case 'edit':\n // Scan ONLY the replacement text. `edits` is [{oldText, newText}] and\n // oldText is pre-existing file content the agent is changing — scanning\n // it blocks edits whose *surroundings* contain a violation, and even\n // edits that are removing one (field FPs: capture edits adjacent to\n // existing identify() PII; pre-existing violations blocking their own\n // replacement). Matches the anthropic path, which scans new_string only.\n content = (Array.isArray(input.edits) ? input.edits : [])\n .map((e) => str((e as Record<string, unknown>)?.newText))\n .join('\\n');\n ctx = 'output';\n triage = llmProvider;\n phase = 'PostToolUse';\n tool = 'Edit';\n break;\n case 'publish_handoff':\n // Agent-authored content persisted to the task stream and the host file.\n // Own labels, not Write's — the block bar differs (critical only).\n content = str(input.content);\n ctx = 'output';\n triage = llmProvider;\n phase = 'PreToolUse';\n tool = 'publish_handoff';\n break;\n default:\n return undefined;\n }\n if (!content) return undefined;\n if (ctx === 'output') observeTransportLeak(tool, content);\n\n let matches = await scanAndTriage(content, ctx, triage);\n if (ctx === 'output' && isWizardDocumentationPath(str(input.path))) {\n matches = matches.filter((m) => m.metadata.category !== 'posthog_pii');\n }\n // Any match blocks — except publish_handoff, critical only.\n const blocking =\n toolName === 'publish_handoff'\n ? publishBlockingMatch(matches)\n : matches[0] ?? null;\n\n recordExternalScan(\n phase,\n tool,\n matches.map(toReportViolation),\n blocking ? 'blocked' : 'warned',\n );\n if (!blocking) return undefined;\n\n const attempt = repeatTracker?.attempt(toolName, content) ?? 1;\n return repeatBlockReason(attempt, toolName, blockMessage(blocking));\n}\n\n/**\n * The pure gate decision for a single tool call. Reuses `wizardCanUseTool`\n * (deny → block) then the YARA content scan (match → block). Fail-closed: any\n * thrown error blocks.\n */\nexport async function evaluateToolCall(\n toolName: string,\n input: Record<string, unknown>,\n ctx: ToolGateContext = {},\n llmProvider?: LLMProvider,\n): Promise<GateDecision> {\n try {\n if (ctx.readOnly && !READ_ONLY_PI_TOOLS.has(toolName)) {\n return {\n block: true,\n reason: `Tool ${toolName} is disabled for read-only runs.`,\n };\n }\n const policy = toClaudePolicyCall(toolName, input);\n const decision = wizardCanUseTool(policy.name, policy.input, {\n disallowedTools: ctx.disallowedTools,\n wizardAskPending: ctx.getWizardAskPending?.() ?? false,\n });\n // The allowlist is a pi-only restriction; the anthropic arm runs bash\n // unrestricted and leans on the shared YARA scan. Let a plain `rm` of\n // project files through to that same scan so pi matches that behavior.\n const allowedLikeAnthropic =\n toolName === 'bash' &&\n isScopedFileRemoval(str(input.command), ctx.workingDirectory);\n\n if (decision.behavior === 'deny' && !allowedLikeAnthropic) {\n return { block: true, reason: decision.message };\n }\n\n const yaraReason = await preExecutionYaraBlock(\n toolName,\n input,\n llmProvider,\n ctx.repeatTracker,\n );\n if (yaraReason) return { block: true, reason: yaraReason };\n\n if (toolName === 'write') {\n const shrinkReason = await overwriteShrinkBlock(\n input,\n ctx.workingDirectory,\n );\n if (shrinkReason) return { block: true, reason: shrinkReason };\n }\n\n return { block: false };\n } catch (err) {\n logToFile('[pi-security] gate error — failing closed:', err);\n // A publish_handoff the gate can't clear leaves the run with no report at\n // all, so end it visibly instead of letting the agent reword and retry.\n return {\n block: true,\n reason: 'Security check failed; tool blocked (fail-closed).',\n terminate: toolName === 'publish_handoff',\n };\n }\n}\n\n/** pi result tool names whose OUTPUT gets scanned for 'input'-context rules. */\nfunction isPostScanTool(toolName: string): boolean {\n return toolName === 'read' || toolName === 'bash';\n}\n\n/** Mutable state the backend reads after the run to classify the outcome. */\nexport interface SecurityState {\n criticalViolation: boolean;\n blockedCount: number;\n toolCalls: number;\n}\n\n/**\n * Build the pi security extension + the shared state the backend inspects.\n * Install the returned factory via `extensionFactories`; pass the same factory\n * into every subagent session so the fence is inherited.\n */\nexport function createSecurityExtension(ctx: ToolGateContext = {}): {\n factory: (pi: PiExtensionApiLike) => void;\n state: SecurityState;\n} {\n const state: SecurityState = {\n criticalViolation: false,\n blockedCount: 0,\n toolCalls: 0,\n };\n\n // One triage provider per extension. Undefined (no gateway auth) means\n // triage is skipped and every flagged match is acted on — fail closed.\n const llmProvider = ctx.triageProvider;\n\n // One tracker per extension = per (sub)agent session, so an identical\n // payload retried after a block gets the escalating reason.\n const gateCtx: ToolGateContext = {\n ...ctx,\n repeatTracker: ctx.repeatTracker ?? createRepeatBlockTracker(),\n };\n\n const factory = (pi: PiExtensionApiLike): void => {\n pi.on('tool_call', async (event) => {\n // A latched post-scan violation blocks everything that follows.\n if (state.criticalViolation) {\n return {\n block: true,\n reason: 'Run terminated by a security violation.',\n };\n }\n state.toolCalls += 1;\n if (state.toolCalls > MAX_TOOL_CALLS) {\n return {\n block: true,\n reason: `Stopped: exceeded ${MAX_TOOL_CALLS} tool calls (runaway guard).`,\n };\n }\n const decision = await evaluateToolCall(\n event.toolName,\n event.input ?? {},\n gateCtx,\n llmProvider,\n );\n if (decision.block) {\n state.blockedCount += 1;\n if (decision.terminate) state.criticalViolation = true;\n logToFile(`[pi-security] BLOCK ${event.toolName}: ${decision.reason}`);\n return { block: true, reason: decision.reason };\n }\n return {};\n });\n\n pi.on('tool_result', async (event) => {\n if (!isPostScanTool(event.toolName)) return {};\n const text = (event.content ?? [])\n .map((c) => (c && c.type === 'text' ? c.text : ''))\n .join('\\n');\n if (!text) return {};\n try {\n // 'input'-context rules (prompt injection in read content), with\n // triage — same policy as the anthropic PostToolUse Read hook.\n const matches = await scanAndTriage(text, 'input', llmProvider);\n const verdict = scanVerdict(matches);\n // Count the scan even when clean, like the anthropic hooks do.\n recordExternalScan(\n 'PostToolUse',\n event.toolName === 'read' ? 'Read' : 'Bash',\n matches.map(toReportViolation),\n verdict?.action ?? 'warned',\n );\n if (!verdict) return {};\n if (verdict.terminal) {\n state.criticalViolation = true;\n logToFile(\n `[pi-security] POST-SCAN VIOLATION ${event.toolName}: ${verdict.match.rule}`,\n );\n } else {\n logToFile(\n `[pi-security] POST-SCAN WARNING ${event.toolName}: ${\n verdict.match.rule\n } (severity: ${verdict.match.metadata.severity ?? 'unknown'})`,\n );\n }\n } catch (err) {\n // Fail closed: a scanner error on output latches a violation.\n state.criticalViolation = true;\n logToFile('[pi-security] post-scan error — failing closed:', err);\n }\n return {};\n });\n };\n\n return { factory, state };\n}\n\n/**\n * Minimal structural type for pi's ExtensionAPI — just the `on` overloads we\n * use. Kept local so this module has no value import from the pi SDK (so the\n * CommonJS unit tests can load it directly). Handlers may return promises —\n * pi's real ExtensionHandler is `(event, ctx) => Promise<R | void> | R | void`.\n */\nexport interface PiExtensionApiLike {\n on(\n event: 'tool_call',\n handler: (event: {\n toolName: string;\n input?: Record<string, unknown>;\n }) =>\n | { block?: boolean; reason?: string }\n | Promise<{ block?: boolean; reason?: string }>,\n ): void;\n on(\n event: 'tool_result',\n handler: (event: {\n toolName: string;\n content?: Array<{ type: string; text?: string }>;\n isError?: boolean;\n }) => Record<string, never> | Promise<Record<string, never>>,\n ): void;\n}\n"],"mappings":"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"}