@posthog/wizard 2.11.0 → 2.12.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 (85) hide show
  1. package/README.md +48 -7
  2. package/dist/{McpScreen-DvUncZBi.js → AuditChecksViewer-DsfXIO9e.js} +330 -21
  3. package/dist/AuditChecksViewer-DsfXIO9e.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-Br1hDRiB.js → add-mcp-server-to-clients-BKoew3aT.js} +5 -5
  5. package/dist/{add-mcp-server-to-clients-Br1hDRiB.js.map → add-mcp-server-to-clients-BKoew3aT.js.map} +1 -1
  6. package/dist/{readiness-gQvQNCeL.js → agent-interface-D5W9BAB2.js} +326 -461
  7. package/dist/agent-interface-D5W9BAB2.js.map +1 -0
  8. package/dist/{agent-runner-fWYFO4H0.js → agent-runner-B8Cx6X6x.js} +19 -30
  9. package/dist/{agent-runner-fWYFO4H0.js.map → agent-runner-B8Cx6X6x.js.map} +1 -1
  10. package/dist/analytics-DmD31Ssc.js +123 -0
  11. package/dist/analytics-DmD31Ssc.js.map +1 -0
  12. package/dist/analytics-JDitS2JI.js +2 -0
  13. package/dist/bin.js +324 -42
  14. package/dist/bin.js.map +1 -1
  15. package/dist/debug-Bkaqv1ab.js +686 -0
  16. package/dist/debug-Bkaqv1ab.js.map +1 -0
  17. package/dist/{debug-D-0xueVl.js → debug-I5sRZubJ.js} +1 -1
  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-C_RfYYDe.js} +3 -3
  21. package/dist/{detection-B7GNzve-.js.map → detection-C_RfYYDe.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-qxP2PpM_.js} +2 -2
  29. package/dist/{package-manager-D3Lo6nXf.js.map → package-manager-qxP2PpM_.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-DX77Msto.js} +41 -13
  33. package/dist/posthog-integration-DX77Msto.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-CHfTOEvg.js +2 -0
  37. package/dist/provisioning-DUj285NO.js +166 -0
  38. package/dist/provisioning-DUj285NO.js.map +1 -0
  39. package/dist/{registry-DaPKstG3.js → registry-CCtIsqb8.js} +4 -5
  40. package/dist/{registry-DaPKstG3.js.map → registry-CCtIsqb8.js.map} +1 -1
  41. package/dist/{router-SgzmfLGi.js → router-BTfmEDDJ.js} +3 -3
  42. package/dist/router-BTfmEDDJ.js.map +1 -0
  43. package/dist/{setup-utils-y4s-3uKT.js → setup-utils-Bv8z6HMb.js} +11 -150
  44. package/dist/setup-utils-Bv8z6HMb.js.map +1 -0
  45. package/dist/setup-utils-CoX-vLgw.js +2 -0
  46. package/dist/{start-playground-g1TxpCZ5.js → start-playground-DYNQ8rOz.js} +102 -7
  47. package/dist/start-playground-DYNQ8rOz.js.map +1 -0
  48. package/dist/{start-tui-CQef69NR.js → start-tui-DleQG3La.js} +969 -124
  49. package/dist/start-tui-DleQG3La.js.map +1 -0
  50. package/dist/{steps-D1zKDqAo.js → steps-C-syS8if.js} +8 -8
  51. package/dist/steps-C-syS8if.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-DHZfjgqx.js} +2 -2
  55. package/dist/{telemetry-CyUUSAYy.js.map → telemetry-DHZfjgqx.js.map} +1 -1
  56. package/dist/{wizard-abort-DZmO_sIZ.js → wizard-abort-DIhFXJ5N.js} +1 -1
  57. package/dist/{wizard-abort-Buodno3f.js → wizard-abort-DfhWuzaw.js} +6 -4
  58. package/dist/{wizard-abort-Buodno3f.js.map → wizard-abort-DfhWuzaw.js.map} +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.map +0 -1
  83. package/dist/steps-D1zKDqAo.js.map +0 -1
  84. package/dist/wizard-session-COhklXAF.js +0 -2
  85. 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";
1
+ import { d as SERVICE_LABELS } from "./debug-Bkaqv1ab.js";
2
+ import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
+ import { n as analytics, r as sessionProperties } from "./analytics-DmD31Ssc.js";
4
+ import { r as buildSession } from "./wizard-session-BcNJTl2I.js";
5
+ import { g as AUDIT_SEVERITY_STYLE } from "./agent-interface-D5W9BAB2.js";
5
6
  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";
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-BTfmEDDJ.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: [
@@ -3480,7 +3480,316 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3480
3480
  })]
