@posthog/wizard 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +48 -7
  2. package/dist/{McpScreen-DvUncZBi.js → AuditChecksViewer-B0J7zcY2.js} +434 -22
  3. package/dist/AuditChecksViewer-B0J7zcY2.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-Br1hDRiB.js → add-mcp-server-to-clients-CUNR00bB.js} +5 -5
  5. package/dist/{add-mcp-server-to-clients-Br1hDRiB.js.map → add-mcp-server-to-clients-CUNR00bB.js.map} +1 -1
  6. package/dist/{readiness-gQvQNCeL.js → agent-interface-CV0-vtxj.js} +328 -462
  7. package/dist/agent-interface-CV0-vtxj.js.map +1 -0
  8. package/dist/{agent-runner-fWYFO4H0.js → agent-runner-LvVQH31D.js} +21 -31
  9. package/dist/{agent-runner-fWYFO4H0.js.map → agent-runner-LvVQH31D.js.map} +1 -1
  10. package/dist/analytics-BH7bEHQR.js +2 -0
  11. package/dist/analytics-VM7laaFx.js +123 -0
  12. package/dist/analytics-VM7laaFx.js.map +1 -0
  13. package/dist/bin.js +529 -42
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{debug-D-0xueVl.js → debug-BdcTB7EF.js} +1 -1
  16. package/dist/debug-Cqi6nVfX.js +686 -0
  17. package/dist/debug-Cqi6nVfX.js.map +1 -0
  18. package/dist/{defaults-CPH6eWhN.js → defaults-GbLPuHxj.js} +1 -1
  19. package/dist/{defaults-CPH6eWhN.js.map → defaults-GbLPuHxj.js.map} +1 -1
  20. package/dist/{detection-B7GNzve-.js → detection-CSjmal-X.js} +3 -3
  21. package/dist/{detection-B7GNzve-.js.map → detection-CSjmal-X.js.map} +1 -1
  22. package/dist/{env-api-key-DU8uIEvo.js → env-api-key-D5G2PrXW.js} +1 -1
  23. package/dist/{env-api-key-DU8uIEvo.js.map → env-api-key-D5G2PrXW.js.map} +1 -1
  24. package/dist/{file-DhSBlq-x.js → file-8iNrXHkG.js} +2 -2
  25. package/dist/{file-DhSBlq-x.js.map → file-8iNrXHkG.js.map} +1 -1
  26. package/dist/{file-utils-Dy9JncCo.js → file-utils-DnTSiTJw.js} +1 -1
  27. package/dist/{file-utils-Dy9JncCo.js.map → file-utils-DnTSiTJw.js.map} +1 -1
  28. package/dist/{package-manager-D3Lo6nXf.js → package-manager-CD8RQW-e.js} +2 -2
  29. package/dist/{package-manager-D3Lo6nXf.js.map → package-manager-CD8RQW-e.js.map} +1 -1
  30. package/dist/paths-DJS47p5x.js +26 -0
  31. package/dist/paths-DJS47p5x.js.map +1 -0
  32. package/dist/{posthog-integration-D4SRhJIQ.js → posthog-integration-BL21S3T6.js} +41 -13
  33. package/dist/posthog-integration-BL21S3T6.js.map +1 -0
  34. package/dist/{posthog-ByrpqEjN.js → posthog-vm0k9PKS.js} +1 -1
  35. package/dist/{posthog-ByrpqEjN.js.map → posthog-vm0k9PKS.js.map} +1 -1
  36. package/dist/provisioning-BdQ1ONIg.js +2 -0
  37. package/dist/provisioning-g9aoVIEd.js +166 -0
  38. package/dist/provisioning-g9aoVIEd.js.map +1 -0
  39. package/dist/{registry-DaPKstG3.js → registry-BaMEaAKd.js} +4 -5
  40. package/dist/{registry-DaPKstG3.js.map → registry-BaMEaAKd.js.map} +1 -1
  41. package/dist/{router-SgzmfLGi.js → router-COhhuIW3.js} +4 -3
  42. package/dist/router-COhhuIW3.js.map +1 -0
  43. package/dist/{setup-utils-y4s-3uKT.js → setup-utils-CNV7FSlY.js} +11 -150
  44. package/dist/setup-utils-CNV7FSlY.js.map +1 -0
  45. package/dist/setup-utils-CU4FIqjB.js +2 -0
  46. package/dist/{start-playground-g1TxpCZ5.js → start-playground-C9GWnVdM.js} +102 -7
  47. package/dist/start-playground-C9GWnVdM.js.map +1 -0
  48. package/dist/start-tui-B_zwutLe.js +4195 -0
  49. package/dist/start-tui-B_zwutLe.js.map +1 -0
  50. package/dist/{steps-D1zKDqAo.js → steps-Dawz7k3T.js} +8 -8
  51. package/dist/steps-Dawz7k3T.js.map +1 -0
  52. package/dist/{task-stream-DX_jKDQu.js → task-stream-CX7Uf6EM.js} +4 -4
  53. package/dist/{task-stream-DX_jKDQu.js.map → task-stream-CX7Uf6EM.js.map} +1 -1
  54. package/dist/{telemetry-CyUUSAYy.js → telemetry-D6bjWA-A.js} +2 -2
  55. package/dist/{telemetry-CyUUSAYy.js.map → telemetry-D6bjWA-A.js.map} +1 -1
  56. package/dist/{wizard-abort-Buodno3f.js → wizard-abort-CJkNkSjT.js} +6 -4
  57. package/dist/{wizard-abort-Buodno3f.js.map → wizard-abort-CJkNkSjT.js.map} +1 -1
  58. package/dist/{wizard-abort-DZmO_sIZ.js → wizard-abort-Dl0BkqhT.js} +1 -1
  59. package/dist/wizard-session-BQC9vy9Z.js +2 -0
  60. package/dist/{wizard-session-D5bggSsu.js → wizard-session-BcNJTl2I.js} +1 -1
  61. package/dist/{wizard-session-D5bggSsu.js.map → wizard-session-BcNJTl2I.js.map} +1 -1
  62. package/dist/{wizard-ui-BExOjdjA.js → wizard-ui-YdGFRyu_.js} +1 -1
  63. package/dist/wizard-ui-YdGFRyu_.js.map +1 -0
  64. package/npm-shrinkwrap.json +2 -2
  65. package/package.json +1 -1
  66. package/dist/McpScreen-DvUncZBi.js.map +0 -1
  67. package/dist/agent-skill-DJOzDaQV.js +0 -59
  68. package/dist/agent-skill-DJOzDaQV.js.map +0 -1
  69. package/dist/analytics-CfAUlt6-.js +0 -2
  70. package/dist/analytics-D3rY3TaN.js +0 -210
  71. package/dist/analytics-D3rY3TaN.js.map +0 -1
  72. package/dist/debug-gWEjmYVV.js +0 -203
  73. package/dist/debug-gWEjmYVV.js.map +0 -1
  74. package/dist/paths-BL-x2rFy.js +0 -16
  75. package/dist/paths-BL-x2rFy.js.map +0 -1
  76. package/dist/posthog-integration-D4SRhJIQ.js.map +0 -1
  77. package/dist/readiness-gQvQNCeL.js.map +0 -1
  78. package/dist/router-SgzmfLGi.js.map +0 -1
  79. package/dist/setup-utils-_ONxN-TT.js +0 -2
  80. package/dist/setup-utils-y4s-3uKT.js.map +0 -1
  81. package/dist/start-playground-g1TxpCZ5.js.map +0 -1
  82. package/dist/start-tui-CQef69NR.js +0 -2167
  83. package/dist/start-tui-CQef69NR.js.map +0 -1
  84. package/dist/steps-D1zKDqAo.js.map +0 -1
  85. package/dist/wizard-session-COhklXAF.js +0 -2
  86. package/dist/wizard-ui-BExOjdjA.js.map +0 -1
