@posthog/wizard 2.72.0 → 2.73.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.
- package/README.md +10 -2
- package/dist/{add-mcp-server-to-clients-QZyr6NuZ.js → add-mcp-server-to-clients-D47ONFCD.js} +4 -4
- package/dist/{add-mcp-server-to-clients-QZyr6NuZ.js.map → add-mcp-server-to-clients-D47ONFCD.js.map} +1 -1
- package/dist/{agent-interface-Yjknz6Al.js → agent-interface-CQ_iz7g7.js} +104 -19
- package/dist/agent-interface-CQ_iz7g7.js.map +1 -0
- package/dist/{agent-prompt-loader-CDXm4C35.js → agent-prompt-loader-Dh2CZEw4.js} +5 -5
- package/dist/{agent-prompt-loader-CDXm4C35.js.map → agent-prompt-loader-Dh2CZEw4.js.map} +1 -1
- package/dist/{agent-runner-CL7rCY0G.js → agent-runner-kj8juD_r.js} +14 -14
- package/dist/{agent-runner-CL7rCY0G.js.map → agent-runner-kj8juD_r.js.map} +1 -1
- package/dist/analytics-BYknS_x4.js +2 -0
- package/dist/{analytics-DjCPD6u-.js → analytics-DHkqXgxG.js} +2 -2
- package/dist/{analytics-DjCPD6u-.js.map → analytics-DHkqXgxG.js.map} +1 -1
- package/dist/{api-xwQeBMcX.js → api-BM5Gaf2x.js} +3 -3
- package/dist/{api-xwQeBMcX.js.map → api-BM5Gaf2x.js.map} +1 -1
- package/dist/bin.js +45 -45
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-BtxN0nYO.js → bounded-fs-Byv2xRSy.js} +3 -3
- package/dist/{bounded-fs-BtxN0nYO.js.map → bounded-fs-Byv2xRSy.js.map} +1 -1
- package/dist/{ci-install-BVzTnIBw.js → ci-install-BUUD2hSG.js} +4 -4
- package/dist/{ci-install-BVzTnIBw.js.map → ci-install-BUUD2hSG.js.map} +1 -1
- package/dist/{debug-BoadIH6Q.js → debug-C14qe0b-.js} +1 -1
- package/dist/{debug-D0T44879.js → debug-D0k3Quos.js} +50 -16
- package/dist/debug-D0k3Quos.js.map +1 -0
- package/dist/{env-api-key-Bj9butHX.js → env-api-key-CBjWUJTZ.js} +2 -2
- package/dist/{env-api-key-Bj9butHX.js.map → env-api-key-CBjWUJTZ.js.map} +1 -1
- package/dist/{environment-vpmKreMf.js → environment-DqdmG3WX.js} +4 -4
- package/dist/{environment-vpmKreMf.js.map → environment-DqdmG3WX.js.map} +1 -1
- package/dist/{file-watcher-BPH4wR8R.js → file-watcher-CxStDuTR.js} +2 -2
- package/dist/{file-watcher-BPH4wR8R.js.map → file-watcher-CxStDuTR.js.map} +1 -1
- package/dist/{headless-ui-vA7lv8m2.js → headless-ui-DC1Qus7M.js} +2 -2
- package/dist/{headless-ui-vA7lv8m2.js.map → headless-ui-DC1Qus7M.js.map} +1 -1
- package/dist/{interactive-jk3IGgns.js → interactive-DeNrHRZE.js} +2 -2
- package/dist/{interactive-jk3IGgns.js.map → interactive-DeNrHRZE.js.map} +1 -1
- package/dist/{mcp-DE2AonGF.js → mcp-Bnjc-Qsz.js} +2 -2
- package/dist/{mcp-DE2AonGF.js.map → mcp-Bnjc-Qsz.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-pPEIwc78.js → mcp-prompt-streaming-Va6vRL7E.js} +4 -4
- package/dist/{mcp-prompt-streaming-pPEIwc78.js.map → mcp-prompt-streaming-Va6vRL7E.js.map} +1 -1
- package/dist/{non-interactive-CEGz0nDY.js → non-interactive-ZACUU6DC.js} +2 -2
- package/dist/{non-interactive-CEGz0nDY.js.map → non-interactive-ZACUU6DC.js.map} +1 -1
- package/dist/{orchestrator-tools-BZ4Nzw6a.js → orchestrator-tools-BI3suN6p.js} +3 -3
- package/dist/{orchestrator-tools-BZ4Nzw6a.js.map → orchestrator-tools-BI3suN6p.js.map} +1 -1
- package/dist/{package-manager-BZjKEDO2.js → package-manager-DgRcS6CY.js} +2 -2
- package/dist/{package-manager-BZjKEDO2.js.map → package-manager-DgRcS6CY.js.map} +1 -1
- package/dist/{pi-D48qAwlf.js → pi-DbEYScTs.js} +11 -11
- package/dist/{pi-D48qAwlf.js.map → pi-DbEYScTs.js.map} +1 -1
- package/dist/{playground-DYGJwugo.js → playground-xa1G6pym.js} +8 -8
- package/dist/playground-xa1G6pym.js.map +1 -0
- package/dist/{posthog-BTvVhvBY.js → posthog-Dk8S5c6h.js} +2 -2
- package/dist/{posthog-BTvVhvBY.js.map → posthog-Dk8S5c6h.js.map} +1 -1
- package/dist/{posthog-integration-BQh-YQAP.js → posthog-integration-BG5Y9Fb4.js} +12 -12
- package/dist/{posthog-integration-BQh-YQAP.js.map → posthog-integration-BG5Y9Fb4.js.map} +1 -1
- package/dist/{provisioning-Dw3B2T_b.js → provisioning-e7J3SvpF.js} +3 -3
- package/dist/{provisioning-Dw3B2T_b.js.map → provisioning-e7J3SvpF.js.map} +1 -1
- package/dist/{queue-tools-DEbzMDrF.js → queue-tools-C3D_nwy_.js} +3 -3
- package/dist/{queue-tools-DEbzMDrF.js.map → queue-tools-C3D_nwy_.js.map} +1 -1
- package/dist/{registry-Dv6JVm5r.js → registry-Bw-e1Fes.js} +5 -5
- package/dist/{registry-Dv6JVm5r.js.map → registry-Bw-e1Fes.js.map} +1 -1
- package/dist/{security-BaggjIE4.js → security-BUg5_2uC.js} +5 -5
- package/dist/{security-BaggjIE4.js.map → security-BUg5_2uC.js.map} +1 -1
- package/dist/{setup-utils-CnW0Zsu8.js → setup-utils-CzMg2Vpy.js} +8 -8
- package/dist/{setup-utils-CnW0Zsu8.js.map → setup-utils-CzMg2Vpy.js.map} +1 -1
- package/dist/{start-tui-SpyGz7wM.js → start-tui-Kt61g7LE.js} +30 -30
- package/dist/start-tui-Kt61g7LE.js.map +1 -0
- package/dist/{steps-ClfUajTv.js → steps-De2a1a0X.js} +7 -7
- package/dist/{steps-ClfUajTv.js.map → steps-De2a1a0X.js.map} +1 -1
- package/dist/{store-Cmy0pN1R.js → store-DDrR7nF6.js} +6 -6
- package/dist/store-DDrR7nF6.js.map +1 -0
- package/dist/{subagent-tYlbbkJt.js → subagent-cD2JOzo1.js} +2 -2
- package/dist/{subagent-tYlbbkJt.js.map → subagent-cD2JOzo1.js.map} +1 -1
- package/dist/{task-B8QfEVcu.js → task-FBY3mllc.js} +12 -12
- package/dist/{task-B8QfEVcu.js.map → task-FBY3mllc.js.map} +1 -1
- package/dist/{task-stream-BRSWhbXQ.js → task-stream-BjTFIY4l.js} +4 -4
- package/dist/{task-stream-BRSWhbXQ.js.map → task-stream-BjTFIY4l.js.map} +1 -1
- package/dist/{tasks-DjEvyWQJ.js → tasks-BjevyqMO.js} +2 -2
- package/dist/{tasks-DjEvyWQJ.js.map → tasks-BjevyqMO.js.map} +1 -1
- package/dist/{telemetry-EPB2n_f6.js → telemetry-Asp60nwm.js} +3 -3
- package/dist/{telemetry-EPB2n_f6.js.map → telemetry-Asp60nwm.js.map} +1 -1
- package/dist/{terminal-DJ4Gaupr.js → terminal-CVgx_zHz.js} +11 -11
- package/dist/{terminal-DJ4Gaupr.js.map → terminal-CVgx_zHz.js.map} +1 -1
- package/dist/{tools-CB0Vfc6r.js → tools-CPwnElLN.js} +6 -6
- package/dist/{tools-CB0Vfc6r.js.map → tools-CPwnElLN.js.map} +1 -1
- package/dist/{wizard-abort-Db_YNkB2.js → wizard-abort-DKpVH-t6.js} +3 -3
- package/dist/{wizard-abort-Db_YNkB2.js.map → wizard-abort-DKpVH-t6.js.map} +1 -1
- package/dist/{wizard-abort-DD-kkQaq.js → wizard-abort-owSE9WC8.js} +1 -1
- package/dist/{yara-hooks-BvyFD2Nb.js → yara-hooks-D-QD1ZCB.js} +7 -6
- package/dist/yara-hooks-D-QD1ZCB.js.map +1 -0
- package/dist/yara-hooks-DPo3t8nU.js +2 -0
- package/package.json +2 -2
- package/dist/agent-interface-Yjknz6Al.js.map +0 -1
- package/dist/analytics-CkNv3N4o.js +0 -2
- package/dist/debug-D0T44879.js.map +0 -1
- package/dist/playground-DYGJwugo.js.map +0 -1
- package/dist/start-tui-SpyGz7wM.js.map +0 -1
- package/dist/store-Cmy0pN1R.js.map +0 -1
- package/dist/yara-hooks-BvyFD2Nb.js.map +0 -1
- package/dist/yara-hooks-CuW_b30M.js +0 -2
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"debug-D0T44879.js","names":["errResult","join","sep"],"sources":["../src/lib/headless-mode.ts","../src/env.ts","../src/lib/version.ts","../src/lib/constants.ts","../src/ui/wizard-ui.ts","../src/lib/health-checks/statuspage.ts","../src/lib/health-checks/incidentio.ts","../src/lib/health-checks/endpoints.ts","../src/lib/health-checks/readiness.ts","../src/ui/logging-ui.ts","../src/ui/index.ts","../src/utils/paths.ts","../src/utils/debug.ts"],"sourcesContent":["/**\n * Headless mode — the published-build, non-interactive run path.\n *\n * The headless flag and `--ci` both drive a non-interactive install\n * (session.ci === true), but through dedicated entry points so they can\n * diverge: runHeadlessInstall → runWizardHeadless for headless,\n * runCIInstall → runWizardCI for `--ci`. Both delegate to one shared pipeline\n * (runNonInteractive) today; the only forks are the api-key prefixes accepted\n * (ci-install) and the analytics build tag (the mode passed to the runner).\n *\n * The flag is deliberately named `--headless-DONOTUSE-EXPERIMENTAL` and hidden\n * from `--help`: the contract is still unstable and subject to breaking\n * changes, so it must not be advertised or relied on by external callers. This\n * module is the single source of truth for the flag's name and detection — keep\n * the scary name out of every other file so a future rename is one edit here.\n */\n\nimport type { Options } from 'yargs';\n\n/**\n * The on-CLI flag name. Intentionally ugly + undocumented; do not surface it in\n * `--help`, the README, or user-facing error messages.\n */\nexport const HEADLESS_FLAG = 'headless-DONOTUSE-EXPERIMENTAL';\n\n/**\n * The yargs option declaration for the headless flag. Declared per-command\n * (basic integration + audit) rather than globally, so no other command\n * accepts it. Spread into a command's `options` to opt it into headless.\n */\nexport const headlessOption: Record<string, Options> = {\n [HEADLESS_FLAG]: {\n default: false,\n // EXPERIMENTAL + UNSTABLE: the non-interactive published-build run path.\n // Declared unconditionally (unlike --ci) so it works in the shipped\n // package, but hidden and intentionally ugly-named — the contract may\n // break without notice, so it must not be advertised.\n describe:\n 'EXPERIMENTAL — do not use. Unstable, subject to breaking changes.',\n type: 'boolean',\n hidden: true,\n },\n};\n\n/**\n * Read the headless signal off a parsed argv / options bag. yargs always sets\n * the value under the declared key (`HEADLESS_FLAG`), so reading that key is\n * reliable regardless of camel-case expansion.\n */\nexport function isHeadless(options: Record<string, unknown>): boolean {\n return options[HEADLESS_FLAG] === true;\n}\n\n// `--region` only means something non-interactively (API-key auth has no OAuth\n// token response to read `posthog_region` from), so only headless-capable\n// commands declare it.\nexport const regionOption: Record<string, Options> = {\n region: {\n describe: 'PostHog cloud region\\nenv: POSTHOG_WIZARD_REGION',\n choices: ['us', 'eu'],\n type: 'string',\n hidden: true,\n },\n};\n","/**\n * Central environment variable access for the PostHog wizard.\n *\n * ── Build-time constants ────────────────────────────────────────────\n * Inlined by tsdown's `env` option at compile time. After build, the\n * runtime value of these env vars has zero effect on the wizard.\n *\n * ── Runtime variables ───────────────────────────────────────────────\n * Read through `runtimeEnv()` with a typed allowlist. This makes every\n * runtime dependency on the environment explicit and grep-able.\n *\n * ── Direct process.env access ───────────────────────────────────────\n * Reserved for subprocess environment configuration (writes) and\n * vendored code. Production source outside those cases should use\n * this module instead.\n */\n\nimport { HEADLESS_FLAG } from '@lib/headless-mode';\n\n// ── Build-time constants ─────────────────────────────────────────────\n// tsdown replaces `process.env.NODE_ENV` with a string literal.\n// After build these are just `\"production\"`, `false`, etc.\n\nexport const NODE_ENV = process.env.NODE_ENV as string;\nexport const IS_DEV =\n process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';\n\n/**\n * True only in published/production builds. tsdown inlines\n * `process.env.NODE_ENV` as the literal `\"production\"` at build time, so this\n * collapses to `true` in `dist/` and stays `false` for `tsx`/dev/test runs\n * (where NODE_ENV is unset, `development`, or `test`). Used to gate features\n * that aren't supported in the shipped package — e.g. `--ci` mode.\n */\nexport const IS_PRODUCTION_BUILD = process.env.NODE_ENV === 'production';\n\n/** 'cloud' when launched with the experimental headless flag, else 'local' — resolved once from argv at launch. */\nexport const RUN_SURFACE: 'cloud' | 'local' = process.argv.some(\n (a) => a === `--${HEADLESS_FLAG}` || a.startsWith(`--${HEADLESS_FLAG}=`),\n)\n ? 'cloud'\n : 'local';\n\n// ── Runtime environment ──────────────────────────────────────────────\n\n/**\n * Exhaustive allowlist of env vars the wizard reads at runtime.\n * Add new keys here when a new runtime dependency is needed.\n */\ntype RuntimeEnvKey =\n // CI-build-only flag overrides (see utils/ci-flag-overrides.ts).\n // Deliberately NOT POSTHOG_WIZARD_-prefixed: yargs .env('POSTHOG_WIZARD')\n // would claim it as an unknown CLI option and strict-reject the run.\n | 'WIZARD_CI_FLAG_OVERRIDES'\n | 'WIZARD_CI_EXCLUDE_TASKS'\n // Wizard CLI configuration (yargs POSTHOG_WIZARD_ prefix)\n | 'POSTHOG_WIZARD_BENCHMARK_CONFIG'\n | 'POSTHOG_WIZARD_BENCHMARK_FILE'\n | 'POSTHOG_WIZARD_LOG_DIR'\n | 'POSTHOG_WIZARD_DEBUG'\n // Identity of the PostHog task run whose sandbox launched this wizard. Set by\n // the sandbox for every run it starts, agent or wizard. Deliberately NOT\n // POSTHOG_WIZARD_-prefixed, for the same reason as the two keys above:\n // yargs .env('POSTHOG_WIZARD') would claim them as CLI options and\n // .strictOptions() would reject the run unless the wizard also declared them,\n // which would tie every sandbox deploy to an npm release of this package.\n | 'POSTHOG_TASK_RUN_ID'\n | 'POSTHOG_TASK_ID'\n | 'POSTHOG_HANDOFF_OUTPUT_PATH'\n // Local/CI escape hatch to disable Warlock scanning without the PostHog flag.\n | 'POSTHOG_WIZARD_WARLOCK_DISABLED'\n | 'DEBUG'\n // Agent / MCP\n | 'MCP_URL'\n | 'POSTHOG_API_KEY'\n // Platform: terminal detection\n | 'TERM'\n | 'TERM_PROGRAM'\n | 'TERMINAL_EMULATOR'\n | 'CI'\n | 'WT_SESSION'\n | 'TERMINUS_SUBLIME'\n | 'ConEmuTask'\n // Platform: paths\n | 'APPDATA'\n | 'OPENCODE_CONFIG_DIR'\n | 'XDG_CONFIG_HOME';\n\n/** Read a runtime environment variable. Only allowlisted keys compile. */\nexport function runtimeEnv(key: RuntimeEnvKey): string | undefined {\n return process.env[key];\n}\n\n/**\n * The PostHog task run that launched this wizard, when one did. A cloud run's\n * sandbox exports both ids into the wizard's environment; every local run\n * leaves them undefined. Resolved once at launch, like RUN_SURFACE above.\n */\nexport const TASK_RUN_ID: string | undefined =\n runtimeEnv('POSTHOG_TASK_RUN_ID') || undefined;\nexport const TASK_ID: string | undefined =\n runtimeEnv('POSTHOG_TASK_ID') || undefined;\n","// Auto-generated by scripts/generate-version.js — do not edit\nexport const VERSION = '2.72.0';\n","/**\n * Shared constants for the PostHog wizard.\n */\n\nimport { VERSION } from './version';\n\n// ── Models ──────────────────────────────────────────────────────────\n\n/**\n * Default model for agent runs. Bare model IDs (no `anthropic/` prefix) so the\n * LLM gateway's Bedrock fallback can match map_to_bedrock_model().\n */\nexport const DEFAULT_AGENT_MODEL = 'claude-sonnet-4-6';\n\n/** Next sonnet generation (a `MODEL_FLAG_VARIANTS` key in the switchboard). */\nexport const SONNET_5_MODEL = 'claude-sonnet-5';\n\n/**\n * Cheaper, faster model for mechanical agent work (e.g. repo classification\n * during source-map detection). Passed via AgentConfig.modelOverride.\n */\nexport const HAIKU_MODEL = 'claude-haiku-4-5-20251001';\n\n/** Undated haiku, for scan triage — the alias tracks the current 4.5 release rather than pinning one. */\nexport const HAIKU_TRIAGE_MODEL = 'claude-haiku-4-5';\n\n/**\n * Larger model for planning / hard work. Named the switchboard could route to\n * from `PROGRAM_BINDINGS[id].model` or `contextMillOverride`.\n */\nexport const OPUS_MODEL = 'claude-opus-4-8';\n\n// The only openai models the wizard runs.\nexport const GPT5_6_LUNA_MODEL = 'openai/gpt-5.6-luna';\nexport const GPT5_6_TERRA_MODEL = 'openai/gpt-5.6-terra';\nexport const GPT5_6_SOL_MODEL = 'openai/gpt-5.6-sol';\n\n// ── Agent runner routing axes ────────────────────────────────────────\n\n/**\n * The two agent runner routing axes: **harness** (which agent SDK drives the LLM)\n * and **sequence** (which pipeline shape orchestrates the work). Single source\n * of truth for yargs `choices`, session fields, the runner registry, and tests\n * — `Object.values(Harness)` gives an iterable of the values when an array is\n * needed. Adding a member is enough to pick it up everywhere.\n *\n * Naming matches the directory layout — see `src/lib/agent/runner/harness/`\n * and `src/lib/agent/runner/sequence/`.\n */\nexport enum Harness {\n anthropic = 'anthropic',\n pi = 'pi',\n}\n\nexport enum Sequence {\n linear = 'linear',\n orchestrator = 'orchestrator',\n}\n\n/**\n * What kind of call produced a gateway generation — the `call_type` trace tag.\n * Splits a program's LLM spend by workload. Every member is sent explicitly so\n * an absent value means \"old build\", not \"agent\".\n */\nexport enum CallType {\n /** The agent doing the work the user asked for. */\n agent = 'agent',\n /** Warlock's classifier deciding whether a YARA match is a true positive. */\n yaraTriage = 'yara-triage',\n /** The cheap repo scan that classifies which projects a program acts on. */\n detection = 'detection',\n}\n\n// ── Integration / CLI ───────────────────────────────────────────────\n\n/**\n * Detection order matters: put framework-specific integrations BEFORE basic language fallbacks.\n */\nexport enum Integration {\n // Frameworks\n nextjs = 'nextjs',\n nuxt = 'nuxt',\n vue = 'vue',\n reactRouter = 'react-router',\n tanstackStart = 'tanstack-start',\n tanstackRouter = 'tanstack-router',\n reactNative = 'react-native',\n angular = 'angular',\n astro = 'astro',\n django = 'django',\n flask = 'flask',\n fastapi = 'fastapi',\n laravel = 'laravel',\n sveltekit = 'sveltekit',\n flutter = 'flutter',\n kmp = 'kmp',\n swift = 'swift',\n android = 'android',\n rails = 'rails',\n elixir = 'elixir',\n go = 'go',\n rust = 'rust',\n // Must stay after kmp/swift/android: those claim gradle projects first.\n java = 'java',\n\n // Language fallbacks. Keep javascriptNode last: it matches any package.json.\n python = 'python',\n ruby = 'ruby',\n javascript_web = 'javascript_web',\n javascriptNode = 'javascript_node',\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\n// ── Environment ──────────────────────────────────────────────────────\n\nimport { IS_DEV } from '@env';\nimport {\n CONTEXT_MILL_LOCAL_URL,\n getLocalDev,\n POSTHOG_LOCAL_URL,\n} from './local-dev';\nexport { IS_DEV };\nexport const DEBUG = false;\n\n// ── URLs ─────────────────────────────────────────────────────────────\n\nexport const DEFAULT_URL = IS_DEV\n ? POSTHOG_LOCAL_URL\n : 'https://us.posthog.com';\n/**\n * Region-agnostic PostHog app URL. Resolves to us.posthog.com or\n * eu.posthog.com server-side based on the signed-in user's profile.\n * Use this for share-with-user links (e.g. settings pages) so they\n * land on the right region without us needing to know it client-side.\n */\nexport const POSTHOG_APP_URL = IS_DEV\n ? POSTHOG_LOCAL_URL\n : 'https://app.posthog.com';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? POSTHOG_LOCAL_URL\n : 'https://us.i.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\n/** Public status page, linked from transient-failure guidance (e.g. OAuth server_error). */\nexport const POSTHOG_STATUS_PAGE_URL = 'https://www.posthogstatus.com';\nexport const CONTEXT_MILL_URL = 'https://github.com/PostHog/context-mill';\n/**\n * Latest context-mill release page — the BYOAI download link shown in\n * the privacy panel. Deliberately the release PAGE, not a direct asset\n * URL: asset URLs are ~89 chars and hard-wrap inside the 64-col panel,\n * which corrupts terminal copy/paste with a mid-URL line break. This\n * stays under one line; the panel names the exact asset to grab.\n */\nexport const CONTEXT_MILL_RELEASES_URL =\n 'https://github.com/PostHog/context-mill/releases/latest';\nexport const POSTHOG_DOCS_URL = 'https://posthog.com/docs';\nexport const POSTHOG_WIZARD_REPO_URL = 'https://github.com/PostHog/wizard';\nexport const POSTHOG_TERMS_URL = 'https://posthog.com/terms';\nexport const POSTHOG_PRIVACY_URL = 'https://posthog.com/privacy';\nexport const POSTHOG_ORG_AI_SETTINGS_URL =\n 'https://app.posthog.com/settings/organization-details#setting=organization-ai-consent';\nexport const WIZARD_CONTACT_EMAIL = 'wizard@posthog.com';\n\n/** Remote base URL for fetching the skill menu + downloading skills. */\nexport const REMOTE_SKILLS_BASE_URL =\n 'https://github.com/PostHog/context-mill/releases/latest/download';\n/** Alias of `@lib/local-dev`'s constant, kept for existing importers. */\nexport const LOCAL_SKILLS_BASE_URL = CONTEXT_MILL_LOCAL_URL;\n\n/**\n * Driven by `--local-context-mill`, NOT `--local-mcp` (which used to select\n * both). Takes no argument on purpose: callers can't pass the wrong flag.\n */\nexport function getSkillsBaseUrl(): string {\n return getLocalDev().localContextMill\n ? LOCAL_SKILLS_BASE_URL\n : REMOTE_SKILLS_BASE_URL;\n}\n\n// ── Analytics (internal) ──────────────────────────────────────────────\n\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const ANALYTICS_TEAM_TAG = 'docs-and-wizard';\n\n// ── OAuth / Auth ────────────────────────────────────────────────────\n\nexport const OAUTH_PORTS = [8239, 8238, 8240, 8237, 8236, 8235] as const;\nexport const POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';\nexport const POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';\nexport const POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';\nexport const POSTHOG_PROXY_CLIENT_ID = POSTHOG_US_CLIENT_ID;\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_TOKEN_';\n\n/**\n * Scopes the wizard requests during the agentic provisioning signup flow.\n *\n * Each entry is justified by what the wizard's agent step does after signup:\n * - user:read identify the user for analytics + agent context\n * - project:read look up the freshly-provisioned project\n * - llm_gateway:read authenticate to gateway.{us,eu}.posthog.com/wizard\n * (the agent's LLM calls — without this scope, every\n * agent message returns 401)\n * - query:read run HogQL queries when the agent needs data\n * - dashboard:write create the onboarding dashboard during setup\n * - insight:write create the onboarding insights during setup\n * - notebook:write upload the events-audit report as a PostHog notebook\n * in step 6 of the events-audit skill (notebooks-create\n * MCP tool requires this scope)\n * - event_definition:write\n * create event definitions from the completed wizard\n * session's event plan\n *\n * Must be a subset of `ALLOWED_PROVISIONING_SCOPES` in\n * `ee/api/agentic_provisioning/views.py` on the backend.\n */\nexport const WIZARD_PROVISIONING_SCOPES = [\n 'user:read',\n 'project:read',\n 'llm_gateway:read',\n 'dashboard:write',\n 'insight:write',\n 'query:read',\n 'notebook:write',\n 'event_definition:write',\n] as const;\n\n/**\n * Scopes the wizard requests during the OAuth login flow. Superset of\n * `WIZARD_PROVISIONING_SCOPES` with scopes that only apply to the login\n * path and are not in the provisioning allowlist:\n * - health_issue:read used by `wizard doctor`\n * - wizard_session:read list / retrieve / stream sessions\n * - wizard_session:write stream run state to /api/projects/{id}/wizard/sessions/\n * - event_definition:write\n * create event definitions when a session completes\n * - organization:read read `organization.is_ai_data_processing_approved`\n * from /api/users/@me/ for the AI opt-in gate\n *\n * NOTE: every scope here must be within the wizard OAuth application's\n * server-side scope ceiling (`OAuthApplication.scopes` in posthog, set\n * via Django admin on BOTH prod regions). A scope outside the ceiling\n * does NOT fail the authorize request — the server silently clamps the\n * request to the ceiling (`clamp_scopes_to_ceiling` in posthog) and the\n * token comes back without it. Separately, the consent screen lets the\n * user deselect any scope the app doesn't mark required. Both paths\n * yield a granted `scope` narrower than requested, with no error, so\n * never assume the token carries this list — the token response's\n * `scope` field is the truth, and `missingOAuthScopes` (utils/oauth.ts)\n * diffs it at login. Ceiling procedure: the \"scope-ceiling-invalid-scope\"\n * runbook in PostHog/runbooks. Keep its worked example in sync when this\n * list changes.\n */\nexport const WIZARD_OAUTH_SCOPES = [\n ...WIZARD_PROVISIONING_SCOPES,\n 'health_issue:read',\n 'wizard_session:read',\n 'wizard_session:write',\n 'organization:read',\n] as const;\n\n// ── Wizard run / variants ───────────────────────────────────────────\n\nexport const WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';\nexport const WIZARD_REMARK_EVENT_NAME = 'wizard remark';\n/** Boolean feature flag that routes a run to the experimental orchestrator runner. */\nexport const WIZARD_ORCHESTRATOR_FLAG_KEY = 'wizard-orchestrator';\n/** Multivariate flag: per-stage orchestrator overrides ride each variant's JSON payload (`{stage: {model?, effort?}}`). */\nexport const WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY =\n 'wizard-orchestrator-override';\n/** Boolean flag: on → pi for self-driving. Payload carries `{model, effort?, harness?, sequence?}` (model = a `MODEL_FLAG_VARIANTS` key); missing/invalid payload keeps the non-flagged default. */\nexport const WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY =\n 'wizard-self-driving-use-pi-harness';\n/** Boolean flag: agentic project scoping for non-interactive basic-integration runs. */\nexport const WIZARD_BASIC_INTEGRATION_AGENTIC_DETECTION_FLAG_KEY =\n 'wizard-basic-integration-agentic-detection';\n/** Boolean flag: the orchestrator queues the program's runner-seeded tasks (the warehouse step). Off, no task is queued and the run is byte-identical to a no-sources project. */\nexport const WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY =\n 'wizard-orchestrator-seeded-tasks';\n// Reading a flag enters this run into that flag's experiment, so a closed set — not a\n// `wizard-` prefix anyone can name into — decides what a run evaluates. Test-pinned exhaustive.\nexport const WIZARD_FLAG_KEYS = [\n WIZARD_ORCHESTRATOR_FLAG_KEY,\n WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY,\n WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY,\n WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY,\n WIZARD_BASIC_INTEGRATION_AGENTIC_DETECTION_FLAG_KEY,\n] as const;\n/** User-Agent for wizard HTTP requests and MCP server identification. */\nexport const WIZARD_USER_AGENT = `posthog/wizard; version: ${VERSION}`;\n\n/**\n * User-Agent for a specific program's MCP calls, tagged with `program: <id>` so the\n * backend can attribute work per program (e.g. the `self-driving` program's warehouse\n * sources are recorded as `created_via=self_driving` rather than plain `wizard`). The\n * base `posthog/wizard` token is preserved, so anything keying only on that still matches.\n */\nexport function wizardUserAgentForProgram(programId?: string): string {\n return programId\n ? `${WIZARD_USER_AGENT}; program: ${programId}`\n : WIZARD_USER_AGENT;\n}\n\n// ── HTTP headers ─────────────────────────────────────────────────────\n\n/** Header prefix for PostHog properties (e.g. X-POSTHOG-PROPERTY-VARIANT). */\nexport const POSTHOG_PROPERTY_HEADER_PREFIX = 'X-POSTHOG-PROPERTY-';\n/** Header prefix for PostHog feature flags. */\nexport const POSTHOG_FLAG_HEADER_PREFIX = 'X-POSTHOG-FLAG-';\n\n// ── Timeouts ─────────────────────────────────────────────────────────\n\n/** Timeout for framework / project detection probes (ms). */\nexport const DETECTION_TIMEOUT_MS = 10_000;\n\n/** Timeout for the agentic project scan (ms); past it the run falls back to root detection. */\nexport const AGENTIC_DETECTION_TIMEOUT_MS = 60_000;\n\n/**\n * Timeout for the OAuth authorization flow (ms).\n *\n * How long the user has to complete the browser login. The authorization\n * code is minted at approval and exchanged immediately on callback, so the\n * server-side code expiry (`AUTHORIZATION_CODE_EXPIRE_SECONDS`, 5 minutes)\n * bounds only the approval→exchange gap — manual-paste users have 5 minutes\n * from approval to submit the code — not how long this window may stay open.\n */\nexport const OAUTH_TIMEOUT_MS = 1_800_000;\n","/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nimport type { SettingsConflict } from '@lib/agent/claude-settings';\nimport type { WizardReadinessResult } from '@lib/health-checks/readiness';\nimport type { ApiUser } from '@lib/api';\nimport type { Credentials, TaskNotice } from '@lib/wizard-session';\nimport type {\n AskAnswers,\n OutroData,\n PendingQuestion,\n} from '@lib/wizard-session';\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n Skipped = 'skipped',\n}\n\nexport function isTaskStatus(value: string): value is TaskStatus {\n return (Object.values(TaskStatus) as string[]).includes(value);\n}\n\n/**\n * One assistant turn's token usage, for the hidden Ctrl+T token/cost HUD.\n * `model` is the model that produced *this* turn (e.g. the SDK's\n * `message.message.model`) — a subagent can run on a different model than\n * the main session, and some programs override to Haiku, so pricing must key\n * off the per-turn model rather than a single run-wide assumption. Omit only\n * when the caller genuinely has no model context (falls back to Sonnet\n * pricing — see `pricePerMtokForModel` in `@lib/agent/token-pricing`).\n */\nexport interface TokenUsageDelta {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n cacheCreation5m: number;\n cacheCreation1h: number;\n model?: string;\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\n/**\n * Context passed to `showAuthError` so the screen can pick the right copy.\n *\n * `hasSettingsConflict` is true when a Claude Code settings file (project,\n * project-local, the user's global config, or managed) actually overrides the\n * LLM Gateway auth. `conflicts` carries the exact files and keys so the screen\n * can name them. When there is no conflict, the 401 has a different cause (bad\n * PAT prefix, missing scope, expired key, region mismatch) and we should not\n * advise the user to log out of Claude Code.\n */\nexport interface AuthErrorDetail {\n hasSettingsConflict: boolean;\n conflicts?: SettingsConflict[];\n /**\n * True when the agent SDK authenticated from a stored Claude login\n * (`apiKeySource: \"/login managed key\"`) instead of the wizard's gateway\n * token — conflicting Anthropic credentials. Takes priority in the screen.\n */\n usingManagedLogin?: boolean;\n /** Human-readable places a conflicting Anthropic credential may live. */\n credentialPlaces?: string[];\n /**\n * True when a pre-run refresh already failed on a dead grant. The login is\n * gone and re-running is the only fix, so this outranks every other branch —\n * none of the usual advice (key type, scopes, region) applies.\n */\n sessionExpired?: boolean;\n logFilePath: string;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n /** Success outro with a plain text message. */\n outro(message: string): void;\n /**\n * Error outro. Sets structured outroData and transitions run phase so\n * the router advances to the outro screen. Use for abort/failure paths\n * that need a custom error render — do NOT build the outroData by\n * mutating session directly (nanostore holds a shallow copy).\n */\n outroError(data: OutroData): void;\n /** Resolves when the user dismisses the outro screen (presses any key).\n * Lets the abort path wait for the user to read the error before the\n * process exits. Resolves immediately in non-TUI environments. */\n waitForOutroDismissed(): Promise<void>;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: Credentials): void;\n\n /**\n * Replace the credentials after a token refresh. Same store write as\n * {@link setCredentials} without the `auth complete` capture — the user\n * authenticated once, and a refresh is not a second login.\n */\n setAccessToken(credentials: Credentials): void;\n\n /**\n * Persist the user's `role_at_organization` once it's been fetched from\n * `/api/users/@me/`. Drives role-tailored prompt suggestions on the\n * McpSuggestedPromptsScreen. Pass `null` to clear / when unknown.\n */\n setRoleAtOrganization(role: string | null): void;\n\n /**\n * Persist the full user payload from `/api/users/@me/` so downstream\n * screens can read account context (current org, team, plan, email,\n * preferences, etc.) without re-fetching. Pass `null` to clear or\n * when the request failed.\n */\n setApiUser(user: ApiUser | null): void;\n\n /**\n * Park until the org's AI opt-in gate clears\n * (`organization.is_ai_data_processing_approved === true`, or the\n * program never registered the gate — requiresAi: false / no auth\n * step / CI session). The agent runner awaits this after setApiUser\n * and BEFORE skill install or agent start: this is the enforcement\n * point that keeps source on the machine while the TUI shows\n * AiOptInRequiredScreen. Resolves immediately in non-TUI\n * environments (CI auto-consents to AI usage).\n */\n waitForAiOptIn(): Promise<void>;\n\n /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */\n showBlockingOutage(result: WizardReadinessResult): Promise<void>;\n\n /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */\n setReadinessWarnings(result: WizardReadinessResult): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void>;\n\n /**\n * Resolve with an OAuth authorization code the user enters by hand — the\n * fallback for headless/remote shells where the browser can't reach the\n * local callback server. The OAuth flow races this against the callback\n * server. Implementations that can't prompt (CI/logging) never resolve.\n */\n waitForManualAuthCode(): Promise<string>;\n\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n /**\n * Show an optional step's notice and return whether to keep that step. Hosts\n * that cannot prompt resolve false: a step nobody can answer must not run.\n */\n showTaskNotice(notice: TaskNotice): Promise<boolean>;\n\n /**\n * Dismiss an in-flight task notice as declined. Called when the offer times\n * out: the notice sits in front of the run's final steps, so left unanswered\n * it would hold the report behind a modal nobody is looking at.\n */\n cancelTaskNotice(): void;\n\n /** Show auth error overlay when Anthropic API returns 401. */\n showAuthError(detail?: AuthErrorDetail): void;\n\n /** Show the session-timeout overlay when the OAuth login window expires. */\n showSessionTimeout(): void;\n\n /**\n * Open the wizard_ask overlay and resolve with the user's answers.\n * Implementations that can't ask (CI/logging) reject so the bridge can\n * surface a clear \"not available\" error to the agent.\n */\n requestQuestion(question: PendingQuestion): Promise<AskAnswers>;\n\n /**\n * Dismiss the in-flight wizard_ask overlay, resolving its request with\n * cancelled sentinels. No-op when nothing is pending. The ask bridge calls\n * this on timeout so a stale pending question can't block later asks.\n */\n cancelPendingQuestion(): void;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n /** Direct PostHog authorize URL, shown in the manual-paste modal. */\n setAuthorizeUrl(url: string | null): void;\n\n // ── Task tracking from SDK TaskCreate/TaskUpdate events ───────────\n // Receives the full materialised task list each call. The caller (agent\n // loop) maintains a Map<taskId, …> from incremental Task* events and\n // re-emits the snapshot here, preserving the existing store semantics.\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n\n // ── Dashboard URL emitted by the agent via [DASHBOARD_URL] marker ──\n setDashboardUrl(url: string): void;\n\n /** Current \"stage of work\" — derived from the active tool call. Drives the\n * Visualizer tab's NOW PLAYING display. Pass an AgentPhase value. */\n setStage(stage: string): void;\n\n // ── Notebook URL emitted by the agent via [NOTEBOOK_URL] marker ──\n setNotebookUrl(url: string): void;\n\n /** Handoff doc from the `publish_handoff` tool; the task-stream push carries it as `handoff_text`. */\n setHandoffText(text: string): void;\n\n /** Accumulate one assistant turn's token usage into the hidden Ctrl+T\n * token/cost HUD's running estimate. No-op outside the TUI. */\n addTokenUsage(delta: TokenUsageDelta): void;\n\n /** Reconcile the HUD's running cost estimate to the SDK's authoritative\n * `total_cost_usd` once the agent run completes. No-op outside the TUI. */\n setFinalTokenCostUsd(costUsd: number): void;\n\n // ── Outro payload built by agent-runner ──\n // Replaces the direct `session.outroData = X` mutation that breaks once\n // setKey-based store mutations have forked the session reference.\n setOutroData(data: OutroData): void;\n\n // ── Generic frameworkContext setter for program file watchers ─────\n setFrameworkContext(key: string, value: unknown): void;\n\n /** Read a frameworkContext value from the LIVE session (store may have\n * forked the reference the runner holds). Used by run configs to read\n * values written by post-auth screens (e.g. the source-maps picker). */\n getFrameworkContext(key: string): unknown;\n\n /** Park until the named program step's gate predicate flips true. Resolves\n * immediately if the step has no gate. Mirrors waitForAiOptIn for any\n * post-auth interactive step the agent run must wait on. */\n waitForGate(stepId: string): Promise<void>;\n}\n","import {\n ServiceHealthStatus,\n type BaseHealthResult,\n type ComponentHealthResult,\n} from './types';\n\n// ---------------------------------------------------------------------------\n// Statuspage.io v2 API helpers\n// https://metastatuspage.com/api\n//\n// status.json – page-level rollup; indicator is one of: none | minor | major | critical\n// summary.json – same rollup + component list; component status is one of:\n// operational | degraded_performance | partial_outage | major_outage | under_maintenance\n// https://support.atlassian.com/statuspage/docs/show-service-status-with-components\n// ---------------------------------------------------------------------------\n\ninterface StatuspageStatusResponse {\n status?: { indicator?: string; description?: string };\n}\n\ninterface StatuspageSummaryResponse extends StatuspageStatusResponse {\n components?: { id: string; name: string; status: string }[];\n}\n\nfunction mapIndicator(v: string | null | undefined): ServiceHealthStatus {\n switch (v) {\n case 'none':\n return ServiceHealthStatus.Healthy;\n case 'minor':\n return ServiceHealthStatus.Degraded;\n case 'major':\n case 'critical':\n return ServiceHealthStatus.Down;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction mapComponentRaw(v: string | null | undefined): ServiceHealthStatus {\n switch (v) {\n case 'operational':\n return ServiceHealthStatus.Healthy;\n case 'degraded_performance':\n case 'under_maintenance':\n return ServiceHealthStatus.Degraded;\n case 'partial_outage':\n case 'major_outage':\n return ServiceHealthStatus.Down;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction errResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Degraded, error };\n}\n\nasync function fetchStatuspageIndicator(\n url: string,\n timeoutMs = 5000,\n): Promise<BaseHealthResult> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) return errResult(`HTTP ${res.status}`);\n\n const data = (await res.json()) as StatuspageStatusResponse;\n const indicator = data.status?.indicator ?? null;\n return {\n status: mapIndicator(indicator),\n rawIndicator: indicator ?? undefined,\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError')\n return errResult('Request timed out');\n return errResult(e instanceof Error ? e.message : 'Unknown error');\n }\n}\n\nasync function fetchStatuspageSummary(\n url: string,\n timeoutMs = 5000,\n): Promise<ComponentHealthResult> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) return errResult(`HTTP ${res.status}`);\n\n const data = (await res.json()) as StatuspageSummaryResponse;\n const indicator = data.status?.indicator ?? null;\n const overall = mapIndicator(indicator);\n\n const affected = (data.components ?? [])\n .map((c) => ({\n name: c.name,\n status: mapComponentRaw(c.status),\n rawStatus: c.status,\n }))\n .filter((c) => c.status !== ServiceHealthStatus.Healthy);\n\n return {\n status: affected.length > 0 ? ServiceHealthStatus.Degraded : overall,\n rawIndicator: indicator ?? undefined,\n degradedOrDownComponents: affected.length > 0 ? affected : undefined,\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError')\n return errResult('Request timed out');\n return errResult(e instanceof Error ? e.message : 'Unknown error');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual statuspage-backed checks\n// ---------------------------------------------------------------------------\n\nexport const checkAnthropicHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://status.claude.com/api/v2/status.json');\n\nexport const checkGithubHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://www.githubstatus.com/api/v2/status.json');\n\nexport const checkNpmOverallHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://status.npmjs.org/api/v2/status.json');\n\nexport const checkNpmComponentHealth = (): Promise<ComponentHealthResult> =>\n fetchStatuspageSummary('https://status.npmjs.org/api/v2/summary.json');\n\nexport const checkCloudflareOverallHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator(\n 'https://www.cloudflarestatus.com/api/v2/status.json',\n );\n\nexport const checkCloudflareComponentHealth =\n (): Promise<ComponentHealthResult> =>\n fetchStatuspageSummary(\n 'https://www.cloudflarestatus.com/api/v2/summary.json',\n );\n","import {\n ServiceHealthStatus,\n type BaseHealthResult,\n type ComponentHealthResult,\n type ComponentStatus,\n} from './types';\n\ninterface IncidentIoAffectedComponent {\n id: string;\n name: string;\n group_name?: string;\n current_status: string;\n}\n\ninterface IncidentIoIncident {\n id: string;\n name: string;\n status: string;\n current_worst_impact: string;\n affected_components: IncidentIoAffectedComponent[];\n}\n\ninterface IncidentIoSummary {\n ongoing_incidents: IncidentIoIncident[];\n in_progress_maintenances: unknown[];\n}\n\nfunction mapIncidentImpact(impact: string): ServiceHealthStatus {\n switch (impact) {\n case 'full_outage':\n return ServiceHealthStatus.Down;\n case 'partial_outage':\n case 'degraded_performance':\n return ServiceHealthStatus.Degraded;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction mapComponentStatus(status: string): ServiceHealthStatus {\n switch (status) {\n case 'operational':\n return ServiceHealthStatus.Healthy;\n case 'full_outage':\n return ServiceHealthStatus.Down;\n case 'partial_outage':\n case 'degraded_performance':\n return ServiceHealthStatus.Degraded;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\n/**\n * Build an error result for fetch failures. The kind matters for\n * downstream reconciliation:\n *\n * - 'http' (incident.io returned a bad status code) → `Down`. We\n * reached the status page but it told us something is wrong on\n * its side. We have a definitive response.\n * - 'network' (timeout, DNS failure, TCP/TLS failure) → `NoConnection`.\n * We never reached the status page. Treating this as `Degraded`\n * (the previous behavior) silently flipped the reconciliation in\n * `readiness.ts` from \"soft\" to \"confirmed outage\" whenever the\n * user's own network was flaky — exactly the false positive this\n * module is meant to help diagnose.\n */\nfunction errResult(error: string, kind: 'http' | 'network'): BaseHealthResult {\n return {\n status:\n kind === 'http'\n ? ServiceHealthStatus.Down\n : ServiceHealthStatus.NoConnection,\n error,\n };\n}\n\nconst POSTHOG_STATUS_URL = 'https://www.posthogstatus.com/api/v1/summary';\n\nasync function fetchPosthogStatus(\n timeoutMs = 5000,\n): Promise<{ overall: BaseHealthResult; components: ComponentHealthResult }> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(POSTHOG_STATUS_URL, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) {\n const err = errResult(`HTTP ${res.status}`, 'http');\n return { overall: err, components: err };\n }\n\n const data = (await res.json()) as IncidentIoSummary;\n const incidents = data.ongoing_incidents ?? [];\n\n if (incidents.length === 0) {\n return {\n overall: { status: ServiceHealthStatus.Healthy },\n components: { status: ServiceHealthStatus.Healthy },\n };\n }\n\n let worstOverall = ServiceHealthStatus.Degraded;\n const affected: ComponentStatus[] = [];\n\n for (const incident of incidents) {\n const impact = mapIncidentImpact(incident.current_worst_impact);\n if (impact === ServiceHealthStatus.Down) {\n worstOverall = ServiceHealthStatus.Down;\n }\n\n for (const comp of incident.affected_components ?? []) {\n const compStatus = mapComponentStatus(comp.current_status);\n if (compStatus !== ServiceHealthStatus.Healthy) {\n affected.push({\n name: comp.group_name\n ? `${comp.group_name} — ${comp.name}`\n : comp.name,\n status: compStatus,\n rawStatus: comp.current_status,\n });\n }\n }\n }\n\n return {\n overall: { status: worstOverall },\n components: {\n status:\n affected.length > 0 ? ServiceHealthStatus.Degraded : worstOverall,\n degradedOrDownComponents: affected.length > 0 ? affected : undefined,\n },\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') {\n const err = errResult('Request timed out', 'network');\n return { overall: err, components: err };\n }\n const err = errResult(\n e instanceof Error ? e.message : 'Unknown error',\n 'network',\n );\n return { overall: err, components: err };\n }\n}\n\nlet _cache: Promise<{\n overall: BaseHealthResult;\n components: ComponentHealthResult;\n}> | null = null;\n\nfunction getPosthogHealth() {\n if (!_cache) _cache = fetchPosthogStatus();\n return _cache;\n}\n\nexport function resetPosthogHealthCache(): void {\n _cache = null;\n}\n\nexport const checkPosthogOverallHealth = async (): Promise<BaseHealthResult> =>\n (await getPosthogHealth()).overall;\n\nexport const checkPosthogComponentHealth =\n async (): Promise<ComponentHealthResult> =>\n (await getPosthogHealth()).components;\n","import { REMOTE_SKILLS_BASE_URL } from '@lib/constants';\nimport { logToFile } from '@utils/debug';\nimport { ServiceHealthStatus, type BaseHealthResult } from './types';\n\n// ---------------------------------------------------------------------------\n// Direct endpoint health checks\n//\n// These ping PostHog-owned services directly (no Statuspage intermediary).\n// Result taxonomy:\n// - HTTP 2xx-3xx (per `isExpectedStatus`) → Healthy\n// - HTTP 4xx / 5xx → Down (confirmed)\n// - Network error / DNS / timeout (after retries) → NoConnection\n// NoConnection means we don't know whose fault it is; readiness reconciles\n// against the status page before deciding how to surface it to the user.\n//\n// LLM Gateway – FastAPI service\n// Source: posthog/services/llm-gateway/src/llm_gateway/api/health.py\n// GET /_liveness → 200 {\"status\":\"alive\"}\n//\n// MCP – Cloudflare Worker\n// Source: posthog/services/mcp/src/index.ts\n// GET / → 302 to posthog.com docs. The redirect proves the worker is up.\n// ---------------------------------------------------------------------------\n\nfunction noConnectionResult(error: string, attempts: number): BaseHealthResult {\n return {\n status: ServiceHealthStatus.NoConnection,\n error,\n rawIndicator: attempts > 1 ? `attempts=${attempts}` : undefined,\n };\n}\n\nfunction downResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Down, error };\n}\n\n// Backoffs sized to cover typical wifi flakiness — a single dropped\n// packet recovers via the 500ms retry; a wifi access point reconnect\n// or wifi↔LTE handoff (2-5s) is caught by the 2000ms retry. Tighter\n// schedules miss multi-second blips because all retries land in the\n// same dead window.\nconst RETRY_BACKOFFS_MS = [500, 2000];\n\nasync function attemptFetch(\n url: string,\n timeoutMs: number,\n redirect: 'follow' | 'manual' | 'error',\n): Promise<\n | { kind: 'response'; res: Response }\n | { kind: 'error'; error: Error; timedOut: boolean }\n> {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal, redirect });\n clearTimeout(tid);\n return { kind: 'response', res };\n } catch (e) {\n clearTimeout(tid);\n const err = e instanceof Error ? e : new Error('Unknown error');\n return { kind: 'error', error: err, timedOut: err.name === 'AbortError' };\n }\n}\n\nasync function fetchEndpointHealth(\n url: string,\n timeoutMs = 5000,\n isExpectedStatus: (status: number) => boolean = (s) => s === 200,\n redirect: 'follow' | 'manual' | 'error' = 'follow',\n): Promise<BaseHealthResult> {\n // Total attempts = 1 initial + RETRY_BACKOFFS_MS.length retries. Both\n // unexpected HTTP statuses (4xx/5xx) and network errors trigger a retry:\n // transient 5xx and Cloudflare edge blips often recover on a retry, and\n // even nominally deterministic 4xx can be transient (CDN propagation\n // lag after a release, token rotation, rate-limit window resets). GETs\n // are idempotent so retrying is safe.\n //\n // Final status if every attempt fails:\n // - At least one HTTP response observed → `Down` (server-side evidence)\n // - Only network errors observed → `NoConnection`\n let lastHttpStatus: number | null = null;\n let lastError = 'Unknown error';\n let attempts = 0;\n\n for (let i = 0; i <= RETRY_BACKOFFS_MS.length; i++) {\n if (i > 0) {\n const wait = RETRY_BACKOFFS_MS[i - 1];\n logToFile(\n `[health-checks] retry ${i}/${RETRY_BACKOFFS_MS.length} for ${url} in ${wait}ms (last: ${lastError})`,\n );\n await new Promise((r) => setTimeout(r, wait));\n }\n attempts++;\n\n const outcome = await attemptFetch(url, timeoutMs, redirect);\n\n if (outcome.kind === 'response') {\n const res = outcome.res;\n if (isExpectedStatus(res.status)) {\n const result: BaseHealthResult = {\n status: ServiceHealthStatus.Healthy,\n rawIndicator:\n attempts > 1\n ? `HTTP ${res.status} (attempts=${attempts})`\n : `HTTP ${res.status}`,\n };\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (${result.rawIndicator})`,\n );\n return result;\n }\n lastHttpStatus = res.status;\n lastError = `HTTP ${res.status}`;\n continue;\n }\n\n lastError = outcome.timedOut\n ? `Request timed out after ${timeoutMs}ms`\n : outcome.error.message;\n }\n\n const result =\n lastHttpStatus !== null\n ? downResult(`HTTP ${lastHttpStatus} (attempts=${attempts})`)\n : noConnectionResult(lastError, attempts);\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (attempts=${attempts}, ${result.error})`,\n );\n return result;\n}\n\nexport const checkLlmGatewayHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth('https://gateway.us.posthog.com/_liveness');\n\nexport const checkMcpHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth(\n 'https://mcp.posthog.com/',\n 5000,\n // 2xx-3xx counts as up (redirect to docs)\n (s) => s >= 200 && s < 400,\n 'manual',\n );\n\nexport const checkGithubReleasesHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth(`${REMOTE_SKILLS_BASE_URL}/skill-menu.json`);\n","import {\n ServiceHealthStatus,\n type AllServicesHealth,\n type BaseHealthResult,\n type ComponentHealthResult,\n type HealthCheckKey,\n} from './types';\nimport {\n checkAnthropicHealth,\n checkGithubHealth,\n checkNpmOverallHealth,\n checkNpmComponentHealth,\n checkCloudflareOverallHealth,\n checkCloudflareComponentHealth,\n} from './statuspage';\nimport {\n checkPosthogOverallHealth,\n checkPosthogComponentHealth,\n} from './incidentio';\nimport {\n checkLlmGatewayHealth,\n checkMcpHealth,\n checkGithubReleasesHealth,\n} from './endpoints';\nimport { logToFile } from '@utils/debug';\n\n// ---------------------------------------------------------------------------\n// Service labels (used in human-readable reason strings)\n// ---------------------------------------------------------------------------\n\nexport const SERVICE_LABELS: Record<HealthCheckKey, string> = {\n anthropic: 'Anthropic',\n posthogOverall: 'PostHog',\n posthogComponents: 'PostHog (components)',\n github: 'GitHub',\n npmOverall: 'npm',\n npmComponents: 'npm (components)',\n cloudflareOverall: 'Cloudflare',\n cloudflareComponents: 'Cloudflare (components)',\n llmGateway: 'LLM Gateway',\n mcp: 'MCP',\n githubReleases: 'GitHub Releases',\n};\n\n// ---------------------------------------------------------------------------\n// Readiness config\n// ---------------------------------------------------------------------------\n\nexport interface WizardReadinessConfig {\n /** Services where status=Down blocks the run (readiness=No). */\n downBlocksRun: HealthCheckKey[];\n /** Services where status=Degraded (or worse) blocks the run (readiness=No). */\n degradedBlocksRun?: HealthCheckKey[];\n}\n\n/**\n * See README section \"Health checks\" for the full rationale.\n * Adjust these arrays to change what blocks a wizard run.\n */\nexport const DEFAULT_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: [\n 'anthropic',\n 'npmOverall',\n 'llmGateway',\n 'mcp',\n 'githubReleases',\n ],\n degradedBlocksRun: ['anthropic'],\n};\n\n/**\n * Reduced readiness config for --signup provisioning flows.\n *\n * Provisioning only needs PostHog and the LLM Gateway - it doesn't\n * use Anthropic directly, npm, GitHub Releases, or MCP.\n */\nexport const SIGNUP_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: ['posthogOverall', 'llmGateway'],\n};\n\n// ---------------------------------------------------------------------------\n// Aggregate check\n// ---------------------------------------------------------------------------\n\nexport async function checkAllExternalServices(): Promise<AllServicesHealth> {\n const [\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n githubReleases,\n ] = await Promise.all([\n checkAnthropicHealth(),\n checkPosthogOverallHealth(),\n checkPosthogComponentHealth(),\n checkGithubHealth(),\n checkNpmOverallHealth(),\n checkNpmComponentHealth(),\n checkCloudflareOverallHealth(),\n checkCloudflareComponentHealth(),\n checkLlmGatewayHealth(),\n checkMcpHealth(),\n checkGithubReleasesHealth(),\n ]);\n\n const health: AllServicesHealth = {\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n githubReleases,\n };\n return reconcilePosthogReachability(health);\n}\n\n/**\n * When a PostHog-owned endpoint probe returns `NoConnection`, decide\n * whether it's a real outage or a likely-local issue by checking the\n * official status page (`posthogstatus.com`):\n *\n * - Status page says PostHog is `Down` / `Degraded` → upgrade\n * llmGateway / mcp to `Down`. The status page corroborates.\n * - Status page is `Healthy` → keep `NoConnection`. The status page\n * contradicts; this is probably the user's network.\n * - Status page is also `NoConnection` → keep `NoConnection`. User\n * can't reach two independent PostHog properties; almost\n * certainly their network. (This case relies on incidentio.ts\n * correctly emitting `NoConnection` for fetch failures rather\n * than the previous `Degraded`, which used to silently flip the\n * reconciliation into a false positive.)\n *\n * Why `Degraded` corroborates: a `Degraded` reading here only fires\n * when incident.io's API parsed successfully and reported a real\n * `partial_outage` or `degraded_performance` for some component. That's\n * PostHog acknowledging an issue, even if narrower than a full outage.\n * If our gateway probe is also failing, those two signals together\n * justify pointing at PostHog rather than the user.\n *\n * A narrower variant — only corroborate when the affected component is\n * gateway-related (LLM, US/EU Cloud, app) — would be more precise. We\n * have the data in `posthogComponents` but don't use it here. If the\n * analytics show false positives concentrated in this case, it's a\n * cheap follow-up.\n *\n * Mutates a copy of `health` and returns it.\n */\nexport function reconcilePosthogReachability(\n health: AllServicesHealth,\n): AllServicesHealth {\n const posthogStatus = health.posthogOverall.status;\n const corroboratesOutage =\n posthogStatus === ServiceHealthStatus.Down ||\n posthogStatus === ServiceHealthStatus.Degraded;\n\n if (!corroboratesOutage) return health;\n\n const upgrade = (r: BaseHealthResult): BaseHealthResult =>\n r.status === ServiceHealthStatus.NoConnection\n ? {\n ...r,\n status: ServiceHealthStatus.Down,\n error: r.error\n ? `${r.error} (corroborated by status page)`\n : 'corroborated by status page',\n }\n : r;\n\n return {\n ...health,\n llmGateway: upgrade(health.llmGateway),\n mcp: upgrade(health.mcp),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Wizard readiness evaluation\n// ---------------------------------------------------------------------------\n\nexport enum WizardReadiness {\n Yes = 'yes',\n No = 'no',\n YesWithWarnings = 'yes_with_warnings',\n}\n\nexport interface WizardReadinessResult {\n decision: WizardReadiness;\n health: AllServicesHealth;\n reasons: string[];\n}\n\nfunction describeResult(label: string, h: BaseHealthResult): string {\n const parts = [`${label}: ${h.status}`];\n if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);\n if (h.error) parts.push(h.error);\n return parts.join(' — ');\n}\n\nconst MAX_COMPONENT_NAMES = 8;\n\nfunction describeComponents(label: string, h: ComponentHealthResult): string {\n const affected = h.degradedOrDownComponents;\n if (!affected || affected.length === 0)\n return `${label} components: all operational`;\n const shown = affected\n .slice(0, MAX_COMPONENT_NAMES)\n .map((c) => `${c.name} (${c.status})`);\n const suffix =\n affected.length > MAX_COMPONENT_NAMES\n ? `, +${affected.length - MAX_COMPONENT_NAMES} more`\n : '';\n return `${label} components impacted: ${shown.join(', ')}${suffix}`;\n}\n\n// Each probe can take up to one base timeout + two retries with the\n// 500ms / 2000ms backoffs in endpoints.ts (worst case ~17.5s for a\n// network failure that exhausts retries). Probes run in parallel so\n// the aggregate ceiling is one probe, not the sum.\nconst READINESS_TIMEOUT_MS = 20_000;\n\nexport async function evaluateWizardReadiness(\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): Promise<WizardReadinessResult> {\n try {\n const health = await Promise.race([\n checkAllExternalServices(),\n new Promise<AllServicesHealth>((resolve) =>\n setTimeout(\n () => resolve(allUnknown('Health check timed out')),\n READINESS_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const reasons: string[] = [];\n\n for (const key of Object.keys(health) as HealthCheckKey[]) {\n const result = health[key];\n const label = SERVICE_LABELS[key];\n\n reasons.push(describeResult(label, result));\n\n if ('degradedOrDownComponents' in result) {\n reasons.push(describeComponents(label, result));\n }\n }\n\n const blockingKeys = getBlockingServiceKeys(health, config);\n if (blockingKeys.length > 0) {\n const blockingDetails = blockingKeys.map((key) => {\n const h = health[key];\n return `${key} (${h.status}${h.error ? ` — ${h.error}` : ''})`;\n });\n logToFile(`[health-checks] blocked by: ${blockingDetails.join(', ')}`);\n return { decision: WizardReadiness.No, health, reasons };\n }\n\n const hasWarnings = Object.values(health).some(\n (h) => h.status !== ServiceHealthStatus.Healthy,\n );\n\n if (hasWarnings) {\n return { decision: WizardReadiness.YesWithWarnings, health, reasons };\n }\n\n return { decision: WizardReadiness.Yes, health, reasons };\n } catch (err) {\n logToFile(\n `[health-checks] error: ${err instanceof Error ? err.message : err}`,\n );\n // Health checks must never block the wizard run\n return {\n decision: WizardReadiness.Yes,\n health: allUnknown('Unexpected error'),\n reasons: ['Health check failed unexpectedly — proceeding anyway'],\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Blocking service detection\n// ---------------------------------------------------------------------------\n\n/** Keys that are component-level detail, not top-level services. */\nconst COMPONENT_KEYS: HealthCheckKey[] = [\n 'posthogComponents',\n 'npmComponents',\n 'cloudflareComponents',\n];\n\n/**\n * Get the keys of services that would block a wizard run per the given config.\n *\n * `NoConnection` blocks the same services as `Down` — the wizard genuinely\n * can't continue if it can't reach the gateway. The screen shows softer\n * framing in that case (HealthCheckScreen) so we don't falsely accuse\n * PostHog of an outage when the user's network is the likely cause.\n */\nexport function getBlockingServiceKeys(\n health: AllServicesHealth,\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): HealthCheckKey[] {\n return (Object.keys(health) as HealthCheckKey[]).filter((key) => {\n if (COMPONENT_KEYS.includes(key)) return false;\n const result = health[key];\n if (\n config.downBlocksRun.includes(key) &&\n (result.status === ServiceHealthStatus.Down ||\n result.status === ServiceHealthStatus.NoConnection)\n ) {\n return true;\n }\n if (\n (config.degradedBlocksRun ?? []).includes(key) &&\n result.status !== ServiceHealthStatus.Healthy\n ) {\n return true;\n }\n return false;\n });\n}\n\n/** Build an AllServicesHealth where every service is Degraded with the given error. */\nfunction allUnknown(error: string): AllServicesHealth {\n const base: BaseHealthResult = {\n status: ServiceHealthStatus.Degraded,\n error,\n };\n return {\n anthropic: base,\n posthogOverall: base,\n posthogComponents: { ...base },\n github: base,\n npmOverall: base,\n npmComponents: { ...base },\n cloudflareOverall: base,\n cloudflareComponents: { ...base },\n llmGateway: base,\n mcp: base,\n githubReleases: base,\n };\n}\n","/* eslint-disable no-console */\n/**\n * LoggingUI — Logging-only implementation for CI mode.\n * No prompts, no TUI, no interactivity. Just console output.\n */\n\nimport {\n TaskStatus,\n type WizardUI,\n type SpinnerHandle,\n type AuthErrorDetail,\n type TokenUsageDelta,\n} from './wizard-ui';\nimport type { SettingsConflict } from '@lib/agent/claude-settings';\nimport type { ApiUser } from '@lib/api';\nimport { OAUTH_TIMEOUT_MS } from '@lib/constants';\nimport {\n type WizardReadinessResult,\n getBlockingServiceKeys,\n SERVICE_LABELS,\n} from '@lib/health-checks/readiness';\nimport type {\n AskAnswers,\n Credentials,\n OutroData,\n PendingQuestion,\n TaskNotice,\n} from '@lib/wizard-session';\n\nexport class LoggingUI implements WizardUI {\n intro(message: string): void {\n console.log(`┌ ${message}`);\n }\n\n outro(message: string): void {\n console.log(`└ ${message}`);\n }\n\n outroError(data: OutroData): void {\n console.log(`✖ ${data.message ?? 'Wizard aborted'}`);\n if (data.body) console.log(`│ ${data.body}`);\n if (data.docsUrl) console.log(`│ Docs: ${data.docsUrl}`);\n }\n\n waitForOutroDismissed(): Promise<void> {\n return Promise.resolve();\n }\n\n waitForAiOptIn(): Promise<void> {\n // Non-TUI runs are CI runs, which auto-consent to AI usage.\n return Promise.resolve();\n }\n\n cancel(message: string): void {\n console.log(`■ ${message}`);\n }\n\n log = {\n info(message: string): void {\n console.log(`│ ${message}`);\n },\n warn(message: string): void {\n console.log(`▲ ${message}`);\n },\n error(message: string): void {\n console.log(`✖ ${message}`);\n },\n success(message: string): void {\n console.log(`✔ ${message}`);\n },\n step(message: string): void {\n console.log(`◇ ${message}`);\n },\n };\n\n note(message: string): void {\n console.log(`│ ${message}`);\n }\n\n spinner(): SpinnerHandle {\n return {\n start(message?: string) {\n if (message) console.log(`◌ ${message}`);\n },\n stop(message?: string) {\n if (message) console.log(`● ${message}`);\n },\n message(msg?: string) {\n if (msg) console.log(`◌ ${msg}`);\n },\n };\n }\n\n pushStatus(message: string): void {\n console.log(`◇ ${message}`);\n }\n\n setDetectedFramework(label: string): void {\n console.log(`✔ Framework: ${label}`);\n }\n\n onEnterScreen(_screen: string, _fn: () => void): void {\n // No screen transitions in CI\n }\n\n setLoginUrl(url: string | null): void {\n if (url) {\n console.log(\n `│ If the browser didn't open automatically, use this link:`,\n );\n console.log(`│ ${url}`);\n }\n }\n\n setAuthorizeUrl(_url: string | null): void {\n // Manual-paste modal is TUI-only; CI/non-interactive runs don't use it.\n }\n\n showBlockingOutage(result: WizardReadinessResult): Promise<void> {\n console.log(`▲ Service health issues detected.`);\n const blockingKeys = getBlockingServiceKeys(result.health);\n if (blockingKeys.length > 0) {\n console.log(`│`);\n console.log(`│ Blocking services:`);\n for (const key of blockingKeys) {\n const status = result.health[key].status;\n const error = result.health[key].error;\n const label = SERVICE_LABELS[key];\n const detail = error ? ` — ${error}` : '';\n console.log(`│ ✖ ${label}: ${status}${detail}`);\n }\n console.log(`│`);\n }\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n console.log(\n `│ Continuing anyway — health checks are advisory in non-interactive runs.`,\n );\n return Promise.resolve();\n }\n\n setReadinessWarnings(result: WizardReadinessResult): void {\n console.log(`▲ Service health warnings detected.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n }\n\n showPortConflict(_processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n return Promise.resolve();\n }\n\n waitForManualAuthCode(): Promise<string> {\n // No interactive prompt in CI/logging mode — never resolves. CI bypasses\n // OAuth entirely, so this is only here to satisfy the interface.\n return new Promise<string>(() => {\n /* intentionally never resolves */\n });\n }\n\n showTaskNotice(_notice: TaskNotice): Promise<boolean> {\n return Promise.resolve(false);\n }\n\n cancelTaskNotice(): void {\n // Nothing to dismiss — showTaskNotice never opened anything.\n }\n\n showSettingsOverride(\n _conflicts: SettingsConflict[],\n _backupAndFix: () => boolean,\n ): Promise<void> {\n return Promise.resolve();\n }\n\n requestQuestion(_question: PendingQuestion): Promise<AskAnswers> {\n return Promise.reject(\n new Error(\n 'wizard_ask is not available in CI / non-interactive mode. ' +\n 'Re-run the wizard without --ci to answer interactively.',\n ),\n );\n }\n\n cancelPendingQuestion(): void {\n // Nothing to dismiss — requestQuestion never opens an overlay here.\n }\n\n showAuthError(detail?: AuthErrorDetail): void {\n console.log(`✖ Authentication failed (401)`);\n if (detail?.hasSettingsConflict) {\n console.log(\n `│ Claude Code auth is conflicting with the wizard. Please try again after logging out:`,\n );\n console.log(`│ claude auth logout`);\n } else {\n console.log(\n `│ The PostHog LLM Gateway rejected the API key. Common causes:`,\n );\n console.log(\n `│ - Wrong key type: pass a personal API key (phx_xxx). pha_ is an OAuth access token, phc_ is a project key.`,\n );\n console.log(\n `│ - Missing scope: the personal API key needs the \"llm_gateway:read\" scope.`,\n );\n console.log(`│ - Expired or revoked key.`);\n console.log(\n `│ - Region mismatch: --region must match the region the key was issued in (us vs eu).`,\n );\n }\n if (detail?.logFilePath) {\n console.log(`│ Verbose log: ${detail.logFilePath}`);\n }\n }\n\n showSessionTimeout(): void {\n const minutes = Math.round(OAUTH_TIMEOUT_MS / 60_000);\n console.log(\n `✖ Login timed out. The OAuth link timed out after ${minutes} minutes.`,\n );\n console.log(`│ Re-run the wizard to get a fresh link and try again.`);\n }\n\n startRun(): void {\n // No-op in CI mode\n }\n\n setCredentials(_credentials: Credentials): void {\n // No-op in CI mode — credentials are handled directly\n }\n\n setAccessToken(_credentials: Credentials): void {\n // No-op in CI mode — CI runs on a non-expiring key and never refreshes\n }\n\n setRoleAtOrganization(_role: string | null): void {\n // No-op in CI mode — there's no TUI to render role-tailored prompts\n }\n\n setApiUser(_user: ApiUser | null): void {\n // No-op in CI mode — there's no TUI to read account context from\n // the session.\n }\n\n private lastTodoLine = '';\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const completed = todos.filter(\n (t) => t.status === TaskStatus.Completed,\n ).length;\n const active = todos.filter((t) => t.status === TaskStatus.InProgress);\n if (active.length === 0) return;\n const labels = active.map((t) => t.activeForm || t.content).join(' · ');\n const line = `◌ [${completed}/${todos.length}] ${labels}`;\n // The queue re-renders on every transition; print only what changed.\n if (line === this.lastTodoLine) return;\n this.lastTodoLine = line;\n console.log(line);\n }\n\n setEventPlan(_events: Array<{ name: string; description: string }>): void {\n // No-op in CI mode\n }\n\n setDashboardUrl(_url: string): void {\n // No-op in CI mode\n }\n\n setStage(_stage: string): void {\n // No-op in CI mode\n }\n\n setNotebookUrl(_url: string): void {\n // No-op in CI mode\n }\n\n setHandoffText(_text: string): void {\n // No-op without a store — HeadlessUI overrides to feed the session sync\n }\n\n addTokenUsage(_delta: TokenUsageDelta): void {\n // No-op — the hidden Ctrl+T HUD is TUI-only\n }\n\n setFinalTokenCostUsd(_costUsd: number): void {\n // No-op — the hidden Ctrl+T HUD is TUI-only\n }\n\n setOutroData(_data: import('@lib/wizard-session').OutroData): void {\n // No-op in CI mode\n }\n\n setFrameworkContext(_key: string, _value: unknown): void {\n // No-op in CI mode\n }\n\n getFrameworkContext(_key: string): unknown {\n // No frameworkContext in CI mode\n return undefined;\n }\n\n waitForGate(_stepId: string): Promise<void> {\n // No interactive gates in CI mode\n return Promise.resolve();\n }\n}\n","/**\n * UI singleton — provides getUI() and setUI() for the wizard.\n * Default: LoggingUI. Swap to InkUI at startup for TUI mode.\n */\n\nimport type { WizardUI } from './wizard-ui';\nimport { LoggingUI } from './logging-ui';\n\nlet currentUI: WizardUI = new LoggingUI();\n\nexport function getUI(): WizardUI {\n return currentUI;\n}\n\nexport function setUI(ui: WizardUI): void {\n currentUI = ui;\n}\n\nexport type { WizardUI, SpinnerHandle } from './wizard-ui';\n","import { tmpdir } from 'node:os';\nimport { join, sep } from 'node:path';\n\n// /tmp is stable and discoverable on macOS/Linux; Windows needs os.tmpdir()\nconst TMP = process.platform === 'win32' ? tmpdir() : '/tmp';\n\nexport const WIZARD_LOG_FILE = join(TMP, 'posthog-wizard.log');\nexport const WIZARD_BENCHMARK_FILE = join(TMP, 'posthog-wizard-benchmark.json');\nexport const WIZARD_YARA_REPORT_FILE = join(\n TMP,\n 'posthog-wizard-yara-report.json',\n);\n/**\n * Strip an absolute installDir prefix off a project file path so the UI\n * renders `index.js:12` instead of `/Users/.../index.js:12`. Defends\n * against false matches like `/Users/foo` ⊂ `/Users/foobar/x.js` by\n * normalizing to a trailing path separator before the prefix check.\n */\nexport function relativeToInstallDir(file: string, installDir: string): string {\n const prefix = installDir.endsWith(sep) ? installDir : installDir + sep;\n return file.startsWith(prefix) ? file.slice(prefix.length) : file;\n}\n","import { appendFileSync, mkdirSync } from 'fs';\nimport path from 'path';\nimport { inspect } from 'node:util';\nimport { getUI } from '@ui';\nimport { IS_DEV, runtimeEnv } from '@env';\nimport { WIZARD_LOG_FILE } from './paths';\n\n// Dev builds may redirect the log so concurrent runs don't interleave one file.\nlet logFilePath =\n (IS_DEV && process.env.POSTHOG_WIZARD_LOG_FILE) || WIZARD_LOG_FILE;\nlet fileLoggingEnabled = true;\nlet consoleLoggingEnabled = false;\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') return value;\n if (value instanceof Error) return value.stack ?? String(value);\n try {\n // JSON.stringify throws on cycles and skips some values — fall back to\n // inspect so a crash log line is never dropped.\n return JSON.stringify(value, null, 2) ?? inspect(value, { depth: 3 });\n } catch {\n return inspect(value, { depth: 3 });\n }\n}\n\nfunction renderLine(args: readonly unknown[]): string {\n return args.map(stringify).join(' ');\n}\n\nexport function getLogFilePath(): string {\n return logFilePath;\n}\n\nexport function configureLogFile(opts: {\n path?: string;\n enabled?: boolean;\n}): void {\n if (opts.path !== undefined) {\n logFilePath = opts.path;\n ensuredLogDir = false;\n }\n if (opts.enabled !== undefined) fileLoggingEnabled = opts.enabled;\n}\n\nlet ensuredLogDir = false;\nlet reportedLogFailure = false;\n\n// Failed log writes go to error tracking, once per process. Dynamic import:\n// analytics logs through this module, so a static import would be a cycle.\nfunction reportLogFailureOnce(err: unknown): void {\n if (reportedLogFailure) return;\n reportedLogFailure = true;\n void import('./analytics')\n .then(({ analytics }) =>\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n {\n source: 'log-file-write',\n log_path: logFilePath,\n platform: process.platform,\n },\n ),\n )\n .catch(() => {\n // Reporting must never crash the wizard either.\n });\n}\n\n// The log's directory isn't guaranteed to exist (Windows %TEMP%,\n// POSTHOG_WIZARD_LOG_DIR) — create it on first failure.\nfunction appendLine(text: string): void {\n try {\n appendFileSync(logFilePath, text);\n } catch (err) {\n if (ensuredLogDir) {\n reportLogFailureOnce(err);\n return;\n }\n ensuredLogDir = true;\n try {\n mkdirSync(path.dirname(logFilePath), { recursive: true });\n appendFileSync(logFilePath, text);\n } catch (retryErr) {\n reportLogFailureOnce(retryErr);\n }\n }\n}\n\nexport function configureLogFileFromEnvironment(): void {\n const dir = runtimeEnv('POSTHOG_WIZARD_LOG_DIR');\n if (dir) {\n configureLogFile({ path: path.join(dir, 'posthog-wizard.log') });\n }\n}\n\nexport function initLogFile(): void {\n if (!fileLoggingEnabled) return;\n const divider = '='.repeat(60);\n appendLine(\n `\\n${divider}\\nPostHog Wizard Run: ${new Date().toISOString()}\\n${divider}\\n`,\n );\n}\n\nexport function logToFile(...args: unknown[]): void {\n if (!fileLoggingEnabled) return;\n const ts = new Date().toISOString();\n appendLine(`[${ts}] ${renderLine(args)}\\n`);\n}\n\nexport function debug(...args: unknown[]): void {\n if (!consoleLoggingEnabled) return;\n getUI().log.info(renderLine(args));\n}\n\nexport function enableDebugLogs(): void {\n consoleLoggingEnabled = true;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"playground-DYGJwugo.js","names":["path","MOCK_TASKS","getSkillContentBlocks"],"sources":["../src/ui/tui/playground/demos/WelcomeDemo.tsx","../src/ui/tui/playground/demos/LayoutDemo.tsx","../src/ui/tui/playground/demos/InputDemo.tsx","../src/ui/tui/playground/demos/ProgressDemo.tsx","../src/ui/tui/playground/demos/LogDemo.tsx","../src/ui/tui/playground/demos/RunScreenDemo.tsx","../src/ui/tui/playground/demos/HealthCheckDemo.tsx","../src/ui/tui/playground/demos/DoctorReportDemo.tsx","../src/ui/tui/playground/demos/ModalDemo.tsx","../src/ui/tui/playground/demos/McpDemo.tsx","../src/ui/tui/playground/demos/McpSuggestedPromptsDemo.tsx","../src/ui/tui/playground/demos/KeyboardHintsDemo.tsx","../src/ui/tui/playground/demos/AuditChecksDemo.tsx","../src/ui/tui/playground/demos/LearnDeckDemo.tsx","../src/ui/tui/playground/demos/EndScreensDemo.tsx","../src/ui/tui/playground/demos/AiOptInDemo.tsx","../src/ui/tui/playground/demos/AskModalDemo.tsx","../src/ui/tui/playground/demos/ViewportGuardDemo.tsx","../src/ui/tui/playground/PlaygroundApp.tsx","../src/ui/tui/playground/start-playground.ts","../src/commands/basic-integration/playground.ts"],"sourcesContent":["/**\n * WelcomeDemo — Splash screen. Press enter to push the tabbed view.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport type { WizardStore } from '@ui/tui/store';\nimport { Colors, Icons } from '@ui/tui/styles';\n\ninterface WelcomeDemoProps {\n store: WizardStore;\n}\n\nexport const WelcomeDemo = ({ store }: WelcomeDemoProps) => {\n useInput((_input, key) => {\n if (key.return) {\n store.completeSetup();\n }\n });\n\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <Text bold color={Colors.accent}>\n {Icons.diamond} PostHog Setup Wizard layout primitives playground\n </Text>\n <Box height={1} />\n <Text>Layout primitives for the PostHog Setup Wizard TUI.</Text>\n <Text dimColor>\n CardLayout, SplitView, TabContainer, ProgressList, and more.\n </Text>\n <Box height={1} />\n <Text color={Colors.primary}>\n Press enter to continue {Icons.triangleRight}\n </Text>\n </Box>\n );\n};\n","/**\n * LayoutDemo — Demonstrates CardLayout + SplitView.\n * Cycles alignment enums with keyboard shortcuts.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useState } from 'react';\nimport { CardLayout, SplitView, ConfirmButton } from '@ui/tui/primitives/index';\nimport { HAlign, VAlign, Colors } from '@ui/tui/styles';\n\nconst hAligns = [HAlign.Left, HAlign.Center, HAlign.Right];\nconst vAligns = [VAlign.Top, VAlign.Center, VAlign.Bottom];\nconst hLabels = ['Left', 'Center', 'Right'];\nconst vLabels = ['Top', 'Center', 'Bottom'];\n\nexport const LayoutDemo = () => {\n const [hIdx, setHIdx] = useState(0);\n const [vIdx, setVIdx] = useState(0);\n\n useInput((input) => {\n if (input === 'h') setHIdx((i) => (i + 1) % hAligns.length);\n if (input === 'v') setVIdx((i) => (i + 1) % vAligns.length);\n });\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Layout Demo\n </Text>\n <Text dimColor>\n Press [h] to cycle hAlign ({hLabels[hIdx]}), [v] to cycle vAlign (\n {vLabels[vIdx]})\n </Text>\n <Box height={1} />\n <SplitView\n left={\n <CardLayout hAlign={hAligns[hIdx]} vAlign={vAligns[vIdx]}>\n <Box borderStyle=\"single\" borderColor={Colors.primary} paddingX={1}>\n <Text color={Colors.primary}>Left Pane</Text>\n </Box>\n </CardLayout>\n }\n right={\n <CardLayout hAlign={HAlign.Center} vAlign={VAlign.Center}>\n <Box borderStyle=\"single\" borderColor={Colors.accent} paddingX={1}>\n <Text color={Colors.accent}>Right Pane</Text>\n </Box>\n </CardLayout>\n }\n />\n <Box height={1} />\n <Text dimColor>\n ConfirmButton — the focusable submit target for multi-select menus\n (focused / unfocused):\n </Text>\n <Box gap={2} marginTop={1}>\n <ConfirmButton focused count={3} />\n <ConfirmButton focused={false} />\n </Box>\n </Box>\n );\n};\n","/**\n * InputDemo — Demonstrates PickerMenu (single + multi) and ConfirmationInput.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { PickerMenu, ConfirmationInput } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nenum DemoStep {\n Single = 'single',\n Multi = 'multi',\n MultiLong = 'multi-long',\n Confirm = 'confirm',\n Done = 'done',\n}\n\n// A long single-column multi-select — more options than a normal terminal can\n// show at once — so the playground exercises PickerMenu's viewport paging\n// (the \"↑/↓ N more\" indicators and the n/p page keys). Shared with\n// AskModalDemo.\nexport const LONG_OPTIONS = [\n 'None of these',\n 'GitHub Issues',\n 'Linear',\n 'Jira',\n 'GitLab',\n 'Gitea',\n 'Shortcut',\n 'Sentry',\n 'Rollbar',\n 'Bugsnag',\n 'Honeybadger',\n 'Raygun',\n 'Zendesk',\n 'Freshdesk',\n 'Freshservice',\n 'Front',\n 'Gorgias',\n 'Kustomer',\n 'Dixa',\n 'Plain',\n 'pganalyze',\n 'Snyk',\n 'SonarQube',\n 'Semgrep',\n 'Rapid7 InsightVM',\n 'Featurebase',\n 'Frill',\n 'Aha',\n 'UserVoice',\n 'Productboard',\n 'Canny',\n 'AskNicely',\n 'Retently',\n 'Appfigures',\n 'AppFollow',\n 'Judge.me',\n 'Google Search Console',\n].map((label) => ({ label, value: label.toLowerCase().replace(/\\s+/g, '-') }));\n\nexport const InputDemo = () => {\n const [step, setStep] = useState<DemoStep>(DemoStep.Single);\n const [results, setResults] = useState<string[]>([]);\n\n if (step === DemoStep.Single) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Single Select\n </Text>\n <Box height={1} />\n <PickerMenu\n message=\"Pick a color\"\n options={[\n { label: 'Red', value: 'red', hint: 'warm' },\n { label: 'Blue', value: 'blue', hint: 'cool' },\n { label: 'Green', value: 'green', hint: 'natural' },\n ]}\n onSelect={(value) => {\n setResults((prev) => [...prev, `Single: ${value}`]);\n setStep(DemoStep.Multi);\n }}\n />\n </Box>\n );\n }\n\n if (step === DemoStep.Multi) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Multi Select\n </Text>\n <Box height={1} />\n <PickerMenu\n message=\"Pick toppings\"\n mode=\"multi\"\n options={[\n { label: 'Cheese', value: 'cheese' },\n { label: 'Pepperoni', value: 'pepperoni' },\n { label: 'Mushrooms', value: 'mushrooms' },\n { label: 'Onions', value: 'onions' },\n ]}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n setResults((prev) => [...prev, `Multi: ${arr.join(', ')}`]);\n setStep(DemoStep.MultiLong);\n }}\n />\n </Box>\n );\n }\n\n if (step === DemoStep.MultiLong) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Multi Select (long, scrolls)\n </Text>\n <Box height={1} />\n <PickerMenu\n message=\"Which of these do you use? (↑/↓ to scroll)\"\n mode=\"multi\"\n options={LONG_OPTIONS}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n setResults((prev) => [\n ...prev,\n `Multi (long): ${arr.length} picked`,\n ]);\n setStep(DemoStep.Confirm);\n }}\n />\n </Box>\n );\n }\n\n if (step === DemoStep.Confirm) {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Confirmation\n </Text>\n <Box height={1} />\n <ConfirmationInput\n message=\"Are you satisfied with your choices?\"\n onConfirm={() => {\n setResults((prev) => [...prev, 'Confirmed: Yes']);\n setStep(DemoStep.Done);\n }}\n onCancel={() => {\n setResults((prev) => [...prev, 'Confirmed: No']);\n setStep(DemoStep.Done);\n }}\n />\n </Box>\n );\n }\n\n // done\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Input Demo — Results\n </Text>\n <Box height={1} />\n {results.map((r, i) => (\n <Text key={i} color={Colors.success}>\n {'\\u2714'} {r}\n </Text>\n ))}\n <Box height={1} />\n <Text dimColor>Switch away from this tab and back to restart.</Text>\n </Box>\n );\n};\n","/**\n * ProgressDemo — Demonstrates ProgressList + LoadingBox.\n * Auto-animates task progression through states.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { ProgressList, LoadingBox } from '@ui/tui/primitives/index';\nimport type { ProgressItem } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nconst INITIAL_ITEMS: ProgressItem[] = [\n {\n label: 'Detect framework',\n activeForm: 'Detecting framework',\n status: 'pending',\n },\n {\n label: 'Install dependencies',\n activeForm: 'Installing dependencies',\n status: 'pending',\n },\n {\n label: 'Configure PostHog',\n activeForm: 'Configuring PostHog',\n status: 'pending',\n },\n {\n label: 'Add analytics provider',\n activeForm: 'Adding analytics provider',\n status: 'pending',\n },\n { label: 'Verify setup', activeForm: 'Verifying setup', status: 'pending' },\n];\n\nexport const ProgressDemo = () => {\n const [items, setItems] = useState<ProgressItem[]>(INITIAL_ITEMS);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => {\n setTick((t) => t + 1);\n }, 1500);\n return () => clearInterval(timer);\n }, []);\n\n useEffect(() => {\n // Cycle: each tick advances the \"active\" task\n const total = INITIAL_ITEMS.length;\n // After all tasks complete, restart\n const cycle = tick % (total + 2); // +2 for a pause at the end\n\n setItems(\n INITIAL_ITEMS.map((item, i) => {\n if (i < cycle) return { ...item, status: 'completed' as const };\n if (i === cycle) return { ...item, status: 'in_progress' as const };\n return { ...item, status: 'pending' as const };\n }),\n );\n }, [tick]);\n\n const allDone = items.every((i) => i.status === 'completed');\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Progress Demo\n </Text>\n <Text dimColor>Tasks auto-advance every 1.5s (cycles continuously)</Text>\n <Box height={1} />\n <ProgressList items={items} title=\"Setup in progress:\" />\n <Box height={1} />\n {!allDone && <LoadingBox message=\"Working...\" />}\n {allDone && (\n <Text color={Colors.success} bold>\n {'\\u2714'} All tasks complete! Restarting...\n </Text>\n )}\n </Box>\n );\n};\n","/**\n * LogDemo — Demonstrates LogViewer.\n * Writes demo log lines to a temp file, then tails it.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useState } from 'react';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { LogViewer } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nconst DEMO_LOG_PATH = path.join(os.tmpdir(), 'posthog-playground.log');\n\nconst LOG_MESSAGES = [\n '[info] Playground started',\n '[info] Initializing demo components...',\n '[debug] Loading primitives barrel export',\n '[info] ScreenContainer mounted',\n '[info] TabContainer initialized with 6 tabs',\n '[debug] LayoutDemo: hAlign=Left, vAlign=Top',\n '[info] NavigationDemo: screenStack depth = 1',\n '[warn] TabDemo: arrow key conflict with outer container',\n '[info] InputDemo: waiting for user selection',\n '[info] ProgressDemo: tick 0, cycling tasks',\n '[debug] LogViewer: watching file for changes',\n '[info] All demos loaded successfully',\n];\n\nexport const LogDemo = () => {\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n // Write initial log content\n fs.writeFileSync(DEMO_LOG_PATH, LOG_MESSAGES.join('\\n') + '\\n');\n setReady(true);\n\n // Append lines periodically\n let lineNum = LOG_MESSAGES.length;\n const timer = setInterval(() => {\n lineNum++;\n const msg = `[info] Demo log line #${lineNum} — ${new Date().toISOString()}\\n`;\n fs.appendFileSync(DEMO_LOG_PATH, msg);\n }, 2000);\n\n return () => {\n clearInterval(timer);\n try {\n fs.unlinkSync(DEMO_LOG_PATH);\n } catch {\n // ignore\n }\n };\n }, []);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n Log Demo\n </Text>\n <Text dimColor>Tailing {DEMO_LOG_PATH} (new line every 2s)</Text>\n <Box height={1} />\n {ready && <LogViewer filePath={DEMO_LOG_PATH} height={15} />}\n </Box>\n );\n};\n","/**\n * RunScreenDemo — Playground demo for the agent run view.\n *\n * Renders RunScreen's tab panels directly (not RunScreen itself) and owns its\n * own tab navigation, the way HealthCheckDemo renders its components directly —\n * a nested TabContainer would fight the playground's outer one over the arrow\n * keys (Ink delivers every key to every handler), leaving the inner tabs\n * unreachable. So the outer playground keeps the arrows and this demo uses:\n *\n * n / p switch run-screen tab (Status, Event plan, Tail logs, Visualizer, HN)\n *\n * Tasks auto-advance every 1.5s and the visualizer stage cycles on its own.\n * Discovered features (Stripe, LLM) are pre-populated so conditional tips appear.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { WizardStore, TaskStatus } from '@ui/tui/store';\nimport { DiscoveredFeature } from '@lib/wizard-session';\nimport { AgentPhase } from '@lib/agent/agent-phase';\nimport {\n SplitView,\n ProgressList,\n LogViewer,\n EventPlanViewer,\n HNViewer,\n} from '@ui/tui/primitives/index';\nimport type { ProgressItem, TabDefinition } from '@ui/tui/primitives/index';\nimport { LearnCard } from '@ui/tui/components/LearnCard';\nimport { TipsCard } from '@ui/tui/components/TipsCard';\nimport { VisualizerTab } from '@ui/tui/components/PhaseVisuals';\nimport { getProgramConfig } from '@lib/programs/program-registry';\nimport { getContentBlocks as getSkillContentBlocks } from '@lib/programs/agent-skill/content/index';\nimport { Colors } from '@ui/tui/styles';\nimport { WIZARD_LOG_FILE } from '@utils/paths';\n\nconst STAGE_CYCLE: AgentPhase[] = [\n AgentPhase.CodebaseScan,\n AgentPhase.SkillInstall,\n AgentPhase.DepInstall,\n AgentPhase.CodeEdits,\n AgentPhase.EnvSetup,\n AgentPhase.Dashboards,\n];\n\nconst MOCK_TASKS = [\n {\n label: 'Checking project structure and finding files for event tracking',\n activeForm: 'Checking project structure',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Load skill menu and install integration-nextjs-app-router skill',\n activeForm: 'Picking the right skill',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Verify PostHog dependencies',\n activeForm: 'Verifying PostHog dependencies',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Generate events plan (.posthog-events.json)',\n activeForm: 'Generating events plan',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Install posthog-js and posthog-node packages',\n activeForm: 'Installing packages',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Set up environment variables',\n activeForm: 'Setting up environment variables',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Create instrumentation-client.ts',\n activeForm: 'Creating instrumentation-client.ts',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Update next.config with rewrites',\n activeForm: 'Updating next.config',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Create posthog-server.ts',\n activeForm: 'Creating posthog-server.ts',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Add PostHog capture events to project files',\n activeForm: 'Adding capture events',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Create onboarding dashboard and insight',\n activeForm: 'Building dashboard',\n status: TaskStatus.Pending,\n done: false,\n },\n {\n label: 'Verify $pageview and $autocapture are arriving',\n activeForm: 'Watching events arrive',\n status: TaskStatus.Pending,\n done: false,\n },\n];\n\nconst MOCK_EVENTS = [\n { name: 'page_viewed', description: 'Fires when a user views any page' },\n {\n name: 'button_clicked',\n description: 'Fires when the CTA button is clicked',\n },\n {\n name: 'form_submitted',\n description: 'Fires when the contact form is submitted',\n },\n {\n name: 'signup_started',\n description: 'Fires when a user begins the signup flow',\n },\n];\n\ninterface RunScreenDemoProps {\n store: WizardStore;\n}\n\nexport const RunScreenDemo = ({ store }: RunScreenDemoProps) => {\n const tickRef = useRef(0);\n const lastStatusRef = useRef('');\n const [activeTab, setActiveTab] = useState(0);\n\n // Re-render whenever the mock timers mutate the store (tasks, stage, etc.).\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Seed the store with mock data on mount\n useEffect(() => {\n store.addDiscoveredFeature(DiscoveredFeature.Stripe);\n store.addDiscoveredFeature(DiscoveredFeature.LLM);\n store.setEventPlan(MOCK_EVENTS);\n store.pushStatus('Checking project structure.');\n lastStatusRef.current = 'Checking project structure.';\n\n // Set initial tasks\n const initial = MOCK_TASKS.map((t, i) =>\n i === 0 ? { ...t, status: TaskStatus.InProgress } : t,\n );\n store.setTasks(initial);\n }, []);\n\n // Auto-advance tasks every 1.5s\n useEffect(() => {\n const timer = setInterval(() => {\n tickRef.current += 1;\n const tick = tickRef.current;\n const total = MOCK_TASKS.length;\n const cycle = tick % (total + 3); // +3 for pause at end before restart\n\n const tasks = MOCK_TASKS.map((t, i) => {\n if (i < cycle)\n return { ...t, status: TaskStatus.Completed, done: true };\n if (i === cycle)\n return { ...t, status: TaskStatus.InProgress, done: false };\n return { ...t, status: TaskStatus.Pending, done: false };\n });\n\n store.setTasks(tasks);\n\n // Only push status when the message actually changes\n if (cycle < total) {\n const msg = MOCK_TASKS[cycle].activeForm + '...';\n if (msg !== lastStatusRef.current) {\n store.pushStatus(msg);\n lastStatusRef.current = msg;\n }\n }\n }, 1500);\n\n return () => clearInterval(timer);\n }, []);\n\n // Cycle through every Visualizer stage on a faster timer so the playground\n // exercises each ASCII visual without needing the real agent loop.\n useEffect(() => {\n let i = 0;\n store.setCurrentStage(STAGE_CYCLE[0]);\n const timer = setInterval(() => {\n i = (i + 1) % STAGE_CYCLE.length;\n store.setCurrentStage(STAGE_CYCLE[i]);\n }, 4000);\n return () => clearInterval(timer);\n }, [store]);\n\n // Mirror RunScreen's tab panels (built here so the demo can drive them with\n // n/p instead of the arrow keys the outer playground TabContainer owns).\n const progressItems: ProgressItem[] = store.tasks.map((t) => ({\n label: t.label,\n activeForm: t.activeForm,\n status: t.status,\n }));\n\n const learnBlocks = useMemo(() => {\n const getBlocks =\n getProgramConfig(store.router.activeProgram).getContentBlocks ??\n getSkillContentBlocks;\n return getBlocks(store);\n }, [store]);\n\n const leftPane = store.learnCardComplete ? (\n <TipsCard store={store} />\n ) : (\n <LearnCard\n store={store}\n blocks={learnBlocks}\n onComplete={() => store.setLearnCardComplete()}\n />\n );\n\n const tabs: TabDefinition[] = [\n {\n id: 'status',\n label: 'Status',\n component: (\n <SplitView\n left={leftPane}\n right={<ProgressList items={progressItems} title=\"Tasks\" />}\n />\n ),\n },\n ...(store.eventPlan.length > 0\n ? [\n {\n id: 'events',\n label: 'Event plan',\n component: <EventPlanViewer events={store.eventPlan} />,\n },\n ]\n : []),\n {\n id: 'logs',\n label: 'Tail logs',\n component: <LogViewer filePath={WIZARD_LOG_FILE} />,\n },\n {\n id: 'visualizer',\n label: 'Visualizer',\n component: <VisualizerTab store={store} />,\n },\n { id: 'hn', label: 'HN', component: <HNViewer /> },\n ];\n\n // The outer playground TabContainer owns the arrow keys, so navigate with n/p.\n useInput((input) => {\n if (input === 'n') {\n setActiveTab((i) => Math.min(tabs.length - 1, i + 1));\n } else if (input === 'p') {\n setActiveTab((i) => Math.max(0, i - 1));\n }\n });\n\n const current = tabs[Math.min(activeTab, tabs.length - 1)];\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box flexDirection=\"column\" flexGrow={1} flexShrink={1} overflow=\"hidden\">\n {current?.component}\n </Box>\n\n <Box height={1} />\n <Box gap={1} paddingX={1}>\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 paddingX={1}>\n <Text dimColor>n/p switch tab</Text>\n </Box>\n </Box>\n );\n};\n","/**\n * HealthCheckDemo — Playground demo for health check UI components.\n *\n * Cycles through three states (2s checking spinner → 5s confirmed-outage\n * red modal → 5s no-connection yellow modal, then loops):\n * 1. Checking (spinner)\n * 2. Confirmed outage (status page corroborates → red framing)\n * 3. No connection only (no status-page incident → yellow \"couldn't\n * reach PostHog\" framing)\n *\n * Renders components directly (not HealthCheckScreen) to avoid useInput\n * conflicts with TabContainer's key handling.\n */\n\nimport { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { LoadingBox, ModalOverlay } from '@ui/tui/primitives/index';\nimport { Icons } from '@ui/tui/styles';\nimport { ServiceHealthList } from '@ui/tui/components/ServiceHealthList';\nimport { getBlockingServiceKeys } from '@lib/health-checks/readiness';\nimport { ServiceHealthStatus } from '@lib/health-checks/types';\nimport type { AllServicesHealth } from '@lib/health-checks/types';\n\nconst HEALTHY = { status: ServiceHealthStatus.Healthy } as const;\n\nconst MOCK_CONFIRMED_OUTAGE: AllServicesHealth = {\n anthropic: { status: ServiceHealthStatus.Down, rawIndicator: 'major' },\n posthogOverall: HEALTHY,\n posthogComponents: { status: ServiceHealthStatus.Healthy },\n github: HEALTHY,\n npmOverall: {\n status: ServiceHealthStatus.Degraded,\n rawIndicator: 'minor',\n },\n npmComponents: {\n status: ServiceHealthStatus.Degraded,\n degradedOrDownComponents: [\n {\n name: 'Registry API',\n status: ServiceHealthStatus.Degraded,\n rawStatus: 'degraded_performance',\n },\n ],\n },\n cloudflareOverall: HEALTHY,\n cloudflareComponents: { status: ServiceHealthStatus.Healthy },\n llmGateway: HEALTHY,\n mcp: HEALTHY,\n githubReleases: HEALTHY,\n};\n\nconst MOCK_NO_CONNECTION: AllServicesHealth = {\n anthropic: HEALTHY,\n posthogOverall: HEALTHY,\n posthogComponents: { status: ServiceHealthStatus.Healthy },\n github: HEALTHY,\n npmOverall: HEALTHY,\n npmComponents: { status: ServiceHealthStatus.Healthy },\n cloudflareOverall: HEALTHY,\n cloudflareComponents: { status: ServiceHealthStatus.Healthy },\n llmGateway: {\n status: ServiceHealthStatus.NoConnection,\n error: 'getaddrinfo ENOTFOUND gateway.us.posthog.com',\n },\n mcp: {\n status: ServiceHealthStatus.NoConnection,\n error: 'fetch failed',\n },\n githubReleases: HEALTHY,\n};\n\ntype Phase = 'checking' | 'confirmed' | 'no-connection';\n\nexport const HealthCheckDemo = () => {\n const [phase, setPhase] = useState<Phase>('checking');\n\n useEffect(() => {\n const t1 = setTimeout(() => setPhase('confirmed'), 2000);\n const t2 = setTimeout(() => setPhase('no-connection'), 7000);\n const t3 = setTimeout(() => setPhase('checking'), 12000);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n clearTimeout(t3);\n };\n }, [phase]);\n\n if (phase === 'checking') {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <LoadingBox message=\"Checking service status...\" />\n </Box>\n );\n }\n\n const health =\n phase === 'confirmed' ? MOCK_CONFIRMED_OUTAGE : MOCK_NO_CONNECTION;\n const blockingKeys = getBlockingServiceKeys(health);\n const isNoConnection = phase === 'no-connection';\n\n return (\n <ModalOverlay\n borderColor={isNoConnection ? 'yellow' : 'red'}\n title={\n isNoConnection\n ? \"Couldn't reach PostHog\"\n : `${Icons.warning} Ongoing service disruptions`\n }\n width={72}\n footer={\n <Box marginLeft={2}>\n <Text dimColor>\n Continue [Enter] / Exit [Esc] (disabled in playground)\n </Text>\n </Box>\n }\n >\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box marginBottom={1}>\n <Text>\n <Text color=\"red\">{Icons.squareFilled}</Text>\n <Text dimColor> Down </Text>\n <Text color=\"#DC9300\">{Icons.squareFilled}</Text>\n <Text dimColor> Degraded </Text>\n <Text color=\"gray\">{Icons.squareFilled}</Text>\n <Text dimColor> No connection</Text>\n </Text>\n </Box>\n\n <ServiceHealthList\n health={health}\n filterKeys={blockingKeys}\n showHealthy={false}\n />\n </Box>\n\n <Text dimColor>\n {isNoConnection\n ? \"We couldn't reach these services. PostHog's status page shows no incidents, likely a network issue (VPN, firewall, captive portal, or Wi-Fi).\"\n : 'The wizard may not work reliably while services are affected.'}\n </Text>\n </ModalOverlay>\n );\n};\n","import { Box, Text } from 'ink';\nimport { Colors, Icons } from '@ui/tui/styles';\nimport { IssueTable } from '@ui/tui/screens/doctor/IssueTable';\nimport type { HealthIssue } from '@lib/programs/posthog-doctor/index';\n\nconst NOW = '2026-04-27T15:00:00Z';\n\nconst MOCK_ISSUES: HealthIssue[] = [\n mock('1', 'ingestion_lag', 'critical'),\n mock('2', 'ingestion_warning', 'critical'),\n mock('3', 'materialized_view_failure', 'critical'),\n mock('4', 'sdk_outdated', 'warning'),\n mock('5', 'no_pageleave_events', 'warning'),\n mock('6', 'scroll_depth', 'warning'),\n mock('7', 'web_vitals', 'warning'),\n mock('8', 'reverse_proxy', 'info'),\n mock('9', 'authorized_urls', 'info'),\n mock('10', 'unrecognised_kind_with_a_long_slug_that_should_truncate', 'info'),\n];\n\nfunction mock(\n id: string,\n kind: string,\n severity: HealthIssue['severity'],\n): HealthIssue {\n return {\n id,\n kind,\n severity,\n status: 'active',\n dismissed: false,\n created_at: NOW,\n updated_at: NOW,\n };\n}\n\nexport const DoctorReportDemo = () => {\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n PostHog Doctor Report\n </Text>\n <Text dimColor>\n Project 12345 {Icons.bullet} https://us.i.posthog.com\n </Text>\n <Box marginTop={1}>\n <Text>\n {MOCK_ISSUES.length} active issues: 3 critical, 4 warning, 3 info\n </Text>\n </Box>\n <IssueTable issues={MOCK_ISSUES} />\n </Box>\n );\n};\n","/**\n * ModalDemo — Playground demo for the ModalOverlay primitive.\n *\n * Shows several modal variants: info, warning, error, and one with feedback text.\n */\n\nimport { Box, Text } from 'ink';\nimport { ModalOverlay } from '@ui/tui/primitives/index';\nimport { Icons } from '@ui/tui/styles';\n\nexport const ModalDemo = () => {\n return (\n <Box flexDirection=\"column\" gap={1} flexGrow={1}>\n <ModalOverlay borderColor=\"cyan\" title=\"Info Modal\" width={60}>\n <Text>A simple informational modal with default styling.</Text>\n </ModalOverlay>\n\n <ModalOverlay\n borderColor=\"#DC9300\"\n title={`${Icons.warning} Warning Modal`}\n width={60}\n feedback=\"Something needs your attention.\"\n >\n <Text>This modal includes a feedback message shown in yellow.</Text>\n </ModalOverlay>\n\n <ModalOverlay\n borderColor=\"red\"\n title={`${Icons.warning} Error Modal`}\n width={60}\n footer={\n <Box marginLeft={2}>\n <Text dimColor>\n Continue [Enter] / Exit [Esc] (disabled in playground)\n </Text>\n </Box>\n }\n >\n <Text>This modal has a footer section below a divider.</Text>\n </ModalOverlay>\n </Box>\n );\n};\n","/**\n * McpDemo — Playground demo for the MCP client selection screen.\n *\n * Uses a mock McpInstaller that simulates detecting three editors,\n * a short install delay, and a successful result.\n */\n\nimport { WizardStore } from '@ui/tui/store';\nimport { McpScreen } from '@ui/tui/screens/McpScreen';\nimport type {\n McpInstaller,\n McpClientInfo,\n} from '@ui/tui/services/mcp-installer';\nimport { McpClientStatus } from '@steps/add-mcp-server-to-clients/results';\n\nconst MOCK_CLIENTS: McpClientInfo[] = [\n { name: 'Claude Code', supportsPlugin: true },\n { name: 'Cursor', supportsPlugin: true },\n { name: 'VS Code', supportsPlugin: false },\n {\n name: 'Claude Desktop/Web',\n supportsPlugin: false,\n finish: {\n url: 'https://claude.ai/directory/connectors/posthog',\n instruction: 'Sign in and click \"Connect\" to finish.',\n },\n },\n];\n\nfunction createMockInstaller(): McpInstaller {\n return {\n async detectClients() {\n await new Promise((r) => setTimeout(r, 800));\n return MOCK_CLIENTS;\n },\n async install(clientNames) {\n await new Promise((r) => setTimeout(r, 1500));\n // Mixed outcomes so the demo shows every Done-phase section.\n return clientNames.map((name, i) => ({\n name,\n status:\n i === 1 ? McpClientStatus.Unchanged : McpClientStatus.Changed,\n }));\n },\n async installPlugins(clientNames) {\n await new Promise((r) => setTimeout(r, 800));\n return clientNames\n .filter(\n (name) => MOCK_CLIENTS.find((c) => c.name === name)?.supportsPlugin,\n )\n .map((name) => ({ name, status: McpClientStatus.Changed }));\n },\n async remove() {\n await new Promise((r) => setTimeout(r, 1000));\n // Mixed outcomes so the demo shows the removal failure copy too.\n return MOCK_CLIENTS.map((c, i) =>\n i === 2\n ? {\n name: c.name,\n status: McpClientStatus.Failed,\n detail: 'EACCES: permission denied',\n }\n : { name: c.name, status: McpClientStatus.Changed },\n );\n },\n };\n}\n\ninterface McpDemoProps {\n store: WizardStore;\n}\n\nexport const McpDemo = ({ store }: McpDemoProps) => {\n return (\n <McpScreen store={store} installer={createMockInstaller()} mode=\"install\" />\n );\n};\n","/**\n * McpSuggestedPromptsDemo — Playground demo for the post-MCP\n * suggested-prompts screen.\n *\n * Mounts the real McpSuggestedPromptsScreen with mock services so every\n * phase (Choose → Authenticating → Scouting → [SeedOffer → Seeding] →\n * Greeting → PromptPicker → Running → FollowUp → Goodbye) can be previewed\n * without touching the network. The Greeting phase auto-advances; FollowUp\n * re-enters Running when a follow-up is picked, building a conversation\n * tree up to MAX_PROMPT_RUNS deep.\n *\n * R cycle role (null → founder → product → ... → data → null)\n * F cycle framework (null → nextjs → vue → swift → django → null)\n * T cycle data tier (rich → sparse → empty) — drives the scout:\n * rich → generated quests from real events;\n * empty → seed-offer fork; sparse → safe read.\n * X remount the screen (useful after Exit)\n *\n * O OAuth outcome: success | error\n * L login delay: 0ms (skip UI) | 2000ms | 6000ms\n * S stream script: short-text | with-tools | mid-stream-error\n * C chunk delay: 50ms | 200ms | 800ms\n *\n * Tips:\n * - Set T to \"empty\" to walk the seed-events fork (SeedOffer → Seeding),\n * which lands on a rich seeded profile.\n * - Switch S to \"with-tools\" and the FollowUp picker after the run will\n * show context-aware suggestions based on the last tool. The mock\n * calls are CLI-mode `exec` chunks (`mcp__posthog-wizard__exec` + a\n * `call <tool> …` command), so they exercise getFollowUps' inner-tool\n * extraction.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport type { WizardStore } from '@ui/tui/store';\nimport { McpSuggestedPromptsScreen } from '@ui/tui/screens/McpSuggestedPromptsScreen';\nimport { Colors } from '@ui/tui/styles';\nimport { Integration } from '@lib/constants';\nimport { McpOutcome } from '@lib/wizard-session';\nimport { HostResolution } from '@lib/host-resolution';\nimport { TAILORED_ROLES } from '@lib/mcp-role-prompts';\nimport {\n assembleProfile,\n type ProjectDataProfile,\n} from '@lib/mcp-project-profile';\nimport { seededProfile } from '@lib/mcp-seed-events';\nimport type {\n AgentChunk,\n McpSuggestedPromptsServices,\n} from '@ui/tui/services/mcp-suggested-prompts-services';\n\n// One Integration per framework family so cycling exercises every\n// override bucket in mcp-role-prompts.ts.\nconst FAMILY_INTEGRATIONS: Array<Integration | null> = [\n null,\n Integration.nextjs, // fullstack\n Integration.vue, // frontend-web\n Integration.swift, // mobile\n Integration.django, // backend\n];\n\nconst ROLE_CYCLE: Array<string | null> = [null, ...TAILORED_ROLES];\n\nconst LOGIN_DELAYS_MS = [0, 2000, 6000] as const;\nconst CHUNK_DELAYS_MS = [50, 200, 800] as const;\n\n// Canned scout outcomes. 'rich' → generated quests from real events;\n// 'sparse' → safe read + a generated quest; 'empty' → seed-offer fork.\nconst PROBE_TIER_CYCLE = ['rich', 'sparse', 'empty'] as const;\ntype ProbeTier = (typeof PROBE_TIER_CYCLE)[number];\n\n// Every product absent, so activation cross-sells are eligible in the demo.\nconst NO_PRODUCTS = {\n sessionReplay: false,\n surveys: false,\n featureFlags: false,\n experiments: false,\n dataWarehouse: false,\n} as const;\n\nfunction mockProfile(tier: ProbeTier): ProjectDataProfile {\n if (tier === 'empty') {\n return assembleProfile([], NO_PRODUCTS);\n }\n if (tier === 'sparse') {\n return assembleProfile(\n [\n { name: '$pageview', count: 12 },\n { name: 'clicked', count: 5 },\n ],\n NO_PRODUCTS,\n );\n }\n return assembleProfile(\n [\n { name: '$pageview', count: 100 },\n { name: 'feature_used', count: 21 },\n { name: 'signed_up', count: 10 },\n { name: 'activated', count: 7 },\n { name: 'upgraded_to_paid', count: 3 },\n ],\n NO_PRODUCTS,\n );\n}\n\ntype LoginOutcome = 'success' | 'error';\ntype StreamScript = 'short-text' | 'with-tools' | 'mid-stream-error';\nconst LOGIN_OUTCOMES: LoginOutcome[] = ['success', 'error'];\nconst STREAM_SCRIPTS: StreamScript[] = [\n 'short-text',\n 'with-tools',\n 'mid-stream-error',\n];\n\nconst SCRIPTS: Record<StreamScript, AgentChunk[]> = {\n 'short-text': [\n { kind: 'text', text: 'Looking at your project…' },\n { kind: 'text', text: ' here is a quick read of the last 24 hours.' },\n {\n kind: 'text',\n text: ' You had 12,308 events from 2,144 distinct users.',\n },\n { kind: 'text', text: '\\n\\nNothing unusual stood out.' },\n { kind: 'done', sessionId: 'mock-session-aaa' },\n ],\n 'with-tools': [\n { kind: 'text', text: 'Looking up your project…' },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__exec',\n detail: 'call query-trends { event: \"signup\", interval: \"day\" }',\n command:\n 'call query-trends {\"event\":\"signup\",\"interval\":\"day\",\"window\":\"7d\"}',\n },\n {\n kind: 'tool-result',\n toolName: 'mcp__posthog-wizard__exec',\n detail: '{ rows: 7, total: 482, change: +8.4% }',\n },\n {\n kind: 'text',\n text: '\\nSignups are up 8.4% week-over-week — 482 over the last 7 days.',\n },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__exec',\n detail: 'call create-insight { name: \"Weekly signups\", save: true }',\n command:\n 'call create-insight {\"name\":\"Weekly signups\",\"query\":\"<trends>\",\"save\":true}',\n },\n {\n kind: 'tool-result',\n toolName: 'mcp__posthog-wizard__exec',\n detail:\n '{ id: \"ins_abc123\", url: \"https://app.posthog.com/i/ins_abc123\" }',\n },\n {\n kind: 'text',\n text: '\\nInsight saved as \"Weekly signups\" — pinned to your team dashboard.',\n },\n { kind: 'done', sessionId: 'mock-session-aaa' },\n ],\n 'mid-stream-error': [\n { kind: 'text', text: 'Looking at the most recent errors…' },\n {\n kind: 'tool-call',\n toolName: 'mcp__posthog-wizard__exec',\n detail: 'call query-error-tracking-issue { window: \"7d\", limit: 5 }',\n command: 'call query-error-tracking-issue {\"window\":\"7d\",\"limit\":5}',\n },\n {\n kind: 'error',\n text: 'MCP server returned 503 — try again in a moment.',\n },\n ],\n};\n\ninterface MockConfig {\n role: string | null;\n tier: ProbeTier;\n loginOutcome: LoginOutcome;\n loginDelayMs: number;\n script: StreamScript;\n chunkDelayMs: number;\n}\n\ninterface McpSuggestedPromptsDemoProps {\n store: WizardStore;\n}\n\nconst delay = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Returns a McpSuggestedPromptsServices instance whose behavior is read\n * fresh from `configRef` on every call. Hotkey changes take effect on\n * the *next* invocation without remounting the screen.\n */\nfunction createMockServices(\n store: WizardStore,\n configRef: { current: MockConfig },\n): McpSuggestedPromptsServices {\n return {\n performLogin: async () => {\n const cfg = configRef.current;\n store.setLoginUrl('https://app.posthog.com/oauth/playground-mock');\n await delay(cfg.loginDelayMs);\n store.setLoginUrl(null);\n\n if (cfg.loginOutcome === 'error') {\n throw new Error('Mock OAuth rejected — exercising error path.');\n }\n\n return {\n credentials: {\n accessToken: 'phx_mock',\n projectApiKey: 'phc_mock',\n host: HostResolution.fromApiHost('http://127.0.0.1:1'),\n projectId: 1,\n },\n roleAtOrganization: cfg.role,\n user: {\n distinct_id: 'demo-distinct-id',\n uuid: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',\n id: 1,\n email: 'joe@demo.example.com',\n first_name: 'Joe',\n last_name: 'Demo',\n role_at_organization: cfg.role,\n team: {\n id: 1,\n uuid: 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',\n organization: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n api_token: 'phc_mock',\n project_id: 1,\n name: 'Demo team',\n timezone: 'UTC',\n },\n organization: {\n id: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n name: 'Demo org',\n slug: 'demo-org',\n membership_level: 1,\n },\n organizations: [\n {\n id: 'cccccccc-cccc-cccc-cccc-cccccccccccc',\n name: 'Demo org',\n membership_level: 1,\n },\n ],\n },\n };\n },\n\n runPromptStreaming: ({ signal }) => mockStream(configRef, signal),\n\n probeProjectData: async () => {\n // Brief delay so the Scouting spinner is visible.\n await delay(800);\n return mockProfile(configRef.current.tier);\n },\n\n seedDemoEvents: async ({ baseProfile }) => {\n // No real ingestion in the playground — just show the spinner and\n // return the same seeded profile the production seeder would yield.\n await delay(1500);\n return seededProfile(baseProfile, new Date());\n },\n };\n}\n\nasync function* mockStream(\n configRef: { current: MockConfig },\n signal: AbortSignal,\n): AsyncIterable<AgentChunk> {\n const cfg = configRef.current;\n const chunks = SCRIPTS[cfg.script];\n for (const chunk of chunks) {\n if (signal.aborted) return;\n await delay(cfg.chunkDelayMs);\n if (signal.aborted) return;\n yield chunk;\n }\n}\n\nexport const McpSuggestedPromptsDemo = ({\n store,\n}: McpSuggestedPromptsDemoProps) => {\n const [roleIdx, setRoleIdx] = useState(2); // 'product' — has overrides\n const [familyIdx, setFamilyIdx] = useState(1); // nextjs (fullstack)\n const [tierIdx, setTierIdx] = useState(0); // 'rich' — shows generated quests\n const [resetKey, setResetKey] = useState(0);\n const [loginOutcomeIdx, setLoginOutcomeIdx] = useState(0);\n const [loginDelayIdx, setLoginDelayIdx] = useState(1); // 2000ms default\n const [scriptIdx, setScriptIdx] = useState(1); // 'with-tools' default\n const [chunkDelayIdx, setChunkDelayIdx] = useState(1); // 200ms default\n\n const role = ROLE_CYCLE[roleIdx];\n const integration = FAMILY_INTEGRATIONS[familyIdx];\n const tier = PROBE_TIER_CYCLE[tierIdx];\n const loginOutcome = LOGIN_OUTCOMES[loginOutcomeIdx];\n const loginDelayMs = LOGIN_DELAYS_MS[loginDelayIdx];\n const script = STREAM_SCRIPTS[scriptIdx];\n const chunkDelayMs = CHUNK_DELAYS_MS[chunkDelayIdx];\n\n // Ref-based config so hotkeys can update behavior without remounting.\n const configRef = useRef<MockConfig>({\n role,\n tier,\n loginOutcome,\n loginDelayMs,\n script,\n chunkDelayMs,\n });\n configRef.current = {\n role,\n tier,\n loginOutcome,\n loginDelayMs,\n script,\n chunkDelayMs,\n };\n\n // Stable services instance — reads from configRef each call.\n const services = useMemo(() => createMockServices(store, configRef), [store]);\n\n // Seed framework + a fake \"installed\" MCP state. setMcpComplete here\n // is harmless — production would have set it from the McpScreen step\n // before this screen mounts.\n useEffect(() => {\n store.setMcpComplete(McpOutcome.Installed, ['Claude Code']);\n store.setFrameworkConfig(integration ?? null, null);\n }, [store, integration]);\n\n useInput((input) => {\n if (input === 'R' || input === 'r') {\n setRoleIdx((i) => (i + 1) % ROLE_CYCLE.length);\n setResetKey((k) => k + 1);\n } else if (input === 'F' || input === 'f') {\n setFamilyIdx((i) => (i + 1) % FAMILY_INTEGRATIONS.length);\n setResetKey((k) => k + 1);\n } else if (input === 'T' || input === 't') {\n // Remount so the new tier is re-probed from the Scouting phase.\n setTierIdx((i) => (i + 1) % PROBE_TIER_CYCLE.length);\n setResetKey((k) => k + 1);\n } else if (input === 'X' || input === 'x') {\n store.setCredentials(null);\n store.setRoleAtOrganization(null);\n setResetKey((k) => k + 1);\n } else if (input === 'O' || input === 'o') {\n setLoginOutcomeIdx((i) => (i + 1) % LOGIN_OUTCOMES.length);\n } else if (input === 'L' || input === 'l') {\n setLoginDelayIdx((i) => (i + 1) % LOGIN_DELAYS_MS.length);\n } else if (input === 'S' || input === 's') {\n setScriptIdx((i) => (i + 1) % STREAM_SCRIPTS.length);\n } else if (input === 'C' || input === 'c') {\n setChunkDelayIdx((i) => (i + 1) % CHUNK_DELAYS_MS.length);\n }\n });\n\n const familyLabel = integration ?? 'unknown';\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <Text dimColor>\n R role · F framework · T data-tier · X reset · O oauth · L login-delay ·\n S script · C chunk-delay\n </Text>\n <Text dimColor>\n role={String(role)} · integration={familyLabel} · tier={tier} · login=\n {loginOutcome}/{loginDelayMs}ms · script={script}/{chunkDelayMs}ms\n </Text>\n <Box marginTop={1} flexDirection=\"column\" flexGrow={1}>\n <McpSuggestedPromptsScreen\n key={resetKey}\n store={store}\n services={services}\n />\n </Box>\n <Box marginTop={1}>\n <Text color={Colors.muted} dimColor>\n (mock services — no real OAuth, no real LLM. Press R/F to preview\n different prompt kits; O/L/S/C to flip mock outcomes.)\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * KeyboardHintsDemo — Demonstrates the KeyboardHintsBar with all input types.\n *\n * Cycles through SinglePicker, MultiPicker, GroupedPicker, and Confirmation\n * so the user can see the hints bar update automatically for each component.\n * The bar appears at the bottom of the screen and stays visible, updating to\n * match the active component.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, type ReactNode } from 'react';\nimport {\n PickerMenu,\n GroupedPickerMenu,\n ConfirmationInput,\n} from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\n\nenum DemoStep {\n SingleSelect = 'single',\n MultiSelect = 'multi',\n GroupedSelect = 'grouped',\n Confirmation = 'confirm',\n Done = 'done',\n}\n\nconst STEP_LABELS: Record<DemoStep, string> = {\n [DemoStep.SingleSelect]: 'Single Select — hints: ↑↓ navigate, enter select',\n [DemoStep.MultiSelect]:\n 'Multi Select — hints: ↑↓ navigate, enter select, arrow to Confirm + enter to submit',\n [DemoStep.GroupedSelect]:\n 'Grouped Select — hints: ↑↓ navigate, enter select, a toggle all, arrow to Confirm + enter to submit',\n [DemoStep.Confirmation]:\n 'Confirmation — hints: ←→ switch, enter confirm, esc cancel',\n [DemoStep.Done]: 'Done',\n};\n\nexport const KeyboardHintsDemo = () => {\n const [step, setStep] = useState<DemoStep>(DemoStep.SingleSelect);\n const [log, setLog] = useState<string[]>([]);\n\n const addLog = (msg: string) => setLog((prev) => [...prev.slice(-4), msg]);\n\n if (step === DemoStep.SingleSelect) {\n return (\n <Wrapper step={step} log={log}>\n <PickerMenu\n message=\"Pick a framework\"\n options={[\n { label: 'Next.js', value: 'next' },\n { label: 'React', value: 'react' },\n { label: 'Vue', value: 'vue' },\n { label: 'Svelte', value: 'svelte' },\n ]}\n columns={2}\n onSelect={(v) => {\n addLog(`Single: ${String(v)}`);\n setStep(DemoStep.MultiSelect);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.MultiSelect) {\n return (\n <Wrapper step={step} log={log}>\n <PickerMenu\n message=\"Pick features to enable\"\n mode=\"multi\"\n options={[\n { label: 'Analytics', value: 'analytics' },\n { label: 'Session Replay', value: 'replay' },\n { label: 'Feature Flags', value: 'flags' },\n { label: 'Surveys', value: 'surveys' },\n ]}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n addLog(`Multi: ${arr.join(', ')}`);\n setStep(DemoStep.GroupedSelect);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.GroupedSelect) {\n return (\n <Wrapper step={step} log={log}>\n <GroupedPickerMenu\n message=\"Select integrations\"\n groups={{\n Frontend: [\n { label: 'React SDK', value: 'react-sdk' },\n { label: 'Web Analytics', value: 'web-analytics' },\n ],\n Backend: [\n { label: 'Node SDK', value: 'node-sdk' },\n { label: 'Python SDK', value: 'python-sdk' },\n ],\n Tooling: [\n { label: 'MCP Server', value: 'mcp' },\n { label: 'CLI', value: 'cli' },\n ],\n }}\n onSelect={(values) => {\n addLog(`Grouped: ${values.join(', ')}`);\n setStep(DemoStep.Confirmation);\n }}\n />\n </Wrapper>\n );\n }\n\n if (step === DemoStep.Confirmation) {\n return (\n <Wrapper step={step} log={log}>\n <ConfirmationInput\n message=\"Apply these settings?\"\n onConfirm={() => {\n addLog('Confirmed!');\n setStep(DemoStep.Done);\n }}\n onCancel={() => {\n addLog('Cancelled');\n setStep(DemoStep.Done);\n }}\n />\n </Wrapper>\n );\n }\n\n return (\n <Wrapper step={step} log={log}>\n <Text dimColor>\n All steps complete. Switch away from this tab and back to restart.\n </Text>\n </Wrapper>\n );\n};\n\nconst Wrapper = ({\n step,\n log,\n children,\n}: {\n step: DemoStep;\n log: string[];\n children: ReactNode;\n}) => (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Keyboard Hints Demo\n </Text>\n <Text dimColor>{STEP_LABELS[step]}</Text>\n <Box height={1} />\n {children}\n {log.length > 0 && (\n <>\n <Box height={1} />\n <Text dimColor>Log:</Text>\n {log.map((entry, i) => (\n <Text key={i} color={Colors.muted}>\n {' '}\n {entry}\n </Text>\n ))}\n </>\n )}\n </Box>\n);\n","/**\n * AuditChecksDemo — renders the AuditChecksViewer against a mock ledger so\n * the scroll/expand/sort behavior can be verified in the playground without\n * running the actual audit agent.\n */\n\nimport { Box } from 'ink';\nimport type { AuditCheck } from '@lib/programs/audit/types';\nimport { AuditChecksViewer } from '@ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer';\n\nconst MOCK_CHECKS: AuditCheck[] = [\n {\n id: 'sdk-installed',\n area: 'Installation',\n label: 'PostHog SDK installed',\n status: 'pass',\n file: 'package.json',\n details: 'posthog-js@1.260.0 found in dependencies.',\n },\n {\n id: 'sdk-up-to-date',\n area: 'Installation',\n label: 'SDK version up to date',\n status: 'warning',\n details: 'installed 1.260.0, latest 1.372.6 — more than one minor behind.',\n },\n {\n id: 'init-correct',\n area: 'Installation',\n label: 'Initialization is correct',\n status: 'warning',\n file: 'index.js:12',\n details:\n 'Init runs at module load with no singleton guard; calling posthog.init() multiple times can cause duplicate events.',\n },\n {\n id: 'identify-stable-distinct-id',\n area: 'Identification',\n label: 'Stable distinct_id (not session UUID)',\n status: 'error',\n file: 'index.js:18',\n details:\n 'distinct_id is crypto.randomUUID() — a per-session ephemeral UUID that resets on every page load. Replace with an authenticated user id.',\n },\n {\n id: 'identify-not-late',\n area: 'Identification',\n label: 'identify() called before captures / flag evals',\n status: 'pass',\n file: 'index.js:18',\n details:\n 'posthog.identify() is called before any posthog.capture() calls in this module.',\n },\n {\n id: 'cross-runtime-distinct-id',\n area: 'Identification',\n label: 'Same distinct_id across client and server',\n status: 'pass',\n details: 'Single runtime — no cross-runtime check needed.',\n },\n {\n id: 'identify-reset-on-logout',\n area: 'Identification',\n label: 'reset() called on logout / account switch',\n status: 'error',\n file: 'auth.ts:44',\n details:\n 'signOut() clears app auth state but never calls posthog.reset(), so the next identify() on this device can merge into the prior user profile.',\n },\n {\n id: 'capture-event-names-static',\n area: 'Event Capture',\n label: 'Event names are static and consistent',\n status: 'pass',\n file: 'index.js:21',\n details:\n \"All posthog.capture() calls use static string literals ('pageview', 'cta_clicked'); no template literals or dynamic variables found.\",\n },\n {\n id: 'capture-uses-proxy',\n area: 'Event Capture',\n label: 'Captures route through a reverse proxy',\n status: 'warning',\n file: 'index.js:13',\n details:\n 'api_host is set to the default PostHog US ingest host (https://us.i.posthog.com) rather than a first-party reverse proxy — ad/tracking blockers can silently drop these events.',\n },\n {\n id: 'capture-growth-events',\n area: 'Event Capture',\n label: 'Key activation events captured',\n status: 'pending',\n },\n];\n\nexport const AuditChecksDemo = () => (\n <Box flexDirection=\"column\" flexGrow={1}>\n <AuditChecksViewer checks={MOCK_CHECKS} />\n </Box>\n);\n","/**\n * LearnDeckDemo — flip through every program's content deck one block at\n * a time so wording, pauses, and visual blocks can be reviewed without\n * waiting for the auto-advance timer.\n *\n * n / p step block (next / previous)\n * [ / ] switch deck\n * r replay current block (re-runs the reveal animation)\n *\n * Arrow keys are reserved for the playground's tab switcher, so this demo\n * uses letter keys.\n *\n * Decks are pulled from `PROGRAM_REGISTRY` so every program that ships a\n * deck is reviewable here. Migration also gets per-variant entries (one\n * per `--product=<id>` choice) so the variant composer in\n * `migration/content/index.tsx` can be exercised side-by-side with the\n * generic deck.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useMemo, useState } from 'react';\nimport {\n ContentSequencer,\n ProgressList,\n SplitView,\n TextRevealMode,\n} from '@ui/tui/primitives/index';\nimport type { ContentBlock, ProgressItem } from '@ui/tui/primitives/index';\nimport { Colors } from '@ui/tui/styles';\nimport type { WizardStore } from '@ui/tui/store';\nimport { PROGRAM_REGISTRY } from '@lib/programs/program-registry';\nimport { AUDIT_AREA_SLIDES } from '@ui/tui/screens/audit/slides/index';\nimport type { AreaSlide } from '@ui/tui/screens/audit/slides/shared';\n\ninterface Deck {\n id: string;\n label: string;\n blocks: ContentBlock[];\n}\n\n/**\n * Fake task list to fill the right-hand pane so the SplitView layout matches\n * what operators actually see during a real run. Mix of statuses so the\n * spinner glyph, the in-progress row, and completed rows all render.\n */\nconst MOCK_TASKS: ProgressItem[] = [\n {\n label: 'Confirm Statsig is in use',\n activeForm: 'Confirming Statsig is in use',\n status: 'completed',\n },\n {\n label: 'Install PostHog',\n activeForm: 'Installing PostHog',\n status: 'completed',\n },\n {\n label: 'Plan call site replacements',\n activeForm: 'Planning call site replacements',\n status: 'in_progress',\n },\n {\n label: 'Rewrite call sites',\n activeForm: 'Rewriting call sites',\n status: 'pending',\n },\n {\n label: 'Remove Statsig',\n activeForm: 'Removing Statsig',\n status: 'pending',\n },\n {\n label: 'Verify the project still builds',\n activeForm: 'Verifying the build',\n status: 'pending',\n },\n {\n label: 'Write migration report',\n activeForm: 'Writing migration report',\n status: 'pending',\n },\n];\n\ninterface LearnDeckDemoProps {\n store: WizardStore;\n}\n\nexport const LearnDeckDemo = ({ store }: LearnDeckDemoProps) => {\n const decks: Deck[] = useMemo(() => {\n const all: Deck[] = [];\n\n // Every program in the registry that ships a deck. Seed the store's\n // skillId from the program config so decks that template the skill\n // name (e.g. agent-skill's \"Running the <skill> skill...\") render the\n // real value instead of \"unknown\".\n for (const program of PROGRAM_REGISTRY) {\n if (!program.getContentBlocks) continue;\n const stub = program.skillId\n ? withSessionOverride(store, { skillId: program.skillId })\n : store;\n all.push({\n id: `program:${program.id}`,\n label: `${program.id} (${program.command ?? 'default'})${\n program.skillId ? ` · skill: ${program.skillId}` : ''\n }`,\n blocks: program.getContentBlocks(stub),\n });\n }\n\n // Audit ships its own per-area slide model (not the ContentBlock deck\n // most programs use). Adapt each AreaSlide into a flat ContentBlock\n // list so the flipper can review them the same way.\n all.push({\n id: 'audit:area-slides',\n label: 'audit · area slides',\n blocks: areaSlidesToBlocks(AUDIT_AREA_SLIDES),\n });\n\n return all;\n }, [store]);\n\n const [deckIdx, setDeckIdx] = useState(0);\n const [blockIdx, setBlockIdx] = useState(0);\n const [replayKey, setReplayKey] = useState(0);\n\n const deck = decks[deckIdx];\n const block = deck.blocks[blockIdx];\n\n useInput((input) => {\n if (input === 'p') {\n setBlockIdx((i) => Math.max(0, i - 1));\n } else if (input === 'n') {\n setBlockIdx((i) => Math.min(deck.blocks.length - 1, i + 1));\n } else if (input === '[') {\n setDeckIdx((i) => (i - 1 + decks.length) % decks.length);\n setBlockIdx(0);\n } else if (input === ']') {\n setDeckIdx((i) => (i + 1) % decks.length);\n setBlockIdx(0);\n } else if (input === 'r') {\n setReplayKey((k) => k + 1);\n }\n });\n\n const pauseMs =\n typeof block === 'object' && 'pause' in block ? block.pause : '—';\n const blockKind = describeBlockKind(block);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <Text bold color={Colors.accent}>\n Learn deck flipper\n </Text>\n <Text dimColor>n/p step block · [ ] switch deck · r replay</Text>\n <Box height={1} />\n\n <Text>\n <Text bold>Deck:</Text> {deck.label}{' '}\n <Text dimColor>\n ({deckIdx + 1}/{decks.length})\n </Text>\n </Text>\n <Text>\n <Text bold>Block:</Text> {blockIdx + 1}/{deck.blocks.length}{' '}\n <Text dimColor>\n · kind: {blockKind} · pause: {String(pauseMs)}ms\n </Text>\n </Text>\n <Box height={1} />\n\n <Box flexGrow={1}>\n <SplitView\n left={\n <ContentSequencer\n key={`${deck.id}-${blockIdx}-${replayKey}`}\n blocks={deck.blocks.slice(0, blockIdx + 1)}\n mode={TextRevealMode.SentenceBySentence}\n startDelay={0}\n initialBlockIdx={blockIdx}\n />\n }\n right={<ProgressList items={MOCK_TASKS} title=\"Tasks\" />}\n />\n </Box>\n </Box>\n );\n};\n\n/**\n * Build a store proxy that exposes an overridden `session` while keeping\n * every prototype method (e.g. `setStatusExpanded`) and atom reference\n * intact. A plain `{...store, session: ...}` spread would drop the\n * prototype, so anything that called a store method on the result would\n * crash at render time.\n */\nfunction withSessionOverride(\n store: WizardStore,\n patch: Partial<WizardStore['session']>,\n): WizardStore {\n const stub = Object.create(Object.getPrototypeOf(store)) as WizardStore;\n Object.assign(stub, store);\n Object.defineProperty(stub, 'session', {\n value: { ...store.session, ...patch },\n writable: false,\n configurable: true,\n });\n return stub;\n}\n\n/**\n * Adapter: turn each audit AreaSlide into a sequence of ContentBlocks so it\n * fits the flipper's renderer. One block per intro paragraph, one for the\n * visual when present. Each slide is preceded by a heading block naming the\n * area so flipping between areas is obvious.\n */\nfunction areaSlidesToBlocks(slides: AreaSlide[]): ContentBlock[] {\n const out: ContentBlock[] = [];\n for (const slide of slides) {\n out.push({\n content: (\n <Text bold color={Colors.accent}>\n {slide.area}\n </Text>\n ),\n pause: 3000,\n });\n for (const paragraph of slide.intro) {\n out.push({ content: paragraph, pause: 5000 });\n }\n if (slide.visual) {\n out.push({\n content: slide.visual,\n pause: 8000,\n persist: true,\n });\n }\n out.push({ type: 'clear', pause: 1000 });\n }\n return out;\n}\n\nfunction describeBlockKind(block: ContentBlock): string {\n if (typeof block === 'string') return 'string';\n if (typeof block === 'object' && block !== null) {\n if ('type' in block && block.type === 'clear') return 'clear';\n if ('type' in block && block.type === 'lines') return 'lines';\n if ('content' in block) {\n return typeof block.content === 'string' ? 'text' : 'jsx';\n }\n }\n return 'unknown';\n}\n","/**\n * EndScreensDemo — Playground demo for the screens shown at the end of\n * a wizard run.\n *\n * Mounts the real SlackConnectScreen and OutroScreen against the shared\n * playground store so every variant can be previewed without a run:\n *\n * V switch view (slack-connect → outro)\n * K toggle Slack state (connected ↔ not connected) — simulates the\n * poll flipping the screen when the user finishes the browser OAuth\n * O cycle outro kind (success → error → cancel)\n *\n * The playground credentials are re-pointed at a localhost dead-end\n * while this demo is mounted, so SlackConnectScreen's poll fails fast\n * without real network traffic; `K` drives `session.slackConnected`\n * directly, which is the same store key the poll writes.\n *\n * KeepSkillsScreen is intentionally absent — it reads the install dir's\n * .claude/skills/ from disk and calls process.exit() when none are\n * found, which would kill the playground.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport type { WizardStore } from '@ui/tui/store';\nimport { SlackConnectScreen } from '@ui/tui/screens/SlackConnectScreen';\nimport { OutroScreen } from '@ui/tui/screens/OutroScreen';\nimport { Colors } from '@ui/tui/styles';\nimport { OutroKind, type OutroData } from '@lib/wizard-session';\nimport { HostResolution } from '@lib/host-resolution';\n\nconst VIEWS = ['slack-connect', 'outro'] as const;\ntype View = (typeof VIEWS)[number];\n\nconst OUTRO_KINDS = [OutroKind.Success, OutroKind.Error, OutroKind.Cancel];\n\nconst OUTRO_FIXTURES: Record<OutroKind, OutroData> = {\n [OutroKind.Success]: {\n kind: OutroKind.Success,\n message: 'PostHog is set up!',\n changes: [\n 'Installed posthog-js and wired the provider',\n 'Added pageview + pageleave capture',\n 'Instrumented 4 product events',\n ],\n reportFile: 'posthog-setup-report.md',\n dashboardUrl: 'https://us.posthog.com/project/1/dashboard/42',\n notebookUrl: 'https://us.posthog.com/project/1/notebooks/demo',\n docsUrl: 'https://posthog.com/docs/libraries/next-js',\n },\n [OutroKind.Error]: {\n kind: OutroKind.Error,\n message: 'The agent hit an error',\n body: 'The integration step failed before any files were changed.\\nRe-run the wizard to try again.',\n docsUrl: 'https://posthog.com/docs/ai-engineering/ai-wizard',\n },\n [OutroKind.Cancel]: {\n kind: OutroKind.Cancel,\n message: 'Cancelled — no changes were made',\n },\n};\n\ninterface EndScreensDemoProps {\n store: WizardStore;\n}\n\nexport const EndScreensDemo = ({ store }: EndScreensDemoProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const [viewIdx, setViewIdx] = useState(0);\n const [outroKindIdx, setOutroKindIdx] = useState(0);\n\n const view: View = VIEWS[viewIdx];\n const outroKind = OUTRO_KINDS[outroKindIdx];\n\n // The playground pre-seeds fake credentials pointed at the real\n // PostHog host, which SlackConnectScreen's poll would hit. Swap the\n // host for a localhost dead-end while this demo is mounted (restore\n // on unmount — tab switches unmount). The credentials must stay\n // non-null: the router derives the active screen from session state,\n // and nulling them drops the playground out of the 'run' screen,\n // unmounting the tab bar and resetting it to the first tab.\n useEffect(() => {\n const previous = store.session.credentials;\n store.setCredentials({\n accessToken: 'playground',\n projectApiKey: 'playground',\n host: HostResolution.fromApiHost('http://127.0.0.1:9'),\n projectId: 0,\n });\n return () => {\n store.setCredentials(previous);\n };\n }, [store]);\n\n // Seed the outro fixture each screen reads. slackConnected starts\n // null (unknown) so the first paint shows the nudge variant, exactly\n // like a wizard run before the poll's first response.\n useEffect(() => {\n store.setOutroData(OUTRO_FIXTURES[outroKind]);\n }, [store, outroKind]);\n\n useInput((input) => {\n if (input === 'V' || input === 'v') {\n setViewIdx((i) => (i + 1) % VIEWS.length);\n } else if (input === 'K' || input === 'k') {\n store.setSlackConnected(store.session.slackConnected !== true);\n } else if (input === 'O' || input === 'o') {\n setOutroKindIdx((i) => (i + 1) % OUTRO_KINDS.length);\n }\n });\n\n const slackState =\n store.session.slackConnected === true ? 'connected' : 'not-connected';\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <Text dimColor>V view · K slack state · O outro kind</Text>\n <Text dimColor>\n view={view} · slack={slackState} · outro={outroKind}\n </Text>\n <Box marginTop={1} flexDirection=\"column\" flexGrow={1}>\n {view === 'slack-connect' ? (\n <SlackConnectScreen store={store} />\n ) : (\n <OutroScreen store={store} />\n )}\n </Box>\n <Box marginTop={1}>\n <Text color={Colors.muted} dimColor>\n (session-driven previews — the Slack poll points at a localhost\n dead-end; K flips the same store key the poll writes.)\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * AiOptInDemo — Playground demo for AiOptInRequiredScreen.\n *\n * Mounts the real screen with a synthetic store pre-populated with an\n * apiUser whose org has `is_ai_data_processing_approved: false`.\n * Variant selection is driven by `membership_level` — admin (>= 8) vs\n * non-admin (< 8), matching what the screen reads in production.\n *\n * One demo function, used by two PlaygroundApp tabs. ⚠ keybindings on\n * the screen are LIVE — [E] exits the playground, [O] opens a real\n * browser URL, [R] fires a network request (which will fail with the\n * fake token, but won't be destructive).\n */\n\nimport { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { WizardStore } from '@ui/tui/store';\nimport { AiOptInRequiredScreen } from '@ui/tui/screens/AiOptInRequiredScreen';\nimport { HostResolution } from '@lib/host-resolution';\n\ntype Variant = 'admin' | 'non-admin';\n\ninterface AiOptInDemoProps {\n variant: Variant;\n}\n\nexport const AiOptInDemo = ({ variant }: AiOptInDemoProps) => {\n const [store] = useState(() => {\n const s = new WizardStore();\n s.setCredentials({\n accessToken: 'demo-fake-token',\n projectApiKey: 'demo-fake-project-key',\n host: HostResolution.fromApiHost('https://us.posthog.com'),\n projectId: 0,\n });\n return s;\n });\n\n useEffect(() => {\n store.session.region = 'us';\n store.setApiUser({\n distinct_id: 'demo-distinct-id',\n email: 'sarah@example.com',\n organization: {\n id: '00000000-0000-0000-0000-000000000000',\n name: 'Demo Org',\n membership_level: variant === 'admin' ? 8 : 1,\n is_ai_data_processing_approved: false,\n } as never,\n organizations: [],\n team: {\n id: 0,\n organization: '00000000-0000-0000-0000-000000000000',\n } as never,\n } as never);\n }, [variant, store]);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Box marginBottom={1}>\n <Text dimColor>\n Playground —{' '}\n <Text bold>\n AiOptInRequiredScreen ({variant === 'admin' ? 'Admin' : 'Non-admin'}\n )\n </Text>\n . Keys are live: [E] exits the playground.\n </Text>\n </Box>\n <AiOptInRequiredScreen store={store} />\n </Box>\n );\n};\n","/**\n * AskModalDemo — Pickers rendered inside an ask-style ModalOverlay, the way\n * WizardAskScreen composes them: prompt paragraph in the modal body, then a\n * label-less PickerMenu. Exercises the viewport height cap (MAX_LIST_ROWS)\n * and the no-label spacing (no stray blank lines under the paragraph).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, type ReactNode } from 'react';\nimport {\n ModalOverlay,\n PickerMenu,\n GroupedPickerMenu,\n} from '@ui/tui/primitives/index';\nimport { Colors, Icons } from '@ui/tui/styles';\nimport { LONG_OPTIONS } from './InputDemo.js';\n\nenum DemoStep {\n ScoutRepro = 'scout-repro',\n CountLabel100 = 'count-label-100',\n CountLabel10 = 'count-label-10',\n CountLabel2 = 'count-label-2',\n CountLabel1 = 'count-label-1',\n CountDesc100 = 'count-desc-100',\n CountDesc10 = 'count-desc-10',\n CountDesc2 = 'count-desc-2',\n CountDesc1 = 'count-desc-1',\n MultiLong = 'multi-long',\n MultiDescriptions = 'multi-descriptions',\n Single = 'single',\n Grouped = 'grouped',\n Done = 'done',\n}\n\n/** Label-only options at a given count, e.g. \"Option 1\" ... \"Option 100\". */\nconst countLabelOptions = (n: number) =>\n Array.from({ length: n }, (_, i) => ({\n label: `Option ${i + 1}`,\n value: `opt-${i + 1}`,\n }));\n\n/** Options at a given count, each with a wrapping description so rows are tall. */\nconst countDescOptions = (n: number) =>\n Array.from({ length: n }, (_, i) => ({\n label: `Option ${i + 1}`,\n value: `opt-${i + 1}`,\n description:\n 'A longer description that wraps onto multiple lines so each option row costs several terminal rows, exercising the viewport cap and the paging math at small counts.',\n }));\n\n/** Repro of the scout-proposal ask that paged 3 tall described options one per page. */\nconst SCOUT_REPRO_OPTIONS = [\n {\n label: 'None — keep the built-in troop',\n value: 'none',\n description:\n 'Skip custom scouts; the built-in troop already covers this project well enough, and adding more scheduled checks would mostly duplicate the coverage you already get out of the box.',\n },\n {\n label: 'Playground snapshot drift scout',\n value: 'snapshot-drift',\n description:\n 'Watches CI snapshot runs and flags visual drift in the playground demos before it reaches a release, so a rendering regression in a picker or overlay never ships to users unnoticed.',\n },\n {\n label: 'Benchmark regression scout',\n value: 'benchmark',\n description:\n 'Tracks wizard-benchmark timings week over week and opens an issue when a run regresses past the recorded baseline, catching slow drift in agent latency before customers feel it.',\n },\n];\n\nconst DESCRIBED_OPTIONS = [\n {\n label: 'Session replay',\n value: 'replay',\n description:\n 'Record and replay real user sessions to see exactly what happened before an error or a rage click.',\n },\n {\n label: 'Feature flags',\n value: 'flags',\n description:\n 'Roll features out gradually, target by cohort, and kill misbehaving code paths without a deploy.',\n },\n {\n label: 'Error tracking',\n value: 'errors',\n description: 'Capture exceptions with stack traces and source maps.',\n },\n];\n\nconst GROUPED = {\n 'Issue trackers': [\n { label: 'GitHub Issues', value: 'github' },\n { label: 'Linear', value: 'linear' },\n { label: 'Jira', value: 'jira' },\n { label: 'Shortcut', value: 'shortcut' },\n ],\n 'Error monitoring': [\n { label: 'Sentry', value: 'sentry' },\n { label: 'Rollbar', value: 'rollbar' },\n { label: 'Bugsnag', value: 'bugsnag' },\n { label: 'Honeybadger', value: 'honeybadger' },\n ],\n 'Support desks': [\n { label: 'Zendesk', value: 'zendesk' },\n { label: 'Freshdesk', value: 'freshdesk' },\n { label: 'Front', value: 'front' },\n { label: 'Intercom', value: 'intercom' },\n ],\n Observability: [\n { label: 'Datadog', value: 'datadog' },\n { label: 'New Relic', value: 'newrelic' },\n { label: 'Grafana', value: 'grafana' },\n { label: 'Splunk', value: 'splunk' },\n ],\n};\n\n/** Mirrors WizardAskScreen's shape: paragraph body, then a label-less input. */\nconst AskModal = ({\n prompt,\n children,\n}: {\n prompt: string;\n children: ReactNode;\n}) => (\n <ModalOverlay\n borderColor={Colors.accent}\n title={`${Icons.diamond} self-driving-setup`}\n titleColor={Colors.accent}\n width={72}\n >\n <Box flexDirection=\"column\">\n <Text>{prompt}</Text>\n </Box>\n <Box marginTop={1}>{children}</Box>\n </ModalOverlay>\n);\n\nexport const AskModalDemo = () => {\n const [step, setStep] = useState<DemoStep>(DemoStep.ScoutRepro);\n const [results, setResults] = useState<string[]>([]);\n\n const advance = (result: string, next: DemoStep) => {\n setResults((prev) => [...prev, result]);\n setStep(next);\n };\n\n const countLabelSteps: Partial<\n Record<DemoStep, { next: DemoStep; count: number }>\n > = {\n [DemoStep.CountLabel100]: {\n next: DemoStep.CountLabel10,\n count: 100,\n },\n [DemoStep.CountLabel10]: { next: DemoStep.CountLabel2, count: 10 },\n [DemoStep.CountLabel2]: { next: DemoStep.CountLabel1, count: 2 },\n [DemoStep.CountLabel1]: { next: DemoStep.CountDesc100, count: 1 },\n };\n\n const countDescSteps: Partial<\n Record<DemoStep, { next: DemoStep; count: number }>\n > = {\n [DemoStep.CountDesc100]: { next: DemoStep.CountDesc10, count: 100 },\n [DemoStep.CountDesc10]: { next: DemoStep.CountDesc2, count: 10 },\n [DemoStep.CountDesc2]: { next: DemoStep.CountDesc1, count: 2 },\n [DemoStep.CountDesc1]: { next: DemoStep.MultiLong, count: 1 },\n };\n\n if (step === DemoStep.ScoutRepro) {\n return (\n <AskModal prompt=\"Scouts are scheduled checks that watch your data and flag issues for your inbox. Based on your repo I found two gaps the built-in troop doesn't cover — add one, both, or none. (Repro: 3 described options must stay on ONE page even in a short terminal.)\">\n <PickerMenu\n key={step}\n mode=\"multi\"\n optionMarginBottom={1}\n options={SCOUT_REPRO_OPTIONS}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n advance(\n `Scout repro: ${arr.length} picked`,\n DemoStep.CountLabel100,\n );\n }}\n />\n </AskModal>\n );\n }\n\n const labelStep = countLabelSteps[step];\n if (labelStep) {\n const { count, next } = labelStep;\n return (\n <AskModal\n prompt={`Multi-select — ${count} label-only option${\n count === 1 ? '' : 's'\n }. Watch whether ${\n count <= 2 ? 'this tiny list still pages' : 'paging kicks in'\n }.`}\n >\n <PickerMenu\n key={step}\n mode=\"multi\"\n options={countLabelOptions(count)}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n advance(`Count label (${count}): ${arr.length} picked`, next);\n }}\n />\n </AskModal>\n );\n }\n\n const descStep = countDescSteps[step];\n if (descStep) {\n const { count, next } = descStep;\n return (\n <AskModal\n prompt={`Multi-select — ${count} option${\n count === 1 ? '' : 's'\n } with wrapping descriptions (tall rows). ${\n count <= 2\n ? 'This is where a tiny list can still split into multiple pages.'\n : ''\n }`}\n >\n <PickerMenu\n key={step}\n mode=\"multi\"\n optionMarginBottom={1}\n options={countDescOptions(count)}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n advance(`Count desc (${count}): ${arr.length} picked`, next);\n }}\n />\n </AskModal>\n );\n }\n\n if (step === DemoStep.MultiLong) {\n return (\n <AskModal prompt=\"Self-driving can also watch your other tools and investigate and fix the problems they surface. Which of these do you use?\">\n <PickerMenu\n key={step}\n mode=\"multi\"\n options={LONG_OPTIONS}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n advance(\n `Multi (long): ${arr.length} picked`,\n DemoStep.MultiDescriptions,\n );\n }}\n />\n </AskModal>\n );\n }\n\n if (step === DemoStep.MultiDescriptions) {\n return (\n <AskModal prompt=\"Besides analytics, which PostHog products should the agent set up while it's in the codebase?\">\n <PickerMenu\n key={step}\n mode=\"multi\"\n optionMarginBottom={1}\n options={DESCRIBED_OPTIONS}\n onSelect={(values) => {\n const arr = Array.isArray(values) ? values : [values];\n advance(\n `Multi (descriptions): ${arr.join(', ') || 'none'}`,\n DemoStep.Single,\n );\n }}\n />\n </AskModal>\n );\n }\n\n if (step === DemoStep.Single) {\n return (\n <AskModal prompt=\"Your project has both an app and a marketing site. Which one should the agent instrument first?\">\n <PickerMenu<string>\n options={[\n { label: 'The app', value: 'app', hint: 'src/app' },\n { label: 'The marketing site', value: 'marketing', hint: 'www/' },\n { label: 'Both, app first', value: 'both' },\n ]}\n onSelect={(value) => {\n advance(`Single: ${String(value)}`, DemoStep.Grouped);\n }}\n />\n </AskModal>\n );\n }\n\n if (step === DemoStep.Grouped) {\n return (\n <AskModal prompt=\"Grouped variant of the same ask — categories with headers, everything pre-selected:\">\n <GroupedPickerMenu\n groups={GROUPED}\n onSelect={(values) => {\n advance(`Grouped: ${values.length} kept`, DemoStep.Done);\n }}\n />\n </AskModal>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text bold color={Colors.accent}>\n Ask Modal Demo — Results\n </Text>\n <Box height={1} />\n {results.map((r, i) => (\n <Text key={i} color={Colors.success}>\n {'✔'} {r}\n </Text>\n ))}\n <Box height={1} />\n <Text dimColor>Switch away from this tab and back to restart.</Text>\n </Box>\n );\n};\n","/**\n * ViewportGuardDemo — Playground demo for the ViewportTooSmall primitive.\n *\n * The real thing only appears when the terminal drops below the minimum, at\n * which point the playground itself is hidden behind it — so render it here at\n * a couple of fake sizes to see the copy and the wrapping.\n */\n\nimport { Box, Text } from 'ink';\nimport {\n ViewportTooSmall,\n MIN_VIEWPORT_COLUMNS,\n MIN_VIEWPORT_ROWS,\n} from '@ui/tui/primitives/index';\n\nconst SAMPLES: Array<[number, number]> = [\n [70, 8],\n [40, 7],\n];\n\nexport const ViewportGuardDemo = () => {\n return (\n <Box flexDirection=\"column\" gap={1} flexGrow={1}>\n <Text dimColor>\n {`Shown full-screen whenever the terminal is under ${MIN_VIEWPORT_COLUMNS}×${MIN_VIEWPORT_ROWS} — shrink this window to see it for real.`}\n </Text>\n {SAMPLES.map(([columns, rows]) => (\n <Box key={`${columns}x${rows}`} flexDirection=\"column\">\n <Text dimColor>{`at ${columns}×${rows}:`}</Text>\n <ViewportTooSmall columns={columns} rows={rows} />\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * PlaygroundApp — Root component for the primitives playground.\n *\n * Two screens mirroring the real wizard flow:\n * intro → (press enter) → run (tabbed demo view)\n */\n\nimport { ScreenContainer, TabContainer } from '@ui/tui/primitives/index';\nimport type { WizardStore } from '@ui/tui/store';\nimport { WelcomeDemo } from './demos/WelcomeDemo.js';\nimport { LayoutDemo } from './demos/LayoutDemo.js';\nimport { InputDemo } from './demos/InputDemo.js';\nimport { ProgressDemo } from './demos/ProgressDemo.js';\nimport { LogDemo } from './demos/LogDemo.js';\nimport { RunScreenDemo } from './demos/RunScreenDemo.js';\nimport { HealthCheckDemo } from './demos/HealthCheckDemo.js';\nimport { DoctorReportDemo } from './demos/DoctorReportDemo.js';\nimport { ModalDemo } from './demos/ModalDemo.js';\nimport { McpDemo } from './demos/McpDemo.js';\nimport { McpSuggestedPromptsDemo } from './demos/McpSuggestedPromptsDemo.js';\nimport { KeyboardHintsDemo } from './demos/KeyboardHintsDemo.js';\nimport { AuditChecksDemo } from './demos/AuditChecksDemo.js';\nimport { LearnDeckDemo } from './demos/LearnDeckDemo.js';\nimport { EndScreensDemo } from './demos/EndScreensDemo.js';\nimport { AiOptInDemo } from './demos/AiOptInDemo.js';\nimport { AskModalDemo } from './demos/AskModalDemo.js';\nimport { ViewportGuardDemo } from './demos/ViewportGuardDemo.js';\n\ninterface PlaygroundAppProps {\n store: WizardStore;\n}\n\nexport const PlaygroundApp = ({ store }: PlaygroundAppProps) => {\n const tabs = [\n { id: 'layout', label: 'Layout', component: <LayoutDemo /> },\n { id: 'input', label: 'Input', component: <InputDemo /> },\n { id: 'ask-modal', label: 'Ask modal', component: <AskModalDemo /> },\n { id: 'progress', label: 'Progress', component: <ProgressDemo /> },\n { id: 'logs', label: 'Logs', component: <LogDemo /> },\n {\n id: 'run',\n label: 'RunScreen',\n component: <RunScreenDemo store={store} />,\n },\n {\n id: 'health',\n label: 'HealthCheck',\n component: <HealthCheckDemo />,\n },\n {\n id: 'doctor',\n label: 'Doctor',\n component: <DoctorReportDemo />,\n },\n {\n id: 'modal',\n label: 'Modal',\n component: <ModalDemo />,\n },\n {\n id: 'mcp',\n label: 'MCP',\n component: <McpDemo store={store} />,\n },\n {\n id: 'mcp-tutorial',\n label: 'MCP tutorial',\n component: <McpSuggestedPromptsDemo store={store} />,\n },\n {\n id: 'hints',\n label: 'KeyHints',\n component: <KeyboardHintsDemo />,\n },\n {\n id: 'audit-checks',\n label: 'Audit checks',\n component: <AuditChecksDemo />,\n },\n {\n id: 'learn-deck',\n label: 'Learn deck',\n component: <LearnDeckDemo store={store} />,\n },\n {\n id: 'end-screens',\n label: 'End screens',\n component: <EndScreensDemo store={store} />,\n },\n {\n id: 'ai-opt-in-admin',\n label: 'AI opt-in (admin)',\n component: <AiOptInDemo variant=\"admin\" />,\n },\n {\n id: 'ai-opt-in-nonadmin',\n label: 'AI opt-in (non-admin)',\n component: <AiOptInDemo variant=\"non-admin\" />,\n },\n {\n id: 'viewport-guard',\n label: 'Viewport guard',\n component: <ViewportGuardDemo />,\n },\n ];\n\n return (\n <ScreenContainer\n store={store}\n screens={{\n intro: <WelcomeDemo store={store} />,\n run: (\n <TabContainer\n tabs={tabs}\n statusMessage=\"Primitives Playground — use arrow keys to switch tabs\"\n />\n ),\n }}\n />\n );\n};\n","/**\n * start-playground.ts — Launches the TUI primitives playground.\n */\n\nimport { render } from 'ink';\nimport { createElement } from 'react';\nimport { WizardStore } from '@ui/tui/store';\nimport { PlaygroundApp } from './PlaygroundApp.js';\nimport { HostResolution } from '@lib/host-resolution';\nimport { WizardReadiness } from '@lib/health-checks/readiness';\nimport { enterDarkTerminal, releaseTerminal } from '../terminal.js';\n\nexport function startPlayground(version: string): void {\n enterDarkTerminal();\n\n const store = new WizardStore();\n store.version = version;\n\n // Pre-fill session so the router skips health-check, auth, and setup,\n // landing on 'run' after the intro screen.\n // dismissOutage() guards against the onInit health-check async result\n // overwriting this with WizardReadiness.No before the user presses enter.\n store.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n store.dismissOutage();\n store.setCredentials({\n accessToken: 'fake',\n projectApiKey: 'fake',\n host: HostResolution.fromApiHost('https://app.posthog.com'),\n projectId: 0,\n });\n\n const { unmount, waitUntilExit } = render(\n createElement(PlaygroundApp, { store }),\n );\n\n void waitUntilExit().then(() => {\n unmount();\n releaseTerminal();\n process.exit(0);\n });\n}\n","import { VERSION } from '@lib/version';\nimport { startPlayground } from '@ui/tui/playground/start-playground';\n\n/** Launch the TUI primitives playground. */\nexport function runPlayground(): void {\n startPlayground(VERSION);\n}\n"],"mappings":"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"}
|