3481
3481
  });
3482
3482
  };
3483
+ /** ScreenContainer wraps content in paddingX={1} inside a width capped at
3484
+ * MAX_WIDTH, so the actual width available to the viewer is
3485
+ * min(cols, MAX_WIDTH) - 2. */
3486
+ function getViewerWidth(rawCols) {
3487
+ return Math.min(120, rawCols) - 2;
3488
+ }
3489
+ function computeLayout(rawCols, termRows) {
3490
+ const cols = getViewerWidth(rawCols);
3491
+ const padding = 2;
3492
+ const statusWidth = 2;
3493
+ const fixedExceptLabel = padding + statusWidth + 2 + 18 + 2 + 2;
3494
+ const labelWidth = Math.max(28, cols - fixedExceptLabel);
3495
+ const detailIndent = statusWidth + 2 + 18 + 2;
3496
+ const viewerChrome = 9;
3497
+ return {
3498
+ cols,
3499
+ visibleHeight: Math.max(5, termRows - 10 - viewerChrome),
3500
+ viewerChrome,
3501
+ padding,
3502
+ statusWidth,
3503
+ areaWidth: 18,
3504
+ labelWidth,
3505
+ colGap: 2,
3506
+ dividerWidth: Math.max(20, cols - padding),
3507
+ detailIndent,
3508
+ detailWidth: Math.max(20, cols - detailIndent - padding)
3509
+ };
3510
+ }
3511
+ function truncate(text, max) {
3512
+ if (max <= 0) return "";
3513
+ if (text.length <= max) return text;
3514
+ return text.slice(0, Math.max(1, max - 1)) + "…";
3515
+ }
3516
+ //#endregion
3517
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx
3518
+ const CheckRow = ({ item, layout }) => {
3519
+ const style = AUDIT_SEVERITY_STYLE[item.status];
3520
+ return /* @__PURE__ */ jsxs(Box, {
3521
+ flexShrink: 0,
3522
+ children: [
3523
+ /* @__PURE__ */ jsx(Box, {
3524
+ width: layout.statusWidth + layout.colGap,
3525
+ children: /* @__PURE__ */ jsx(Text, {
3526
+ color: style.color,
3527
+ children: style.glyph
3528
+ })
3529
+ }),
3530
+ /* @__PURE__ */ jsx(Box, {
3531
+ width: layout.areaWidth + layout.colGap,
3532
+ children: /* @__PURE__ */ jsx(Text, {
3533
+ dimColor: true,
3534
+ children: truncate(item.area, layout.areaWidth)
3535
+ })
3536
+ }),
3537
+ /* @__PURE__ */ jsx(Box, {
3538
+ width: layout.labelWidth + layout.colGap,
3539
+ children: /* @__PURE__ */ jsx(Text, {
3540
+ bold: item.status !== "pending",
3541
+ dimColor: item.status === "pending",
3542
+ children: truncate(item.label, layout.labelWidth)
3543
+ })
3544
+ })
3545
+ ]
3546
+ });
3547
+ };
3548
+ //#endregion
3549
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx
3550
+ /** Indented under the CHECK column; wrap continuation aligns with the prefix. */
3551
+ const DetailRow = ({ item, layout }) => /* @__PURE__ */ jsxs(Box, {
3552
+ flexShrink: 0,
3553
+ children: [/* @__PURE__ */ jsx(Box, { width: layout.detailIndent }), /* @__PURE__ */ jsxs(Box, {
3554
+ flexDirection: "column",
3555
+ width: layout.detailWidth,
3556
+ children: [item.file && /* @__PURE__ */ jsx(Text, {
3557
+ dimColor: true,
3558
+ wrap: "wrap",
3559
+ children: `↳ File: ${item.file}`
3560
+ }), item.details && /* @__PURE__ */ jsx(Text, {
3561
+ dimColor: true,
3562
+ italic: true,
3563
+ wrap: "wrap",
3564
+ children: `${item.file ? " " : "↳ "}Details: ${item.details}`
3565
+ })]
3566
+ })]
3567
+ });
3568
+ //#endregion
3569
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx
3570
+ const Legend = () => /* @__PURE__ */ jsxs(Text, { children: [
3571
+ /* @__PURE__ */ jsx(Text, {
3572
+ color: "green",
3573
+ children: "✔ pass"
3574
+ }),
3575
+ /* @__PURE__ */ jsx(Text, {
3576
+ dimColor: true,
3577
+ children: " · "
3578
+ }),
3579
+ /* @__PURE__ */ jsx(Text, {
3580
+ color: "red",
3581
+ children: "✘ error"
3582
+ }),
3583
+ /* @__PURE__ */ jsx(Text, {
3584
+ dimColor: true,
3585
+ children: " · "
3586
+ }),
3587
+ /* @__PURE__ */ jsx(Text, {
3588
+ color: "yellow",
3589
+ children: "⚠ warning"
3590
+ }),
3591
+ /* @__PURE__ */ jsx(Text, {
3592
+ dimColor: true,
3593
+ children: " · "
3594
+ }),
3595
+ /* @__PURE__ */ jsx(Text, {
3596
+ color: "cyan",
3597
+ children: "• suggestion"
3598
+ })
3599
+ ] });
3600
+ //#endregion
3601
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx
3602
+ function statusCounts(checks) {
3603
+ const out = {
3604
+ pending: 0,
3605
+ pass: 0,
3606
+ error: 0,
3607
+ warning: 0,
3608
+ suggestion: 0
3609
+ };
3610
+ for (const c of checks) out[c.status] += 1;
3611
+ return out;
3612
+ }
3613
+ const Header = ({ layout }) => /* @__PURE__ */ jsxs(Box, { children: [
3614
+ /* @__PURE__ */ jsx(Box, {
3615
+ width: layout.statusWidth + layout.colGap,
3616
+ children: /* @__PURE__ */ jsx(Text, {
3617
+ dimColor: true,
3618
+ bold: true,
3619
+ children: " "
3620
+ })
3621
+ }),
3622
+ /* @__PURE__ */ jsx(Box, {
3623
+ width: layout.areaWidth + layout.colGap,
3624
+ children: /* @__PURE__ */ jsx(Text, {
3625
+ dimColor: true,
3626
+ bold: true,
3627
+ children: "AREA"
3628
+ })
3629
+ }),
3630
+ /* @__PURE__ */ jsx(Box, {
3631
+ width: layout.labelWidth + layout.colGap,
3632
+ children: /* @__PURE__ */ jsx(Text, {
3633
+ dimColor: true,
3634
+ bold: true,
3635
+ children: "CHECK"
3636
+ })
3637
+ })
3638
+ ] });
3639
+ const Summary = ({ total, counts }) => /* @__PURE__ */ jsxs(Text, {
3640
+ dimColor: true,
3641
+ children: [
3642
+ total,
3643
+ " total · ",
3644
+ counts.pending,
3645
+ " pending · ",
3646
+ counts.error,
3647
+ " errors ·",
3648
+ " ",
3649
+ counts.warning,
3650
+ " warnings · ",
3651
+ counts.suggestion,
3652
+ " suggestions · ",
3653
+ counts.pass,
3654
+ " ",
3655
+ "passes"
3656
+ ]
3657
+ });
3658
+ //#endregion
3659
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx
3660
+ const Footer = ({ total, counts }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Legend, {}), /* @__PURE__ */ jsx(Summary, {
3661
+ total,
3662
+ counts
3663
+ })] });
3664
+ //#endregion
3665
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/sort.ts
3666
+ const STATUS_ORDER = {
3667
+ error: 0,
3668
+ warning: 1,
3669
+ suggestion: 2,
3670
+ pass: 3,
3671
+ pending: 4
3672
+ };
3673
+ /** Issues at the top (error → warning → suggestion), then passes, then pending todos. */
3674
+ function sortChecks(checks) {
3675
+ return [...checks].sort((a, b) => {
3676
+ const da = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];
3677
+ if (da !== 0) return da;
3678
+ return a.area.localeCompare(b.area);
3679
+ });
3680
+ }
3681
+ //#endregion
3682
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx
3683
+ /**
3684
+ * AuditChecksViewer — "Audit plan" tab.
3685
+ *
3686
+ * Renders the full audit ledger as a scrollable table grouped by status:
3687
+ * resolved checks (issues + passes, sorted by severity) on top, pending
3688
+ * checks at the bottom, separated by a blank row.
3689
+ *
3690
+ * Two interactions, both registered via `useKeyBindings`:
3691
+ * - `e` — toggle detail rows (file:line + agent's `details` text)
3692
+ * - `↑` / `↓` — scroll one row at a time, clamped to content bounds
3693
+ *
3694
+ * Auto-expands on first mount when the ledger contains any issue, since
3695
+ * the AuditAreaPane's `[→] View issues` hint sends users here precisely
3696
+ * to read those details.
3697
+ */
3698
+ const AuditChecksViewer = ({ checks }) => {
3699
+ const [rawCols, termRows] = useStdoutDimensions();
3700
+ const layout = computeLayout(rawCols, termRows);
3701
+ const totalHeight = layout.visibleHeight + layout.viewerChrome;
3702
+ const sorted = useMemo(() => sortChecks(checks), [checks]);
3703
+ const resolved = sorted.filter((c) => c.status !== "pending");
3704
+ const pending = sorted.filter((c) => c.status === "pending");
3705
+ const hasExpandable = sorted.some((c) => Boolean(c.details || c.file));
3706
+ const [expanded, setExpanded] = useState(sorted.some((c) => c.status === "error" || c.status === "warning" || c.status === "suggestion") && hasExpandable);
3707
+ const allRows = useMemo(() => {
3708
+ const rows = [];
3709
+ const buildRow = (item) => {
3710
+ rows.push(/* @__PURE__ */ jsx(CheckRow, {
3711
+ item,
3712
+ layout
3713
+ }, item.id));
3714
+ if (expanded && (item.details || item.file)) rows.push(/* @__PURE__ */ jsx(DetailRow, {
3715
+ item,
3716
+ layout
3717
+ }, `${item.id}-detail`));
3718
+ };
3719
+ resolved.forEach(buildRow);
3720
+ if (resolved.length > 0 && pending.length > 0) rows.push(/* @__PURE__ */ jsx(Box, { height: 1 }, "separator"));
3721
+ pending.forEach(buildRow);
3722
+ return rows;
3723
+ }, [
3724
+ resolved,
3725
+ pending,
3726
+ expanded,
3727
+ layout
3728
+ ]);
3729
+ const [offset, setOffset] = useState(0);
3730
+ const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);
3731
+ const clampedOffset = Math.min(offset, maxOffset);
3732
+ const hiddenAbove = clampedOffset;
3733
+ const hiddenBelow = Math.max(0, allRows.length - clampedOffset - layout.visibleHeight);
3734
+ const bindings = [];
3735
+ if (hasExpandable) bindings.push({
3736
+ match: "e",
3737
+ label: "e",
3738
+ action: expanded ? "collapse details" : "expand details",
3739
+ handler: () => setExpanded((prev) => !prev)
3740
+ });
3741
+ bindings.push({
3742
+ match: ["upArrow", "downArrow"],
3743
+ label: "↑↓",
3744
+ action: "scroll",
3745
+ handler: (_input, key) => {
3746
+ if (key.upArrow) setOffset((o) => Math.max(0, o - 1));
3747
+ else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));
3748
+ }
3749
+ });
3750
+ useKeyBindings("audit-checks-viewer", bindings);
3751
+ const visibleRows = allRows.slice(clampedOffset, clampedOffset + layout.visibleHeight);
3752
+ return /* @__PURE__ */ jsxs(Box, {
3753
+ flexDirection: "column",
3754
+ paddingX: 1,
3755
+ height: totalHeight,
3756
+ children: [
3757
+ /* @__PURE__ */ jsx(Text, {
3758
+ bold: true,
3759
+ children: "Audit plan"
3760
+ }),
3761
+ /* @__PURE__ */ jsx(Text, {
3762
+ dimColor: true,
3763
+ children: "Read-only review of installation, identification, and event capture"
3764
+ }),
3765
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
3766
+ /* @__PURE__ */ jsx(Header, { layout }),
3767
+ /* @__PURE__ */ jsx(Text, {
3768
+ dimColor: true,
3769
+ children: "─".repeat(layout.dividerWidth)
3770
+ }),
3771
+ /* @__PURE__ */ jsx(Text, {
3772
+ dimColor: true,
3773
+ children: hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : " "
3774
+ }),
3775
+ /* @__PURE__ */ jsx(Box, {
3776
+ flexDirection: "column",
3777
+ height: layout.visibleHeight,
3778
+ overflow: "hidden",
3779
+ children: visibleRows.map((node, i) => /* @__PURE__ */ jsx(Fragment, { children: node }, `row-${clampedOffset + i}`))
3780
+ }),
3781
+ /* @__PURE__ */ jsx(Text, {
3782
+ dimColor: true,
3783
+ children: hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : " "
3784
+ }),
3785
+ /* @__PURE__ */ jsx(Footer, {
3786
+ total: checks.length,
3787
+ counts: statusCounts(checks)
3788
+ })
3789
+ ]
3790
+ });
3791
+ };
3483
3792
  //#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 };
3793
+ export { Colors as C, CardLayout as S, WizardStore as T, useStdoutDimensions as _, SEVERITY_ORDER as a, LoadingBox 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, Icons as w, SplitView as x, ProgressList as y };
3485
3794
 
3486
- //# sourceMappingURL=McpScreen-DvUncZBi.js.map
3795
+ //# sourceMappingURL=AuditChecksViewer-DsfXIO9e.js.map