package/README.md CHANGED
@@ -2,11 +2,14 @@
2
2
  <img alt="posthoglogo" src="https://user-images.githubusercontent.com/65415371/205059737-c8a4f836-4889-4654-902e-f302b187b6a0.png">
3
3
  </p>
4
4
 
5
- > **⚠️ Experimental:** This wizard is still in an experimental phase. If you
5
+
6
6
  > have any feedback, please drop an email to **[wizard@posthog.com](mailto:wizard@posthog.com)**.
7
7
 
8
8
  <h1>PostHog wizard ✨</h1>
9
- <h4>The PostHog wizard helps you quickly add PostHog to your project using AI.</h4>
9
+
10
+ The PostHog wizard helps you quickly add PostHog to your project using AI.
11
+
12
+ ![Wizard clip](https://res.cloudinary.com/dmukukwp6/image/upload/q_auto,f_auto/pasted_image_2026_05_01_T19_53_26_002_Z_398f697f5c.png)
10
13
 
11
14
  # Usage
12
15
 
@@ -16,10 +19,11 @@ To use the wizard, you can run it directly using:
16
19
  npx @posthog/wizard
17
20
  ```
18
21
 
19
- Currently the wizard can be used for **React, NextJS, Svelte, Astro and React
20
- Native** projects. If you have other integrations you would like the wizard to
22
+ Currently the wizard can be used for over 16 frameworks for frontend, backend, and mobile applications. If you have other integrations you would like the wizard to
21
23
  support, please open a [GitHub issue](https://github.com/posthog/wizard/issues)!
22
24
 
25
+ Visit our [docs](https://posthog.com/docs/ai-engineering/ai-wizard) to learn more.
26
+
23
27
  ## MCP Commands
24
28
 
25
29
  The wizard also includes commands for managing PostHog MCP (Model Context
@@ -44,6 +48,46 @@ npx @posthog/wizard revenue
44
48
  Requires PostHog and Stripe SDKs already installed. Supports `--ci` with the
45
49
  same flags as the main wizard.
46
50
 
51
+ ## Headless signup + install (agents / CI)
52
+
53
+ For a fully non-interactive first-run (no existing PostHog account, no TTY,
54
+ no browser), combine `--ci --signup --email`. The wizard provisions a new
55
+ account, uses the returned personal API key to run the normal CI install,
56
+ and wires PostHog into the project at `--install-dir`:
57
+
58
+ ```bash
59
+ npx @posthog/wizard --ci --signup \
60
+ --email you@example.com \
61
+ --install-dir .
62
+ ```
63
+
64
+ Optional flags: `--name "Your Name"`, `--region eu` (default `us`),
65
+ `--integration nextjs` (else auto-detected).
66
+
67
+ ### Provision only
68
+
69
+ If you just want credentials — for tests, pre-flight checks, or wiring up
70
+ PostHog yourself — use the `provision` subcommand, which emits a structured
71
+ `ProvisioningResult` and does nothing else:
72
+
73
+ ```bash
74
+ # Human-readable (when stdout is a TTY)
75
+ npx @posthog/wizard provision --email user@example.com --region us
76
+
77
+ # Machine-readable — auto when stdout is piped, or force with --json
78
+ npx @posthog/wizard provision --email user@example.com --region eu --json
79
+ ```
80
+
81
+ Success prints the full `ProvisioningResult` (`projectApiKey`, `host`,
82
+ `projectId`, `accountId`, `accessToken`, `refreshToken`, and
83
+ `personalApiKey` if present). Failure exits 1; in `--json` mode the error
84
+ is emitted to stderr as `{"error":"...","code":"..."}`, with `code` set to
85
+ `email_exists` when the address is already registered.
86
+
87
+ > ⚠️ **Output contains live credentials.** Pipe it into a secrets store —
88
+ > do not let it be captured by shared CI logs. Mask the step output or
89
+ > redirect stdout to a file your job reads and discards.
90
+
47
91
  # Options
48
92
 
49
93
  The following CLI arguments are available:
@@ -62,9 +106,6 @@ The following CLI arguments are available:
62
106
  | `--ci` | Enable CI mode for non-interactive execution | boolean | `false` | | `POSTHOG_WIZARD_CI` |
63
107
  | `--api-key` | PostHog personal API key (phx_xxx) for authentication | string | | | `POSTHOG_WIZARD_API_KEY` |
64
108
 
65
- > Note: A large amount of the scaffolding for this came from the amazing Sentry
66
- > wizard, which you can find [here](https://github.com/getsentry/sentry-wizard)
67
- > 💖
68
109
 
69
110
  # CI Mode
70
111
 
@@ -1,15 +1,16 @@
1
- import { n as analytics, r as sessionProperties } from "./analytics-D3rY3TaN.js";
2
- import { n as isTaskStatus } from "./wizard-ui-BExOjdjA.js";
3
- import { r as buildSession } from "./wizard-session-D5bggSsu.js";
4
- import { t as SERVICE_LABELS } from "./readiness-gQvQNCeL.js";
5
- import { n as getKindMeta } from "./bin.js";
6
- import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-CPH6eWhN.js";
7
- import { i as WORKFLOW_STEPS, t as WizardRouter } from "./router-SgzmfLGi.js";
1
+ import { d as SERVICE_LABELS } from "./debug-Cqi6nVfX.js";
2
+ import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
+ import { n as analytics, r as sessionProperties } from "./analytics-VM7laaFx.js";
4
+ import { r as buildSession } from "./wizard-session-BcNJTl2I.js";
5
+ import { g as AUDIT_SEVERITY_STYLE } from "./agent-interface-CV0-vtxj.js";
6
+ import { r as getKindMeta } from "./bin.js";
7
+ import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-GbLPuHxj.js";
8
+ import { i as WORKFLOW_STEPS, t as WizardRouter } from "./router-COhhuIW3.js";
8
9
  import * as fs$1 from "fs";
9
10
  import { Box, Text, measureElement, useInput, useStdout } from "ink";
10
- import { Component, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
11
+ import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
11
12
  import { atom, map } from "nanostores";
12
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
14
  import { Spinner } from "@inkjs/ui";
14
15
  //#region src/ui/tui/store.ts
15
16
  /**
@@ -525,7 +526,7 @@ const ProgressList = ({ items, title }) => {
525
526
  return /* @__PURE__ */ jsxs(Box, {
526
527
  flexDirection: "column",
527
528
  children: [
528
- title && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
529
+ title && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Text, {
529
530
  bold: true,
530
531
  children: title
531
532
  }), /* @__PURE__ */ jsx(Text, { children: " " })] }),
@@ -1275,7 +1276,7 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
1275
1276
  children: feedback
1276
1277
  })
1277
1278
  }),
1278
- footer && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Box, {
1279
+ footer && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
1279
1280
  marginY: 1,
1280
1281
  children: /* @__PURE__ */ jsx(Divider, {})
1281
1282
  }), footer] })
@@ -1290,10 +1291,10 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
1290
1291
  * Only renders the last N lines that fit on screen.
1291
1292
  */
1292
1293
  /** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */
1293
- const CHROME_ROWS = 8;
1294
+ const CHROME_ROWS$1 = 8;
1294
1295
  const LogViewer = ({ filePath, height }) => {
1295
1296
  const [, rows] = useStdoutDimensions();
1296
- const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);
1297
+ const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS$1);
1297
1298
  const [lines, setLines] = useState([]);
1298
1299
  useEffect(() => {
1299
1300
  const readTail = () => {
@@ -1461,7 +1462,7 @@ const DissolveTransition = ({ transitionKey, width, height, children, direction
1461
1462
  maxTicks,
1462
1463
  width
1463
1464
  ]);
1464
- if (phase === "idle") return /* @__PURE__ */ jsx(Fragment, { children: displayChildren });
1465
+ if (phase === "idle") return /* @__PURE__ */ jsx(Fragment$1, { children: displayChildren });
1465
1466
  const easedValue = easeInOutCirc(Math.min(tick / easerSteps, 1));
1466
1467
  const activatedCount = Math.floor(easedValue * width);
1467
1468
  const columnOrder = [];
@@ -1576,11 +1577,10 @@ var ScreenErrorBoundary = class extends Component {
1576
1577
  * screen content (inside the transition area) so all screens get it.
1577
1578
  */
1578
1579
  const MIN_WIDTH = 80;
1579
- const MAX_WIDTH = 120;
1580
1580
  /** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */
1581
1581
  function getContentWidth(terminalColumns) {
1582
1582
  if (terminalColumns < MIN_WIDTH) return terminalColumns;
1583
- return Math.min(MAX_WIDTH, terminalColumns);
1583
+ return Math.min(120, terminalColumns);
1584
1584
  }
1585
1585
  const ScreenContainer = ({ store, screens }) => {
1586
1586
  const [columns, rows] = useStdoutDimensions();
@@ -2104,7 +2104,7 @@ const NodeBlock = ({ content, active, completed, onComplete }) => {
2104
2104
  dimColor: true,
2105
2105
  children: content
2106
2106
  });
2107
- return /* @__PURE__ */ jsx(Fragment, { children: content });
2107
+ return /* @__PURE__ */ jsx(Fragment$1, { children: content });
2108
2108
  };
2109
2109
  //#endregion
2110
2110
  //#region src/ui/tui/primitives/ContentSequencer.tsx
@@ -3098,7 +3098,7 @@ const TipsCard = ({ store }) => {
3098
3098
  ]
3099
3099
  }) : /* @__PURE__ */ jsxs(Text, {
3100
3100
  dimColor: true,
3101
- children: [tip.description, tip.url && /* @__PURE__ */ jsxs(Fragment, { children: [" ", /* @__PURE__ */ jsx(Text, {
3101
+ children: [tip.description, tip.url && /* @__PURE__ */ jsxs(Fragment$1, { children: [" ", /* @__PURE__ */ jsx(Text, {
3102
3102
  color: "cyan",
3103
3103
  children: tip.url
3104
3104
  })] })]
@@ -3417,7 +3417,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3417
3417
  " MCP clients detected. Skipping..."
3418
3418
  ]
3419
3419
  }),
3420
- phase === "ask" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
3420
+ phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
3421
3421
  dimColor: true,
3422
3422
  children: ["Detected: ", clients.map((c) => c.name).join(", ")]
3423
3423
  }), /* @__PURE__ */ jsx(Box, {
@@ -3455,7 +3455,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3455
3455
  }),
3456
3456
  phase === "done" && /* @__PURE__ */ jsx(Box, {
3457
3457
  flexDirection: "column",
3458
- children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
3458
+ children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
3459
3459
  color: "green",
3460
3460
  bold: true,
3461
3461
  children: [
@@ -3481,6 +3481,418 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3481
3481
  });
3482
3482
  };
3483
3483
  //#endregion
3484
- export { Icons as C, Colors as S, PickerMenu as _, ServiceHealthList as a, SplitView as b, HNViewer as c, EventPlanViewer as d, LogViewer as f, useStdoutDimensions as g, GroupedPickerMenu as h, SEVERITY_ORDER as i, TabContainer as l, ConfirmationInput as m, IssueTable as n, TipsCard as o, ModalOverlay as p, SEVERITY_LABEL as r, LearnCard as s, McpScreen as t, ScreenContainer as u, ProgressList as v, WizardStore as w, CardLayout as x, LoadingBox as y };
3484
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx
3485
+ /** Sub-header row inside the scrollable body — one per area group. */
3486
+ const AreaHeaderRow = ({ area, resolved, total }) => /* @__PURE__ */ jsxs(Box, {
3487
+ flexShrink: 0,
3488
+ marginTop: 1,
3489
+ children: [/* @__PURE__ */ jsxs(Text, {
3490
+ bold: true,
3491
+ color: "cyan",
3492
+ children: [area, " "]
3493
+ }), /* @__PURE__ */ jsxs(Text, {
3494
+ dimColor: true,
3495
+ children: [
3496
+ "(",
3497
+ resolved,
3498
+ "/",
3499
+ total,
3500
+ ")"
3501
+ ]
3502
+ })]
3503
+ });
3504
+ /** ScreenContainer wraps content in paddingX={1} inside a width capped at
3505
+ * MAX_WIDTH, so the actual width available to the viewer is
3506
+ * min(cols, MAX_WIDTH) - 2. */
3507
+ function getViewerWidth(rawCols) {
3508
+ return Math.min(120, rawCols) - 2;
3509
+ }
3510
+ function computeLayout(rawCols, termRows) {
3511
+ const cols = getViewerWidth(rawCols);
3512
+ const padding = 2;
3513
+ const statusWidth = 2;
3514
+ const fixedExceptLabel = padding + statusWidth + 2 + 18 + 2 + 2;
3515
+ const labelWidth = Math.max(28, cols - fixedExceptLabel);
3516
+ const detailIndent = statusWidth + 2 + 18 + 2;
3517
+ const viewerChrome = 10;
3518
+ return {
3519
+ cols,
3520
+ visibleHeight: Math.max(5, termRows - 10 - viewerChrome),
3521
+ viewerChrome,
3522
+ padding,
3523
+ statusWidth,
3524
+ areaWidth: 18,
3525
+ labelWidth,
3526
+ colGap: 2,
3527
+ dividerWidth: Math.max(20, cols - padding),
3528
+ detailIndent,
3529
+ detailWidth: Math.max(20, cols - detailIndent - padding)
3530
+ };
3531
+ }
3532
+ function truncate(text, max) {
3533
+ if (max <= 0) return "";
3534
+ if (text.length <= max) return text;
3535
+ return text.slice(0, Math.max(1, max - 1)) + "…";
3536
+ }
3537
+ //#endregion
3538
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx
3539
+ const CheckRow = ({ item, layout }) => {
3540
+ const style = AUDIT_SEVERITY_STYLE[item.status];
3541
+ return /* @__PURE__ */ jsxs(Box, {
3542
+ flexShrink: 0,
3543
+ children: [
3544
+ /* @__PURE__ */ jsx(Box, {
3545
+ width: layout.statusWidth + layout.colGap,
3546
+ children: /* @__PURE__ */ jsx(Text, {
3547
+ color: style.color,
3548
+ children: style.glyph
3549
+ })
3550
+ }),
3551
+ /* @__PURE__ */ jsx(Box, {
3552
+ width: layout.areaWidth + layout.colGap,
3553
+ children: /* @__PURE__ */ jsx(Text, {
3554
+ dimColor: true,
3555
+ children: truncate(item.area, layout.areaWidth)
3556
+ })
3557
+ }),
3558
+ /* @__PURE__ */ jsx(Box, {
3559
+ width: layout.labelWidth + layout.colGap,
3560
+ children: /* @__PURE__ */ jsx(Text, {
3561
+ bold: item.status !== "pending",
3562
+ dimColor: item.status === "pending",
3563
+ children: truncate(item.label, layout.labelWidth)
3564
+ })
3565
+ })
3566
+ ]
3567
+ });
3568
+ };
3569
+ //#endregion
3570
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx
3571
+ /** Format a `details` string. If it parses as a JSON object, render it as
3572
+ * indented key: value lines (skipping huge nested arrays/objects which we
3573
+ * truncate). Otherwise return the original text. v3000 emits structured
3574
+ * JSON for several event-quality checks — a raw dump is unreadable. */
3575
+ function formatDetails(raw) {
3576
+ const trimmed = raw.trim();
3577
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return [raw];
3578
+ let parsed;
3579
+ try {
3580
+ parsed = JSON.parse(trimmed);
3581
+ } catch {
3582
+ return [raw];
3583
+ }
3584
+ if (parsed === null || typeof parsed !== "object") return [raw];
3585
+ const lines = [];
3586
+ const renderValue = (v) => {
3587
+ if (v === null) return "null";
3588
+ if (typeof v === "string") return v;
3589
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
3590
+ if (Array.isArray(v)) {
3591
+ if (v.length === 0) return "[]";
3592
+ if (v.every((e) => e === null || typeof e !== "object")) return v.map(renderValue).join(", ");
3593
+ return `[${v.length} item${v.length === 1 ? "" : "s"}]`;
3594
+ }
3595
+ if (typeof v === "object") {
3596
+ const keys = Object.keys(v);
3597
+ return `{${keys.length} field${keys.length === 1 ? "" : "s"}}`;
3598
+ }
3599
+ return String(v);
3600
+ };
3601
+ for (const [key, value] of Object.entries(parsed)) lines.push(`${key}: ${renderValue(value)}`);
3602
+ return lines.length > 0 ? lines : [raw];
3603
+ }
3604
+ /** Indented under the CHECK column; wrap continuation aligns with the prefix. */
3605
+ const DetailRow = ({ item, layout }) => {
3606
+ const detailLines = item.details ? formatDetails(item.details) : [];
3607
+ return /* @__PURE__ */ jsxs(Box, {
3608
+ flexShrink: 0,
3609
+ children: [/* @__PURE__ */ jsx(Box, { width: layout.detailIndent }), /* @__PURE__ */ jsxs(Box, {
3610
+ flexDirection: "column",
3611
+ width: layout.detailWidth,
3612
+ children: [item.file && /* @__PURE__ */ jsx(Text, {
3613
+ dimColor: true,
3614
+ wrap: "wrap",
3615
+ children: `↳ File: ${item.file}`
3616
+ }), detailLines.map((line, i) => /* @__PURE__ */ jsx(Text, {
3617
+ dimColor: true,
3618
+ italic: true,
3619
+ wrap: "wrap",
3620
+ children: i === 0 ? `${item.file ? " " : "↳ "}${line}` : ` ${line}`
3621
+ }, i))]
3622
+ })]
3623
+ });
3624
+ };
3625
+ //#endregion
3626
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx
3627
+ const Legend = () => /* @__PURE__ */ jsxs(Text, { children: [
3628
+ /* @__PURE__ */ jsx(Text, {
3629
+ color: "green",
3630
+ children: "✔ pass"
3631
+ }),
3632
+ /* @__PURE__ */ jsx(Text, {
3633
+ dimColor: true,
3634
+ children: " · "
3635
+ }),
3636
+ /* @__PURE__ */ jsx(Text, {
3637
+ color: "red",
3638
+ children: "✘ error"
3639
+ }),
3640
+ /* @__PURE__ */ jsx(Text, {
3641
+ dimColor: true,
3642
+ children: " · "
3643
+ }),
3644
+ /* @__PURE__ */ jsx(Text, {
3645
+ color: "yellow",
3646
+ children: "⚠ warning"
3647
+ }),
3648
+ /* @__PURE__ */ jsx(Text, {
3649
+ dimColor: true,
3650
+ children: " · "
3651
+ }),
3652
+ /* @__PURE__ */ jsx(Text, {
3653
+ color: "cyan",
3654
+ children: "• suggestion"
3655
+ })
3656
+ ] });
3657
+ //#endregion
3658
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx
3659
+ function statusCounts(checks) {
3660
+ const out = {
3661
+ pending: 0,
3662
+ pass: 0,
3663
+ error: 0,
3664
+ warning: 0,
3665
+ suggestion: 0
3666
+ };
3667
+ for (const c of checks) out[c.status] += 1;
3668
+ return out;
3669
+ }
3670
+ const Header = ({ layout }) => /* @__PURE__ */ jsxs(Box, { children: [
3671
+ /* @__PURE__ */ jsx(Box, {
3672
+ width: layout.statusWidth + layout.colGap,
3673
+ children: /* @__PURE__ */ jsx(Text, {
3674
+ dimColor: true,
3675
+ bold: true,
3676
+ children: " "
3677
+ })
3678
+ }),
3679
+ /* @__PURE__ */ jsx(Box, {
3680
+ width: layout.areaWidth + layout.colGap,
3681
+ children: /* @__PURE__ */ jsx(Text, {
3682
+ dimColor: true,
3683
+ bold: true,
3684
+ children: "AREA"
3685
+ })
3686
+ }),
3687
+ /* @__PURE__ */ jsx(Box, {
3688
+ width: layout.labelWidth + layout.colGap,
3689
+ children: /* @__PURE__ */ jsx(Text, {
3690
+ dimColor: true,
3691
+ bold: true,
3692
+ children: "CHECK"
3693
+ })
3694
+ })
3695
+ ] });
3696
+ const Summary = ({ total, counts }) => /* @__PURE__ */ jsxs(Text, {
3697
+ dimColor: true,
3698
+ children: [
3699
+ total,
3700
+ " total · ",
3701
+ counts.pending,
3702
+ " pending · ",
3703
+ counts.error,
3704
+ " errors ·",
3705
+ " ",
3706
+ counts.warning,
3707
+ " warnings · ",
3708
+ counts.suggestion,
3709
+ " suggestions · ",
3710
+ counts.pass,
3711
+ " ",
3712
+ "passes"
3713
+ ]
3714
+ });
3715
+ //#endregion
3716
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx
3717
+ const Footer = ({ total, counts }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Legend, {}), /* @__PURE__ */ jsx(Summary, {
3718
+ total,
3719
+ counts
3720
+ })] });
3721
+ //#endregion
3722
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/sort.ts
3723
+ const STATUS_ORDER = {
3724
+ error: 0,
3725
+ warning: 1,
3726
+ suggestion: 2,
3727
+ pass: 3,
3728
+ pending: 4
3729
+ };
3730
+ /** Audit areas in the order they should be displayed. Areas not listed
3731
+ * here fall through to alphabetical order at the end. Mirrors the
3732
+ * Full audit section grouping in the generated report. */
3733
+ const AREA_ORDER = [
3734
+ "Installation",
3735
+ "Identification",
3736
+ "Event Capture",
3737
+ "Event Quality",
3738
+ "Feature Flags",
3739
+ "Session Replay",
3740
+ "Session Replay — Optimize",
3741
+ "Use Case: Expansion",
3742
+ "Additional Sections"
3743
+ ];
3744
+ function areaRank(area) {
3745
+ const idx = AREA_ORDER.indexOf(area);
3746
+ return idx === -1 ? AREA_ORDER.length : idx;
3747
+ }
3748
+ /** Group checks by area, in AREA_ORDER. Within each area, sort by status. */
3749
+ function groupChecksByArea(checks) {
3750
+ const byArea = /* @__PURE__ */ new Map();
3751
+ for (const c of checks) {
3752
+ const list = byArea.get(c.area);
3753
+ if (list) list.push(c);
3754
+ else byArea.set(c.area, [c]);
3755
+ }
3756
+ const groups = [];
3757
+ for (const [area, areaChecks] of byArea) {
3758
+ const sorted = [...areaChecks].sort((a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status]);
3759
+ const resolved = sorted.filter((c) => c.status !== "pending").length;
3760
+ groups.push({
3761
+ area,
3762
+ checks: sorted,
3763
+ counts: {
3764
+ total: sorted.length,
3765
+ resolved
3766
+ }
3767
+ });
3768
+ }
3769
+ groups.sort((a, b) => {
3770
+ const dr = areaRank(a.area) - areaRank(b.area);
3771
+ if (dr !== 0) return dr;
3772
+ return a.area.localeCompare(b.area);
3773
+ });
3774
+ return groups;
3775
+ }
3776
+ //#endregion
3777
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx
3778
+ /**
3779
+ * AuditChecksViewer — "Audit plan" tab.
3780
+ *
3781
+ * Renders the full audit ledger as a scrollable, area-grouped list that
3782
+ * mirrors the structure of the final report. Each area gets a sub-header
3783
+ * with a resolved/total count; checks within an area are sorted by
3784
+ * severity (error → warning → suggestion → pass → pending).
3785
+ *
3786
+ * Two interactions, both registered via `useKeyBindings`:
3787
+ * - `e` — toggle detail rows (file:line + agent's `details` text)
3788
+ * - `↑` / `↓` — scroll one row at a time, clamped to content bounds
3789
+ *
3790
+ * Auto-expands on first mount when the ledger contains any issue, since
3791
+ * the AuditAreaPane's `[→] View issues` hint sends users here precisely
3792
+ * to read those details.
3793
+ */
3794
+ const AuditChecksViewer = ({ checks }) => {
3795
+ const [rawCols, termRows] = useStdoutDimensions();
3796
+ const layout = computeLayout(rawCols, termRows);
3797
+ const totalHeight = layout.visibleHeight + layout.viewerChrome;
3798
+ const groups = useMemo(() => groupChecksByArea(checks), [checks]);
3799
+ const counts = useMemo(() => statusCounts(checks), [checks]);
3800
+ const hasExpandable = checks.some((c) => Boolean(c.details || c.file));
3801
+ const [expanded, setExpanded] = useState(checks.some((c) => c.status === "error" || c.status === "warning" || c.status === "suggestion") && hasExpandable);
3802
+ const allRows = useMemo(() => {
3803
+ const rows = [];
3804
+ for (const group of groups) {
3805
+ rows.push(/* @__PURE__ */ jsx(AreaHeaderRow, {
3806
+ area: group.area,
3807
+ resolved: group.counts.resolved,
3808
+ total: group.counts.total
3809
+ }, `header-${group.area}`));
3810
+ for (const item of group.checks) {
3811
+ rows.push(/* @__PURE__ */ jsx(CheckRow, {
3812
+ item,
3813
+ layout
3814
+ }, item.id));
3815
+ if (expanded && (item.details || item.file)) rows.push(/* @__PURE__ */ jsx(DetailRow, {
3816
+ item,
3817
+ layout
3818
+ }, `${item.id}-detail`));
3819
+ }
3820
+ }
3821
+ return rows;
3822
+ }, [
3823
+ groups,
3824
+ expanded,
3825
+ layout
3826
+ ]);
3827
+ const [offset, setOffset] = useState(0);
3828
+ const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);
3829
+ const clampedOffset = Math.min(offset, maxOffset);
3830
+ const hiddenAbove = clampedOffset;
3831
+ const hiddenBelow = Math.max(0, allRows.length - clampedOffset - layout.visibleHeight);
3832
+ const bindings = [];
3833
+ if (hasExpandable) bindings.push({
3834
+ match: "e",
3835
+ label: "e",
3836
+ action: expanded ? "collapse details" : "expand details",
3837
+ handler: () => setExpanded((prev) => !prev)
3838
+ });
3839
+ bindings.push({
3840
+ match: ["upArrow", "downArrow"],
3841
+ label: "↑↓",
3842
+ action: "scroll",
3843
+ handler: (_input, key) => {
3844
+ if (key.upArrow) setOffset((o) => Math.max(0, o - 1));
3845
+ else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));
3846
+ }
3847
+ });
3848
+ useKeyBindings("audit-checks-viewer", bindings);
3849
+ const visibleRows = allRows.slice(clampedOffset, clampedOffset + layout.visibleHeight);
3850
+ const subtitle = groups.length === 0 ? "No checks yet." : `Review across ${groups.length} ${groups.length === 1 ? "area" : "areas"} — mirrors the final report.`;
3851
+ return /* @__PURE__ */ jsxs(Box, {
3852
+ flexDirection: "column",
3853
+ paddingX: 1,
3854
+ height: totalHeight,
3855
+ children: [
3856
+ /* @__PURE__ */ jsx(Text, {
3857
+ bold: true,
3858
+ children: "Audit plan"
3859
+ }),
3860
+ /* @__PURE__ */ jsx(Text, {
3861
+ dimColor: true,
3862
+ children: subtitle
3863
+ }),
3864
+ /* @__PURE__ */ jsx(Summary, {
3865
+ total: checks.length,
3866
+ counts
3867
+ }),
3868
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
3869
+ /* @__PURE__ */ jsx(Header, { layout }),
3870
+ /* @__PURE__ */ jsx(Text, {
3871
+ dimColor: true,
3872
+ children: "─".repeat(layout.dividerWidth)
3873
+ }),
3874
+ /* @__PURE__ */ jsx(Text, {
3875
+ dimColor: true,
3876
+ children: hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : " "
3877
+ }),
3878
+ /* @__PURE__ */ jsx(Box, {
3879
+ flexDirection: "column",
3880
+ height: layout.visibleHeight,
3881
+ overflow: "hidden",
3882
+ children: visibleRows.map((node, i) => /* @__PURE__ */ jsx(Fragment, { children: node }, `row-${clampedOffset + i}`))
3883
+ }),
3884
+ /* @__PURE__ */ jsx(Text, {
3885
+ dimColor: true,
3886
+ children: hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : " "
3887
+ }),
3888
+ /* @__PURE__ */ jsx(Footer, {
3889
+ total: checks.length,
3890
+ counts
3891
+ })
3892
+ ]
3893
+ });
3894
+ };
3895
+ //#endregion
3896
+ export { CardLayout as C, WizardStore as E, SplitView as S, Icons as T, useStdoutDimensions as _, SEVERITY_ORDER as a, ProgressList as b, LearnCard as c, ScreenContainer as d, EventPlanViewer as f, GroupedPickerMenu as g, ConfirmationInput as h, SEVERITY_LABEL as i, HNViewer as l, ModalOverlay as m, McpScreen as n, ServiceHealthList as o, LogViewer as p, IssueTable as r, TipsCard as s, AuditChecksViewer as t, TabContainer as u, PickerMenu as v, Colors as w, LoadingBox as x, useKeyBindings as y };
3485
3897
 
3486
- //# sourceMappingURL=McpScreen-DvUncZBi.js.map
3898
+ //# sourceMappingURL=AuditChecksViewer-B0J7zcY2.js.map